From 6e33c26dc5aa8edeef35ef44d3ab023802df7abc Mon Sep 17 00:00:00 2001 From: pje Date: Sat, 9 Jul 2005 04:32:02 +0000 Subject: Migrate wsgiref package to use common ez_setup checkout. git-svn-id: svn://svn.eby-sarna.com/svnroot/wsgiref@2069 571e12c6-e1fa-0310-aee7-ff1267fa46bd --- setup.py | 3 + setuptools/__init__.py | 82 ------- setuptools/command/__init__.py | 11 - setuptools/command/build_ext.py | 7 - setuptools/command/build_py.py | 123 ---------- setuptools/command/depends.py | 164 ------------- setuptools/command/install.py | 11 - setuptools/command/install_lib.py | 17 -- setuptools/command/test.py | 82 ------- setuptools/depends.py | 246 ------------------- setuptools/dist.py | 492 -------------------------------------- setuptools/extension.py | 27 --- setuptools/tests/__init__.py | 451 ---------------------------------- 13 files changed, 3 insertions(+), 1713 deletions(-) delete mode 100644 setuptools/__init__.py delete mode 100644 setuptools/command/__init__.py delete mode 100644 setuptools/command/build_ext.py delete mode 100644 setuptools/command/build_py.py delete mode 100644 setuptools/command/depends.py delete mode 100644 setuptools/command/install.py delete mode 100644 setuptools/command/install_lib.py delete mode 100644 setuptools/command/test.py delete mode 100644 setuptools/depends.py delete mode 100644 setuptools/dist.py delete mode 100644 setuptools/extension.py delete mode 100644 setuptools/tests/__init__.py diff --git a/setup.py b/setup.py index 6cb4206..a5ddd14 100755 --- a/setup.py +++ b/setup.py @@ -2,6 +2,9 @@ """Distutils setup file""" +import ez_setup +ez_setup.use_setuptools() + from setuptools import setup, find_packages # Metadata diff --git a/setuptools/__init__.py b/setuptools/__init__.py deleted file mode 100644 index 12b6b57..0000000 --- a/setuptools/__init__.py +++ /dev/null @@ -1,82 +0,0 @@ -"""Extensions to the 'distutils' for large or complex distributions""" - -import distutils.core, setuptools.command -from setuptools.dist import Distribution, Feature -from setuptools.extension import Extension -from setuptools.depends import Require -from distutils.core import Command -from distutils.util import convert_path -import os.path - -__version__ = '0.0.1' - -__all__ = [ - 'setup', 'Distribution', 'Feature', 'Command', 'Extension', 'Require', - 'find_packages' -] - - -def find_packages(where='.'): - """Return a list all Python packages found within directory 'where' - - 'where' should be supplied as a "cross-platform" (i.e. URL-style) path; it - will be converted to the appropriate local path syntax. - """ - - out = [] - stack=[(convert_path(where), '')] - - while stack: - where,prefix = stack.pop(0) - for name in os.listdir(where): - fn = os.path.join(where,name) - if (os.path.isdir(fn) and - os.path.isfile(os.path.join(fn,'__init__.py')) - ): - out.append(prefix+name); stack.append((fn,prefix+name+'.')) - return out - - - - -def setup(**attrs): - """Do package setup - - This function takes the same arguments as 'distutils.core.setup()', except - that the default distribution class is 'setuptools.dist.Distribution'. See - that class' documentation for details on the new keyword arguments that it - makes available via this function. - """ - attrs.setdefault("distclass",Distribution) - return distutils.core.setup(**attrs) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/setuptools/command/__init__.py b/setuptools/command/__init__.py deleted file mode 100644 index 3429634..0000000 --- a/setuptools/command/__init__.py +++ /dev/null @@ -1,11 +0,0 @@ -import distutils.command - -__all__ = ['test', 'depends'] - - -# Make our commands available as though they were part of the distutils - -distutils.command.__path__.extend(__path__) -distutils.command.__all__.extend( - [cmd for cmd in __all__ if cmd not in distutils.command.__all__] -) diff --git a/setuptools/command/build_ext.py b/setuptools/command/build_ext.py deleted file mode 100644 index 86ac13a..0000000 --- a/setuptools/command/build_ext.py +++ /dev/null @@ -1,7 +0,0 @@ -# Attempt to use Pyrex for building extensions, if available - -try: - from Pyrex.Distutils.build_ext import build_ext -except ImportError: - from distutils.command.build_ext import build_ext - diff --git a/setuptools/command/build_py.py b/setuptools/command/build_py.py deleted file mode 100644 index 7d5b6ff..0000000 --- a/setuptools/command/build_py.py +++ /dev/null @@ -1,123 +0,0 @@ -from distutils.command.build_py import build_py as _build_py -from distutils.util import convert_path -from glob import glob -import os.path - -class build_py(_build_py): - - """Enhanced 'build_py' command that includes data files with packages - - The data files are specified via a 'package_data' argument to 'setup()'. - See 'setuptools.dist.Distribution' for more details. - - Also, this version of the 'build_py' command allows you to specify both - 'py_modules' and 'packages' in the same setup operation. - """ - - def finalize_options(self): - _build_py.finalize_options(self) - self.package_data = self.distribution.package_data - self.data_files = self.get_data_files() - - - def run(self): - - """Build modules, packages, and copy data files to build directory""" - - if not self.py_modules and not self.packages: - return - - if self.py_modules: - self.build_modules() - - if self.packages: - self.build_packages() - self.build_package_data() - - # Only compile actual .py files, using our base class' idea of what our - # output files are. - self.byte_compile(_build_py.get_outputs(self,include_bytecode=0)) - - - def get_data_files(self): - - """Generate list of '(package,src_dir,build_dir,filenames)' tuples""" - - data = [] - - for package in self.packages: - # Locate package source directory - src_dir = self.get_package_dir(package) - - # Compute package build directory - build_dir = os.path.join(*([self.build_lib]+package.split('.'))) - - # Length of path to strip from found files - plen = len(src_dir)+1 - - # Strip directory from globbed filenames - filenames = [ - file[plen:] for file in self.find_data_files(package, src_dir) - ] - - data.append( (package, src_dir, build_dir, filenames) ) - - return data - - - def find_data_files(self, package, src_dir): - - """Return filenames for package's data files in 'src_dir'""" - - globs = self.package_data.get('',[])+self.package_data.get(package,[]) - files = [] - - for pattern in globs: - # Each pattern has to be converted to a platform-specific path - files.extend(glob(os.path.join(src_dir, convert_path(pattern)))) - - return files - - - - def build_package_data(self): - - """Copy data files into build directory""" - - lastdir = None - - for package, src_dir, build_dir, filenames in self.data_files: - - for filename in filenames: - target = os.path.join(build_dir,filename) - self.mkpath(os.path.dirname(target)) - self.copy_file(os.path.join(src_dir,filename), target) - - - def get_outputs(self, include_bytecode=1): - - """Return complete list of files copied to the build directory - - This includes both '.py' files and data files, as well as '.pyc' and - '.pyo' files if 'include_bytecode' is true. (This method is needed for - the 'install_lib' command to do its job properly, and to generate a - correct installation manifest.) - """ - - return _build_py.get_outputs(self,include_bytecode) + [ - os.path.join(build_dir,filename) - for package,src_dir,build_dir,filenames in self.data_files - for filename in filenames - ] - - - - - - - - - - - - diff --git a/setuptools/command/depends.py b/setuptools/command/depends.py deleted file mode 100644 index 9d9c9f4..0000000 --- a/setuptools/command/depends.py +++ /dev/null @@ -1,164 +0,0 @@ -from distutils.cmd import Command -import os, sys - - -class depends(Command): - - """Download and install dependencies, if needed""" - - description = "download and install dependencies, if needed" - - user_options = [ - ('temp=', 't', - "directory where dependencies will be downloaded and built"), - ('ignore-extra-args', 'i', - "ignore options that won't be passed to child setup scripts"), - ] - - path_attrs = [ - # Note: these must be in *reverse* order, as they are pushed onto the - # *front* of a copy of sys.path. - ('install','install_libbase'), # installation base if extra_path - ('install_lib','install_dir'), # where modules are installed - ] - - # Command options that can be safely passed to dependencies' setup scripts - safe_opts = { - 'install': [ - 'prefix','exec-prefix','home','install-base','install-platbase', - 'root','optimize','force','verbose','quiet' - ], - 'build': ['compiler','debug','force','verbose','quiet'], - } - - # Options with string arguments that are *not* directories or files, and - # so should *not* have absolute-path fixups applied. - non_fs_opts = {'build':['compiler'] } - - - def initialize_options(self): - self.temp = None; self.ignore_extra_args = None - - def finalize_options(self): - self.set_undefined_options('build',('build_temp', 'temp')) - self.set_search_path() - self.set_subcommand_args() - - def set_subcommand_args(self): - safe = {'install':[]} # ensure we at least perform an install - unsafe = {} - copts = self.distribution.get_cmdline_options() - - if 'depends' in copts: - del copts['depends'] - - for cmd,opts in copts.items(): - safe_opts = self.safe_opts.get(cmd,()) - non_fs_opts = self.non_fs_opts.get(cmd,()) - - for opt,val in opts.items(): - if opt in safe_opts: - cmdline = safe.setdefault(cmd,[]) - if val is not None and opt not in non_fs_opts: - val = os.path.abspath(val) - else: - cmdline = unsafe.setdefault(cmd,[]) - - cmdline.append('--'+opt) - if val is not None: - cmdline.append(val) - - self.safe_options = safe - self.unsafe_options = unsafe - - def set_search_path(self): - """Determine paths to check for installed dependencies""" - path = sys.path[:] # copy sys path - for cmd,attr in self.path_attrs: - dir = getattr(self.get_finalized_command(cmd),attr,None) - if dir and dir not in path: - path.insert(0,dir) # prepend - self.search_path = path - - def run(self): - self.announce("checking for installed dependencies") - - needed = [ - dep for dep in self.distribution.requires if self.is_needed(dep) - ] - - if not needed: - self.announce("all dependencies are present and up-to-date") - return - - argv = [sys.executable,'setup.py'] - for cmd,line in self.safe_options.items(): - argv.append(cmd); argv.extend(line) - - self.announce( - "dependencies will be installed using:\n "+' '.join(argv)+'\n' - ) - - # Alert for unsupported commands/options, unless '-i' was used - if self.unsafe_options: - self.warn_unsafe_options_used() - if not self.ignore_extra_args: - raise SystemExit( - "Unsupported options for building dependencies; please" - " add 'depends -i'\nto your command line if you want to" - " force the build to proceed.\nOtherwise, you will need" - " to omit the unsupported options,\nor install the" - " dependencies manually." - ) - - - # Alert the user to missing items - fmt = "\t%s\t%s\n" - items = [fmt % (dep.full_name(),dep.homepage) for dep in needed] - items.insert(0,"Please install the following packages *first*:\n") - items.append('') - raise SystemExit('\n'.join(items)) # dump msg to stderr and exit - - - - def warn_unsafe_options_used(self): - lines = []; write = lines.append - write("the following command options are not supported for building") - write("dependencies, and will be IGNORED:") - for cmd,line in self.unsafe_options.items(): - write('\t%s %s' % (cmd,' '.join(line))) - write('') - self.warn('\n'.join(lines)) - - - def is_needed(self,dep): - """Does the specified dependency need to be installed/updated?""" - - self.announce("searching for "+dep.full_name()) - version = dep.get_version(self.search_path) - - if version is None: - self.announce(name+" not found!") - return True - - if str(version)=="unknown": - status = dep.name+" is installed" - else: - status = dep.name+" version "+str(version)+" found" - - if dep.version_ok(version): - self.announce(status+" (OK)") - return False - else: - self.announce(status+" (update needed)") - return True - - - - - - - - - - diff --git a/setuptools/command/install.py b/setuptools/command/install.py deleted file mode 100644 index 82e7ebe..0000000 --- a/setuptools/command/install.py +++ /dev/null @@ -1,11 +0,0 @@ -from distutils.command.install import install as _install - -class install(_install): - """Build dependencies before installation""" - - def has_dependencies(self): - return self.distribution.has_dependencies() - - sub_commands = [('depends',has_dependencies)] + _install.sub_commands - - diff --git a/setuptools/command/install_lib.py b/setuptools/command/install_lib.py deleted file mode 100644 index ec406f7..0000000 --- a/setuptools/command/install_lib.py +++ /dev/null @@ -1,17 +0,0 @@ -from distutils.command.install_lib import install_lib as _install_lib - -class install_lib(_install_lib): - """Don't add compiled flags to filenames of non-Python files""" - - def _bytecode_filenames (self, py_filenames): - bytecode_files = [] - for py_file in py_filenames: - if not py_file.endswith('.py'): - continue - if self.compile: - bytecode_files.append(py_file + "c") - if self.optimize > 0: - bytecode_files.append(py_file + "o") - - return bytecode_files - diff --git a/setuptools/command/test.py b/setuptools/command/test.py deleted file mode 100644 index 6b37a9f..0000000 --- a/setuptools/command/test.py +++ /dev/null @@ -1,82 +0,0 @@ -from distutils.cmd import Command -from distutils.errors import DistutilsOptionError -import sys - -class test(Command): - - """Command to run unit tests after installation""" - - description = "run unit tests after installation" - - user_options = [ - ('test-module=','m', "Run 'test_suite' in specified module"), - ('test-suite=','s', - "Test suite to run (e.g. 'some_module.test_suite')"), - ] - - test_suite = None - test_module = None - - def initialize_options(self): - pass - - - def finalize_options(self): - - if self.test_suite is None: - if self.test_module is None: - self.test_suite = self.distribution.test_suite - else: - self.test_suite = self.test_module+".test_suite" - elif self.test_module: - raise DistutilsOptionError( - "You may specify a module or a suite, but not both" - ) - - self.test_args = [self.test_suite] - - if self.verbose: - self.test_args.insert(0,'--verbose') - - - def run(self): - - # Install before testing - self.run_command('install') - - if self.test_suite: - cmd = ' '.join(self.test_args) - - if self.dry_run: - self.announce('skipping "unittest %s" (dry run)' % cmd) - else: - self.announce('running "unittest %s"' % cmd) - import unittest - unittest.main(None, None, [unittest.__file__]+self.test_args) - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/setuptools/depends.py b/setuptools/depends.py deleted file mode 100644 index 20e5cec..0000000 --- a/setuptools/depends.py +++ /dev/null @@ -1,246 +0,0 @@ -from __future__ import generators -import sys, imp, marshal -from imp import PKG_DIRECTORY, PY_COMPILED, PY_SOURCE, PY_FROZEN -from distutils.version import StrictVersion, LooseVersion - -__all__ = [ - 'Require', 'find_module', 'get_module_constant', 'extract_constant' -] - -class Require: - """A prerequisite to building or installing a distribution""" - - def __init__(self,name,requested_version,module,homepage='', - attribute=None,format=None - ): - - if format is None and requested_version is not None: - format = StrictVersion - - if format is not None: - requested_version = format(requested_version) - if attribute is None: - attribute = '__version__' - - self.__dict__.update(locals()) - del self.self - - - def full_name(self): - """Return full package/distribution name, w/version""" - if self.requested_version is not None: - return '%s-%s' % (self.name,self.requested_version) - return self.name - - - def version_ok(self,version): - """Is 'version' sufficiently up-to-date?""" - return self.attribute is None or self.format is None or \ - str(version)<>"unknown" and version >= self.requested_version - - - def get_version(self, paths=None, default="unknown"): - - """Get version number of installed module, 'None', or 'default' - - Search 'paths' for module. If not found, return 'None'. If found, - return the extracted version attribute, or 'default' if no version - attribute was specified, or the value cannot be determined without - importing the module. The version is formatted according to the - requirement's version format (if any), unless it is 'None' or the - supplied 'default'. - """ - - if self.attribute is None: - try: - f,p,i = find_module(self.module,paths) - if f: f.close() - return default - except ImportError: - return None - - v = get_module_constant(self.module,self.attribute,default,paths) - - if v is not None and v is not default and self.format is not None: - return self.format(v) - - return v - - - def is_present(self,paths=None): - """Return true if dependency is present on 'paths'""" - return self.get_version(paths) is not None - - - def is_current(self,paths=None): - """Return true if dependency is present and up-to-date on 'paths'""" - version = self.get_version(paths) - if version is None: - return False - return self.version_ok(version) - - -def _iter_code(code): - - """Yield '(op,arg)' pair for each operation in code object 'code'""" - - from array import array - from dis import HAVE_ARGUMENT, EXTENDED_ARG - - bytes = array('b',code.co_code) - eof = len(code.co_code) - - ptr = 0 - extended_arg = 0 - - while ptr=HAVE_ARGUMENT: - - arg = bytes[ptr+1] + bytes[ptr+2]*256 + extended_arg - ptr += 3 - - if op==EXTENDED_ARG: - extended_arg = arg * 65536L - continue - - else: - arg = None - ptr += 1 - - yield op,arg - - - - - - - - - - -def find_module(module, paths=None): - """Just like 'imp.find_module()', but with package support""" - - parts = module.split('.') - - while parts: - part = parts.pop(0) - f, path, (suffix,mode,kind) = info = imp.find_module(part, paths) - - if kind==PKG_DIRECTORY: - parts = parts or ['__init__'] - paths = [path] - - elif parts: - raise ImportError("Can't find %r in %s" % (parts,module)) - - return info - - - - - - - - - - - - - - - - - - - - - - - - -def get_module_constant(module, symbol, default=-1, paths=None): - - """Find 'module' by searching 'paths', and extract 'symbol' - - Return 'None' if 'module' does not exist on 'paths', or it does not define - 'symbol'. If the module defines 'symbol' as a constant, return the - constant. Otherwise, return 'default'.""" - - try: - f, path, (suffix,mode,kind) = find_module(module,paths) - except ImportError: - # Module doesn't exist - return None - - try: - if kind==PY_COMPILED: - f.read(8) # skip magic & date - code = marshal.load(f) - elif kind==PY_FROZEN: - code = imp.get_frozen_object(module) - elif kind==PY_SOURCE: - code = compile(f.read(), path, 'exec') - else: - # Not something we can parse; we'll have to import it. :( - if module not in sys.modules: - imp.load_module(module,f,path,(suffix,mode,kind)) - return getattr(sys.modules[module],symbol,None) - - finally: - if f: - f.close() - - return extract_constant(code,symbol,default) - - - - - - - - -def extract_constant(code,symbol,default=-1): - - """Extract the constant value of 'symbol' from 'code' - - If the name 'symbol' is bound to a constant value by the Python code - object 'code', return that value. If 'symbol' is bound to an expression, - return 'default'. Otherwise, return 'None'. - - Return value is based on the first assignment to 'symbol'. 'symbol' must - be a global, or at least a non-"fast" local in the code block. That is, - only 'STORE_NAME' and 'STORE_GLOBAL' opcodes are checked, and 'symbol' - must be present in 'code.co_names'. - """ - - if symbol not in code.co_names: - # name's not there, can't possibly be an assigment - return None - - name_idx = list(code.co_names).index(symbol) - - STORE_NAME = 90 - STORE_GLOBAL = 97 - LOAD_CONST = 100 - - const = default - - for op, arg in _iter_code(code): - - if op==LOAD_CONST: - const = code.co_consts[arg] - elif arg==name_idx and (op==STORE_NAME or op==STORE_GLOBAL): - return const - else: - const = default - - - - - - - diff --git a/setuptools/dist.py b/setuptools/dist.py deleted file mode 100644 index cb5a906..0000000 --- a/setuptools/dist.py +++ /dev/null @@ -1,492 +0,0 @@ -__all__ = ['Distribution', 'Feature'] -from distutils.core import Distribution as _Distribution -from distutils.core import Extension -from setuptools.depends import Require -from setuptools.command.build_py import build_py -from setuptools.command.build_ext import build_ext -from setuptools.command.install import install -from setuptools.command.install_lib import install_lib -from distutils.errors import DistutilsOptionError, DistutilsPlatformError -from distutils.errors import DistutilsSetupError -sequence = tuple, list - -class Distribution(_Distribution): - """Distribution with support for features, tests, and package data - - This is an enhanced version of 'distutils.dist.Distribution' that - effectively adds the following new optional keyword arguments to 'setup()': - - 'features' -- a dictionary mapping option names to 'setuptools.Feature' - objects. Features are a portion of the distribution that can be - included or excluded based on user options, inter-feature dependencies, - and availability on the current system. Excluded features are omitted - from all setup commands, including source and binary distributions, so - you can create multiple distributions from the same source tree. - - Feature names should be valid Python identifiers, except that they may - contain the '-' (minus) sign. Features can be included or excluded - via the command line options '--with-X' and '--without-X', where 'X' is - the name of the feature. Whether a feature is included by default, and - whether you are allowed to control this from the command line, is - determined by the Feature object. See the 'Feature' class for more - information. - - 'test_suite' -- the name of a test suite to run for the 'test' command. - If the user runs 'python setup.py test', the package will be installed, - and the named test suite will be run. The format is the same as - would be used on a 'unittest.py' command line. That is, it is the - dotted name of an object to import and call to generate a test suite. - - 'package_data' -- a dictionary mapping package names to lists of filenames - or globs to use to find data files contained in the named packages. - If the dictionary has filenames or globs listed under '""' (the empty - string), those names will be searched for in every package, in addition - to any names for the specific package. Data files found using these - names/globs will be installed along with the package, in the same - location as the package. Note that globs are allowed to reference - the contents of non-package subdirectories, as long as you use '/' as - a path separator. (Globs are automatically converted to - platform-specific paths at runtime.) - - In addition to these new keywords, this class also has several new methods - for manipulating the distribution's contents. For example, the 'include()' - and 'exclude()' methods can be thought of as in-place add and subtract - commands that add or remove packages, modules, extensions, and so on from - the distribution. They are used by the feature subsystem to configure the - distribution for the included and excluded features. - """ - - def __init__ (self, attrs=None): - self.features = {} - self.package_data = {} - self.test_suite = None - self.requires = [] - _Distribution.__init__(self,attrs) - self.cmdclass.setdefault('build_py',build_py) - self.cmdclass.setdefault('build_ext',build_ext) - self.cmdclass.setdefault('install',install) - self.cmdclass.setdefault('install_lib',install_lib) - if self.features: - self._set_global_opts_from_features() - - def parse_command_line(self): - """Process features after parsing command line options""" - result = _Distribution.parse_command_line(self) - if self.features: - self._finalize_features() - return result - - def _feature_attrname(self,name): - """Convert feature name to corresponding option attribute name""" - return 'with_'+name.replace('-','_') - - def _set_global_opts_from_features(self): - """Add --with-X/--without-X options based on optional features""" - - go = [] - no = self.negative_opt.copy() - - for name,feature in self.features.items(): - self._set_feature(name,None) - feature.validate(self) - - if feature.optional: - descr = feature.description - incdef = ' (default)' - excdef='' - if not feature.include_by_default(): - excdef, incdef = incdef, excdef - - go.append(('with-'+name, None, 'include '+descr+incdef)) - go.append(('without-'+name, None, 'exclude '+descr+excdef)) - no['without-'+name] = 'with-'+name - - self.global_options = self.feature_options = go + self.global_options - self.negative_opt = self.feature_negopt = no - - def _finalize_features(self): - """Add/remove features and resolve dependencies between them""" - - # First, flag all the enabled items (and thus their dependencies) - for name,feature in self.features.items(): - enabled = self.feature_is_included(name) - if enabled or (enabled is None and feature.include_by_default()): - feature.include_in(self) - self._set_feature(name,1) - - # Then disable the rest, so that off-by-default features don't - # get flagged as errors when they're required by an enabled feature - for name,feature in self.features.items(): - if not self.feature_is_included(name): - feature.exclude_from(self) - self._set_feature(name,0) - - def _set_feature(self,name,status): - """Set feature's inclusion status""" - setattr(self,self._feature_attrname(name),status) - - def feature_is_included(self,name): - """Return 1 if feature is included, 0 if excluded, 'None' if unknown""" - return getattr(self,self._feature_attrname(name)) - - def include_feature(self,name): - """Request inclusion of feature named 'name'""" - - if self.feature_is_included(name)==0: - descr = self.features[name].description - raise DistutilsOptionError( - descr + " is required, but was excluded or is not available" - ) - self.features[name].include_in(self) - self._set_feature(name,1) - - def include(self,**attrs): - """Add items to distribution that are named in keyword arguments - - For example, 'dist.exclude(py_modules=["x"])' would add 'x' to - the distribution's 'py_modules' attribute, if it was not already - there. - - Currently, this method only supports inclusion for attributes that are - lists or tuples. If you need to add support for adding to other - attributes in this or a subclass, you can add an '_include_X' method, - where 'X' is the name of the attribute. The method will be called with - the value passed to 'include()'. So, 'dist.include(foo={"bar":"baz"})' - will try to call 'dist._include_foo({"bar":"baz"})', which can then - handle whatever special inclusion logic is needed. - """ - for k,v in attrs.items(): - include = getattr(self, '_include_'+k, None) - if include: - include(v) - else: - self._include_misc(k,v) - - def exclude_package(self,package): - """Remove packages, modules, and extensions in named package""" - - pfx = package+'.' - if self.packages: - self.packages = [ - p for p in self.packages - if p<>package and not p.startswith(pfx) - ] - - if self.py_modules: - self.py_modules = [ - p for p in self.py_modules - if p<>package and not p.startswith(pfx) - ] - - if self.ext_modules: - self.ext_modules = [ - p for p in self.ext_modules - if p.name<>package and not p.name.startswith(pfx) - ] - - - def has_contents_for(self,package): - """Return true if 'exclude_package(package)' would do something""" - - pfx = package+'.' - - for p in self.packages or (): - if p==package or p.startswith(pfx): - return True - - for p in self.py_modules or (): - if p==package or p.startswith(pfx): - return True - - for p in self.ext_modules or (): - if p.name==package or p.name.startswith(pfx): - return True - - - def _exclude_misc(self,name,value): - """Handle 'exclude()' for list/tuple attrs without a special handler""" - if not isinstance(value,sequence): - raise DistutilsSetupError( - "%s: setting must be a list or tuple (%r)" % (name, value) - ) - try: - old = getattr(self,name) - except AttributeError: - raise DistutilsSetupError( - "%s: No such distribution setting" % name - ) - if old is not None and not isinstance(old,sequence): - raise DistutilsSetupError( - name+": this setting cannot be changed via include/exclude" - ) - elif old: - setattr(self,name,[item for item in old if item not in value]) - - def _include_misc(self,name,value): - """Handle 'include()' for list/tuple attrs without a special handler""" - - if not isinstance(value,sequence): - raise DistutilsSetupError( - "%s: setting must be a list (%r)" % (name, value) - ) - try: - old = getattr(self,name) - except AttributeError: - raise DistutilsSetupError( - "%s: No such distribution setting" % name - ) - if old is None: - setattr(self,name,value) - elif not isinstance(old,sequence): - raise DistutilsSetupError( - name+": this setting cannot be changed via include/exclude" - ) - else: - setattr(self,name,old+[item for item in value if item not in old]) - - def exclude(self,**attrs): - """Remove items from distribution that are named in keyword arguments - - For example, 'dist.exclude(py_modules=["x"])' would remove 'x' from - the distribution's 'py_modules' attribute. Excluding packages uses - the 'exclude_package()' method, so all of the package's contained - packages, modules, and extensions are also excluded. - - Currently, this method only supports exclusion from attributes that are - lists or tuples. If you need to add support for excluding from other - attributes in this or a subclass, you can add an '_exclude_X' method, - where 'X' is the name of the attribute. The method will be called with - the value passed to 'exclude()'. So, 'dist.exclude(foo={"bar":"baz"})' - will try to call 'dist._exclude_foo({"bar":"baz"})', which can then - handle whatever special exclusion logic is needed. - """ - for k,v in attrs.items(): - exclude = getattr(self, '_exclude_'+k, None) - if exclude: - exclude(v) - else: - self._exclude_misc(k,v) - - def _exclude_packages(self,packages): - if not isinstance(packages,sequence): - raise DistutilsSetupError( - "packages: setting must be a list or tuple (%r)" % (packages,) - ) - map(self.exclude_package, packages) - - def _parse_command_opts(self, parser, args): - # Remove --with-X/--without-X options when processing command args - self.global_options = self.__class__.global_options - self.negative_opt = self.__class__.negative_opt - return _Distribution._parse_command_opts(self, parser, args) - - def has_dependencies(self): - return not not self.requires - - - - def get_cmdline_options(self): - """Return a '{cmd: {opt:val}}' map of all command-line options - - Option names are all long, but do not include the leading '--', and - contain dashes rather than underscores. If the option doesn't take - an argument (e.g. '--quiet'), the 'val' is 'None'. - - Note that options provided by config files are intentionally excluded. - """ - - d = {} - - for cmd,opts in self.command_options.items(): - - for opt,(src,val) in opts.items(): - - if src != "command line": - continue - - opt = opt.replace('_','-') - - if val==0: - cmdobj = self.get_command_obj(cmd) - neg_opt = self.negative_opt.copy() - neg_opt.update(getattr(cmdobj,'negative_opt',{})) - for neg,pos in neg_opt.items(): - if pos==opt: - opt=neg - val=None - break - else: - raise AssertionError("Shouldn't be able to get here") - - elif val==1: - val = None - - d.setdefault(cmd,{})[opt] = val - - return d - - -class Feature: - """A subset of the distribution that can be excluded if unneeded/wanted - - Features are created using these keyword arguments: - - 'description' -- a short, human readable description of the feature, to - be used in error messages, and option help messages. - - 'standard' -- if true, the feature is included by default if it is - available on the current system. Otherwise, the feature is only - included if requested via a command line '--with-X' option, or if - another included feature requires it. The default setting is 'False'. - - 'available' -- if true, the feature is available for installation on the - current system. The default setting is 'True'. - - 'optional' -- if true, the feature's inclusion can be controlled from the - command line, using the '--with-X' or '--without-X' options. If - false, the feature's inclusion status is determined automatically, - based on 'availabile', 'standard', and whether any other feature - requires it. The default setting is 'True'. - - 'requires' -- a string or sequence of strings naming features that should - also be included if this feature is included. Defaults to empty list. - May also contain 'Require' objects that should be added/removed from - the distribution. - - 'remove' -- a string or list of strings naming packages to be removed - from the distribution if this feature is *not* included. If the - feature *is* included, this argument is ignored. This argument exists - to support removing features that "crosscut" a distribution, such as - defining a 'tests' feature that removes all the 'tests' subpackages - provided by other features. The default for this argument is an empty - list. (Note: the named package(s) or modules must exist in the base - distribution when the 'setup()' function is initially called.) - - other keywords -- any other keyword arguments are saved, and passed to - the distribution's 'include()' and 'exclude()' methods when the - feature is included or excluded, respectively. So, for example, you - could pass 'packages=["a","b"]' to cause packages 'a' and 'b' to be - added or removed from the distribution as appropriate. - - A feature must include at least one 'requires', 'remove', or other - keyword argument. Otherwise, it can't affect the distribution in any way. - Note also that you can subclass 'Feature' to create your own specialized - feature types that modify the distribution in other ways when included or - excluded. See the docstrings for the various methods here for more detail. - Aside from the methods, the only feature attributes that distributions look - at are 'description' and 'optional'. - """ - - def __init__(self, description, standard=False, available=True, - optional=True, requires=(), remove=(), **extras - ): - - self.description = description - self.standard = standard - self.available = available - self.optional = optional - if isinstance(requires,(str,Require)): - requires = requires, - - self.requires = [r for r in requires if isinstance(r,str)] - er = [r for r in requires if not isinstance(r,str)] - if er: extras['requires'] = er - - if isinstance(remove,str): - remove = remove, - self.remove = remove - self.extras = extras - - if not remove and not requires and not extras: - raise DistutilsSetupError( - "Feature %s: must define 'requires', 'remove', or at least one" - " of 'packages', 'py_modules', etc." - ) - - - def include_by_default(self): - """Should this feature be included by default?""" - return self.available and self.standard - - def include_in(self,dist): - - """Ensure feature and its requirements are included in distribution - - You may override this in a subclass to perform additional operations on - the distribution. Note that this method may be called more than once - per feature, and so should be idempotent. - - """ - - if not self.available: - raise DistutilsPlatformError( - self.description+" is required," - "but is not available on this platform" - ) - - dist.include(**self.extras) - - for f in self.requires: - dist.include_feature(f) - - - - def exclude_from(self,dist): - - """Ensure feature is excluded from distribution - - You may override this in a subclass to perform additional operations on - the distribution. This method will be called at most once per - feature, and only after all included features have been asked to - include themselves. - """ - - dist.exclude(**self.extras) - - if self.remove: - for item in self.remove: - dist.exclude_package(item) - - - - def validate(self,dist): - - """Verify that feature makes sense in context of distribution - - This method is called by the distribution just before it parses its - command line. It checks to ensure that the 'remove' attribute, if any, - contains only valid package/module names that are present in the base - distribution when 'setup()' is called. You may override it in a - subclass to perform any other required validation of the feature - against a target distribution. - """ - - for item in self.remove: - if not dist.has_contents_for(item): - raise DistutilsSetupError( - "%s wants to be able to remove %s, but the distribution" - " doesn't contain any packages or modules under %s" - % (self.description, item, item) - ) - - - - - - - - - - - - - - - - - - - - - - diff --git a/setuptools/extension.py b/setuptools/extension.py deleted file mode 100644 index 55a4d94..0000000 --- a/setuptools/extension.py +++ /dev/null @@ -1,27 +0,0 @@ -from distutils.core import Extension as _Extension - -try: - from Pyrex.Distutils.build_ext import build_ext - -except ImportError: - - # Pyrex isn't around, so fix up the sources - - class Extension(_Extension): - - """Extension that uses '.c' files in place of '.pyx' files""" - - def __init__(self,*args,**kw): - _Extension.__init__(self,*args,**kw) - sources = [] - for s in self.sources: - if s.endswith('.pyx'): - sources.append(s[:-3]+'c') - else: - sources.append(s) - self.sources = sources - -else: - - # Pyrex is here, just use regular extension type - Extension = _Extension diff --git a/setuptools/tests/__init__.py b/setuptools/tests/__init__.py deleted file mode 100644 index 66b1264..0000000 --- a/setuptools/tests/__init__.py +++ /dev/null @@ -1,451 +0,0 @@ -"""Tests for the 'setuptools' package""" - -from unittest import TestSuite, TestCase, makeSuite -import distutils.core, distutils.cmd -from distutils.errors import DistutilsOptionError, DistutilsPlatformError -from distutils.errors import DistutilsSetupError -import setuptools, setuptools.dist -from setuptools import Feature -from distutils.core import Extension -from setuptools.depends import extract_constant, get_module_constant -from setuptools.depends import find_module, Require -from distutils.version import StrictVersion, LooseVersion -from distutils.util import convert_path -import sys, os.path - - -def makeSetup(**args): - """Return distribution from 'setup(**args)', without executing commands""" - - distutils.core._setup_stop_after = "commandline" - - # Don't let system command line leak into tests! - args.setdefault('script_args',['install']) - - try: - return setuptools.setup(**args) - finally: - distutils.core_setup_stop_after = None - - - - - - - - - - - - - -class DependsTests(TestCase): - - def testExtractConst(self): - - from setuptools.depends import extract_constant - - def f1(): - global x,y,z - x = "test" - y = z - - # unrecognized name - self.assertEqual(extract_constant(f1.func_code,'q', -1), None) - - # constant assigned - self.assertEqual(extract_constant(f1.func_code,'x', -1), "test") - - # expression assigned - self.assertEqual(extract_constant(f1.func_code,'y', -1), -1) - - # recognized name, not assigned - self.assertEqual(extract_constant(f1.func_code,'z', -1), None) - - - def testFindModule(self): - self.assertRaises(ImportError, find_module, 'no-such.-thing') - self.assertRaises(ImportError, find_module, 'setuptools.non-existent') - f,p,i = find_module('setuptools.tests'); f.close() - - def testModuleExtract(self): - from distutils import __version__ - self.assertEqual( - get_module_constant('distutils','__version__'), __version__ - ) - self.assertEqual( - get_module_constant('sys','version'), sys.version - ) - self.assertEqual( - get_module_constant('setuptools.tests','__doc__'),__doc__ - ) - - def testRequire(self): - - req = Require('Distutils','1.0.3','distutils') - - self.assertEqual(req.name, 'Distutils') - self.assertEqual(req.module, 'distutils') - self.assertEqual(req.requested_version, '1.0.3') - self.assertEqual(req.attribute, '__version__') - self.assertEqual(req.full_name(), 'Distutils-1.0.3') - - from distutils import __version__ - self.assertEqual(req.get_version(), __version__) - self.failUnless(req.version_ok('1.0.9')) - self.failIf(req.version_ok('0.9.1')) - self.failIf(req.version_ok('unknown')) - - self.failUnless(req.is_present()) - self.failUnless(req.is_current()) - - req = Require('Distutils 3000','03000','distutils',format=LooseVersion) - self.failUnless(req.is_present()) - self.failIf(req.is_current()) - self.failIf(req.version_ok('unknown')) - - req = Require('Do-what-I-mean','1.0','d-w-i-m') - self.failIf(req.is_present()) - self.failIf(req.is_current()) - - req = Require('Tests', None, 'tests', homepage="http://example.com") - self.assertEqual(req.format, None) - self.assertEqual(req.attribute, None) - self.assertEqual(req.requested_version, None) - self.assertEqual(req.full_name(), 'Tests') - self.assertEqual(req.homepage, 'http://example.com') - - paths = [os.path.dirname(p) for p in __path__] - self.failUnless(req.is_present(paths)) - self.failUnless(req.is_current(paths)) - - - - def testDependsCmd(self): - path1 = convert_path('foo/bar/baz') - path2 = convert_path('foo/bar/baz/spam') - - dist = makeSetup( - extra_path='spam', - script_args=[ - 'install','--install-lib',path1, '--prefix',path2, - 'build','--compiler=mingw32', - ] - ) - - cmd = dist.get_command_obj('depends') - cmd.ensure_finalized() - - self.assertEqual(cmd.temp, dist.get_command_obj('build').build_temp) - self.assertEqual(cmd.search_path, [path2,path1]+sys.path) - - self.assertEqual(cmd.unsafe_options, - {'install':['--install-lib',path1]} - ) - self.assertEqual(cmd.safe_options, { - 'build':['--compiler','mingw32'], - 'install':['--prefix',os.path.abspath(path2)] - }) - - - - - - - - - - - - - - - - -class DistroTests(TestCase): - - def setUp(self): - self.e1 = Extension('bar.ext',['bar.c']) - self.e2 = Extension('c.y', ['y.c']) - - self.dist = makeSetup( - packages=['a', 'a.b', 'a.b.c', 'b', 'c'], - py_modules=['b.d','x'], - ext_modules = (self.e1, self.e2), - script_args = [ - 'build', '-q', 'build_ext', '-i', - 'install', '--prefix=/usr/lib', '--install-lib','/test' - ], - package_dir = {}, - ) - - - def testDistroType(self): - self.failUnless(isinstance(self.dist,setuptools.dist.Distribution)) - - - def testExcludePackage(self): - self.dist.exclude_package('a') - self.assertEqual(self.dist.packages, ['b','c']) - - self.dist.exclude_package('b') - self.assertEqual(self.dist.packages, ['c']) - self.assertEqual(self.dist.py_modules, ['x']) - self.assertEqual(self.dist.ext_modules, [self.e1, self.e2]) - - self.dist.exclude_package('c') - self.assertEqual(self.dist.packages, []) - self.assertEqual(self.dist.py_modules, ['x']) - self.assertEqual(self.dist.ext_modules, [self.e1]) - - # test removals from unspecified options - makeSetup().exclude_package('x') - - - - def testIncludeExclude(self): - # remove an extension - self.dist.exclude(ext_modules=[self.e1]) - self.assertEqual(self.dist.ext_modules, [self.e2]) - - # add it back in - self.dist.include(ext_modules=[self.e1]) - self.assertEqual(self.dist.ext_modules, [self.e2, self.e1]) - - # should not add duplicate - self.dist.include(ext_modules=[self.e1]) - self.assertEqual(self.dist.ext_modules, [self.e2, self.e1]) - - def testExcludePackages(self): - self.dist.exclude(packages=['c','b','a']) - self.assertEqual(self.dist.packages, []) - self.assertEqual(self.dist.py_modules, ['x']) - self.assertEqual(self.dist.ext_modules, [self.e1]) - - def testEmpty(self): - dist = makeSetup() - dist.include(packages=['a'], py_modules=['b'], ext_modules=[self.e2]) - dist = makeSetup() - dist.exclude(packages=['a'], py_modules=['b'], ext_modules=[self.e2]) - - def testContents(self): - self.failUnless(self.dist.has_contents_for('a')) - self.dist.exclude_package('a') - self.failIf(self.dist.has_contents_for('a')) - - self.failUnless(self.dist.has_contents_for('b')) - self.dist.exclude_package('b') - self.failIf(self.dist.has_contents_for('b')) - - self.failUnless(self.dist.has_contents_for('c')) - self.dist.exclude_package('c') - self.failIf(self.dist.has_contents_for('c')) - - - - - def testInvalidIncludeExclude(self): - self.assertRaises(DistutilsSetupError, - self.dist.include, nonexistent_option='x' - ) - self.assertRaises(DistutilsSetupError, - self.dist.exclude, nonexistent_option='x' - ) - self.assertRaises(DistutilsSetupError, - self.dist.include, packages={'x':'y'} - ) - self.assertRaises(DistutilsSetupError, - self.dist.exclude, packages={'x':'y'} - ) - self.assertRaises(DistutilsSetupError, - self.dist.include, ext_modules={'x':'y'} - ) - self.assertRaises(DistutilsSetupError, - self.dist.exclude, ext_modules={'x':'y'} - ) - - self.assertRaises(DistutilsSetupError, - self.dist.include, package_dir=['q'] - ) - self.assertRaises(DistutilsSetupError, - self.dist.exclude, package_dir=['q'] - ) - - def testCmdLineOpts(self): - self.assertEqual(self.dist.get_cmdline_options(), - { 'install':{'prefix':'/usr/lib', 'install-lib':'/test'}, - 'build': {'quiet':None}, 'build_ext':{'inplace':None}, - } - ) - - - - - - - - -class FeatureTests(TestCase): - - def setUp(self): - self.req = Require('Distutils','1.0.3','distutils') - self.dist = makeSetup( - features={ - 'foo': Feature("foo",standard=True,requires=['baz',self.req]), - 'bar': Feature("bar", standard=True, packages=['pkg.bar'], - py_modules=['bar_et'], remove=['bar.ext'], - ), - 'baz': Feature( - "baz", optional=False, packages=['pkg.baz'], - scripts = ['scripts/baz_it'], - libraries=[('libfoo','foo/foofoo.c')] - ), - 'dwim': Feature("DWIM", available=False, remove='bazish'), - }, - script_args=['--without-bar', 'install'], - packages = ['pkg.bar', 'pkg.foo'], - py_modules = ['bar_et', 'bazish'], - ext_modules = [Extension('bar.ext',['bar.c'])] - ) - - def testDefaults(self): - self.failIf( - Feature( - "test",standard=True,remove='x',available=False - ).include_by_default() - ) - self.failUnless( - Feature("test",standard=True,remove='x').include_by_default() - ) - # Feature must have either kwargs, removes, or requires - self.assertRaises(DistutilsSetupError, Feature, "test") - - def testAvailability(self): - self.assertRaises( - DistutilsPlatformError, - self.dist.features['dwim'].include_in, self.dist - ) - - def testFeatureOptions(self): - dist = self.dist - self.failUnless( - ('with-dwim',None,'include DWIM') in dist.feature_options - ) - self.failUnless( - ('without-dwim',None,'exclude DWIM (default)') in dist.feature_options - ) - self.failUnless( - ('with-bar',None,'include bar (default)') in dist.feature_options - ) - self.failUnless( - ('without-bar',None,'exclude bar') in dist.feature_options - ) - self.assertEqual(dist.feature_negopt['without-foo'],'with-foo') - self.assertEqual(dist.feature_negopt['without-bar'],'with-bar') - self.assertEqual(dist.feature_negopt['without-dwim'],'with-dwim') - self.failIf('without-baz' in dist.feature_negopt) - - def testUseFeatures(self): - dist = self.dist - self.assertEqual(dist.with_foo,1) - self.assertEqual(dist.with_bar,0) - self.assertEqual(dist.with_baz,1) - self.failIf('bar_et' in dist.py_modules) - self.failIf('pkg.bar' in dist.packages) - self.failUnless('pkg.baz' in dist.packages) - self.failUnless('scripts/baz_it' in dist.scripts) - self.failUnless(('libfoo','foo/foofoo.c') in dist.libraries) - self.assertEqual(dist.ext_modules,[]) - self.assertEqual(dist.requires, [self.req]) - - # If we ask for bar, it should fail because we explicitly disabled - # it on the command line - self.assertRaises(DistutilsOptionError, dist.include_feature, 'bar') - - def testFeatureWithInvalidRemove(self): - self.assertRaises( - SystemExit, makeSetup, features = {'x':Feature('x', remove='y')} - ) - -class TestCommandTests(TestCase): - - def testTestIsCommand(self): - test_cmd = makeSetup().get_command_obj('test') - self.failUnless(isinstance(test_cmd, distutils.cmd.Command)) - - def testLongOptSuiteWNoDefault(self): - ts1 = makeSetup(script_args=['test','--test-suite=foo.tests.suite']) - ts1 = ts1.get_command_obj('test') - ts1.ensure_finalized() - self.assertEqual(ts1.test_suite, 'foo.tests.suite') - - def testDefaultSuite(self): - ts2 = makeSetup(test_suite='bar.tests.suite').get_command_obj('test') - ts2.ensure_finalized() - self.assertEqual(ts2.test_suite, 'bar.tests.suite') - - def testDefaultWModuleOnCmdLine(self): - ts3 = makeSetup( - test_suite='bar.tests', - script_args=['test','-m','foo.tests'] - ).get_command_obj('test') - ts3.ensure_finalized() - self.assertEqual(ts3.test_module, 'foo.tests') - self.assertEqual(ts3.test_suite, 'foo.tests.test_suite') - - def testConflictingOptions(self): - ts4 = makeSetup( - script_args=['test','-m','bar.tests', '-s','foo.tests.suite'] - ).get_command_obj('test') - self.assertRaises(DistutilsOptionError, ts4.ensure_finalized) - - def testNoSuite(self): - ts5 = makeSetup().get_command_obj('test') - ts5.ensure_finalized() - self.assertEqual(ts5.test_suite, None) - - - - - -testClasses = (DependsTests, DistroTests, FeatureTests, TestCommandTests) - -def test_suite(): - return TestSuite([makeSuite(t,'test') for t in testClasses]) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- cgit v1.2.1