|
8 | 8 | # This needs to be the very first thing to use distribute |
9 | 9 | from distribute_setup import use_setuptools |
10 | 10 | use_setuptools() |
| 11 | +from setuptools.command.test import test as TestCommand |
11 | 12 |
|
12 | 13 | import sys |
13 | 14 |
|
|
121 | 122 | 'Topic :: Scientific/Engineering :: Visualization', |
122 | 123 | ] |
123 | 124 |
|
| 125 | + |
| 126 | +class NoseTestCommand(TestCommand): |
| 127 | + """Invoke unit tests using nose after an in-place build.""" |
| 128 | + |
| 129 | + description = "Invoke unit tests using nose after an in-place build." |
| 130 | + user_options = [ |
| 131 | + ("pep8-only", None, "pep8 checks"), |
| 132 | + ("omit-pep8", None, "Do not perform pep8 checks"), |
| 133 | + ("nocapture", None, "do not capture stdout (nosetests)"), |
| 134 | + ("nose-verbose", None, "be verbose (nosetests)"), |
| 135 | + ("processes=", None, "number of processes (nosetests)"), |
| 136 | + ("process-timeout=", None, "process timeout (nosetests)"), |
| 137 | + ("with-coverage", None, "with coverage"), |
| 138 | + ("detailed-error-msg", None, "detailed error message (nosetest)"), |
| 139 | + ("tests=", None, "comma separated selection of tests (nosetest)"), |
| 140 | + ] |
| 141 | + |
| 142 | + def initialize_options(self): |
| 143 | + self.pep8_only = None |
| 144 | + self.omit_pep8 = None |
| 145 | + |
| 146 | + # parameters passed to nose tests |
| 147 | + self.processes = None |
| 148 | + self.process_timeout = None |
| 149 | + self.nose_verbose = None |
| 150 | + self.nocapture = None |
| 151 | + self.with_coverage = None |
| 152 | + self.detailed_error_msg = None |
| 153 | + self.tests = None |
| 154 | + |
| 155 | + def finalize_options(self): |
| 156 | + self.test_args = [] |
| 157 | + if self.pep8_only: |
| 158 | + self.pep8_only = True |
| 159 | + if self.omit_pep8: |
| 160 | + self.omit_pep8 = True |
| 161 | + |
| 162 | + if self.pep8_only and self.omit_pep8: |
| 163 | + from distutils.errors import DistutilsOptionError |
| 164 | + raise DistutilsOptionError( |
| 165 | + "You are using several options for the test command in an " |
| 166 | + "incompatible manner. Please use either --pep8-only or " |
| 167 | + "--omit-pep8" |
| 168 | + ) |
| 169 | + |
| 170 | + if self.processes: |
| 171 | + self.test_args.append("--processes={prc}".format( |
| 172 | + prc=self.processes)) |
| 173 | + |
| 174 | + if self.process_timeout: |
| 175 | + self.test_args.append("--process-timeout={tout}".format( |
| 176 | + tout=self.process_timeout)) |
| 177 | + |
| 178 | + if self.nose_verbose: |
| 179 | + self.test_args.append("--verbose") |
| 180 | + |
| 181 | + if self.nocapture: |
| 182 | + self.test_args.append("--nocapture") |
| 183 | + |
| 184 | + if self.with_coverage: |
| 185 | + self.test_args.append("--with-coverage") |
| 186 | + |
| 187 | + if self.detailed_error_msg: |
| 188 | + self.test_args.append("-d") |
| 189 | + |
| 190 | + if self.tests: |
| 191 | + self.test_args.append("--tests={names}".format(names=self.tests)) |
| 192 | + |
| 193 | + |
| 194 | + def run(self): |
| 195 | + if self.distribution.install_requires: |
| 196 | + self.distribution.fetch_build_eggs( |
| 197 | + self.distribution.install_requires) |
| 198 | + if self.distribution.tests_require: |
| 199 | + self.distribution.fetch_build_eggs(self.distribution.tests_require) |
| 200 | + |
| 201 | + self.announce('running unittests with nose') |
| 202 | + self.with_project_on_sys_path(self.run_tests) |
| 203 | + |
| 204 | + |
| 205 | + def run_tests(self): |
| 206 | + import matplotlib |
| 207 | + matplotlib.use('agg') |
| 208 | + import nose |
| 209 | + from matplotlib.testing.noseclasses import KnownFailure |
| 210 | + from matplotlib import default_test_modules as testmodules |
| 211 | + from matplotlib import font_manager |
| 212 | + import time |
| 213 | + # Make sure the font caches are created before starting any possibly |
| 214 | + # parallel tests |
| 215 | + if font_manager._fmcache is not None: |
| 216 | + while not os.path.exists(font_manager._fmcache): |
| 217 | + time.sleep(0.5) |
| 218 | + plugins = [KnownFailure] |
| 219 | + |
| 220 | + # Nose doesn't automatically instantiate all of the plugins in the |
| 221 | + # child processes, so we have to provide the multiprocess plugin |
| 222 | + # with a list. |
| 223 | + from nose.plugins import multiprocess |
| 224 | + multiprocess._instantiate_plugins = plugins |
| 225 | + |
| 226 | + if self.omit_pep8: |
| 227 | + testmodules.remove('matplotlib.tests.test_coding_standards') |
| 228 | + elif self.pep8_only: |
| 229 | + testmodules = ['matplotlib.tests.test_coding_standards'] |
| 230 | + |
| 231 | + nose.main(addplugins=[x() for x in plugins], |
| 232 | + defaultTest=testmodules, |
| 233 | + argv=['nosetests'] + self.test_args, |
| 234 | + exit=False) |
| 235 | + |
| 236 | + |
124 | 237 | # One doesn't normally see `if __name__ == '__main__'` blocks in a setup.py, |
125 | 238 | # however, this is needed on Windows to avoid creating infinite subprocesses |
126 | 239 | # when using multiprocessing. |
|
135 | 248 | package_dir = {'': 'lib'} |
136 | 249 | install_requires = [] |
137 | 250 | setup_requires = [] |
| 251 | + tests_require = [] |
138 | 252 | default_backend = None |
139 | 253 |
|
140 | 254 | # Go through all of the packages and figure out which ones we are |
|
195 | 309 | package_data[key] = list(set(val + package_data[key])) |
196 | 310 | install_requires.extend(package.get_install_requires()) |
197 | 311 | setup_requires.extend(package.get_setup_requires()) |
| 312 | + tests_require.extend(package.get_tests_require()) |
198 | 313 |
|
199 | 314 | # Write the default matplotlibrc file |
200 | 315 | if default_backend is None: |
|
254 | 369 | # List third-party Python packages that we require |
255 | 370 | install_requires=install_requires, |
256 | 371 | setup_requires=setup_requires, |
| 372 | + tests_require=tests_require, |
257 | 373 |
|
258 | 374 | # matplotlib has C/C++ extensions, so it's not zip safe. |
259 | 375 | # Telling setuptools this prevents it from doing an automatic |
260 | 376 | # check for zip safety. |
261 | 377 | zip_safe=False, |
| 378 | + cmdclass={'test': NoseTestCommand}, |
262 | 379 |
|
263 | 380 | **extra_args |
264 | 381 | ) |
0 commit comments