mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 02:15:10 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			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, basestring) 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
 | 
