Mercurial > repos > shellac > sam_consensus_v3
comparison env/lib/python3.9/site-packages/setuptools/command/test.py @ 0:4f3585e2f14b draft default tip
"planemo upload commit 60cee0fc7c0cda8592644e1aad72851dec82c959"
author | shellac |
---|---|
date | Mon, 22 Mar 2021 18:12:50 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4f3585e2f14b |
---|---|
1 import os | |
2 import operator | |
3 import sys | |
4 import contextlib | |
5 import itertools | |
6 import unittest | |
7 from distutils.errors import DistutilsError, DistutilsOptionError | |
8 from distutils import log | |
9 from unittest import TestLoader | |
10 | |
11 from pkg_resources import (resource_listdir, resource_exists, normalize_path, | |
12 working_set, _namespace_packages, evaluate_marker, | |
13 add_activation_listener, require, EntryPoint) | |
14 from setuptools import Command | |
15 from .build_py import _unique_everseen | |
16 | |
17 | |
18 class ScanningLoader(TestLoader): | |
19 | |
20 def __init__(self): | |
21 TestLoader.__init__(self) | |
22 self._visited = set() | |
23 | |
24 def loadTestsFromModule(self, module, pattern=None): | |
25 """Return a suite of all tests cases contained in the given module | |
26 | |
27 If the module is a package, load tests from all the modules in it. | |
28 If the module has an ``additional_tests`` function, call it and add | |
29 the return value to the tests. | |
30 """ | |
31 if module in self._visited: | |
32 return None | |
33 self._visited.add(module) | |
34 | |
35 tests = [] | |
36 tests.append(TestLoader.loadTestsFromModule(self, module)) | |
37 | |
38 if hasattr(module, "additional_tests"): | |
39 tests.append(module.additional_tests()) | |
40 | |
41 if hasattr(module, '__path__'): | |
42 for file in resource_listdir(module.__name__, ''): | |
43 if file.endswith('.py') and file != '__init__.py': | |
44 submodule = module.__name__ + '.' + file[:-3] | |
45 else: | |
46 if resource_exists(module.__name__, file + '/__init__.py'): | |
47 submodule = module.__name__ + '.' + file | |
48 else: | |
49 continue | |
50 tests.append(self.loadTestsFromName(submodule)) | |
51 | |
52 if len(tests) != 1: | |
53 return self.suiteClass(tests) | |
54 else: | |
55 return tests[0] # don't create a nested suite for only one return | |
56 | |
57 | |
58 # adapted from jaraco.classes.properties:NonDataProperty | |
59 class NonDataProperty: | |
60 def __init__(self, fget): | |
61 self.fget = fget | |
62 | |
63 def __get__(self, obj, objtype=None): | |
64 if obj is None: | |
65 return self | |
66 return self.fget(obj) | |
67 | |
68 | |
69 class test(Command): | |
70 """Command to run unit tests after in-place build""" | |
71 | |
72 description = "run unit tests after in-place build (deprecated)" | |
73 | |
74 user_options = [ | |
75 ('test-module=', 'm', "Run 'test_suite' in specified module"), | |
76 ('test-suite=', 's', | |
77 "Run single test, case or suite (e.g. 'module.test_suite')"), | |
78 ('test-runner=', 'r', "Test runner to use"), | |
79 ] | |
80 | |
81 def initialize_options(self): | |
82 self.test_suite = None | |
83 self.test_module = None | |
84 self.test_loader = None | |
85 self.test_runner = None | |
86 | |
87 def finalize_options(self): | |
88 | |
89 if self.test_suite and self.test_module: | |
90 msg = "You may specify a module or a suite, but not both" | |
91 raise DistutilsOptionError(msg) | |
92 | |
93 if self.test_suite is None: | |
94 if self.test_module is None: | |
95 self.test_suite = self.distribution.test_suite | |
96 else: | |
97 self.test_suite = self.test_module + ".test_suite" | |
98 | |
99 if self.test_loader is None: | |
100 self.test_loader = getattr(self.distribution, 'test_loader', None) | |
101 if self.test_loader is None: | |
102 self.test_loader = "setuptools.command.test:ScanningLoader" | |
103 if self.test_runner is None: | |
104 self.test_runner = getattr(self.distribution, 'test_runner', None) | |
105 | |
106 @NonDataProperty | |
107 def test_args(self): | |
108 return list(self._test_args()) | |
109 | |
110 def _test_args(self): | |
111 if not self.test_suite and sys.version_info >= (2, 7): | |
112 yield 'discover' | |
113 if self.verbose: | |
114 yield '--verbose' | |
115 if self.test_suite: | |
116 yield self.test_suite | |
117 | |
118 def with_project_on_sys_path(self, func): | |
119 """ | |
120 Backward compatibility for project_on_sys_path context. | |
121 """ | |
122 with self.project_on_sys_path(): | |
123 func() | |
124 | |
125 @contextlib.contextmanager | |
126 def project_on_sys_path(self, include_dists=[]): | |
127 with_2to3 = getattr(self.distribution, 'use_2to3', False) | |
128 | |
129 if with_2to3: | |
130 # If we run 2to3 we can not do this inplace: | |
131 | |
132 # Ensure metadata is up-to-date | |
133 self.reinitialize_command('build_py', inplace=0) | |
134 self.run_command('build_py') | |
135 bpy_cmd = self.get_finalized_command("build_py") | |
136 build_path = normalize_path(bpy_cmd.build_lib) | |
137 | |
138 # Build extensions | |
139 self.reinitialize_command('egg_info', egg_base=build_path) | |
140 self.run_command('egg_info') | |
141 | |
142 self.reinitialize_command('build_ext', inplace=0) | |
143 self.run_command('build_ext') | |
144 else: | |
145 # Without 2to3 inplace works fine: | |
146 self.run_command('egg_info') | |
147 | |
148 # Build extensions in-place | |
149 self.reinitialize_command('build_ext', inplace=1) | |
150 self.run_command('build_ext') | |
151 | |
152 ei_cmd = self.get_finalized_command("egg_info") | |
153 | |
154 old_path = sys.path[:] | |
155 old_modules = sys.modules.copy() | |
156 | |
157 try: | |
158 project_path = normalize_path(ei_cmd.egg_base) | |
159 sys.path.insert(0, project_path) | |
160 working_set.__init__() | |
161 add_activation_listener(lambda dist: dist.activate()) | |
162 require('%s==%s' % (ei_cmd.egg_name, ei_cmd.egg_version)) | |
163 with self.paths_on_pythonpath([project_path]): | |
164 yield | |
165 finally: | |
166 sys.path[:] = old_path | |
167 sys.modules.clear() | |
168 sys.modules.update(old_modules) | |
169 working_set.__init__() | |
170 | |
171 @staticmethod | |
172 @contextlib.contextmanager | |
173 def paths_on_pythonpath(paths): | |
174 """ | |
175 Add the indicated paths to the head of the PYTHONPATH environment | |
176 variable so that subprocesses will also see the packages at | |
177 these paths. | |
178 | |
179 Do this in a context that restores the value on exit. | |
180 """ | |
181 nothing = object() | |
182 orig_pythonpath = os.environ.get('PYTHONPATH', nothing) | |
183 current_pythonpath = os.environ.get('PYTHONPATH', '') | |
184 try: | |
185 prefix = os.pathsep.join(_unique_everseen(paths)) | |
186 to_join = filter(None, [prefix, current_pythonpath]) | |
187 new_path = os.pathsep.join(to_join) | |
188 if new_path: | |
189 os.environ['PYTHONPATH'] = new_path | |
190 yield | |
191 finally: | |
192 if orig_pythonpath is nothing: | |
193 os.environ.pop('PYTHONPATH', None) | |
194 else: | |
195 os.environ['PYTHONPATH'] = orig_pythonpath | |
196 | |
197 @staticmethod | |
198 def install_dists(dist): | |
199 """ | |
200 Install the requirements indicated by self.distribution and | |
201 return an iterable of the dists that were built. | |
202 """ | |
203 ir_d = dist.fetch_build_eggs(dist.install_requires) | |
204 tr_d = dist.fetch_build_eggs(dist.tests_require or []) | |
205 er_d = dist.fetch_build_eggs( | |
206 v for k, v in dist.extras_require.items() | |
207 if k.startswith(':') and evaluate_marker(k[1:]) | |
208 ) | |
209 return itertools.chain(ir_d, tr_d, er_d) | |
210 | |
211 def run(self): | |
212 self.announce( | |
213 "WARNING: Testing via this command is deprecated and will be " | |
214 "removed in a future version. Users looking for a generic test " | |
215 "entry point independent of test runner are encouraged to use " | |
216 "tox.", | |
217 log.WARN, | |
218 ) | |
219 | |
220 installed_dists = self.install_dists(self.distribution) | |
221 | |
222 cmd = ' '.join(self._argv) | |
223 if self.dry_run: | |
224 self.announce('skipping "%s" (dry run)' % cmd) | |
225 return | |
226 | |
227 self.announce('running "%s"' % cmd) | |
228 | |
229 paths = map(operator.attrgetter('location'), installed_dists) | |
230 with self.paths_on_pythonpath(paths): | |
231 with self.project_on_sys_path(): | |
232 self.run_tests() | |
233 | |
234 def run_tests(self): | |
235 # Purge modules under test from sys.modules. The test loader will | |
236 # re-import them from the build location. Required when 2to3 is used | |
237 # with namespace packages. | |
238 if getattr(self.distribution, 'use_2to3', False): | |
239 module = self.test_suite.split('.')[0] | |
240 if module in _namespace_packages: | |
241 del_modules = [] | |
242 if module in sys.modules: | |
243 del_modules.append(module) | |
244 module += '.' | |
245 for name in sys.modules: | |
246 if name.startswith(module): | |
247 del_modules.append(name) | |
248 list(map(sys.modules.__delitem__, del_modules)) | |
249 | |
250 test = unittest.main( | |
251 None, None, self._argv, | |
252 testLoader=self._resolve_as_ep(self.test_loader), | |
253 testRunner=self._resolve_as_ep(self.test_runner), | |
254 exit=False, | |
255 ) | |
256 if not test.result.wasSuccessful(): | |
257 msg = 'Test failed: %s' % test.result | |
258 self.announce(msg, log.ERROR) | |
259 raise DistutilsError(msg) | |
260 | |
261 @property | |
262 def _argv(self): | |
263 return ['unittest'] + self.test_args | |
264 | |
265 @staticmethod | |
266 def _resolve_as_ep(val): | |
267 """ | |
268 Load the indicated attribute value, called, as a as if it were | |
269 specified as an entry point. | |
270 """ | |
271 if val is None: | |
272 return | |
273 parsed = EntryPoint.parse("x=" + val) | |
274 return parsed.resolve()() |