diff options
40 files changed, 295 insertions, 225 deletions
diff --git a/bootstrap.py b/bootstrap.py index 70f96258..bf7fb431 100644 --- a/bootstrap.py +++ b/bootstrap.py @@ -27,6 +27,7 @@ minimal_egg_info = textwrap.dedent(""" requires.txt = setuptools.command.egg_info:write_requirements """) + def ensure_egg_info(): if os.path.exists('setuptools.egg-info'): return diff --git a/pavement.py b/pavement.py index 303e9bac..f620c790 100644 --- a/pavement.py +++ b/pavement.py @@ -3,10 +3,12 @@ import re from paver.easy import task, path as Path import pip + def remove_all(paths): for path in paths: path.rmtree() if path.isdir() else path.remove() + @task def update_vendored(): vendor = Path('pkg_resources/_vendor') @@ -26,6 +26,7 @@ import setuptools scripts = [] + def _gen_console_scripts(): yield "easy_install = setuptools.command.easy_install:main" diff --git a/setuptools/__init__.py b/setuptools/__init__.py index 67b57e4f..2523ccc7 100644 --- a/setuptools/__init__.py +++ b/setuptools/__init__.py @@ -32,6 +32,7 @@ lib2to3_fixer_packages = ['lib2to3.fixes'] class PackageFinder(object): + @classmethod def find(cls, where='.', exclude=(), include=('*',)): """Return a list all Python packages found within directory 'where' @@ -108,7 +109,9 @@ class PackageFinder(object): """ return lambda name: any(fnmatchcase(name, pat=pat) for pat in patterns) + class PEP420PackageFinder(PackageFinder): + @staticmethod def _looks_like_package(path): return True @@ -119,6 +122,7 @@ setup = distutils.core.setup _Command = _get_unpatched(_Command) + class Command(_Command): __doc__ = _Command.__doc__ diff --git a/setuptools/archive_util.py b/setuptools/archive_util.py index b3c9fa56..d1950638 100755 --- a/setuptools/archive_util.py +++ b/setuptools/archive_util.py @@ -15,10 +15,12 @@ import contextlib from pkg_resources import ensure_directory, ContextualZipFile from distutils.errors import DistutilsError + class UnrecognizedFormat(DistutilsError): """Couldn't recognize the archive type""" -def default_filter(src,dst): + +def default_filter(src, dst): """The default progress/filter callback; returns True for all files""" return dst diff --git a/setuptools/command/bdist_wininst.py b/setuptools/command/bdist_wininst.py index 073de97b..8243c917 100755 --- a/setuptools/command/bdist_wininst.py +++ b/setuptools/command/bdist_wininst.py @@ -2,6 +2,7 @@ import distutils.command.bdist_wininst as orig class bdist_wininst(orig.bdist_wininst): + def reinitialize_command(self, command, reinit_subcommands=0): """ Supplement reinitialize_command to work around diff --git a/setuptools/command/build_ext.py b/setuptools/command/build_ext.py index 1caf8c81..e6db0764 100644 --- a/setuptools/command/build_ext.py +++ b/setuptools/command/build_ext.py @@ -59,7 +59,9 @@ elif os.name != 'nt': if_dl = lambda s: s if have_rtld else '' + class build_ext(_build_ext): + def run(self): """Build extensions in build directory, then copy if --inplace""" old_inplace, self.inplace = self.inplace, 0 diff --git a/setuptools/command/build_py.py b/setuptools/command/build_py.py index 0bad8295..b5de9bda 100644 --- a/setuptools/command/build_py.py +++ b/setuptools/command/build_py.py @@ -15,6 +15,7 @@ try: from setuptools.lib2to3_ex import Mixin2to3 except ImportError: class Mixin2to3: + def run_2to3(self, files, doctests=True): "do nothing" diff --git a/setuptools/command/develop.py b/setuptools/command/develop.py index 11b5df10..3eb86120 100755 --- a/setuptools/command/develop.py +++ b/setuptools/command/develop.py @@ -186,6 +186,7 @@ class VersionlessRequirement(object): >>> str(adapted_dist.as_requirement()) 'foo' """ + def __init__(self, dist): self.__dist = dist diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 9ca1554e..73bdb0cb 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -2158,6 +2158,7 @@ class WindowsScriptWriter(ScriptWriter): class WindowsExecutableLauncherWriter(WindowsScriptWriter): + @classmethod def _get_script_args(cls, type_, name, header, script_text): """ diff --git a/setuptools/command/install_lib.py b/setuptools/command/install_lib.py index 78fe6891..2b31c3e3 100644 --- a/setuptools/command/install_lib.py +++ b/setuptools/command/install_lib.py @@ -3,6 +3,7 @@ import imp from itertools import product, starmap import distutils.command.install_lib as orig + class install_lib(orig.install_lib): """Don't add compiled flags to filenames of non-Python files""" diff --git a/setuptools/command/sdist.py b/setuptools/command/sdist.py index f200b946..041ee42e 100755 --- a/setuptools/command/sdist.py +++ b/setuptools/command/sdist.py @@ -15,6 +15,7 @@ READMES = 'README', 'README.rst', 'README.txt' _default_revctrl = list + def walk_revctrl(dirname=''): """Find all files under revision control""" for ep in pkg_resources.iter_entry_points('setuptools.file_finders'): diff --git a/setuptools/command/test.py b/setuptools/command/test.py index 39746a02..2d1adba8 100644 --- a/setuptools/command/test.py +++ b/setuptools/command/test.py @@ -14,6 +14,7 @@ from setuptools.py31compat import unittest_main class ScanningLoader(TestLoader): + def loadTestsFromModule(self, module, pattern=None): """Return a suite of all tests cases contained in the given module @@ -46,6 +47,7 @@ class ScanningLoader(TestLoader): # adapted from jaraco.classes.properties:NonDataProperty class NonDataProperty(object): + def __init__(self, fget): self.fget = fget diff --git a/setuptools/depends.py b/setuptools/depends.py index 9f7c9a35..eb1d7b13 100644 --- a/setuptools/depends.py +++ b/setuptools/depends.py @@ -10,6 +10,7 @@ __all__ = [ 'Require', 'find_module', 'get_module_constant', 'extract_constant' ] + class Require: """A prerequisite to building or installing a distribution""" @@ -30,7 +31,7 @@ class Require: 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 '%s-%s' % (self.name, self.requested_version) return self.name def version_ok(self, version): @@ -39,7 +40,6 @@ class Require: 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, @@ -52,7 +52,7 @@ class Require: if self.attribute is None: try: - f,p,i = find_module(self.module,paths) + f, p, i = find_module(self.module, paths) if f: f.close() return default except ImportError: @@ -78,13 +78,12 @@ class Require: 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) + bytes = array('b', code.co_code) eof = len(code.co_code) ptr = 0 @@ -108,7 +107,7 @@ def _iter_code(code): arg = None ptr += 1 - yield op,arg + yield op, arg def find_module(module, paths=None): @@ -118,20 +117,19 @@ def find_module(module, paths=None): while parts: part = parts.pop(0) - f, path, (suffix,mode,kind) = info = imp.find_module(part, paths) + 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)) + 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 diff --git a/setuptools/dist.py b/setuptools/dist.py index 086e0a58..f229d726 100644 --- a/setuptools/dist.py +++ b/setuptools/dist.py @@ -38,6 +38,7 @@ def _get_unpatched(cls): _Distribution = _get_unpatched(_Distribution) + def _patch_distribution_metadata_write_pkg_info(): """ Workaround issue #197 - Python 3 prior to 3.2.2 uses an environment-local @@ -61,14 +62,15 @@ _patch_distribution_metadata_write_pkg_info() sequence = tuple, list + def check_importable(dist, attr, value): try: ep = pkg_resources.EntryPoint.parse('x='+value) assert not ep.extras - except (TypeError,ValueError,AttributeError,AssertionError): + except (TypeError, ValueError, AttributeError, AssertionError): raise DistutilsSetupError( "%r must be importable 'module:attrs' string (got %r)" - % (attr,value) + % (attr, value) ) @@ -76,13 +78,15 @@ def assert_string_list(dist, attr, value): """Verify that value is a string list or None""" try: assert ''.join(value)!=value - except (TypeError,ValueError,AttributeError,AssertionError): + except (TypeError, ValueError, AttributeError, AssertionError): raise DistutilsSetupError( - "%r must be a list of strings (got %r)" % (attr,value) + "%r must be a list of strings (got %r)" % (attr, value) ) + + def check_nsp(dist, attr, value): """Verify that namespace packages are valid""" - assert_string_list(dist,attr,value) + assert_string_list(dist, attr, value) for nsp in value: if not dist.has_contents_for(nsp): raise DistutilsSetupError( @@ -97,22 +101,24 @@ def check_nsp(dist, attr, value): " is not: please correct this in setup.py", nsp, parent ) + def check_extras(dist, attr, value): """Verify that extras_require mapping is valid""" try: - for k,v in value.items(): + for k, v in value.items(): if ':' in k: - k,m = k.split(':',1) + k, m = k.split(':', 1) if pkg_resources.invalid_marker(m): raise DistutilsSetupError("Invalid environment marker: "+m) list(pkg_resources.parse_requirements(v)) - except (TypeError,ValueError,AttributeError): + except (TypeError, ValueError, AttributeError): raise DistutilsSetupError( "'extras_require' must be a dictionary whose values are " "strings or lists of strings containing valid project/version " "requirement specifiers." ) + def assert_bool(dist, attr, value): """Verify that value is True, False, 0, or 1""" if bool(value) != value: @@ -131,6 +137,7 @@ def check_requirements(dist, attr, value): ) raise DistutilsSetupError(tmpl.format(attr=attr, error=error)) + def check_entry_points(dist, attr, value): """Verify that entry_points map is parseable""" try: @@ -138,15 +145,17 @@ def check_entry_points(dist, attr, value): except ValueError as e: raise DistutilsSetupError(e) + def check_test_suite(dist, attr, value): if not isinstance(value, six.string_types): raise DistutilsSetupError("test_suite must be a string") + def check_package_data(dist, attr, value): """Verify that value is a dictionary of package names to glob lists""" - if isinstance(value,dict): - for k,v in value.items(): - if not isinstance(k,str): break + if isinstance(value, dict): + for k, v in value.items(): + if not isinstance(k, str): break try: iter(v) except TypeError: break @@ -157,6 +166,7 @@ def check_package_data(dist, attr, value): "wildcard patterns" ) + def check_packages(dist, attr, value): for pkgname in value: if not re.match(r'\w+(\.\w+)*', pkgname): @@ -264,12 +274,12 @@ class Distribution(_Distribution): # Make sure we have any eggs needed to interpret 'attrs' if attrs is not None: self.dependency_links = attrs.pop('dependency_links', []) - assert_string_list(self,'dependency_links',self.dependency_links) + assert_string_list(self, 'dependency_links', self.dependency_links) if attrs and 'setup_requires' in attrs: self.fetch_build_eggs(attrs['setup_requires']) for ep in pkg_resources.iter_entry_points('distutils.setup_keywords'): vars(self).setdefault(ep.name, None) - _Distribution.__init__(self,attrs) + _Distribution.__init__(self, attrs) if isinstance(self.metadata.version, numbers.Number): # Some people apparently take "version number" too literally :) self.metadata.version = str(self.metadata.version) @@ -301,9 +311,9 @@ class Distribution(_Distribution): self._finalize_features() return result - def _feature_attrname(self,name): + def _feature_attrname(self, name): """Convert feature name to corresponding option attribute name""" - return 'with_'+name.replace('-','_') + return 'with_'+name.replace('-', '_') def fetch_build_eggs(self, requires): """Resolve pre-setup requirements""" @@ -321,7 +331,7 @@ class Distribution(_Distribution): self._set_global_opts_from_features() for ep in pkg_resources.iter_entry_points('distutils.setup_keywords'): - value = getattr(self,ep.name,None) + value = getattr(self, ep.name, None) if value is not None: ep.require(installer=self.fetch_build_egg) ep.load()(self, ep.name, value) @@ -354,7 +364,7 @@ class Distribution(_Distribution): cmd.package_index.to_scan = [] except AttributeError: from setuptools.command.easy_install import easy_install - dist = self.__class__({'script_args':['easy_install']}) + dist = self.__class__({'script_args': ['easy_install']}) dist.parse_config_files() opts = dist.get_option_dict('easy_install') keep = ( @@ -385,8 +395,8 @@ class Distribution(_Distribution): go = [] no = self.negative_opt.copy() - for name,feature in self.features.items(): - self._set_feature(name,None) + for name, feature in self.features.items(): + self._set_feature(name, None) feature.validate(self) if feature.optional: @@ -407,25 +417,25 @@ class Distribution(_Distribution): """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(): + 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) + 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(): + for name, feature in self.features.items(): if not self.feature_is_included(name): feature.exclude_from(self) - self._set_feature(name,0) + self._set_feature(name, 0) def get_command_class(self, command): """Pluggable version of get_command_class()""" if command in self.cmdclass: return self.cmdclass[command] - for ep in pkg_resources.iter_entry_points('distutils.commands',command): + for ep in pkg_resources.iter_entry_points('distutils.commands', command): ep.require(installer=self.fetch_build_egg) self.cmdclass[command] = cmdclass = ep.load() return cmdclass @@ -448,15 +458,15 @@ class Distribution(_Distribution): self.cmdclass[ep.name] = cmdclass return _Distribution.get_command_list(self) - def _set_feature(self,name,status): + def _set_feature(self, name, status): """Set feature's inclusion status""" - setattr(self,self._feature_attrname(name),status) + setattr(self, self._feature_attrname(name), status) - def feature_is_included(self,name): + 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)) + return getattr(self, self._feature_attrname(name)) - def include_feature(self,name): + def include_feature(self, name): """Request inclusion of feature named 'name'""" if self.feature_is_included(name)==0: @@ -465,9 +475,9 @@ class Distribution(_Distribution): descr + " is required, but was excluded or is not available" ) self.features[name].include_in(self) - self._set_feature(name,1) + self._set_feature(name, 1) - def include(self,**attrs): + 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 @@ -482,14 +492,14 @@ class Distribution(_Distribution): 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(): + for k, v in attrs.items(): include = getattr(self, '_include_'+k, None) if include: include(v) else: - self._include_misc(k,v) + self._include_misc(k, v) - def exclude_package(self,package): + def exclude_package(self, package): """Remove packages, modules, and extensions in named package""" pfx = package+'.' @@ -511,7 +521,7 @@ class Distribution(_Distribution): if p.name != package and not p.name.startswith(pfx) ] - def has_contents_for(self,package): + def has_contents_for(self, package): """Return true if 'exclude_package(package)' would do something""" pfx = package+'.' @@ -520,48 +530,48 @@ class Distribution(_Distribution): if p==package or p.startswith(pfx): return True - def _exclude_misc(self,name,value): + def _exclude_misc(self, name, value): """Handle 'exclude()' for list/tuple attrs without a special handler""" - if not isinstance(value,sequence): + if not isinstance(value, sequence): raise DistutilsSetupError( "%s: setting must be a list or tuple (%r)" % (name, value) ) try: - old = getattr(self,name) + old = getattr(self, name) except AttributeError: raise DistutilsSetupError( "%s: No such distribution setting" % name ) - if old is not None and not isinstance(old,sequence): + 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]) + setattr(self, name, [item for item in old if item not in value]) - def _include_misc(self,name,value): + def _include_misc(self, name, value): """Handle 'include()' for list/tuple attrs without a special handler""" - if not isinstance(value,sequence): + if not isinstance(value, sequence): raise DistutilsSetupError( "%s: setting must be a list (%r)" % (name, value) ) try: - old = getattr(self,name) + 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): + 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]) + setattr(self, name, old+[item for item in value if item not in old]) - def exclude(self,**attrs): + 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 @@ -577,15 +587,15 @@ class Distribution(_Distribution): 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(): + for k, v in attrs.items(): exclude = getattr(self, '_exclude_'+k, None) if exclude: exclude(v) else: - self._exclude_misc(k,v) + self._exclude_misc(k, v) - def _exclude_packages(self,packages): - if not isinstance(packages,sequence): + def _exclude_packages(self, packages): + if not isinstance(packages, sequence): raise DistutilsSetupError( "packages: setting must be a list or tuple (%r)" % (packages,) ) @@ -600,17 +610,17 @@ class Distribution(_Distribution): command = args[0] aliases = self.get_option_dict('aliases') while command in aliases: - src,alias = aliases[command] + src, alias = aliases[command] del aliases[command] # ensure each alias can expand only once! import shlex - args[:1] = shlex.split(alias,True) + args[:1] = shlex.split(alias, True) command = args[0] nargs = _Distribution._parse_command_opts(self, parser, args) # Handle commands that want to consume all remaining arguments cmd_class = self.get_command_class(command) - if getattr(cmd_class,'command_consumes_arguments',None): + if getattr(cmd_class, 'command_consumes_arguments', None): self.get_option_dict(command)['args'] = ("command line", nargs) if nargs is not None: return [] @@ -629,20 +639,20 @@ class Distribution(_Distribution): d = {} - for cmd,opts in self.command_options.items(): + for cmd, opts in self.command_options.items(): - for opt,(src,val) in opts.items(): + for opt, (src, val) in opts.items(): if src != "command line": continue - opt = opt.replace('_','-') + 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(): + neg_opt.update(getattr(cmdobj, 'negative_opt', {})) + for neg, pos in neg_opt.items(): if pos==opt: opt=neg val=None @@ -653,7 +663,7 @@ class Distribution(_Distribution): elif val==1: val = None - d.setdefault(cmd,{})[opt] = val + d.setdefault(cmd, {})[opt] = val return d @@ -667,7 +677,7 @@ class Distribution(_Distribution): yield module for ext in self.ext_modules or (): - if isinstance(ext,tuple): + if isinstance(ext, tuple): name, buildinfo = ext else: name = ext.name @@ -790,16 +800,16 @@ class Feature: self.standard = standard self.available = available self.optional = optional - if isinstance(require_features,(str,Require)): + if isinstance(require_features, (str, Require)): require_features = require_features, self.require_features = [ - r for r in require_features if isinstance(r,str) + r for r in require_features if isinstance(r, str) ] - er = [r for r in require_features if not isinstance(r,str)] + er = [r for r in require_features if not isinstance(r, str)] if er: extras['require_features'] = er - if isinstance(remove,str): + if isinstance(remove, str): remove = remove, self.remove = remove self.extras = extras @@ -814,8 +824,7 @@ class Feature: """Should this feature be included by default?""" return self.available and self.standard - def include_in(self,dist): - + 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 @@ -835,8 +844,7 @@ class Feature: for f in self.require_features: dist.include_feature(f) - def exclude_from(self,dist): - + def exclude_from(self, dist): """Ensure feature is excluded from distribution You may override this in a subclass to perform additional operations on @@ -851,8 +859,7 @@ class Feature: for item in self.remove: dist.exclude_package(item) - def validate(self,dist): - + 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 diff --git a/setuptools/extension.py b/setuptools/extension.py index b9d68178..d265b7a3 100644 --- a/setuptools/extension.py +++ b/setuptools/extension.py @@ -14,6 +14,7 @@ _Extension = _get_unpatched(distutils.core.Extension) msvc.patch_for_specialized_compiler() + def _have_cython(): """ Return True if Cython can be imported. @@ -48,6 +49,7 @@ class Extension(_Extension): sub = functools.partial(re.sub, '.pyx$', target_ext) self.sources = list(map(sub, self.sources)) + class Library(Extension): """Just like a regular Extension, but built as a library instead""" diff --git a/setuptools/lib2to3_ex.py b/setuptools/lib2to3_ex.py index feef591a..f7296786 100644 --- a/setuptools/lib2to3_ex.py +++ b/setuptools/lib2to3_ex.py @@ -12,7 +12,9 @@ from distutils import log from lib2to3.refactor import RefactoringTool, get_fixers_from_package import setuptools + class DistutilsRefactoringTool(RefactoringTool): + def log_error(self, msg, *args, **kw): log.error(msg, *args) @@ -22,7 +24,9 @@ class DistutilsRefactoringTool(RefactoringTool): def log_debug(self, msg, *args): log.debug(msg, *args) + class Mixin2to3(_Mixin2to3): + def run_2to3(self, files, doctests = False): # See of the distribution option has been set, otherwise check the # setuptools default. diff --git a/setuptools/msvc.py b/setuptools/msvc.py index b543c568..012ab32c 100644 --- a/setuptools/msvc.py +++ b/setuptools/msvc.py @@ -769,6 +769,7 @@ class EnvironmentInfo: """ # Variables and properties in this class use originals CamelCase variables # names from Microsoft source files for more easy comparaison. + def __init__(self, arch, vc_ver=None, vc_min_ver=None): self.pi = PlatformInfo(arch) self.ri = RegistryInfo(self.pi) diff --git a/setuptools/package_index.py b/setuptools/package_index.py index e87504db..f3ee5ec0 100755 --- a/setuptools/package_index.py +++ b/setuptools/package_index.py @@ -37,7 +37,7 @@ PYPI_MD5 = re.compile( '<a href="([^"#]+)">([^<]+)</a>\n\s+\\(<a (?:title="MD5 hash"\n\s+)' 'href="[^?]+\?:action=show_md5&digest=([0-9a-f]{32})">md5</a>\\)' ) -URL_SCHEME = re.compile('([-+.a-z0-9]{2,}):',re.I).match +URL_SCHEME = re.compile('([-+.a-z0-9]{2,}):', re.I).match EXTENSIONS = ".tar.gz .tar.bz2 .tar .zip .tgz".split() __all__ = [ @@ -62,18 +62,18 @@ def parse_bdist_wininst(name): if lower.endswith('.win32.exe'): base = name[:-10] plat = 'win32' - elif lower.startswith('.win32-py',-16): + elif lower.startswith('.win32-py', -16): py_ver = name[-7:-4] base = name[:-16] plat = 'win32' elif lower.endswith('.win-amd64.exe'): base = name[:-14] plat = 'win-amd64' - elif lower.startswith('.win-amd64-py',-20): + elif lower.startswith('.win-amd64-py', -20): py_ver = name[-7:-4] base = name[:-20] plat = 'win-amd64' - return base,py_ver,plat + return base, py_ver, plat def egg_info_for_url(url): @@ -82,8 +82,9 @@ def egg_info_for_url(url): base = urllib.parse.unquote(path.split('/')[-1]) if server=='sourceforge.net' and base=='download': # XXX Yuck base = urllib.parse.unquote(path.split('/')[-2]) - if '#' in base: base, fragment = base.split('#',1) - return base,fragment + if '#' in base: base, fragment = base.split('#', 1) + return base, fragment + def distros_for_url(url, metadata=None): """Yield egg or source distribution objects that might be found at a URL""" @@ -97,6 +98,7 @@ def distros_for_url(url, metadata=None): ): yield dist + def distros_for_location(location, basename, metadata=None): """Yield egg or source distribution objects based on basename""" if basename.endswith('.egg.zip'): @@ -118,6 +120,7 @@ def distros_for_location(location, basename, metadata=None): return interpret_distro_name(location, basename, metadata) return [] # no extension matched + def distros_for_filename(filename, metadata=None): """Yield possible egg or source distribution objects based on a filename""" return distros_for_location( @@ -152,7 +155,7 @@ def interpret_distro_name( # it is a bdist_dumb, not an sdist -- bail out return - for p in range(1,len(parts)+1): + for p in range(1, len(parts)+1): yield Distribution( location, metadata, '-'.join(parts[:p]), '-'.join(parts[p:]), py_version=py_version, precedence = precedence, @@ -177,6 +180,7 @@ def unique_everseen(iterable, key=None): seen_add(k) yield element + def unique_values(func): """ Wrap a function returning an iterable such that the resulting iterable @@ -190,6 +194,7 @@ def unique_values(func): REL = re.compile("""<([^>]*\srel\s*=\s*['"]?([^'">]+)[^>]*)>""", re.I) # this line is here to fix emacs' cruddy broken syntax highlighting + @unique_values def find_external_links(url, page): """Find rel="homepage" and rel="download" links in `page`, yielding URLs""" @@ -204,7 +209,7 @@ def find_external_links(url, page): for tag in ("<th>Home Page", "<th>Download URL"): pos = page.find(tag) if pos!=-1: - match = HREF.search(page,pos) + match = HREF.search(page, pos) if match: yield urllib.parse.urljoin(url, htmldecode(match.group(1))) @@ -213,6 +218,7 @@ class ContentChecker(object): """ A null content checker that defines the interface for checking content """ + def feed(self, block): """ Feed a block of data to the hash. @@ -232,6 +238,7 @@ class ContentChecker(object): """ return + class HashChecker(ContentChecker): pattern = re.compile( r'(?P<hash_name>sha1|sha224|sha384|sha256|sha512|md5)=' @@ -272,12 +279,12 @@ class PackageIndex(Environment): self, index_url="https://pypi.python.org/simple", hosts=('*',), ca_bundle=None, verify_ssl=True, *args, **kw ): - Environment.__init__(self,*args,**kw) + Environment.__init__(self, *args, **kw) self.index_url = index_url + "/"[:not index_url.endswith('/')] self.scanned_urls = {} self.fetched_urls = {} self.package_pages = {} - self.allows = re.compile('|'.join(map(translate,hosts))).match + self.allows = re.compile('|'.join(map(translate, hosts))).match self.to_scan = [] if verify_ssl and ssl_support.is_available and (ca_bundle or ssl_support.find_ca_bundle()): self.opener = ssl_support.opener_for(ca_bundle) @@ -328,7 +335,7 @@ class PackageIndex(Environment): for match in HREF.finditer(page): link = urllib.parse.urljoin(base, htmldecode(match.group(1))) self.process_url(link) - if url.startswith(self.index_url) and getattr(f,'code',None)!=404: + if url.startswith(self.index_url) and getattr(f, 'code', None)!=404: page = self.process_index(url, page) def process_filename(self, fn, nested=False): @@ -340,7 +347,7 @@ class PackageIndex(Environment): if os.path.isdir(fn) and not nested: path = os.path.realpath(fn) for item in os.listdir(path): - self.process_filename(os.path.join(path,item), True) + self.process_filename(os.path.join(path, item), True) dists = distros_for_filename(fn) if dists: @@ -384,7 +391,7 @@ class PackageIndex(Environment): dist.precedence = SOURCE_DIST self.add(dist) - def process_index(self,url,page): + def process_index(self, url, page): """Process the contents of a PyPI page""" def scan(link): # Process a URL to see if it's for a package page @@ -396,7 +403,7 @@ class PackageIndex(Environment): # it's a package page, sanitize and index it pkg = safe_name(parts[0]) ver = safe_version(parts[1]) - self.package_pages.setdefault(pkg.lower(),{})[link] = True + self.package_pages.setdefault(pkg.lower(), {})[link] = True return to_filename(pkg), to_filename(ver) return None, None @@ -415,13 +422,13 @@ class PackageIndex(Environment): base, frag = egg_info_for_url(new_url) if base.endswith('.py') and not frag: if ver: - new_url+='#egg=%s-%s' % (pkg,ver) + new_url+='#egg=%s-%s' % (pkg, ver) else: self.need_version_info(url) self.scan_url(new_url) return PYPI_MD5.sub( - lambda m: '<a href="%s#md5=%s">%s</a>' % m.group(1,3,2), page + lambda m: '<a href="%s#md5=%s">%s</a>' % m.group(1, 3, 2), page ) else: return "" # no sense double-scanning non-package pages @@ -434,7 +441,7 @@ class PackageIndex(Environment): def scan_all(self, msg=None, *args): if self.index_url not in self.fetched_urls: - if msg: self.warn(msg,*args) + if msg: self.warn(msg, *args) self.info( "Scanning index of all packages (this may take a while)" ) @@ -451,7 +458,7 @@ class PackageIndex(Environment): # We couldn't find the target package, so search the index page too self.not_found_in_index(requirement) - for url in list(self.package_pages.get(requirement.key,())): + for url in list(self.package_pages.get(requirement.key, ())): # scan each page that might be related to the desired package self.scan_url(url) @@ -462,7 +469,7 @@ class PackageIndex(Environment): if dist in requirement: return dist self.debug("%s does not match %s", requirement, dist) - return super(PackageIndex, self).obtain(requirement,installer) + return super(PackageIndex, self).obtain(requirement, installer) def check_hash(self, checker, filename, tfp): """ @@ -527,14 +534,14 @@ class PackageIndex(Environment): of `tmpdir`, and the local filename is returned. Various errors may be raised if a problem occurs during downloading. """ - if not isinstance(spec,Requirement): + if not isinstance(spec, Requirement): scheme = URL_SCHEME(spec) if scheme: # It's a url, download it to tmpdir found = self._download_url(scheme.group(1), spec, tmpdir) base, fragment = egg_info_for_url(spec) if base.endswith('.py'): - found = self.gen_setup(found,fragment,tmpdir) + found = self.gen_setup(found, fragment, tmpdir) return found elif os.path.exists(spec): # Existing file or directory, just return it @@ -547,7 +554,7 @@ class PackageIndex(Environment): "Not a URL, existing file, or requirement spec: %r" % (spec,) ) - return getattr(self.fetch_distribution(spec, tmpdir),'location',None) + return getattr(self.fetch_distribution(spec, tmpdir), 'location', None) def fetch_distribution( self, requirement, tmpdir, force_scan=False, source=False, @@ -583,7 +590,7 @@ class PackageIndex(Environment): if dist.precedence==DEVELOP_DIST and not develop_ok: if dist not in skipped: - self.warn("Skipping development or system egg: %s",dist) + self.warn("Skipping development or system egg: %s", dist) skipped[dist] = 1 continue @@ -625,7 +632,7 @@ class PackageIndex(Environment): ``location`` of the downloaded distribution instead of a distribution object. """ - dist = self.fetch_distribution(requirement,tmpdir,force_scan,source) + dist = self.fetch_distribution(requirement, tmpdir, force_scan, source) if dist is not None: return dist.location return None @@ -663,7 +670,7 @@ class PackageIndex(Environment): raise DistutilsError( "Can't unambiguously interpret project/version identifier %r; " "any dashes in the name or version should be escaped using " - "underscores. %r" % (fragment,dists) + "underscores. %r" % (fragment, dists) ) else: raise DistutilsError( @@ -672,6 +679,7 @@ class PackageIndex(Environment): ) dl_blocksize = 8192 + def _download_to(self, url, filename): self.info("Downloading %s", url) # Download the file @@ -681,7 +689,7 @@ class PackageIndex(Environment): fp = self.open_url(strip_fragment(url)) if isinstance(fp, urllib.error.HTTPError): raise DistutilsError( - "Can't download %s: %s %s" % (url, fp.code,fp.msg) + "Can't download %s: %s %s" % (url, fp.code, fp.msg) ) headers = fp.info() blocknum = 0 @@ -692,7 +700,7 @@ class PackageIndex(Environment): sizes = get_all_headers(headers, 'Content-Length') size = max(map(int, sizes)) self.reporthook(url, filename, blocknum, bs, size) - with open(filename,'wb') as tfp: + with open(filename, 'wb') as tfp: while True: block = fp.read(bs) if block: @@ -751,14 +759,14 @@ class PackageIndex(Environment): name, fragment = egg_info_for_url(url) if name: while '..' in name: - name = name.replace('..','.').replace('\\','_') + name = name.replace('..', '.').replace('\\', '_') else: name = "__downloaded__" # default if URL has no path contents if name.endswith('.egg.zip'): name = name[:-4] # strip the extra .zip before download - filename = os.path.join(tmpdir,name) + filename = os.path.join(tmpdir, name) # Download the file # @@ -779,7 +787,7 @@ class PackageIndex(Environment): def _attempt_download(self, url, filename): headers = self._download_to(url, filename) - if 'html' in headers.get('content-type','').lower(): + if 'html' in headers.get('content-type', '').lower(): return self._download_html(url, headers, filename) else: return filename @@ -800,16 +808,16 @@ class PackageIndex(Environment): raise DistutilsError("Unexpected HTML page found at "+url) def _download_svn(self, url, filename): - url = url.split('#',1)[0] # remove any fragment for svn's sake + url = url.split('#', 1)[0] # remove any fragment for svn's sake creds = '' if url.lower().startswith('svn:') and '@' in url: scheme, netloc, path, p, q, f = urllib.parse.urlparse(url) if not netloc and path.startswith('//') and '/' in path[2:]: - netloc, path = path[2:].split('/',1) + netloc, path = path[2:].split('/', 1) auth, host = splituser(netloc) if auth: if ':' in auth: - user, pw = auth.split(':',1) + user, pw = auth.split(':', 1) creds = " --username=%s --password=%s" % (user, pw) else: creds = " --username="+auth @@ -827,7 +835,7 @@ class PackageIndex(Environment): scheme = scheme.split('+', 1)[-1] # Some fragment identification fails - path = path.split('#',1)[0] + path = path.split('#', 1)[0] rev = None if '@' in path: @@ -839,7 +847,7 @@ class PackageIndex(Environment): return url, rev def _download_git(self, url, filename): - filename = filename.split('#',1)[0] + filename = filename.split('#', 1)[0] url, rev = self._vcs_split_rev_from_url(url, pop_prefix=True) self.info("Doing git clone from %s to %s", url, filename) @@ -855,7 +863,7 @@ class PackageIndex(Environment): return filename def _download_hg(self, url, filename): - filename = filename.split('#',1)[0] + filename = filename.split('#', 1)[0] url, rev = self._vcs_split_rev_from_url(url, pop_prefix=True) self.info("Doing hg clone from %s to %s", url, filename) @@ -883,12 +891,14 @@ class PackageIndex(Environment): # references, a hexadecimal numeric reference, or a named reference). entity_sub = re.compile(r'&(#(\d+|x[\da-fA-F]+)|[\w.:-]+);?').sub + def uchr(c): if not isinstance(c, int): return c if c>255: return six.unichr(c) return chr(c) + def decode_entity(match): what = match.group(1) if what.startswith('#x'): @@ -899,10 +909,12 @@ def decode_entity(match): what = six.moves.html_entities.name2codepoint.get(what, match.group(0)) return uchr(what) + def htmldecode(text): """Decode HTML entities in the given text.""" return entity_sub(decode_entity, text) + def socket_timeout(timeout=15): def _socket_timeout(func): def _socket_timeout(*args, **kwargs): @@ -915,6 +927,7 @@ def socket_timeout(timeout=15): return _socket_timeout return _socket_timeout + def _encode_auth(auth): """ A function compatible with Python 2.3-3.3 that will encode @@ -935,12 +948,14 @@ def _encode_auth(auth): # convert back to a string encoded = encoded_bytes.decode() # strip the trailing carriage return - return encoded.replace('\n','') + return encoded.replace('\n', '') + class Credential(object): """ A username/password pair. Use like a namedtuple. """ + def __init__(self, username, password): self.username = username self.password = password @@ -952,6 +967,7 @@ class Credential(object): def __str__(self): return '%(username)s:%(password)s' % vars(self) + class PyPIConfig(configparser.RawConfigParser): def __init__(self): @@ -1042,6 +1058,7 @@ open_with_auth = socket_timeout(_SOCKET_TIMEOUT)(open_with_auth) def fix_sf_url(url): return url # backward compatibility + def local_open(url): """Read a local path, with special support for directories""" scheme, server, path, param, query, frag = urllib.parse.urlparse(url) diff --git a/setuptools/py26compat.py b/setuptools/py26compat.py index 40cbb88e..7c60c90e 100644 --- a/setuptools/py26compat.py +++ b/setuptools/py26compat.py @@ -9,6 +9,7 @@ try: except ImportError: from urllib import splittag + def strip_fragment(url): """ In `Python 8280 <http://bugs.python.org/issue8280>`_, Python 2.7 and @@ -18,5 +19,5 @@ def strip_fragment(url): url, fragment = splittag(url) return url -if sys.version_info >= (2,7): +if sys.version_info >= (2, 7): strip_fragment = lambda x: x diff --git a/setuptools/py27compat.py b/setuptools/py27compat.py index 702f7d65..66aecc2a 100644 --- a/setuptools/py27compat.py +++ b/setuptools/py27compat.py @@ -4,6 +4,7 @@ Compatibility Support for Python 2.7 and earlier import sys + def get_all_headers(message, key): """ Given an HTTPMessage, return all headers matching a given key. diff --git a/setuptools/py31compat.py b/setuptools/py31compat.py index 8fe6dd9d..04a314ef 100644 --- a/setuptools/py31compat.py +++ b/setuptools/py31compat.py @@ -8,6 +8,7 @@ try: from sysconfig import get_config_vars, get_path except ImportError: from distutils.sysconfig import get_config_vars, get_python_lib + def get_path(name): if name not in ('platlib', 'purelib'): raise ValueError("Name must be purelib or platlib") @@ -19,12 +20,14 @@ try: except ImportError: import shutil import tempfile + class TemporaryDirectory(object): """ Very simple temporary directory context manager. Will try to delete afterward, but will also ignore OS and similar errors on deletion. """ + def __init__(self): self.name = None # Handle mkdtemp raising an exception self.name = tempfile.mkdtemp() diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 23e296b1..c6bab096 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -29,6 +29,7 @@ __all__ = [ "AbstractSandbox", "DirectorySandbox", "SandboxViolation", "run_setup", ] + def _execfile(filename, globals, locals=None): """ Python 3 implementation of execfile. @@ -117,6 +118,7 @@ class ExceptionSaver: A Context Manager that will save an exception, serialized, and restore it later. """ + def __enter__(self): return self @@ -236,7 +238,8 @@ def run_setup(setup_script, args): sys.path.insert(0, setup_dir) # reset to include setup dir, w/clean callback list working_set.__init__() - working_set.callbacks.append(lambda dist:dist.activate()) + working_set.callbacks.append(lambda dist: dist.activate()) + def runner(): ns = dict(__file__=setup_script, __name__='__main__') _execfile(setup_script, ns) @@ -255,12 +258,12 @@ class AbstractSandbox: def __init__(self): self._attrs = [ name for name in dir(_os) - if not name.startswith('_') and hasattr(self,name) + if not name.startswith('_') and hasattr(self, name) ] def _copy(self, source): for name in self._attrs: - setattr(os, name, getattr(source,name)) + setattr(os, name, getattr(source, name)) def run(self, func): """Run 'func' under os sandboxing""" @@ -279,22 +282,24 @@ class AbstractSandbox: self._copy(_os) def _mk_dual_path_wrapper(name): - original = getattr(_os,name) - def wrap(self,src,dst,*args,**kw): + original = getattr(_os, name) + + def wrap(self, src, dst, *args, **kw): if self._active: - src,dst = self._remap_pair(name,src,dst,*args,**kw) - return original(src,dst,*args,**kw) + src, dst = self._remap_pair(name, src, dst, *args, **kw) + return original(src, dst, *args, **kw) return wrap for name in ["rename", "link", "symlink"]: - if hasattr(_os,name): locals()[name] = _mk_dual_path_wrapper(name) + if hasattr(_os, name): locals()[name] = _mk_dual_path_wrapper(name) def _mk_single_path_wrapper(name, original=None): - original = original or getattr(_os,name) - def wrap(self,path,*args,**kw): + original = original or getattr(_os, name) + + def wrap(self, path, *args, **kw): if self._active: - path = self._remap_input(name,path,*args,**kw) - return original(path,*args,**kw) + path = self._remap_input(name, path, *args, **kw) + return original(path, *args, **kw) return wrap if _file: @@ -305,49 +310,51 @@ class AbstractSandbox: "remove", "unlink", "rmdir", "utime", "lchown", "chroot", "lstat", "startfile", "mkfifo", "mknod", "pathconf", "access" ]: - if hasattr(_os,name): locals()[name] = _mk_single_path_wrapper(name) + if hasattr(_os, name): locals()[name] = _mk_single_path_wrapper(name) def _mk_single_with_return(name): - original = getattr(_os,name) - def wrap(self,path,*args,**kw): + original = getattr(_os, name) + + def wrap(self, path, *args, **kw): if self._active: - path = self._remap_input(name,path,*args,**kw) - return self._remap_output(name, original(path,*args,**kw)) - return original(path,*args,**kw) + path = self._remap_input(name, path, *args, **kw) + return self._remap_output(name, original(path, *args, **kw)) + return original(path, *args, **kw) return wrap for name in ['readlink', 'tempnam']: - if hasattr(_os,name): locals()[name] = _mk_single_with_return(name) + if hasattr(_os, name): locals()[name] = _mk_single_with_return(name) def _mk_query(name): - original = getattr(_os,name) - def wrap(self,*args,**kw): - retval = original(*args,**kw) + original = getattr(_os, name) + + def wrap(self, *args, **kw): + retval = original(*args, **kw) if self._active: return self._remap_output(name, retval) return retval return wrap for name in ['getcwd', 'tmpnam']: - if hasattr(_os,name): locals()[name] = _mk_query(name) + if hasattr(_os, name): locals()[name] = _mk_query(name) - def _validate_path(self,path): + def _validate_path(self, path): """Called to remap or validate any path, whether input or output""" return path - def _remap_input(self,operation,path,*args,**kw): + def _remap_input(self, operation, path, *args, **kw): """Called for path inputs""" return self._validate_path(path) - def _remap_output(self,operation,path): + def _remap_output(self, operation, path): """Called for path outputs""" return self._validate_path(path) - def _remap_pair(self,operation,src,dst,*args,**kw): + def _remap_pair(self, operation, src, dst, *args, **kw): """Called for path pairs like rename, link, and symlink operations""" return ( - self._remap_input(operation+'-from',src,*args,**kw), - self._remap_input(operation+'-to',dst,*args,**kw) + self._remap_input(operation+'-from', src, *args, **kw), + self._remap_input(operation+'-to', dst, *args, **kw) ) @@ -364,6 +371,7 @@ except ImportError: # it appears pywin32 is not installed, so no need to exclude. pass + class DirectorySandbox(AbstractSandbox): """Restrict operations to a single subdirectory - pseudo-chroot""" @@ -380,7 +388,7 @@ class DirectorySandbox(AbstractSandbox): def __init__(self, sandbox, exceptions=_EXCEPTIONS): self._sandbox = os.path.normcase(os.path.realpath(sandbox)) - self._prefix = os.path.join(self._sandbox,'') + self._prefix = os.path.join(self._sandbox, '') self._exceptions = [ os.path.normcase(os.path.realpath(path)) for path in exceptions @@ -395,12 +403,12 @@ class DirectorySandbox(AbstractSandbox): def _file(self, path, mode='r', *args, **kw): if mode not in ('r', 'rt', 'rb', 'rU', 'U') and not self._ok(path): self._violation("file", path, mode, *args, **kw) - return _file(path,mode,*args,**kw) + return _file(path, mode, *args, **kw) def _open(self, path, mode='r', *args, **kw): if mode not in ('r', 'rt', 'rb', 'rU', 'U') and not self._ok(path): self._violation("open", path, mode, *args, **kw) - return _open(path,mode,*args,**kw) + return _open(path, mode, *args, **kw) def tmpnam(self): self._violation("tmpnam") @@ -440,19 +448,20 @@ class DirectorySandbox(AbstractSandbox): """Called for path pairs like rename, link, and symlink operations""" if not self._ok(src) or not self._ok(dst): self._violation(operation, src, dst, *args, **kw) - return (src,dst) + return (src, dst) def open(self, file, flags, mode=0o777, *args, **kw): """Called for low-level os.open()""" if flags & WRITE_FLAGS and not self._ok(file): self._violation("os.open", file, flags, mode, *args, **kw) - return _os.open(file,flags,mode, *args, **kw) + return _os.open(file, flags, mode, *args, **kw) WRITE_FLAGS = functools.reduce( operator.or_, [getattr(_os, a, 0) for a in "O_WRONLY O_RDWR O_APPEND O_CREAT O_TRUNC O_TEMPORARY".split()] ) + class SandboxViolation(DistutilsError): """A setup script attempted to modify the filesystem outside the sandbox""" @@ -468,29 +477,4 @@ script by hand. Please inform the package's author and the EasyInstall maintainers to find out if a fix or workaround is available.""" % self.args - - - - - - - - - - - - - - - - - - - - - - - - - # diff --git a/setuptools/site-patch.py b/setuptools/site-patch.py index bb887ad0..680e9355 100644 --- a/setuptools/site-patch.py +++ b/setuptools/site-patch.py @@ -7,7 +7,7 @@ def __boot(): else: PYTHONPATH = PYTHONPATH.split(os.pathsep) - pic = getattr(sys,'path_importer_cache',{}) + pic = getattr(sys, 'path_importer_cache', {}) stdpath = sys.path[len(PYTHONPATH):] mydir = os.path.dirname(__file__) # print "searching",stdpath,sys.path @@ -25,14 +25,14 @@ def __boot(): else: try: import imp # Avoid import loop in Python >= 3.3 - stream, path, descr = imp.find_module('site',[item]) + stream, path, descr = imp.find_module('site', [item]) except ImportError: continue if stream is None: continue try: # This should actually reload the current module - imp.load_module('site',stream,path,descr) + imp.load_module('site', stream, path, descr) finally: stream.close() break @@ -41,9 +41,9 @@ def __boot(): # print "loaded", __file__ - known_paths = dict([(makepath(item)[1],1) for item in sys.path]) # 2.2 comp + known_paths = dict([(makepath(item)[1], 1) for item in sys.path]) # 2.2 comp - oldpos = getattr(sys,'__egginsert',0) # save old insertion position + oldpos = getattr(sys, '__egginsert', 0) # save old insertion position sys.__egginsert = 0 # and reset the current one for item in PYTHONPATH: diff --git a/setuptools/ssl_support.py b/setuptools/ssl_support.py index 657197cf..ecede509 100644 --- a/setuptools/ssl_support.py +++ b/setuptools/ssl_support.py @@ -161,6 +161,7 @@ class VerifyingHTTPSHandler(HTTPSHandler): class VerifyingHTTPSConn(HTTPSConnection): """Simple verifying connection: no auth, subclasses, timeouts, etc.""" + def __init__(self, host, ca_bundle, **kw): HTTPSConnection.__init__(self, host, **kw) self.ca_bundle = ca_bundle @@ -192,6 +193,7 @@ class VerifyingHTTPSConn(HTTPSConnection): self.sock.close() raise + def opener_for(ca_bundle=None): """Get a urlopen() replacement that uses ca_bundle for verification""" return urllib.request.build_opener( @@ -201,6 +203,7 @@ def opener_for(ca_bundle=None): _wincerts = None + def get_win_certfile(): global _wincerts if _wincerts is not None: @@ -212,6 +215,7 @@ def get_win_certfile(): return None class MyCertFile(CertFile): + def __init__(self, stores=(), certs=()): CertFile.__init__(self) for store in stores: diff --git a/setuptools/tests/__init__.py b/setuptools/tests/__init__.py index 32447356..a54ae7c9 100644 --- a/setuptools/tests/__init__.py +++ b/setuptools/tests/__init__.py @@ -27,7 +27,7 @@ def makeSetup(**args): distutils.core._setup_stop_after = "commandline" # Don't let system command line leak into tests! - args.setdefault('script_args',['install']) + args.setdefault('script_args', ['install']) try: return setuptools.setup(**args) @@ -40,6 +40,7 @@ needs_bytecode = pytest.mark.skipif( reason="bytecode support not available", ) + class TestDepends: def testExtractConst(self): @@ -55,35 +56,35 @@ class TestDepends: fc = six.get_function_code(f1) # unrecognized name - assert dep.extract_constant(fc,'q', -1) is None + assert dep.extract_constant(fc, 'q', -1) is None # constant assigned - dep.extract_constant(fc,'x', -1) == "test" + dep.extract_constant(fc, 'x', -1) == "test" # expression assigned - dep.extract_constant(fc,'y', -1) == -1 + dep.extract_constant(fc, 'y', -1) == -1 # recognized name, not assigned - dep.extract_constant(fc,'z', -1) is None + dep.extract_constant(fc, 'z', -1) is None def testFindModule(self): with pytest.raises(ImportError): dep.find_module('no-such.-thing') with pytest.raises(ImportError): dep.find_module('setuptools.non-existent') - f,p,i = dep.find_module('setuptools.tests') + f, p, i = dep.find_module('setuptools.tests') f.close() @needs_bytecode def testModuleExtract(self): from email import __version__ - assert dep.get_module_constant('email','__version__') == __version__ - assert dep.get_module_constant('sys','version') == sys.version - assert dep.get_module_constant('setuptools.tests','__doc__') == __doc__ + assert dep.get_module_constant('email', '__version__') == __version__ + assert dep.get_module_constant('sys', 'version') == sys.version + assert dep.get_module_constant('setuptools.tests', '__doc__') == __doc__ @needs_bytecode def testRequire(self): - req = Require('Email','1.0.3','email') + req = Require('Email', '1.0.3', 'email') assert req.name == 'Email' assert req.module == 'email' @@ -100,12 +101,12 @@ class TestDepends: assert req.is_present() assert req.is_current() - req = Require('Email 3000','03000','email',format=LooseVersion) + req = Require('Email 3000', '03000', 'email', format=LooseVersion) assert req.is_present() assert not req.is_current() assert not req.version_ok('unknown') - req = Require('Do-what-I-mean','1.0','d-w-i-m') + req = Require('Do-what-I-mean', '1.0', 'd-w-i-m') assert not req.is_present() assert not req.is_current() @@ -124,22 +125,22 @@ class TestDepends: class TestDistro: def setup_method(self, method): - self.e1 = Extension('bar.ext',['bar.c']) + 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'], + py_modules=['b.d', 'x'], ext_modules = (self.e1, self.e2), package_dir = {}, ) def testDistroType(self): - assert isinstance(self.dist,setuptools.dist.Distribution) + assert isinstance(self.dist, setuptools.dist.Distribution) def testExcludePackage(self): self.dist.exclude_package('a') - assert self.dist.packages == ['b','c'] + assert self.dist.packages == ['b', 'c'] self.dist.exclude_package('b') assert self.dist.packages == ['c'] @@ -168,7 +169,7 @@ class TestDistro: assert self.dist.ext_modules == [self.e2, self.e1] def testExcludePackages(self): - self.dist.exclude(packages=['c','b','a']) + self.dist.exclude(packages=['c', 'b', 'a']) assert self.dist.packages == [] assert self.dist.py_modules == ['x'] assert self.dist.ext_modules == [self.e1] @@ -198,13 +199,13 @@ class TestDistro: with pytest.raises(DistutilsSetupError): self.dist.exclude(nonexistent_option='x') with pytest.raises(DistutilsSetupError): - self.dist.include(packages={'x':'y'}) + self.dist.include(packages={'x': 'y'}) with pytest.raises(DistutilsSetupError): - self.dist.exclude(packages={'x':'y'}) + self.dist.exclude(packages={'x': 'y'}) with pytest.raises(DistutilsSetupError): - self.dist.include(ext_modules={'x':'y'}) + self.dist.include(ext_modules={'x': 'y'}) with pytest.raises(DistutilsSetupError): - self.dist.exclude(ext_modules={'x':'y'}) + self.dist.exclude(ext_modules={'x': 'y'}) with pytest.raises(DistutilsSetupError): self.dist.include(package_dir=['q']) @@ -215,31 +216,31 @@ class TestDistro: class TestFeatures: def setup_method(self, method): - self.req = Require('Distutils','1.0.3','distutils') + self.req = Require('Distutils', '1.0.3', 'distutils') self.dist = makeSetup( features={ - 'foo': Feature("foo",standard=True,require_features=['baz',self.req]), + 'foo': Feature("foo", standard=True, require_features=['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')] + 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'])] + ext_modules = [Extension('bar.ext', ['bar.c'])] ) def testDefaults(self): assert not Feature( - "test",standard=True,remove='x',available=False + "test", standard=True, remove='x', available=False ).include_by_default() - assert Feature("test",standard=True,remove='x').include_by_default() + assert Feature("test", standard=True, remove='x').include_by_default() # Feature must have either kwargs, removes, or require_features with pytest.raises(DistutilsSetupError): Feature("test") @@ -251,16 +252,16 @@ class TestFeatures: def testFeatureOptions(self): dist = self.dist assert ( - ('with-dwim',None,'include DWIM') in dist.feature_options + ('with-dwim', None, 'include DWIM') in dist.feature_options ) assert ( - ('without-dwim',None,'exclude DWIM (default)') in dist.feature_options + ('without-dwim', None, 'exclude DWIM (default)') in dist.feature_options ) assert ( - ('with-bar',None,'include bar (default)') in dist.feature_options + ('with-bar', None, 'include bar (default)') in dist.feature_options ) assert ( - ('without-bar',None,'exclude bar') in dist.feature_options + ('without-bar', None, 'exclude bar') in dist.feature_options ) assert dist.feature_negopt['without-foo'] == 'with-foo' assert dist.feature_negopt['without-bar'] == 'with-bar' @@ -276,7 +277,7 @@ class TestFeatures: assert (not 'pkg.bar' in dist.packages) assert ('pkg.baz' in dist.packages) assert ('scripts/baz_it' in dist.scripts) - assert (('libfoo','foo/foofoo.c') in dist.libraries) + assert (('libfoo', 'foo/foofoo.c') in dist.libraries) assert dist.ext_modules == [] assert dist.require_features == [self.req] @@ -287,7 +288,8 @@ class TestFeatures: def testFeatureWithInvalidRemove(self): with pytest.raises(SystemExit): - makeSetup(features={'x':Feature('x', remove='y')}) + makeSetup(features={'x': Feature('x', remove='y')}) + class TestCommandTests: @@ -296,7 +298,7 @@ class TestCommandTests: assert (isinstance(test_cmd, distutils.cmd.Command)) def testLongOptSuiteWNoDefault(self): - ts1 = makeSetup(script_args=['test','--test-suite=foo.tests.suite']) + ts1 = makeSetup(script_args=['test', '--test-suite=foo.tests.suite']) ts1 = ts1.get_command_obj('test') ts1.ensure_finalized() assert ts1.test_suite == 'foo.tests.suite' @@ -309,7 +311,7 @@ class TestCommandTests: def testDefaultWModuleOnCmdLine(self): ts3 = makeSetup( test_suite='bar.tests', - script_args=['test','-m','foo.tests'] + script_args=['test', '-m', 'foo.tests'] ).get_command_obj('test') ts3.ensure_finalized() assert ts3.test_module == 'foo.tests' @@ -317,7 +319,7 @@ class TestCommandTests: def testConflictingOptions(self): ts4 = makeSetup( - script_args=['test','-m','bar.tests', '-s','foo.tests.suite'] + script_args=['test', '-m', 'bar.tests', '-s', 'foo.tests.suite'] ).get_command_obj('test') with pytest.raises(DistutilsOptionError): ts4.ensure_finalized() @@ -325,4 +327,4 @@ class TestCommandTests: def testNoSuite(self): ts5 = makeSetup().get_command_obj('test') ts5.ensure_finalized() - assert ts5.test_suite == None + assert ts5.test_suite is None diff --git a/setuptools/tests/contexts.py b/setuptools/tests/contexts.py index ae28c7c3..535ae107 100644 --- a/setuptools/tests/contexts.py +++ b/setuptools/tests/contexts.py @@ -10,7 +10,7 @@ import pkg_resources @contextlib.contextmanager -def tempdir(cd=lambda dir:None, **kwargs): +def tempdir(cd=lambda dir: None, **kwargs): temp_dir = tempfile.mkdtemp(**kwargs) orig_dir = os.getcwd() try: diff --git a/setuptools/tests/py26compat.py b/setuptools/tests/py26compat.py index 7211f275..5325dad6 100644 --- a/setuptools/tests/py26compat.py +++ b/setuptools/tests/py26compat.py @@ -2,6 +2,7 @@ import sys import tarfile import contextlib + def _tarfile_open_ex(*args, **kwargs): """ Extend result as a context manager. diff --git a/setuptools/tests/server.py b/setuptools/tests/server.py index 6a687937..9e5fefb7 100644 --- a/setuptools/tests/server.py +++ b/setuptools/tests/server.py @@ -18,6 +18,7 @@ class IndexServer(BaseHTTPServer.HTTPServer): # The index files should be located in setuptools/tests/indexes s.stop() """ + def __init__(self, server_address=('', 0), RequestHandlerClass=SimpleHTTPServer.SimpleHTTPRequestHandler): BaseHTTPServer.HTTPServer.__init__(self, server_address, @@ -42,16 +43,20 @@ class IndexServer(BaseHTTPServer.HTTPServer): port = self.server_port return 'http://127.0.0.1:%s/setuptools/tests/indexes/' % port + class RequestRecorder(BaseHTTPServer.BaseHTTPRequestHandler): + def do_GET(self): requests = vars(self.server).setdefault('requests', []) requests.append(self) self.send_response(200, 'OK') + class MockServer(BaseHTTPServer.HTTPServer, threading.Thread): """ A simple HTTP Server that records the requests made to it. """ + def __init__(self, server_address=('', 0), RequestHandlerClass=RequestRecorder): BaseHTTPServer.HTTPServer.__init__(self, server_address, diff --git a/setuptools/tests/test_bdist_egg.py b/setuptools/tests/test_bdist_egg.py index ccfb2ea7..a7ceac86 100644 --- a/setuptools/tests/test_bdist_egg.py +++ b/setuptools/tests/test_bdist_egg.py @@ -15,6 +15,7 @@ from setuptools import setup setup(name='foo', py_modules=['hi']) """ + @pytest.yield_fixture def setup_context(tmpdir): with (tmpdir/'setup.py').open('w') as f: diff --git a/setuptools/tests/test_build_ext.py b/setuptools/tests/test_build_ext.py index 0719ba44..5168ebf0 100644 --- a/setuptools/tests/test_build_ext.py +++ b/setuptools/tests/test_build_ext.py @@ -3,7 +3,9 @@ import distutils.command.build_ext as orig from setuptools.command.build_ext import build_ext from setuptools.dist import Distribution + class TestBuildExt: + def test_get_ext_filename(self): """ Setuptools needs to give back the same diff --git a/setuptools/tests/test_develop.py b/setuptools/tests/test_develop.py index 1b844499..d22e5e4a 100644 --- a/setuptools/tests/test_develop.py +++ b/setuptools/tests/test_develop.py @@ -26,6 +26,7 @@ setup(name='foo', INIT_PY = """print "foo" """ + @pytest.yield_fixture def temp_user(monkeypatch): with contexts.tempdir() as user_base: @@ -54,6 +55,7 @@ def test_env(tmpdir, temp_user): class TestDevelop: in_virtualenv = hasattr(sys, 'real_prefix') in_venv = hasattr(sys, 'base_prefix') and sys.base_prefix != sys.prefix + @pytest.mark.skipif(in_virtualenv or in_venv, reason="Cannot run when invoked in a virtualenv or venv") def test_2to3_user_mode(self, test_env): diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index fd06b6ef..894c4fd8 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -41,6 +41,7 @@ from .textwrap import DALS class FakeDist(object): + def get_entry_map(self, group): if group != 'console_scripts': return {} @@ -55,6 +56,7 @@ SETUP_PY = DALS(""" setup(name='foo') """) + class TestEasyInstallTest: def test_install_site_py(self, tmpdir): @@ -133,6 +135,7 @@ class TestEasyInstallTest: class TestPTHFileWriter: + def test_add_from_cwd_site_sets_dirty(self): '''a pth file manager should set dirty if a distribution is in site but also the cwd @@ -266,6 +269,7 @@ def distutils_package(): class TestDistutilsPackage: + def test_bdist_egg_available_on_distutils_pkg(self, distutils_package): run_setup('setup.py', ['bdist_egg']) @@ -557,6 +561,7 @@ class TestScriptHeader: class TestCommandSpec: + def test_custom_launch_command(self): """ Show how a custom CommandSpec could be used to specify a #! executable @@ -601,6 +606,7 @@ class TestCommandSpec: class TestWindowsScriptWriter: + def test_header(self): hdr = ei.WindowsScriptWriter.get_script_header('') assert hdr.startswith('#!') diff --git a/setuptools/tests/test_egg_info.py b/setuptools/tests/test_egg_info.py index 3a0db58f..afbda2cc 100644 --- a/setuptools/tests/test_egg_info.py +++ b/setuptools/tests/test_egg_info.py @@ -235,6 +235,7 @@ class TestEggInfo(object): def _find_egg_info_files(self, root): class DirList(list): + def __init__(self, files, base): super(DirList, self).__init__(files) self.base = base diff --git a/setuptools/tests/test_find_packages.py b/setuptools/tests/test_find_packages.py index 06a7c02e..df51b04f 100644 --- a/setuptools/tests/test_find_packages.py +++ b/setuptools/tests/test_find_packages.py @@ -13,6 +13,8 @@ from setuptools import find_packages find_420_packages = setuptools.PEP420PackageFinder.find # modeled after CPython's test.support.can_symlink + + def can_symlink(): TESTFN = tempfile.mktemp() symlink_path = TESTFN + "can_symlink" @@ -26,13 +28,15 @@ def can_symlink(): globals().update(can_symlink=lambda: can) return can + def has_symlink(): bad_symlink = ( # Windows symlink directory detection is broken on Python 3.2 - platform.system() == 'Windows' and sys.version_info[:2] == (3,2) + platform.system() == 'Windows' and sys.version_info[:2] == (3, 2) ) return can_symlink() and not bad_symlink + class TestFindPackages: def setup_method(self, method): diff --git a/setuptools/tests/test_packageindex.py b/setuptools/tests/test_packageindex.py index 6a76b5fc..61f5909b 100644 --- a/setuptools/tests/test_packageindex.py +++ b/setuptools/tests/test_packageindex.py @@ -209,6 +209,7 @@ class TestContentCheckers: class TestPyPIConfig: + def test_percent_in_password(self, tmpdir, monkeypatch): monkeypatch.setitem(os.environ, 'HOME', str(tmpdir)) pypirc = tmpdir / '.pypirc' diff --git a/setuptools/tests/test_sandbox.py b/setuptools/tests/test_sandbox.py index fefd46f7..aa6138e4 100644 --- a/setuptools/tests/test_sandbox.py +++ b/setuptools/tests/test_sandbox.py @@ -57,6 +57,7 @@ class TestSandbox: class TestExceptionSaver: + def test_exception_trapped(self): with setuptools.sandbox.ExceptionSaver(): raise ValueError("details") diff --git a/setuptools/tests/test_sdist.py b/setuptools/tests/test_sdist.py index d2a1f1bb..16d0eb07 100644 --- a/setuptools/tests/test_sdist.py +++ b/setuptools/tests/test_sdist.py @@ -132,7 +132,6 @@ class TestSdistTest: assert os.path.join('sdist_test', 'b.txt') in manifest assert os.path.join('sdist_test', 'c.rst') not in manifest - def test_defaults_case_sensitivity(self): """ Make sure default files (README.*, etc.) are added in a case-sensitive diff --git a/setuptools/utils.py b/setuptools/utils.py index 91e4b87f..080b9a8e 100644 --- a/setuptools/utils.py +++ b/setuptools/utils.py @@ -3,9 +3,9 @@ import os.path def cs_path_exists(fspath): - if not os.path.exists(fspath): + if not os.path.exists(fspath): return False # make absolute so we always have a directory abspath = os.path.abspath(fspath) directory, filename = os.path.split(abspath) - return filename in os.listdir(directory)
\ No newline at end of file + return filename in os.listdir(directory) diff --git a/tests/manual_test.py b/tests/manual_test.py index 808fa55a..0904b607 100644 --- a/tests/manual_test.py +++ b/tests/manual_test.py @@ -10,9 +10,11 @@ from string import Template from six.moves import urllib + def _system_call(*args): assert subprocess.call(args) == 0 + def tempdir(func): def _tempdir(*args, **kwargs): test_dir = tempfile.mkdtemp() @@ -62,6 +64,7 @@ def test_virtualenv(): res = f.read() assert 'setuptools' in res + @tempdir def test_full(): """virtualenv + pip + buildout""" |