1881
Comment:
|
1901
use PEP 8 for code examples
|
Deletions are marked like this. | Additions are marked like this. |
Line 12: | Line 12: |
def isPackage( filename ): | def is_package(path): |
Line 14: | Line 15: |
os.path.isdir(filename) and os.path.isfile( os.path.join(filename,'__init__.py') ) def packagesFor( filename, basePackage="" ): """Find all packages in filename""" set = {} for item in os.listdir(filename): dir = os.path.join(filename, item) if isPackage( dir ): if basePackage: moduleName = basePackage+'.'+item |
os.path.isdir(path) and os.path.isfile(os.path.join(path, '__init__.py') ) def find_packages(path, base="" ): """ Find all packages in path """ packages = {} for item in os.listdir(path): dir = os.path.join(path, item) if is_package( dir ): if base: module_name = "%(base)s.%(item)s" % vars() |
Line 26: | Line 28: |
moduleName = item set[ moduleName] = dir set.update( packagesFor( dir, moduleName)) return set |
module_name = item packages[module_name] = dir packages.update(find_packages(dir, module_name)) return packages |
Line 32: | Line 34: |
Then call packagesFor to get the set of packages to be included (note that this call assumes that the packages are sub-directories of the directory where setup.py resides). | Then call {{{find_packages}}} to get the set of packages to be included (note that this call assumes that the packages are sub-directories of the directory where setup.py resides). |
Line 35: | Line 37: |
packages = packagesFor( "." ) | packages = find_packages(".") |
Line 38: | Line 40: |
Then use packages as the source within your call to setup: | Then use {{{packages}}} as the source within your call to setup: |
Line 44: | Line 46: |
... | #... |
Line 46: | Line 48: |
**extraArguments ) |
**extra_arguments ) |
Problem
Distutils requires that you manually specify each package to be included in the distribution. For packages with large and deep sub-package hierarchies it can be a pain to keep this list in sync with the code, particularly as forgetting an entry is not noticable until a user happens to report that an entire sub-package is missing.
Solution
Use an automatic sub-package scanning mechanism to generate the package_dir and packages parameters for setup:
import os def is_package(path): return ( os.path.isdir(path) and os.path.isfile(os.path.join(path, '__init__.py') ) def find_packages(path, base="" ): """ Find all packages in path """ packages = {} for item in os.listdir(path): dir = os.path.join(path, item) if is_package( dir ): if base: module_name = "%(base)s.%(item)s" % vars() else: module_name = item packages[module_name] = dir packages.update(find_packages(dir, module_name)) return packages
Then call find_packages to get the set of packages to be included (note that this call assumes that the packages are sub-directories of the directory where setup.py resides).
packages = find_packages(".")
Then use packages as the source within your call to setup:
setup ( name = "pytable", package_dir = packages, #... packages = packages.keys(), **extra_arguments )
You can see a real-world usage example in the PyTable setup script
Discussion
There should be some way to do this with distutils own machinery, I just don't know what it would be.