mirror of
				https://github.com/python/cpython.git
				synced 2025-11-04 03:44:55 +00:00 
			
		
		
		
	Here's a draft. I have no immediate use for it, but I'd like this to be available for experimentation. I may withdraw it or change it radically up to and including the release of Python 2.3b1.
		
			
				
	
	
		
			78 lines
		
	
	
	
		
			3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			78 lines
		
	
	
	
		
			3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
"""Utilities to support packages."""
 | 
						|
 | 
						|
import os
 | 
						|
import sys
 | 
						|
 | 
						|
def extend_path(path, name):
 | 
						|
    """Extend a package's path.
 | 
						|
 | 
						|
    Intended use is to place the following code in a package's __init__.py:
 | 
						|
 | 
						|
        from pkgutil import extend_path
 | 
						|
        __path__ = extend_path(__path__, __name__)
 | 
						|
 | 
						|
    This will add to the package's __path__ all subdirectories of
 | 
						|
    directories on sys.path named after the package.  This is useful
 | 
						|
    if one wants to distribute different parts of a single logical
 | 
						|
    package as multiple directories.
 | 
						|
 | 
						|
    It also looks for *.pkg files beginning where * matches the name
 | 
						|
    argument.  This feature is similar to *.pth files (see site.py),
 | 
						|
    except that it doesn't special-case lines starting with 'import'.
 | 
						|
    A *.pkg file is trusted at face value: apart from checking for
 | 
						|
    duplicates, all entries found in a *.pkg file are added to the
 | 
						|
    path, regardless of whether they are exist the filesystem.  (This
 | 
						|
    is a feature.)
 | 
						|
 | 
						|
    If the input path is not a list (as is the case for frozen
 | 
						|
    packages) it is returned unchanged.  The input path is not
 | 
						|
    modified; an extended copy is returned.  Items are only appended
 | 
						|
    to the copy at the end.
 | 
						|
 | 
						|
    It is assumed that sys.path is a sequence.  Items of sys.path that
 | 
						|
    are not (unicode or 8-bit) strings referring to existing
 | 
						|
    directories are ignored.  Unicode items of sys.path that cause
 | 
						|
    errors when used as filenames may cause this function to raise an
 | 
						|
    exception (in line with os.path.isdir() behavior).
 | 
						|
    """
 | 
						|
 | 
						|
    if not isinstance(path, list):
 | 
						|
        # This could happen e.g. when this is called from inside a
 | 
						|
        # frozen package.  Return the path unchanged in that case.
 | 
						|
        return path
 | 
						|
 | 
						|
    pname = os.path.join(*name.split('.')) # Reconstitute as relative path
 | 
						|
    # Just in case os.extsep != '.'
 | 
						|
    sname = os.extsep.join(name.split('.'))
 | 
						|
    sname_pkg = sname + os.extsep + "pkg"
 | 
						|
    init_py = "__init__" + os.extsep + "py"
 | 
						|
 | 
						|
    path = path[:] # Start with a copy of the existing path
 | 
						|
 | 
						|
    for dir in sys.path:
 | 
						|
        if not isinstance(dir, (str, unicode)) or not os.path.isdir(dir):
 | 
						|
            continue
 | 
						|
        subdir = os.path.join(dir, pname)
 | 
						|
        # XXX This may still add duplicate entries to path on
 | 
						|
        # case-insensitive filesystems
 | 
						|
        initfile = os.path.join(subdir, init_py)
 | 
						|
        if subdir not in path and os.path.isfile(initfile):
 | 
						|
            path.append(subdir)
 | 
						|
        # XXX Is this the right thing for subpackages like zope.app?
 | 
						|
        # It looks for a file named "zope.app.pkg"
 | 
						|
        pkgfile = os.path.join(dir, sname_pkg)
 | 
						|
        if os.path.isfile(pkgfile):
 | 
						|
            try:
 | 
						|
                f = open(pkgfile)
 | 
						|
            except IOError, msg:
 | 
						|
                sys.stderr.write("Can't open %s: %s\n" %
 | 
						|
                                 (pkgfile, msg))
 | 
						|
            else:
 | 
						|
                for line in f:
 | 
						|
                    line = line.rstrip('\n')
 | 
						|
                    if not line or line.startswith('#'):
 | 
						|
                        continue
 | 
						|
                    path.append(line) # Don't check for existence!
 | 
						|
                f.close()
 | 
						|
 | 
						|
    return path
 |