[Distutils] patch: solving the two major things that people dislike about setuptools, part 1

Mark Sienkiewicz sienkiew at stsci.edu
Tue Nov 25 22:55:37 CET 2008

Phillip J. Eby wrote:
> At 10:56 AM 11/25/2008 -0500, Mark Sienkiewicz wrote:
>> >I think the correct behaviour is to insert the .egg file either just 
>> before or just after the directory where we found the .pth file.
>> >
>> >So, instead of
>> >p=getattr(sys,'__egginsert',len(os.environ.get('PYTHONPATH','').spl 
>> it(os.pathsep)));
>> >
>> >we want
>> >p=sys.path.index(sitedir);
>> >
>> Does this meet your criterion without breaking anything else?
> The principle is correct; I'm not sure the implementation is.  For 
> case-insensitive filesystems, sitedir may or may not be normalized, 
> and sys.path probably isn't.  But yes, that's the general idea.
> The only reason I didn't take that approach myself is because my head 
> hurt trying to come up with a provably-correct way to implement this 
> policy.  ;-)

That's a good question about normalized names and case-insensitive 
filesystems, but setuptools needs to deal with this problem, so we need 
an answer.

There appear to be two cases:

1. in the system site.py

I looked around lib/python25/site.py a little.  The name of the 
site-packages directory is created in addsitepackages() then passed to 
addsitedir()  where it is appended to sys.path and then passed to 

Since the value that was appended to sys.path is the same value that was 
passed to addpackage() as parameter sitedir, we know that they will match.

2. in the site.py that setuptools put in the directory where setuptools 
installed something

I think the real interesting part is where it says:

    for item in PYTHONPATH:

Here, PYTHONPATH was constructed directly from the environment variable, 
not somehow derived from sys.path.  This means that it potentially 
_could_ contain duplicate and un-normalized directory names.  But I see 
that we already have access to the function makepath() from the system 
site.py, so we can say:

    for item in PYTHONPATH:
        p,np = makepath(item)

If you do that, then you know that the directory names that you are 
passing to addsitedir() have been normalized by exactly the same 
algorithm that normalized them for sys.path.  Therefore we know that we 
can use a string comparison to find a match.

So, you know setuptools way better than I do.  Have  I missed anything?

b.t.w.  If you have a few minutes, could you write a paragraph about why 
each of those two big loops in the setuptools site.py are doing what 
they do?  The first one seems to be trying different ways to find the 
system site.py (why?), but I don't see why you would bother with the 
second one.

>> b.t.w. You could make easy_install.pth read:
>>    import setuptools; setuptools.prep_sys_path()
>>    module-name.egg
>>    import setuptools; setuptools.alter_sys_path()
>> and then patches to the first/last line would be easier -- they would 
>> just happen when you install a new setuptools.
> It would have to be a separate module, added just for this purpose...  
> and of course it would introduce a runtime dependency that would 
> otherwise be unnecessary.

Is that a problem? 

Mark S.

More information about the Distutils-SIG mailing list