How do I avoid naming clashes within Python's module system? - python

In my Django project I have an app called profile, which mostly contains my profile.models.UserProfile class for additional information on User objects (may seem familiar to Django folks). Now I've put some initialization code into profile/__init__.py (some signals) and have ran into a problem: Django tells me that a table called hotshot_profile has not been found.
After literally hours of searching, I traced the problem back to importing order. Running python -v manage.py test I've found the following:
import nose.plugins.prof # precompiled from /home/rassie/.virtualenvs/myproject/lib/python2.6/site-packages/nose/plugins/prof.pyc
import hotshot # directory /usr/lib64/python2.6/hotshot
import hotshot # precompiled from /usr/lib64/python2.6/hotshot/__init__.pyc
dlopen("/home/rassie/.virtualenvs/myproject/lib64/python2.6/lib-dynload/_hotshot.so", 2);
import _hotshot # dynamically loaded from /home/rassie/.virtualenvs/myproject/lib64/python2.6/lib-dynload/_hotshot.so
import hotshot.stats # from /usr/lib64/python2.6/hotshot/stats.py
import profile # directory /home/rassie/MyProject/apps/profile
import profile # precompiled from /home/rassie/MyProject/apps/profile/__init__.pyc
So my Nose runner imports the nose.plugins.prof (even though this plugin is off), imports hotshot, which tries to import profile. However, profile gets imported from my project, while it ready should have been imported from system Python.
Obviously, my own profile module clashes with system profile module. I obviously can't exclude every module name that comes bundled with Python from my own programming. So the question is, where do I go from here? Do I have to create a myproject namespace for all of my apps? Will Django work with that?
PS: Table's name hotshot_profile seems to come from a further yet-to-be-fully-analyzed naming clash with a Profile class from pybb, which I'm also using in my project. But that's out of this question's scope.

You should never import your own modules in the form import mymodule (relative imports). Instead you should always use import myproject.mymodule instead (absolute imports). This avoids all name clashes.

Related

Sharing PonyORM's db session across different python module

I initially started a small python project (Python, Tkinter amd PonyORM) and became larger that is why I decided to divide the code (used to be single file only) to several modules (e.g. main, form1, entity, database). Main acting as the main controller, form1 as an example can contain a tkinter Frame which can be used as an interface where the user can input data, entity contains the db.Enttiy mappings and database for the pony.Database instance along with its connection details. I think problem is that during import, I'm getting this error "pony.orm.core.ERDiagramError: Cannot define entity 'EmpInfo': database mapping has already been generated". Can you point me to any existing code how should be done.
Probably you import your modules in a wrong order. Any module which contains entity definitions should be imported before db.generate_mapping() call.
I think you should call db.generate_mapping() right before entering tk.mainloop() when all imports are already done.
A good approach to avoid this is rather than having your db.generate_mapping() call happening at a module's top-level code, have a function that a module exports that calls db.generate_mapping() after all other modules have been imported.
The pattern I use is to put all of my db.Entity subclasses into a single module named model, and then at the bottom of model.py is:
def setup():
""" Set up the database """
db.bind(**database_config, create_db=True)
db.generate_mapping(create_tables=True)
This function is called by my application's own startup (which is also responsible for setting up database_config). This way the correct import and setup order can be guaranteed.
The db object itself is also owned by this model module; if I need to use it somewhere else I import model and use model.db.
If you want to further separate things out (with different model classes living in different modules) you can have a module that owns db, then your separate model modules, and then a third module that imports db and the models and provides the setup function. For example, your directory structure could look like this:
model/
__init__.py -- imports all of the model sub-modules and provides a setup function
db.py -- provides the db object itself and any common entities objects that everyone else needs
form1.py, form2.py, etc. -- imports db and uses its database object to define the entities
Then your main app can do something like:
import model
model.setup()

Django package naming issues

I have developed a backend library, say, cool_project. Now I want to build a web interface for it. So I create a Django project. Of course, I want to name it cool_project: my mother told me that Hungarian notation is bad and that the name cool_project is much better than any of cool_project_web etc.
But now I have a collision. As long as I try importing cool_project (the backend one) from django/cool_project/views.py (the views.py of the main Django app) a frontend package is being imported.
Is there any way to import backend project in this case? I tried to add full path to backend package (sys.path.insert(0, "/home/.../...")) but it didn't help.
Or maybe there is some well-known naming convention which helps avoiding such collisions?
You can use relative imports likefrom .. import cool_project as long you modules are in a package. I would suggest you to rename your app to something else though. It would create unnecessary complexity

