undeclared variable appearing in django/db/models/__init__.py

86 views
Skip to first unread message

Tim Graham

unread,
Oct 6, 2016, 9:10:03 PM10/6/16
to Django developers (Contributions to Django itself)
I'm seeing an issue while running the Django test suite that I can't explain.

If you add print(functions) before
from django.db.models.manager import Manager
in https://github.com/django/django/blob/master/django/db/models/__init__.py#L15, it gives name 'functions' is not defined  as I would expect.

However, if you add the same print on the line after, it gives <module 'django.db.models.functions' from '/home/tim/code/django/django/db/models/functions/__init__.py'>. A "functions" variable is magically defined!

Why does importing django.db.models.manager have this side effect? manager.py imports django.db.models.query which imports django.db.models.functions. If I move the functions import to an inner import in query.py as done in https://github.com/django/django/pull/7348, there's no more magic "functions" variable available in db/models/__init__.py.

Can you explain this? I checked all the "from *" imports in models/__init__.py to rule that out.

Peter Inglesby

unread,
Oct 7, 2016, 7:31:42 AM10/7/16
to django-d...@googlegroups.com
Hi Tim,

Disappointingly, I don't think Django's doing anything off the wall here!

When you import a package's submodule, the name of that submodule is added to the package's namespace.  This is what allows you to put `import p.m`, and to then to use `p.m` in your code -- module m is added to package p's namespace.

In the Django code, we end up importing django.db.models.functions (via django.db.models.manager and django.db.models.query)  in django/db/models/__init__.py.  `functions` gets added to the namespace of the package django.db.models, which Python does by adding it to the  __init__ module's locals(), which makes `functions` available as a label in the remainder of the code.

Note that I can't actually find the chapter and verse for how this works in the Python docs, but I've been caught out by something similar in the past!

Hope this helps,

Peter.

--
You received this message because you are subscribed to the Google Groups "Django developers (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-developers+unsubscribe@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-developers/d8247cc5-e9e8-4725-9714-8a30b0ebc60c%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Tim Graham

unread,
Oct 7, 2016, 12:51:18 PM10/7/16
to Django developers (Contributions to Django itself)
Thanks for the pointer! I think Django is misbehaving by importing "from django.db.models import *" in "django/contrib/gis/db/models/__init__.py" while django.db.models doesn't declare an __all__, so the "functions" submodule can be imported there which obscures the version at contrib/gis/db/models/functions.py.

I updated the PR to to add __all__ as needed and that seems to fix the issue I was having.

https://github.com/django/django/pull/7348


On Friday, October 7, 2016 at 7:31:42 AM UTC-4, Peter Inglesby wrote:
Hi Tim,

Disappointingly, I don't think Django's doing anything off the wall here!

When you import a package's submodule, the name of that submodule is added to the package's namespace.  This is what allows you to put `import p.m`, and to then to use `p.m` in your code -- module m is added to package p's namespace.

In the Django code, we end up importing django.db.models.functions (via django.db.models.manager and django.db.models.query)  in django/db/models/__init__.py.  `functions` gets added to the namespace of the package django.db.models, which Python does by adding it to the  __init__ module's locals(), which makes `functions` available as a label in the remainder of the code.

Note that I can't actually find the chapter and verse for how this works in the Python docs, but I've been caught out by something similar in the past!

Hope this helps,

Peter.
On 7 October 2016 at 02:10, Tim Graham <timog...@gmail.com> wrote:
I'm seeing an issue while running the Django test suite that I can't explain.

If you add print(functions) before
from django.db.models.manager import Manager
in https://github.com/django/django/blob/master/django/db/models/__init__.py#L15, it gives name 'functions' is not defined  as I would expect.

However, if you add the same print on the line after, it gives <module 'django.db.models.functions' from '/home/tim/code/django/django/db/models/functions/__init__.py'>. A "functions" variable is magically defined!

Why does importing django.db.models.manager have this side effect? manager.py imports django.db.models.query which imports django.db.models.functions. If I move the functions import to an inner import in query.py as done in https://github.com/django/django/pull/7348, there's no more magic "functions" variable available in db/models/__init__.py.

Can you explain this? I checked all the "from *" imports in models/__init__.py to rule that out.

--
You received this message because you are subscribed to the Google Groups "Django developers (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-develop...@googlegroups.com.
To post to this group, send email to django-d...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages