Path: blob/master/venv/Lib/site-packages/setuptools/__init__.py
811 views
"""Extensions to the 'distutils' for large or complex distributions"""12import os3import functools45# Disabled for now due to: #2228, #22306# import setuptools.distutils_patch # noqa: F40178import distutils.core9import distutils.filelist10import re11from distutils.errors import DistutilsOptionError12from distutils.util import convert_path13from fnmatch import fnmatchcase1415from ._deprecation_warning import SetuptoolsDeprecationWarning1617from setuptools.extern.six import PY3, string_types18from setuptools.extern.six.moves import filter, map1920import setuptools.version21from setuptools.extension import Extension22from setuptools.dist import Distribution23from setuptools.depends import Require24from . import monkey2526__metaclass__ = type272829__all__ = [30'setup', 'Distribution', 'Command', 'Extension', 'Require',31'SetuptoolsDeprecationWarning',32'find_packages'33]3435if PY3:36__all__.append('find_namespace_packages')3738__version__ = setuptools.version.__version__3940bootstrap_install_from = None4142# If we run 2to3 on .py files, should we also convert docstrings?43# Default: yes; assume that we can detect doctests reliably44run_2to3_on_doctests = True45# Standard package names for fixer packages46lib2to3_fixer_packages = ['lib2to3.fixes']474849class PackageFinder:50"""51Generate a list of all Python packages found within a directory52"""5354@classmethod55def find(cls, where='.', exclude=(), include=('*',)):56"""Return a list all Python packages found within directory 'where'5758'where' is the root directory which will be searched for packages. It59should be supplied as a "cross-platform" (i.e. URL-style) path; it will60be converted to the appropriate local path syntax.6162'exclude' is a sequence of package names to exclude; '*' can be used63as a wildcard in the names, such that 'foo.*' will exclude all64subpackages of 'foo' (but not 'foo' itself).6566'include' is a sequence of package names to include. If it's67specified, only the named packages will be included. If it's not68specified, all found packages will be included. 'include' can contain69shell style wildcard patterns just like 'exclude'.70"""7172return list(cls._find_packages_iter(73convert_path(where),74cls._build_filter('ez_setup', '*__pycache__', *exclude),75cls._build_filter(*include)))7677@classmethod78def _find_packages_iter(cls, where, exclude, include):79"""80All the packages found in 'where' that pass the 'include' filter, but81not the 'exclude' filter.82"""83for root, dirs, files in os.walk(where, followlinks=True):84# Copy dirs to iterate over it, then empty dirs.85all_dirs = dirs[:]86dirs[:] = []8788for dir in all_dirs:89full_path = os.path.join(root, dir)90rel_path = os.path.relpath(full_path, where)91package = rel_path.replace(os.path.sep, '.')9293# Skip directory trees that are not valid packages94if ('.' in dir or not cls._looks_like_package(full_path)):95continue9697# Should this package be included?98if include(package) and not exclude(package):99yield package100101# Keep searching subdirectories, as there may be more packages102# down there, even if the parent was excluded.103dirs.append(dir)104105@staticmethod106def _looks_like_package(path):107"""Does a directory look like a package?"""108return os.path.isfile(os.path.join(path, '__init__.py'))109110@staticmethod111def _build_filter(*patterns):112"""113Given a list of patterns, return a callable that will be true only if114the input matches at least one of the patterns.115"""116return lambda name: any(fnmatchcase(name, pat=pat) for pat in patterns)117118119class PEP420PackageFinder(PackageFinder):120@staticmethod121def _looks_like_package(path):122return True123124125find_packages = PackageFinder.find126127if PY3:128find_namespace_packages = PEP420PackageFinder.find129130131def _install_setup_requires(attrs):132# Note: do not use `setuptools.Distribution` directly, as133# our PEP 517 backend patch `distutils.core.Distribution`.134class MinimalDistribution(distutils.core.Distribution):135"""136A minimal version of a distribution for supporting the137fetch_build_eggs interface.138"""139def __init__(self, attrs):140_incl = 'dependency_links', 'setup_requires'141filtered = {142k: attrs[k]143for k in set(_incl) & set(attrs)144}145distutils.core.Distribution.__init__(self, filtered)146147def finalize_options(self):148"""149Disable finalize_options to avoid building the working set.150Ref #2158.151"""152153dist = MinimalDistribution(attrs)154155# Honor setup.cfg's options.156dist.parse_config_files(ignore_option_errors=True)157if dist.setup_requires:158dist.fetch_build_eggs(dist.setup_requires)159160161def setup(**attrs):162# Make sure we have any requirements needed to interpret 'attrs'.163_install_setup_requires(attrs)164return distutils.core.setup(**attrs)165166167setup.__doc__ = distutils.core.setup.__doc__168169170_Command = monkey.get_unpatched(distutils.core.Command)171172173class Command(_Command):174__doc__ = _Command.__doc__175176command_consumes_arguments = False177178def __init__(self, dist, **kw):179"""180Construct the command for dist, updating181vars(self) with any keyword parameters.182"""183_Command.__init__(self, dist)184vars(self).update(kw)185186def _ensure_stringlike(self, option, what, default=None):187val = getattr(self, option)188if val is None:189setattr(self, option, default)190return default191elif not isinstance(val, string_types):192raise DistutilsOptionError("'%s' must be a %s (got `%s`)"193% (option, what, val))194return val195196def ensure_string_list(self, option):197r"""Ensure that 'option' is a list of strings. If 'option' is198currently a string, we split it either on /,\s*/ or /\s+/, so199"foo bar baz", "foo,bar,baz", and "foo, bar baz" all become200["foo", "bar", "baz"].201"""202val = getattr(self, option)203if val is None:204return205elif isinstance(val, string_types):206setattr(self, option, re.split(r',\s*|\s+', val))207else:208if isinstance(val, list):209ok = all(isinstance(v, string_types) for v in val)210else:211ok = False212if not ok:213raise DistutilsOptionError(214"'%s' must be a list of strings (got %r)"215% (option, val))216217def reinitialize_command(self, command, reinit_subcommands=0, **kw):218cmd = _Command.reinitialize_command(self, command, reinit_subcommands)219vars(cmd).update(kw)220return cmd221222223def _find_all_simple(path):224"""225Find all files under 'path'226"""227results = (228os.path.join(base, file)229for base, dirs, files in os.walk(path, followlinks=True)230for file in files231)232return filter(os.path.isfile, results)233234235def findall(dir=os.curdir):236"""237Find all files under 'dir' and return the list of full filenames.238Unless dir is '.', return full filenames with dir prepended.239"""240files = _find_all_simple(dir)241if dir == os.curdir:242make_rel = functools.partial(os.path.relpath, start=dir)243files = map(make_rel, files)244return list(files)245246247class sic(str):248"""Treat this string as-is (https://en.wikipedia.org/wiki/Sic)"""249250251# Apply monkey patches252monkey.patch_all()253254255