aboutsummaryrefslogtreecommitdiffstats
path: root/setuptools/__init__.py
blob: 05a14329fd209caa5cde78c3bd0c69ef9e7f6866 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
"""Extensions to the 'distutils' for large or complex distributions"""

import os
import sys
import distutils.core
import distutils.filelist
from distutils.core import Command as _Command
from distutils.util import convert_path
from fnmatch import fnmatchcase

import setuptools.version
from setuptools.extension import Extension
from setuptools.dist import Distribution, Feature, _get_unpatched
from setuptools.depends import Require
from setuptools.compat import filterfalse

__all__ = [
    'setup', 'Distribution', 'Feature', 'Command', 'Extension', 'Require',
    'find_packages'
]

__version__ = setuptools.version.__version__

bootstrap_install_from = None

# If we run 2to3 on .py files, should we also convert docstrings?
# Default: yes; assume that we can detect doctests reliably
run_2to3_on_doctests = True
# Standard package names for fixer packages
lib2to3_fixer_packages = ['lib2to3.fixes']

def find_packages(where='.', exclude=(), include=('*',)):
    """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.  'exclude' is a
    sequence of package names to exclude; '*' can be used as a wildcard in the
    names, such that 'foo.*' will exclude all subpackages of 'foo' (but not
    'foo' itself).

    'include' is a sequence of package names to include.  If it's specified,
    only the named packages will be included.  If it's not specified, all found
    packages will be included.  'include' can contain shell style wildcard
    patterns just like 'exclude'.

    The list of included packages is built up first and then any explicitly
    excluded packages are removed from it.
    """
    out = _find_packages_iter(convert_path(where))
    includes = _build_filter(*include)
    excludes = _build_filter('ez_setup', '*__pycache__', *exclude)
    out = filter(includes, out)
    out = filterfalse(excludes, out)
    return list(out)

def _all_dirs(base_path):
    """
    Return all dirs in base_path, relative to base_path
    """
    for root, dirs, files in os.walk(base_path):
        for dir in dirs:
            yield os.path.relpath(os.path.join(root, dir), base_path)

def _find_packages_iter(base_path):
    dirs = _all_dirs(base_path)
    suitable = filterfalse(lambda n: '.' in n, dirs)
    packages = (
        path
        for path in suitable
        if _looks_like_package(os.path.join(base_path, path))
    )
    for pkg_path in packages:
        yield pkg_path.replace(os.path.sep, '.')

def _looks_like_package(path):
    return (
        os.path.isfile(os.path.join(path, '__init__.py'))
        or sys.version_info[:2] >= (3, 3)  # PEP 420
    )

def _build_filter(*patterns):
    """
    Given a list of patterns, return a callable that will be true only if
    the input matches one of the patterns.
    """
    return lambda name: any(fnmatchcase(name, pat=pat) for pat in patterns)

setup = distutils.core.setup

_Command = _get_unpatched(_Command)

class Command(_Command):
    __doc__ = _Command.__doc__

    command_consumes_arguments = False

    def __init__(self, dist, **kw):
        # Add support for keyword arguments
        _Command.__init__(self,dist)
        for k,v in kw.items():
            setattr(self,k,v)

    def reinitialize_command(self, command, reinit_subcommands=0, **kw):
        cmd = _Command.reinitialize_command(self, command, reinit_subcommands)
        for k,v in kw.items():
            setattr(cmd,k,v)    # update command with keywords
        return cmd

distutils.core.Command = Command    # we can't patch distutils.cmd, alas

def findall(dir = os.curdir):
    """Find all files under 'dir' and return the list of full filenames
    (relative to 'dir').
    """
    all_files = []
    for base, dirs, files in os.walk(dir):
        if base==os.curdir or base.startswith(os.curdir+os.sep):
            base = base[2:]
        if base:
            files = [os.path.join(base, f) for f in files]
        all_files.extend(filter(os.path.isfile, files))
    return all_files

distutils.filelist.findall = findall    # fix findall bug in distutils.

# sys.dont_write_bytecode was introduced in Python 2.6.
_dont_write_bytecode = getattr(sys, 'dont_write_bytecode',
    bool(os.environ.get("PYTHONDONTWRITEBYTECODE")))