Python package naming issue

I have a python package named gutils, which contains a lot of useful tools for development, some of them are generic, some of them use reportlabs and the most important part forms a layer of abstraction on top of django, customizing a lot of default behaviour
I would like to keep the convention of the exterior interface similar to django's, as to not add complexity to the development proccess..
I have this structure (as an example):
gutils
|---- django
|
|----forms
|
|---widgets.py
The problem is, inside this widgets.py file, the imports resolve to the current subpackage.
For example:
from django.forms import TextInput
Is treated as if it were:
from gutils.django.forms import TextInput
As a workaround, I've named the top-level package gdjango, but it looks awkward.
So, the question is:
Is there a way to reference the real django package from within the gutils.django package?
NOTE: I'm using python 3
If you're dealing with a package, for example, like this:
mypackage /
mypackagesubdir /
myfile.py
mypackagesubdirII /
myfileII.py
and you're editting myfile.py, import myfileII like import .mypackagessubdirII.myfileII. . means the root of the package.

How can I import a specific module with an ambiguous name?

This happens in Django context, but the question is not Django specific.
I'm trying to split my big urls.py into smaller and more manageable chunks (app includes, third-party modules, search, admin, development and so on). So instead of urls.py, I'm using urls/ directory now, with urls/__init__.py containing code like this:
import admin
urlpatterns += admin.urlpatterns
Now I've got into trouble with third-party modules. For example, I'm overriding a bunch of URLs and views for django-messages, and so I've put all of it into urls/messages.py. It turns out, I can't import django-messages' views then, since
from messages.views import inbox
inside urls/messages.py tries to import from local directory first, finds a messages module, but can't import messages.views then, since urls/messages/views.py is obviously absent. I wouldn't like having to rename my modules to something like urls.messages_urls, but I haven't found a way to explicitely tell Python to import the "other" messages.views. Neither would I like to specify my imported views via strings, even though I can do that in Django.
How can I solve this situation cleanly?
This is the wrong way to do it.
Django has a method for splitting urls.py into separate files, and that is to use include(). Keep the urls for each application in its own urls.py, and include them into the main one.
For those who could not find it, I was hitting ambiguous import errors. For example, in a django project, let's say I have this tree :
tax module
models module
init.py
tax.py
foo.py
In init.py, I want to import tax.models.tax.Tax.
So I write :
from tax.models.tax import Tax
But python does not find the correct import (it looks for models inside tax.models) and throws
ImportError: No module named models
You have indeed understood that it's all about relative imports. python first looks in the current module. If the first part of your import exists in the current module, it fails.
This behaviour has been fixed in Python 2.5 (and may have become default in Python 3.0), you just have to add :
from __future__ import absolute_import
before your absolute imports.
Have a look at Python 2.5 introduces absolute imports for more thorough information.
Have you tried:
from django.contrib.messages.views import inbox
Untested, but I'd think the full import would work as expected.

django - circular import problem when executing a command

I'm developing a django application. Modules of importance to my problem are given below:
globals.py --> contains constants that are used throughout the application. SITE_NAME and SITE_DOMAIN are two of those and are used to fill some strings. Here is how I define them:
from django.contrib.sites.models import Site
...
SITE_DOMAIN = Site.objects.get_current().domain
SITE_NAME = Site.objects.get_current().name
models.py --> models live inside this module. imports some constants from globals.py
some_command.py --> a command that imports some constants from globals also.
when executed, the command imports a constant from globals.py and runs into a circular import problem: inside globals.py, get_current() from sites app is called, and sites app in turn imports models.py which has imports from globals.py as well.
EDIT:
The application runs flawlessly, without encountering this circular import issue. Importing globals.py from shell brings no problems. Even the command can be executed from the shell without calling manage.py.
So why does manage.py some_command fail due to a circular import?
Thanks in advance.
Is there any particular reason you need to store SITE_DOMAIN and SITE_NAME in globals.py? These are already available directly from the sites framework.
According to the docs, the site object is cached the first time you access it, so importing it and using it there directly doesn't hurt.

Categories

Resources