At 01:03 PM 6/5/2007 -0400, Ryan O'Neil wrote:
My apologies if this was already covered; I couldn't find appropriate mention of the issue.
What is the best way to require Python 2.5 in setuptools? In PyGEP 0.1.2 I did the following:
setup( # --- snip --- install_requires = ['python>=2.5'], # --- snip --- )
This worked wonderfully on Linux using setuptools 0.6c5, but on Windows (also with Python 2.5 and setuptools 0.6c5), it couldn't recognize the installed version of Python and tried to download and compile it (python) from source.
Interesting; it sounds like there might be a problem with what files are being installed on Windows; Python 2.5 is supposed to include a Python.egg-info file that indicates Python 2.5 is installed. However, it's probably the case that EasyInstall should not try to install Python from source, regardless. :)
I was able to get things mostly working by getting rid of the install_requires line and adding this code to my setup.py:
import sys
if sys.version_info[:2] < (2, 5): raise Exception('PyGEP requires Python 2.5')
I'd recommend using either a DistutilsError subclass or SystemExit; both will be handled more gracefully by easy_install.
However, easy_install will now download PyGEP for Python 2.4 and fail during setup, which is less than ideal (and ends up with cheesecaking slandering its installability ;). Am I just doing everything completely wrong?
No; at the moment the infrastructure for requiring a particular version of Python just isn't that great.
Is there a way to have my package tell setuptools to "ignore" certain other packages? I'm working on a project called Enstaller, which basically sits on top of setuptools and adds functionality like query options, a GUI, etc. I'm attempting to make it a standalone "bundled" egg, where all of it's dependencies are included in 2 eggs: the "core" egg, and the optional GUI egg. Prior to this, it was distributed as a single egg with several dependencies specified in the install_requires line which were automatically installed. The problem with that was that these packages were used for many other related projects, and when users would upgrade, downgrade, or unknowingly remove them, the Enstaller app would be left broken. The "bundled" approach seemed to work great: it was installed with -m so other projects would not import the possibly incompatible packages in enstaller, and only one or two eggs were installed instead of the intimidating dozen or so. A console_script entry point allowed users to type "enstaller" to start the app. The bundled egg is structured like this: enstaller.egg/ enthought/ enstaller/ traits/ Here, I've "bundled" in the enthought.traits package. The problem is, when I install the enthought.traits egg separately, python finds the traits package in the enthought.traits egg instead of the the one in the enstaller egg. I've tried removing all the "enthought." eggs from sys.path before anything else gets imported, but even that doesn't work (and it just felt wrong, and probably is). I looked at the docs for manipulating the WorkingSet, but made no progress there either...python always managed to find the incompatible enthought.traits code in the enthought.traits egg. When I remove the incompatible enthought.traits, all works fine. What I'd like to do is simply say "do not use any enthought.* eggs". Is this possible? Thanks in advance! -- Rick Ratzel - Enthought, Inc. 515 Congress Avenue, Suite 2100 - Austin, Texas 78701 512-536-1057 x229 - Fax: 512-536-1059 http://www.enthought.com
At 09:26 PM 6/8/2007 -0500, Rick Ratzel wrote:
Is there a way to have my package tell setuptools to "ignore" certain other packages?
Only through version specifications; i.e., request the exact versions you want.
I've tried removing all the "enthought." eggs from sys.path before anything else gets imported, but even that doesn't work (and it just felt wrong, and probably is).
If "enthought" is a namespace package, you would need to either be using an 0.7-development version of setuptools (i.e., a trunk SVN version), or else you'd need to remove those eggs from the path *before* pkg_resources is first imported. Otherwise, it would indeed not work.
I looked at the docs for manipulating the WorkingSet, but made no progress there either...python always managed to find the incompatible enthought.traits code in the enthought.traits egg. When I remove the incompatible enthought.traits, all works fine.
What I'd like to do is simply say "do not use any enthought.* eggs". Is this possible? Thanks in advance!
Not without using an 0.7 version of setuptools, or manipulating enthought.__path__. The straightforward way to do it would be for enstaller's __init__.py to do this: import enthought, os enthought.__path__ = os.path.dirname(os.path.dirname(__file__)) This will ensure that all enthought.* modules imported from then on will only be from within the parent directory of enstaller. I don't think I'd recommend this to anyone in the general case, but this might be a reasonable workaround if you truly want to "de-namespace" the package. (It will *not*, however, prevent new eggs from being added to __path__ if you add anything to sys.path or the working set afterward.)
(sorry about the subject line...I meant to start a new thread) Phillip, Thanks for the response. I implemented your recommendation and it did exactly what I needed it to do. More comments inline:
Date: Sat, 09 Jun 2007 16:04:45 -0400 From: "Phillip J. Eby"
At 09:26 PM 6/8/2007 -0500, Rick Ratzel wrote:
Is there a way to have my package tell setuptools to "ignore" certain other packages?
Only through version specifications; i.e., request the exact versions you want.
Yep, that's initially what I wanted to do since it was the "standard" way to do it. Unfortunatley, the packages that enstaller required were just recently "egg'd", and most of them had broken dependencies and stale version numbers. Many of the interdependencies did not even specify versions, so an old, incompatible version that was already installed satisfied the dependency but left enstaller broken. Many of the packages are now fixed (we've been undergoing a huge effort to convert our OSS repository to an egg-based deployment), but I was later convinced that it might be a good idea to keep enstaller isolated from the other eggs. Plus, enstaller[gui] requires about 13 eggs, almost all of which are used by other projects too. Users would "uninstall" their eggs and not realize that they were breaking enstaller. The monolithic egg approach seems to have solved all these problems. Unfortunately the eggs are obviously much bigger and downloading will be more expensive, especially for the enstaller.gui egg, which is installed by default by a bootstrapping script.
I've tried removing all the "enthought." eggs from sys.path before anything else gets imported, but even that doesn't work (and it just felt wrong, and probably is).
If "enthought" is a namespace package, you would need to either be using an 0.7-development version of setuptools (i.e., a trunk SVN version), or else you'd need to remove those eggs from the path *before* pkg_resources is first imported. Otherwise, it would indeed not work.
I looked at the docs for manipulating the WorkingSet, but made no progress there either...python always managed to find the incompatible enthought.traits code in the enthought.traits egg. When I remove the incompatible enthought.traits, all works fine.
What I'd like to do is simply say "do not use any enthought.* eggs". Is this possible? Thanks in advance!
Not without using an 0.7 version of setuptools, or manipulating enthought.__path__. The straightforward way to do it would be for enstaller's __init__.py to do this:
import enthought, os enthought.__path__ = os.path.dirname(os.path.dirname(__file__))
This will ensure that all enthought.* modules imported from then on will only be from within the parent directory of enstaller.
I ended up setting enthought.__path__ like you suggested, and will probably stick with that rather than force users to upgrade to 0.7 right now. However, I'm curious about how this is addressed in 0.7. Is there a new API for doing this?
I don't think I'd recommend this to anyone in the general case, but this might be a reasonable workaround if you truly want to "de-namespace" the package. (It will *not*, however, prevent new eggs from being added to __path__ if you add anything to sys.path or the working set afterward.)
Right. Fortunately, all the path "magic" is contained to this change, so I should be safe. Thanks again, -- Rick Ratzel - Enthought, Inc. 515 Congress Avenue, Suite 2100 - Austin, Texas 78701 512-536-1057 x229 - Fax: 512-536-1059 http://www.enthought.com
At 01:45 AM 6/10/2007 -0500, Rick Ratzel wrote:
I ended up setting enthought.__path__ like you suggested, and will probably stick with that rather than force users to upgrade to 0.7 right now. However, I'm curious about how this is addressed in 0.7. Is there a new API for doing this?
No; in 0.7 namespace packages are not automatically imported/created when pkg_resources is imported. This means you would have the chance to manipulate sys.path and/or the working_set before the other eggs could get added to enthought.__path__.
Arg...I thought I had this working, but it turns out I had a setuptools 0.7 dev release installed. When I go to a setuptools 0.6 release, I get the same old problem. Here are more details... Enstaller is started with a script generated when easy_install installs the egg, so right away pkg_resources is imported and I have no chance to do anything before. I put the following in enstaller's __init__.py as recommended: from os import path import enthought enthought.__path__ = [path.dirname( path.dirname( __file__ ) )] and confirmed that it is indeed setting the __path__ for enthought correctly with a "print enthought.__path__" in another enstaller module imported later, which produced: ['c:\\python25\\lib\\site-packages\\enstaller-2.1.0b1-py2.5-win32.egg\\enthought'] This is compared to the two screenfuls of 'enthought.' paths without that code. As mentioned, this works great for setuptools 0.7, but as soon as I switch out 0.7 for 0.6, I get ImportErrors from package mismatches as python finds other incompatible 'enthought.' packages on the system instead of the ones bundled in the enstaller egg. If I leave the above code out completely, neither 0.6 or 0.7 work (as expected). Can you point out what, if anything, I'm doing wrong, since I thought setting enthought.__path__ is supposed to work with 0.6? I think I have three options at this point: 1.) have enstaller require setuptools>=0.7 (which enthought is hosting and will be found automatically by the enstaller install script) 2.) write a function in the enstaller egg build script that bundles all the packages into a namespace other than 'enthought.' inside of the egg, say 'bundle.' for example, and does a global search-and-replace of 'enthought.' with 'bundle.' Assuming the script gets everything, this seems like it would be the most straightforward and would not require me to fiddle with the python/setuptools import machinery. 3.) find the silly mistake I made which is causing the initial fix to break for 0.6, if possible. Thanks in advance!
Date: Sat, 09 Jun 2007 16:04:45 -0400 From: "Phillip J. Eby"
At 09:26 PM 6/8/2007 -0500, Rick Ratzel wrote:
Is there a way to have my package tell setuptools to "ignore" certain other packages?
Only through version specifications; i.e., request the exact versions you want.
I've tried removing all the "enthought." eggs from sys.path before anything else gets imported, but even that doesn't work (and it just felt wrong, and probably is).
If "enthought" is a namespace package, you would need to either be using an 0.7-development version of setuptools (i.e., a trunk SVN version), or else you'd need to remove those eggs from the path *before* pkg_resources is first imported. Otherwise, it would indeed not work.
I looked at the docs for manipulating the WorkingSet, but made no progress there either...python always managed to find the incompatible enthought.traits code in the enthought.traits egg. When I remove the incompatible enthought.traits, all works fine.
What I'd like to do is simply say "do not use any enthought.* eggs". Is this possible? Thanks in advance!
Not without using an 0.7 version of setuptools, or manipulating enthought.__path__. The straightforward way to do it would be for enstaller's __init__.py to do this:
import enthought, os enthought.__path__ = os.path.dirname(os.path.dirname(__file__))
This will ensure that all enthought.* modules imported from then on will only be from within the parent directory of enstaller.
I don't think I'd recommend this to anyone in the general case, but this might be a reasonable workaround if you truly want to "de-namespace" the package. (It will *not*, however, prevent new eggs from being added to __path__ if you add anything to sys.path or the working set afterward.)
-- Rick Ratzel - Enthought, Inc. 515 Congress Avenue, Suite 2100 - Austin, Texas 78701 512-536-1057 x229 - Fax: 512-536-1059 http://www.enthought.com
Rick, We require setuptools >=0.7.0 for windows anyway, if that makes any difference... Bryce Rick Ratzel wrote:
Arg...I thought I had this working, but it turns out I had a setuptools 0.7 dev release installed. When I go to a setuptools 0.6 release, I get the same old problem. Here are more details...
Enstaller is started with a script generated when easy_install installs the egg, so right away pkg_resources is imported and I have no chance to do anything before. I put the following in enstaller's __init__.py as recommended:
from os import path import enthought enthought.__path__ = [path.dirname( path.dirname( __file__ ) )]
and confirmed that it is indeed setting the __path__ for enthought correctly with a "print enthought.__path__" in another enstaller module imported later, which produced:
['c:\\python25\\lib\\site-packages\\enstaller-2.1.0b1-py2.5-win32.egg\\enthought']
This is compared to the two screenfuls of 'enthought.' paths without that code. As mentioned, this works great for setuptools 0.7, but as soon as I switch out 0.7 for 0.6, I get ImportErrors from package mismatches as python finds other incompatible 'enthought.' packages on the system instead of the ones bundled in the enstaller egg. If I leave the above code out completely, neither 0.6 or 0.7 work (as expected).
Can you point out what, if anything, I'm doing wrong, since I thought setting enthought.__path__ is supposed to work with 0.6?
I think I have three options at this point:
1.) have enstaller require setuptools>=0.7 (which enthought is hosting and will be found automatically by the enstaller install script)
2.) write a function in the enstaller egg build script that bundles all the packages into a namespace other than 'enthought.' inside of the egg, say 'bundle.' for example, and does a global search-and-replace of 'enthought.' with 'bundle.' Assuming the script gets everything, this seems like it would be the most straightforward and would not require me to fiddle with the python/setuptools import machinery.
3.) find the silly mistake I made which is causing the initial fix to break for 0.6, if possible.
Thanks in advance!
Date: Sat, 09 Jun 2007 16:04:45 -0400 From: "Phillip J. Eby"
At 09:26 PM 6/8/2007 -0500, Rick Ratzel wrote:
Is there a way to have my package tell setuptools to "ignore" certain other packages?
Only through version specifications; i.e., request the exact versions you want.
I've tried removing all the "enthought." eggs from sys.path before anything else gets imported, but even that doesn't work (and it just felt wrong, and probably is).
If "enthought" is a namespace package, you would need to either be using an 0.7-development version of setuptools (i.e., a trunk SVN version), or else you'd need to remove those eggs from the path *before* pkg_resources is first imported. Otherwise, it would indeed not work.
I looked at the docs for manipulating the WorkingSet, but made no progress there either...python always managed to find the incompatible enthought.traits code in the enthought.traits egg. When I remove the incompatible enthought.traits, all works fine.
What I'd like to do is simply say "do not use any enthought.* eggs". Is this possible? Thanks in advance!
Not without using an 0.7 version of setuptools, or manipulating enthought.__path__. The straightforward way to do it would be for enstaller's __init__.py to do this:
import enthought, os enthought.__path__ = os.path.dirname(os.path.dirname(__file__))
This will ensure that all enthought.* modules imported from then on will only be from within the parent directory of enstaller.
I don't think I'd recommend this to anyone in the general case, but this might be a reasonable workaround if you truly want to "de-namespace" the package. (It will *not*, however, prevent new eggs from being added to __path__ if you add anything to sys.path or the working set afterward.)
At 06:25 PM 6/14/2007 -0500, Rick Ratzel wrote:
Arg...I thought I had this working, but it turns out I had a setuptools 0.7 dev release installed. When I go to a setuptools 0.6 release, I get the same old problem. Here are more details...
Enstaller is started with a script generated when easy_install installs the egg, so right away pkg_resources is imported and I have no chance to do anything before. I put the following in enstaller's __init__.py as recommended:
from os import path import enthought enthought.__path__ = [path.dirname( path.dirname( __file__ ) )]
and confirmed that it is indeed setting the __path__ for enthought correctly with a "print enthought.__path__" in another enstaller module imported later, which produced:
['c:\\python25\\lib\\site-packages\\enstaller-2.1.0b1-py2.5-win32.egg\\enthought']
This is compared to the two screenfuls of 'enthought.' paths without that code. As mentioned, this works great for setuptools 0.7, but as soon as I switch out 0.7 for 0.6, I get ImportErrors from package mismatches as python finds other incompatible 'enthought.' packages on the system instead of the ones bundled in the enstaller egg.
It sounds like the other paths are being added (again) to __path__ later. This should only happen if new eggs get require()'d or otherwise added to the working set. Can you narrow down where this is happening? Is it possible, for example, that enstaller is being imported while pkg_resources is being imported? If you could raise an exception at the point of setting __path__, what is the full traceback? Likewise, what is the full traceback of the import errors you're getting? (Also, perhaps you could try setting __path__ to a tuple instead of a list? I'm not sure if that would work, but if it does, then an exception would occur when any other code modifies the __path__, so that might be another way to track it down. Full traceback, please, if this works...)
Date: Thu, 14 Jun 2007 22:05:43 -0400 From: "Phillip J. Eby"
It sounds like the other paths are being added (again) to __path__ later. This should only happen if new eggs get require()'d or otherwise added to the working set. Can you narrow down where this is happening?
Is it possible, for example, that enstaller is being imported while pkg_resources is being imported? If you could raise an exception at the point of setting __path__, what is the full traceback? Likewise, what is the full traceback of the import errors you're getting?
(Also, perhaps you could try setting __path__ to a tuple instead of a list? I'm not sure if that would work, but if it does, then an exception would occur when any other code modifies the __path__, so that might be another way to track it down. Full traceback, please, if this works...)
Well, I do make one more require() call, but it's to add the enstaller.gui egg. enstaller is the command-line tool, and enstaller.gui adds the GUI. Both are "bundled" eggs, where enstaller has a few packages and enstaller.gui has many more. When I print the value of enthought.__path__ after that last require though, it only contains the path to the enstaller egg, and the path to enstaller.gui. I hope that's not the problem... So I tried to get an exception raised when enthought.__path__ is modified, but I could not. It appeared that it never did. Here is the traceback from the ImportError when using setuptools 0.6: Error: No module named app_data_locator.api File c:\python25\lib\site-packages\enstaller-2.1.0b1-py2.5-win32.egg\enthought\enstaller\launcher.py, line 72, in launch from enthought.enstaller.main import main File c:\python25\lib\site-packages\enstaller-2.1.0b1-py2.5-win32.egg\enthought\enstaller\main.py, line 65, in <module> from enthought.enstaller.session import \ File c:\python25\lib\site-packages\enstaller-2.1.0b1-py2.5-win32.egg\enthought\enstaller\session.py, line 33, in <module> from enthought.traits.api import \ File c:\python25\lib\site-packages\enthought.traits-2.0b2.dev_r12224-py2.5-win32.egg\enthought\traits\api.py, line 20, in <module> from trait_base \ File c:\python25\lib\site-packages\enthought.traits-2.0b2.dev_r12224-py2.5-win32.egg\enthought\traits\trait_base.py, line 38, in <module> from enthought.app_data_locator.api import AppDataLocator Not terribly helpful, but you can see that in enstaller\session.py line 33, it tries to import enthought.traits.api. Next line shows enthought.traits.api coming from the enthought.traits egg when it should be coming from the traits package in the enstaller egg. So, I put a breakpoint in session.py at line 32 to inspect, and here is what that looked like: Z:\>enstaller -l setuptools IN INIT: ('c:\\python25\\lib\\site-packages\\enstaller-2.1.0b1-py2.5-win32.egg\\enthought',)
c:\python25\lib\site-packages\enstaller-2.1.0b1-py2.5-win32.egg\enthought\enstaller\session.py(33)<module>() -> from enthought.traits.api import \
(Pdb) l 28 import xmlrpclib 29 30 import pdb 31 pdb.set_trace() 32 33 -> from enthought.traits.api import \ 34 Trait, HasTraits, Str, List, Instance, Property 35 36 from enthought.enstaller.enstaller_traits import \ 37 CreatableDir, Url 38 from enthought.enstaller.api import \ (Pdb) import enthought (Pdb) p enthought.__path__ ('c:\\python25\\lib\\site-packages\\enstaller-2.1.0b1-py2.5-win32.egg\\enthought',) (Pdb) s --Call--
c:\python25\lib\site-packages\enthought.traits-2.0b2.dev_r12224-py2.5-win32.egg\enthought\traits\api.py(16)<module>() -> """
(Pdb) import enthought
(Pdb) p enthought.__path__
('c:\\python25\\lib\\site-packages\\enstaller-2.1.0b1-py2.5-win32.egg\\enthought',)
(Pdb) import setuptools
(Pdb) setuptools
c:\python25\lib\site-packages\enstaller-2.1.0b1-py2.5-win32.egg\enthought\enstaller\session.py(33)<module>() -> from enthought.traits.api import \
(Pdb) import enthought (Pdb) p enthought.__path__ ('c:\\python25\\lib\\site-packages\\enstaller-2.1.0b1-py2.5-win32.egg\\enthought',) (Pdb) s ImportError: 'No module named traits.api'
c:\python25\lib\site-packages\enstaller-2.1.0b1-py2.5-win32.egg\enthought\enstaller\session.py(33)<module>() -> from enthought.traits.api import \
I get a different ImportError now. Now here is the pdb session when I set enthought.__path__ back to a list instead of a tuple using 0.7: Z:\>enstaller -l setuptools IN INIT: ['c:\\python25\\lib\\site-packages\\enstaller-2.1.0b1-py2.5-win32.egg\\enthought']
c:\python25\lib\site-packages\enstaller-2.1.0b1-py2.5-win32.egg\enthought\enstaller\session.py(33)<module>() -> from enthought.traits.api import \
(Pdb) import enthought (Pdb) p enthought.__path__ ['c:\\python25\\lib\\site-packages\\enstaller-2.1.0b1-py2.5-win32.egg\\enthought'] (Pdb) s --Call--
c:\python25\lib\site-packages\enstaller-2.1.0b1-py2.5-win32.egg\enthought\traits\__init__.py(22)<module>() -> try:
(Pdb) import enthought
(Pdb) p enthought.__path__
['c:\\python25\\lib\\site-packages\\enstaller-2.1.0b1-py2.5-win32.egg\\enthought']
(Pdb) import setuptools
(Pdb) setuptools
At 12:50 AM 6/15/2007 -0500, Rick Ratzel wrote:
(Pdb) l 28 import xmlrpclib 29 30 import pdb 31 pdb.set_trace() 32 33 -> from enthought.traits.api import \ 34 Trait, HasTraits, Str, List, Instance, Property 35 36 from enthought.enstaller.enstaller_traits import \ 37 CreatableDir, Url 38 from enthought.enstaller.api import \
(Pdb) import enthought
(Pdb) p enthought.__path__ ('c:\\python25\\lib\\site-packages\\enstaller-2.1.0b1-py2.5-win32.egg\\enthought',)
(Pdb) s --Call--
c:\python25\lib\site-packages\enthought.traits-2.0b2.dev_r12224-py2.5-win32.egg\enthought\traits\api.py(16)<module>() -> """
Okay, so the problem here is that enthought.traits got imported *before* the __path__ was set. The __path__ needs to get set before any enthought.* imports occur.
(Pdb) p enthought.__path__ ('c:\\python25\\lib\\site-packages\\enstaller-2.1.0b1-py2.5-win32.egg\\enthought',)
(Pdb) s ImportError: 'No module named traits.api'
c:\python25\lib\site-packages\enstaller-2.1.0b1-py2.5-win32.egg\enthought\enstaller\session.py(33)<module>() -> from enthought.traits.api import \
I get a different ImportError now.
It appears that enthought.traits is not available in the enstaller egg; have you checked that?
Date: Fri, 15 Jun 2007 11:48:31 -0400 From: "Phillip J. Eby"
At 12:50 AM 6/15/2007 -0500, Rick Ratzel wrote:
(Pdb) l 28 import xmlrpclib 29 30 import pdb 31 pdb.set_trace() 32 33 -> from enthought.traits.api import \ 34 Trait, HasTraits, Str, List, Instance, Property 35 36 from enthought.enstaller.enstaller_traits import \ 37 CreatableDir, Url 38 from enthought.enstaller.api import \
(Pdb) import enthought
(Pdb) p enthought.__path__ ('c:\\python25\\lib\\site-packages\\enstaller-2.1.0b1-py2.5-win32.egg\\enthought',)
(Pdb) s --Call--
c:\python25\lib\site-packages\enthought.traits-2.0b2.dev_r12224-py2.5-win32.egg\enthought\traits\api.py(16)<module>() -> """
Okay, so the problem here is that enthought.traits got imported *before* the __path__ was set. The __path__ needs to get set before any enthought.* imports occur.
Yes, I see now that it does get imported, but unfortunately not by my code. It's imported as a result of importing pkg_resources, since enthought.traits is a namespace package. Here's a little more detail: enstaller | - enthought.traits enstaller.gui | - enthought.traits.ui.wx And here's more pdb inspection: Z:\>python -m pdb c:\Python25\Scripts\enstaller-script.py
c:\python25\scripts\enstaller-script.py(3)<module>() -> __requires__ = 'enstaller==2.1.0b1'
(Pdb) n
c:\python25\scripts\enstaller-script.py(4)<module>() -> import sys
(Pdb) n
c:\python25\scripts\enstaller-script.py(5)<module>() -> from pkg_resources import load_entry_point
(Pdb) "enthought" in "".join(sys.modules.keys()) False (Pdb) n
c:\python25\scripts\enstaller-script.py(7)<module>() -> sys.exit(
(Pdb) "enthought" in "".join(sys.modules.keys())
True
(Pdb) [sys.modules[p] for p in sys.modules.keys() if p.startswith("enthought.")]
[
c:\python25\lib\site-packages\enstaller-2.1.0b1-py2.5-win32.egg\enthought\enst aller\session.py(33)<module>() -> from enthought.traits.api import \
(Pdb) l
28 import xmlrpclib
29
30 import pdb
31 pdb.set_trace()
32
33 -> from enthought.traits.api import \
34 Trait, HasTraits, Str, List, Instance, Property
35
36 from enthought.enstaller.enstaller_traits import \
37 CreatableDir, Url
38 from enthought.enstaller.api import \
(Pdb) [sys.modules[p] for p in sys.modules.keys() if p.startswith("enthought.tra
its")]
[]
(Pdb) for p in [(p, sys.modules[p]) for p in sys.modules.keys() if p.startswith("enthought.")] : print p
('enthought.enstaller.optparse', None)
('enthought.enstaller.re', None)
('enthought.enstaller.session',
c:\python25\lib\site-packages\enstaller-2.1.0b1-py2.5-win32.egg\enthought\traits\__init__.py(22)<module>() -> try:
(Pdb) c ------------------------------------------------------------ name | version | act | location ------------------------------------------------------------ setuptools | 0.6c6 | n | c:\python25\lib\site-packages setuptools | 0.7a1dev_r53614 | Y | c:\python25\lib\site-packages
(Pdb) p enthought.__path__ ('c:\\python25\\lib\\site-packages\\enstaller-2.1.0b1-py2.5-win32.egg\\enthought',)
(Pdb) s ImportError: 'No module named traits.api'
c:\python25\lib\site-packages\enstaller-2.1.0b1-py2.5-win32.egg\enthought\enstaller\session.py(33)<module>() -> from enthought.traits.api import \
I get a different ImportError now.
It appears that enthought.traits is not available in the enstaller egg; have you checked that?
I wish! Unfortunately it is. This is how Enstaller is able to work when no other enthought eggs are installed, or when I use setuptools 0.7. You can see the path to it in the pdb session above. Phillip, I really appreciate the time you're taking to look at this. I'm going to release a version which simply requires setuptools 0.7...unless you think that's a terrible idea, or you discover that I'm doing something wrong that I can fix. -- Rick Ratzel - Enthought, Inc. 515 Congress Avenue, Suite 2100 - Austin, Texas 78701 512-536-1057 x229 - Fax: 512-536-1059 http://www.enthought.com
At 12:59 PM 6/15/2007 -0500, Rick Ratzel wrote:
Yes, I see now that it does get imported, but unfortunately not by my code. It's imported as a result of importing pkg_resources, since enthought.traits is a namespace package.
Does it *need* to be a namespace package?
Grasping at straws, I set enthought.__path__ in enstaller-script.py immediately before and after pkg_resources is imported, only to get the same results both times.
But when I switch to setuptools 0.7 there are no enthought.traits modules loaded at all (in fact, the only enthought. modules loaded are the enstaller ones)...this must have been one of the changes you mentioned.
Yes, that's exactly the change I'm talking about; in 0.7, namespace packages are always loaded lazily.
Phillip, I really appreciate the time you're taking to look at this. I'm going to release a version which simply requires setuptools 0.7...unless you think that's a terrible idea, or you discover that I'm doing something wrong that I can fix.
The only things I can think of would be removing traits as a namespace package, or manually setting its __path__ also. That is, first set enthought.__path__, then enthought.traits.__path__. However, this will only work right if no traits.__init__ module does anything but declare the namespace.
Date: Fri, 15 Jun 2007 14:57:17 -0400 From: "Phillip J. Eby"
At 12:59 PM 6/15/2007 -0500, Rick Ratzel wrote:
Yes, I see now that it does get imported, but unfortunately not by my code. It's imported as a result of importing pkg_resources, since enthought.traits is a namespace package.
Does it *need* to be a namespace package?
Yes, I think it does. enthought.traits is our package for adding manifestly typed attributes to Python classes, and enthought.traits.ui.wx contributes to the enthought.traits.ui namespace by adding a wxPython backend for creating UIs out of classes with traits using wxPython. We don't want to require wxPython (we have a wxPython egg) when users may never use the UI features of traits, so we broke it out as an extra. So naturally, enthought.traits is bundled in the enstaller egg, and enthought.traits.ui is in the enstaller.gui egg.
Grasping at straws, I set enthought.__path__ in enstaller-script.py immediately before and after pkg_resources is imported, only to get the same results both times.
But when I switch to setuptools 0.7 there are no enthought.traits modules loaded at all (in fact, the only enthought. modules loaded are the enstaller ones)...this must have been one of the changes you mentioned.
Yes, that's exactly the change I'm talking about; in 0.7, namespace packages are always loaded lazily.
Phillip, I really appreciate the time you're taking to look at this. I'm going to release a version which simply requires setuptools 0.7...unless you think that's a terrible idea, or you discover that I'm doing something wrong that I can fix.
The only things I can think of would be removing traits as a namespace package, or manually setting its __path__ also. That is, first set enthought.__path__, then enthought.traits.__path__. However, this will only work right if no traits.__init__ module does anything but declare the namespace.
Ah, of course...enthought.traits being a namespace package means it needs the same treatment. I fixed up the enthought.traits and enthought.traits.ui __path__ vars and it seems to be working with both versions of setuptools, with and without various conflicting enthought.* eggs installed. This should be OK since we've made an effort to move all code (except for namespace decls) from __init__.py to api.py for all of our packages. I'm going to do a formal build which "re-bundles" the enstaller egg and install it again for a more thorough test, but I think I'm in the clear (famous last words). My code looks like this now (it's actually in a "main" file which is basically imported first, and not __init__.py): enthought_path = path.dirname( path.dirname( __file__ ) ) import enthought enthought.__path__ = [enthought_path] enthought_traits_path = path.join( enthought_path, "traits" ) import enthought.traits enthought.traits.__path__ = [enthought_traits_path] import enthought.traits.ui enthought.traits.ui.__path__ = [path.join( enthought_traits_path, "ui" )] Basically, I have to keep an eye out for any other namespace packages that I use and make sure I do the same for them. Thanks again for all your help, -- Rick Ratzel - Enthought, Inc. 515 Congress Avenue, Suite 2100 - Austin, Texas 78701 512-536-1057 x229 - Fax: 512-536-1059 http://www.enthought.com
participants (3)
-
Bryce Hendrix
-
Phillip J. Eby
-
Rick Ratzel