This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Reloading pseudo modules
Type: enhancement Stage:
Components: Interpreter Core Versions: Python 2.7, Python 2.6
process
Status: closed Resolution: rejected
Dependencies: Superseder:
Assigned To: brett.cannon Nosy List: brett.cannon, doerwalter, facundobatista, loewis
Priority: normal Keywords: patch

Created on 2003-03-11 18:59 by doerwalter, last changed 2022-04-10 16:07 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
diff.txt doerwalter, 2003-03-11 18:59
diff2.txt doerwalter, 2003-03-17 14:25
diff3.txt loewis, 2007-03-13 09:29
Messages (10)
msg43002 - (view) Author: Walter Dörwald (doerwalter) * (Python committer) Date: 2003-03-11 18:59
Python allows to put something that is not a module in
sys.modules. Unfortunately reload() does not work wth
such a pseudo module ("TypeError: reload() argument
must be module" is raised). This patch changes
Python/import.c::PyImport_ReloadModule() so that it
works with anything that has a __name__ attribute that
can be found in sys.modules.keys().
msg43003 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2003-03-15 13:51
Logged In: YES 
user_id=21627

I think the exceptions need to be reworked: "must be a
module" now only occurs if m is NULL. Under what
circumstances could that happen? Failure to provide __name__
is passed through; shouldn't this get diagnosed in a better way?
msg43004 - (view) Author: Walter Dörwald (doerwalter) * (Python committer) Date: 2003-03-17 14:25
Logged In: YES 
user_id=89016

PyImport_ReloadModule() is only called by the implementation
of the reload builtin, so it seems that m==NULL can only
happen with broken extension modules. I've updated the patch
accordingly (raising a SystemError) and changed the error
case for a missing __name__ attribute to raise a TypeError
when an AttributeError is detected. Unfortunately this might
mask exceptions (e.g. when __name__ is implemented as a
property.)

Another problem is that reload() seems to repopulate the
existing module object when reloading real modules. Example:
Write a simple foo.py which contains "x = 1" and then:
>>> import foo
>>> foo.x
1
[ Now open your editor and change foo.py to "x = 2" ]
>>> foo2 = reload(foo)
>>> foo.x
2
>>> foo2.x
2
>>> print id(foo), id(foo2)
1077466884 1077466884
>>> 

Of course this can't work with pseudo modules. I wonder why
reload() has a return value at all, as it always modifies
its parameter for real modules.
msg43005 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2003-03-30 16:34
Logged In: YES 
user_id=21627

The patch looks fine now as far as it goes. I'm unsure what
the use case is, though: What object do you have in
sys.modules for which reload() would be meaningful? Can you
attach an example where reloading fails now but succeeds
with your patch applied?

As for reload modifying the module object: It needs to, or
else all clients would have to run reload; this would
include things like function default arguments. I guess it
returns a result for historical reasons.
msg43006 - (view) Author: Walter Dörwald (doerwalter) * (Python committer) Date: 2003-03-31 19:38
Logged In: YES 
user_id=89016

A use case can be found at
http://www.livinglogic.de/viewcvs/index.cgi/LivingLogic/xist/_xist/xsc.py?rev=2.235
(Look for the classmethod makemod() in the class Namespace).
This puts a class object into sys.modules instead of the
module that defines this class. This makes it possible to
derive from "modules". 

Of course the patch does not fully fix the problem, because
reload() does not repopulate the class object. Unfortunately
that's impossible to fix with Python code, as it's
impossible for Python code to distinguish the first import
from subsequent ones. If this was possible (and Python code
had access to the old "module"), a real reload could be
coded in pure Python for this specific case.

But with the patch at least it's possible to use the return
value of reload() afterwards to use the new "module".
msg43007 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2007-03-13 09:29
I have now updated the patch to the current trunk, however, I fail to see how it fixes the bug. See the included test case: it reports an ImportError on the reload, saying that there is no module named 'fake'.
File Added: diff3.txt
msg43008 - (view) Author: Walter Dörwald (doerwalter) * (Python committer) Date: 2007-03-13 17:55
This patch only works if there's a real module behind the fake one, i.e. if the imported module replaces itself if sys.modules.

To test, put the following into fake.py:
---
class FakeMod:
   def __init__(self, n):
      self.__name__ = n
   def foo(self):
      return 42

import sys

sys.modules[__name__] = FakeMod(__name__)
---
On the commandline do:
>>> import fake
>>> import sys
>>> fake
<fake.FakeMod instance at 0xb77bdea4>
>>> fake.foo()
42
[Now edit fake.py and change 42 to 43]
>>> fake2 = reload(fake)
>>> fake2
<fake.FakeMod instance at 0xb77bdaec>
>>> fake.foo()
42
>>> fake2.foo()
43
>>> sys.modules['fake'].foo()

However I'm no longer sure that the patch in this form is all that useful.
msg68585 - (view) Author: Facundo Batista (facundobatista) * (Python committer) Date: 2008-06-22 22:07
Walter, the import mechanisms changed by a big rework from Brett Cannon
in the last months. 

Do you think still have a use case that should be fulfilled? Do you want
to update your patch?

Thank you!
msg68616 - (view) Author: Walter Dörwald (doerwalter) * (Python committer) Date: 2008-06-23 08:50
AFAIK reload() is gone in 3.0 anyway, so I don't think this patch is
relevant any longer.
msg85146 - (view) Author: Brett Cannon (brett.cannon) * (Python committer) Date: 2009-04-02 02:53
Since reload is about reloading modules and sticking stuff other than
modules in sys.modules is a partial hack I am closing as "rejected".
History
Date User Action Args
2022-04-10 16:07:34adminsetgithub: 38145
2009-04-02 02:53:29brett.cannonsetstatus: open -> closed
resolution: rejected
messages: + msg85146
2009-02-11 03:01:11ajaksu2setassignee: brett.cannon
versions: + Python 2.6, Python 2.7, - Python 2.3
type: enhancement
nosy: + brett.cannon
2008-06-23 08:50:23doerwaltersetmessages: + msg68616
2008-06-22 22:07:08facundobatistasetnosy: + facundobatista
messages: + msg68585
2003-03-11 18:59:26doerwaltercreate