Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/setuptools/__init__.py: 51%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

105 statements  

1"""Extensions to the 'distutils' for large or complex distributions""" 

2 

3import os 

4import sys 

5import functools 

6import distutils.core 

7import distutils.filelist 

8import re 

9from distutils.errors import DistutilsOptionError 

10from distutils.util import convert_path 

11from fnmatch import fnmatchcase 

12 

13from ._deprecation_warning import SetuptoolsDeprecationWarning 

14 

15from setuptools.extern.six import PY3, string_types 

16from setuptools.extern.six.moves import filter, map 

17 

18import setuptools.version 

19from setuptools.extension import Extension 

20from setuptools.dist import Distribution, Feature 

21from setuptools.depends import Require 

22from . import monkey 

23 

24__metaclass__ = type 

25 

26 

27__all__ = [ 

28 'setup', 'Distribution', 'Feature', 'Command', 'Extension', 'Require', 

29 'SetuptoolsDeprecationWarning', 

30 'find_packages' 

31] 

32 

33if PY3: 

34 __all__.append('find_namespace_packages') 

35 

36__version__ = setuptools.version.__version__ 

37 

38bootstrap_install_from = None 

39 

40# If we run 2to3 on .py files, should we also convert docstrings? 

41# Default: yes; assume that we can detect doctests reliably 

42run_2to3_on_doctests = True 

43# Standard package names for fixer packages 

44lib2to3_fixer_packages = ['lib2to3.fixes'] 

45 

46 

47class PackageFinder: 

48 """ 

49 Generate a list of all Python packages found within a directory 

50 """ 

51 

52 @classmethod 

53 def find(cls, where='.', exclude=(), include=('*',)): 

54 """Return a list all Python packages found within directory 'where' 

55 

56 'where' is the root directory which will be searched for packages. It 

57 should be supplied as a "cross-platform" (i.e. URL-style) path; it will 

58 be converted to the appropriate local path syntax. 

59 

60 'exclude' is a sequence of package names to exclude; '*' can be used 

61 as a wildcard in the names, such that 'foo.*' will exclude all 

62 subpackages of 'foo' (but not 'foo' itself). 

63 

64 'include' is a sequence of package names to include. If it's 

65 specified, only the named packages will be included. If it's not 

66 specified, all found packages will be included. 'include' can contain 

67 shell style wildcard patterns just like 'exclude'. 

68 """ 

69 

70 return list(cls._find_packages_iter( 

71 convert_path(where), 

72 cls._build_filter('ez_setup', '*__pycache__', *exclude), 

73 cls._build_filter(*include))) 

74 

75 @classmethod 

76 def _find_packages_iter(cls, where, exclude, include): 

77 """ 

78 All the packages found in 'where' that pass the 'include' filter, but 

79 not the 'exclude' filter. 

80 """ 

81 for root, dirs, files in os.walk(where, followlinks=True): 

82 # Copy dirs to iterate over it, then empty dirs. 

83 all_dirs = dirs[:] 

84 dirs[:] = [] 

85 

86 for dir in all_dirs: 

87 full_path = os.path.join(root, dir) 

88 rel_path = os.path.relpath(full_path, where) 

89 package = rel_path.replace(os.path.sep, '.') 

90 

91 # Skip directory trees that are not valid packages 

92 if ('.' in dir or not cls._looks_like_package(full_path)): 

93 continue 

94 

95 # Should this package be included? 

96 if include(package) and not exclude(package): 

97 yield package 

98 

99 # Keep searching subdirectories, as there may be more packages 

100 # down there, even if the parent was excluded. 

101 dirs.append(dir) 

102 

103 @staticmethod 

104 def _looks_like_package(path): 

105 """Does a directory look like a package?""" 

106 return os.path.isfile(os.path.join(path, '__init__.py')) 

107 

108 @staticmethod 

109 def _build_filter(*patterns): 

110 """ 

111 Given a list of patterns, return a callable that will be true only if 

112 the input matches at least one of the patterns. 

113 """ 

