|
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 one of --pep8-only," |
| 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 | + try: |
| 207 | + import matplotlib |
| 208 | + matplotlib.use('agg') |
| 209 | + import nose |
| 210 | + from matplotlib.testing.noseclasses import KnownFailure |
| 211 | + from matplotlib import default_test_modules as testmodules |
| 212 | + from matplotlib import font_manager |
| 213 | + import time |
| 214 | + # Make sure the font caches are created before starting any possibly |
| 215 | + # parallel tests |
| 216 | + if font_manager._fmcache is not None: |
| 217 | + while not os.path.exists(font_manager._fmcache): |
| 218 | + time.sleep(0.5) |
| 219 | + plugins = [KnownFailure] |
| 220 | + |
| 221 | + # Nose doesn't automatically instantiate all of the plugins in the |
| 222 | + # child processes, so we have to provide the multiprocess plugin |
| 223 | + # with a list. |
| 224 | + from nose.plugins import multiprocess |
| 225 | + multiprocess._instantiate_plugins = plugins |
| 226 | + |
| 227 | + if self.omit_pep8: |
| 228 | + testmodules.remove('matplotlib.tests.test_coding_standards') |
| 229 | + elif self.pep8_only: |
| 230 | + testmodules = ['matplotlib.tests.test_coding_standards'] |
| 231 | + |
| 232 | + nose.main(addplugins=[x() for x in plugins], |
| 233 | + defaultTest=testmodules, |
| 234 | + argv=['nosetests'] + self.test_args, |
| 235 | + exit=False) |
| 236 | + except ImportError: |
| 237 | + sys.exit(-1) |
| 238 | + |
| 239 | + |
124 | 240 | # One doesn't normally see `if __name__ == '__main__'` blocks in a setup.py,
|
125 | 241 | # however, this is needed on Windows to avoid creating infinite subprocesses
|
126 | 242 | # when using multiprocessing.
|
|
135 | 251 | package_dir = {'': 'lib'}
|
136 | 252 | install_requires = []
|
137 | 253 | setup_requires = []
|
| 254 | + tests_require = [] |
138 | 255 | default_backend = None
|
139 | 256 |
|
140 | 257 | # Go through all of the packages and figure out which ones we are
|
|
195 | 312 | package_data[key] = list(set(val + package_data[key]))
|
196 | 313 | install_requires.extend(package.get_install_requires())
|
197 | 314 | setup_requires.extend(package.get_setup_requires())
|
| 315 | + tests_require.extend(package.get_tests_require()) |
198 | 316 |
|
199 | 317 | # Write the default matplotlibrc file
|
200 | 318 | if default_backend is None:
|
|
254 | 372 | # List third-party Python packages that we require
|
255 | 373 | install_requires=install_requires,
|
256 | 374 | setup_requires=setup_requires,
|
| 375 | + tests_require=tests_require, |
257 | 376 |
|
258 | 377 | # matplotlib has C/C++ extensions, so it's not zip safe.
|
259 | 378 | # Telling setuptools this prevents it from doing an automatic
|
260 | 379 | # check for zip safety.
|
261 | 380 | zip_safe=False,
|
| 381 | + cmdclass={'test': NoseTestCommand}, |
262 | 382 |
|
263 | 383 | **extra_args
|
264 | 384 | )
|
0 commit comments