114 return lambda name: any(fnmatchcase(name, pat=pat) for pat in patterns) 

115 

116 

117class PEP420PackageFinder(PackageFinder): 

118 @staticmethod 

119 def _looks_like_package(path): 

120 return True 

121 

122 

123find_packages = PackageFinder.find 

124 

125if PY3: 

126 find_namespace_packages = PEP420PackageFinder.find 

127 

128 

129def _install_setup_requires(attrs): 

130 # Note: do not use `setuptools.Distribution` directly, as 

131 # our PEP 517 backend patch `distutils.core.Distribution`. 

132 dist = distutils.core.Distribution(dict( 

133 (k, v) for k, v in attrs.items() 

134 if k in ('dependency_links', 'setup_requires') 

135 )) 

136 # Honor setup.cfg's options. 

137 dist.parse_config_files(ignore_option_errors=True) 

138 if dist.setup_requires: 

139 dist.fetch_build_eggs(dist.setup_requires) 

140 

141 

142def setup(**attrs): 

143 # Make sure we have any requirements needed to interpret 'attrs'. 

144 _install_setup_requires(attrs) 

145 return distutils.core.setup(**attrs) 

146 

147setup.__doc__ = distutils.core.setup.__doc__ 

148 

149 

150_Command = monkey.get_unpatched(distutils.core.Command) 

151 

152 

153class Command(_Command): 

154 __doc__ = _Command.__doc__ 

155 

156 command_consumes_arguments = False 

157 

158 def __init__(self, dist, **kw): 

159 """ 

160 Construct the command for dist, updating 

161 vars(self) with any keyword parameters. 

162 """ 

163 _Command.__init__(self, dist) 

164 vars(self).update(kw) 

165 

166 def _ensure_stringlike(self, option, what, default=None): 

167 val = getattr(self, option) 

168 if val is None: 

169 setattr(self, option, default) 

170 return default 

171 elif not isinstance(val, string_types): 

172 raise DistutilsOptionError("'%s' must be a %s (got `%s`)" 

173 % (option, what, val)) 

174 return val 

175 

176 def ensure_string_list(self, option): 

177 r"""Ensure that 'option' is a list of strings. If 'option' is 

178 currently a string, we split it either on /,\s*/ or /\s+/, so 

179 "foo bar baz", "foo,bar,baz", and "foo, bar baz" all become 

180 ["foo", "bar", "baz"]. 

181 """ 

182 val = getattr(self, option) 

183 if val is None: 

184 return 

185 elif isinstance(val, string_types): 

186 setattr(self, option, re.split(r',\s*|\s+', val)) 

187 else: 

188 if isinstance(val, list): 

189 ok = all(isinstance(v, string_types) for v in val) 

190 else: 

191 ok = False 

192 if not ok: 

193 raise DistutilsOptionError( 

194 "'%s' must be a list of strings (got %r)" 

195 % (option, val)) 

196 

197 def reinitialize_command(self, command, reinit_subcommands=0, **kw): 

198 cmd = _Command.reinitialize_command(self, command, reinit_subcommands) 

199 vars(cmd).update(kw) 

200 return cmd 

201 

202 

203def _find_all_simple(path): 

204 """ 

205 Find all files under 'path' 

206 """ 

207 results = ( 

208 os.path.join(base, file) 

209 for base, dirs, files in os.walk(path, followlinks=True) 

210 for file in files 

211 ) 

212 return filter(os.path.isfile, results) 

213 

214 

215def findall(dir=os.curdir): 

216 """ 

217 Find all files under 'dir' and return the list of full filenames. 

218 Unless dir is '.', return full filenames with dir prepended. 

219 """ 

220 files = _find_all_simple(dir) 

221 if dir == os.curdir: 

222 make_rel = functools.partial(os.path.relpath, start=dir) 

223 files = map(make_rel, files) 

224 return list(files) 

225 

226 

227# Apply monkey patches 

228monkey.patch_all()