|
| 1 | +""" |
| 2 | +Nose test running. |
| 3 | +
|
| 4 | +This module implements ``test()`` function for pandas modules. |
| 5 | +
|
| 6 | +""" |
| 7 | +from __future__ import division, absolute_import, print_function |
| 8 | + |
| 9 | +import os |
| 10 | +import sys |
| 11 | +import warnings |
| 12 | +from pandas.compat import string_types |
| 13 | +from numpy.testing import nosetester |
| 14 | + |
| 15 | + |
| 16 | +def get_package_name(filepath): |
| 17 | + """ |
| 18 | + Given a path where a package is installed, determine its name. |
| 19 | +
|
| 20 | + Parameters |
| 21 | + ---------- |
| 22 | + filepath : str |
| 23 | + Path to a file. If the determination fails, "pandas" is returned. |
| 24 | +
|
| 25 | + Examples |
| 26 | + -------- |
| 27 | + >>> pandas.util.nosetester.get_package_name('nonsense') |
| 28 | + 'pandas' |
| 29 | +
|
| 30 | + """ |
| 31 | + |
| 32 | + pkg_name = [] |
| 33 | + while 'site-packages' in filepath or 'dist-packages' in filepath: |
| 34 | + filepath, p2 = os.path.split(filepath) |
| 35 | + if p2 in ('site-packages', 'dist-packages'): |
| 36 | + break |
| 37 | + pkg_name.append(p2) |
| 38 | + |
| 39 | + # if package name determination failed, just default to pandas |
| 40 | + if not pkg_name: |
| 41 | + return "pandas" |
| 42 | + |
| 43 | + # otherwise, reverse to get correct order and return |
| 44 | + pkg_name.reverse() |
| 45 | + |
| 46 | + # don't include the outer egg directory |
| 47 | + if pkg_name[0].endswith('.egg'): |
| 48 | + pkg_name.pop(0) |
| 49 | + |
| 50 | + return '.'.join(pkg_name) |
| 51 | + |
| 52 | +import_nose = nosetester.import_nose |
| 53 | +run_module_suite = nosetester.run_module_suite |
| 54 | + |
| 55 | + |
| 56 | +class NoseTester(nosetester.NoseTester): |
| 57 | + """ |
| 58 | + Nose test runner. |
| 59 | +
|
| 60 | + This class is made available as pandas.util.nosetester.NoseTester, and |
| 61 | + a test function is typically added to a package's __init__.py like so:: |
| 62 | +
|
| 63 | + from numpy.testing import Tester |
| 64 | + test = Tester().test |
| 65 | +
|
| 66 | + Calling this test function finds and runs all tests associated with the |
| 67 | + package and all its sub-packages. |
| 68 | +
|
| 69 | + Attributes |
| 70 | + ---------- |
| 71 | + package_path : str |
| 72 | + Full path to the package to test. |
| 73 | + package_name : str |
| 74 | + Name of the package to test. |
| 75 | +
|
| 76 | + Parameters |
| 77 | + ---------- |
| 78 | + package : module, str or None, optional |
| 79 | + The package to test. If a string, this should be the full path to |
| 80 | + the package. If None (default), `package` is set to the module from |
| 81 | + which `NoseTester` is initialized. |
| 82 | + raise_warnings : None, str or sequence of warnings, optional |
| 83 | + This specifies which warnings to configure as 'raise' instead |
| 84 | + of 'warn' during the test execution. Valid strings are: |
| 85 | +
|
| 86 | + - "develop" : equals ``(DeprecationWarning, RuntimeWarning)`` |
| 87 | + - "release" : equals ``()``, don't raise on any warnings. |
| 88 | +
|
| 89 | + See Notes for more details. |
| 90 | +
|
| 91 | + Notes |
| 92 | + ----- |
| 93 | + The default for `raise_warnings` is |
| 94 | + ``(DeprecationWarning, RuntimeWarning)`` for development versions of |
| 95 | + pandas, and ``()`` for released versions. The purpose of this switching |
| 96 | + behavior is to catch as many warnings as possible during development, but |
| 97 | + not give problems for packaging of released versions. |
| 98 | +
|
| 99 | + """ |
| 100 | + excludes = [] |
| 101 | + |
| 102 | + def _show_system_info(self): |
| 103 | + nose = import_nose() |
| 104 | + |
| 105 | + import pandas |
| 106 | + print("pandas version %s" % pandas.__version__) |
| 107 | + import numpy |
| 108 | + print("numpy version %s" % numpy.__version__) |
| 109 | + pddir = os.path.dirname(pandas.__file__) |
| 110 | + print("pandas is installed in %s" % pddir) |
| 111 | + |
| 112 | + pyversion = sys.version.replace('\n', '') |
| 113 | + print("Python version %s" % pyversion) |
| 114 | + print("nose version %d.%d.%d" % nose.__versioninfo__) |
| 115 | + |
| 116 | + def _get_custom_doctester(self): |
| 117 | + """ Return instantiated plugin for doctests |
| 118 | +
|
| 119 | + Allows subclassing of this class to override doctester |
| 120 | +
|
| 121 | + A return value of None means use the nose builtin doctest plugin |
| 122 | + """ |
| 123 | + return None |
| 124 | + |
| 125 | + def test(self, label='fast', verbose=1, extra_argv=None, |
| 126 | + doctests=False, coverage=False, raise_warnings=None): |
| 127 | + """ |
| 128 | + Run tests for module using nose. |
| 129 | +
|
| 130 | + Parameters |
| 131 | + ---------- |
| 132 | + label : {'fast', 'full', '', attribute identifier}, optional |
| 133 | + Identifies the tests to run. This can be a string to pass to |
| 134 | + the nosetests executable with the '-A' option, or one of several |
| 135 | + special values. Special values are: |
| 136 | + * 'fast' - the default - which corresponds to the ``nosetests -A`` |
| 137 | + option of 'not slow'. |
| 138 | + * 'full' - fast (as above) and slow tests as in the |
| 139 | + 'no -A' option to nosetests - this is the same as ''. |
| 140 | + * None or '' - run all tests. |
| 141 | + attribute_identifier - string passed directly to nosetests as '-A'. |
| 142 | + verbose : int, optional |
| 143 | + Verbosity value for test outputs, in the range 1-10. Default is 1. |
| 144 | + extra_argv : list, optional |
| 145 | + List with any extra arguments to pass to nosetests. |
| 146 | + doctests : bool, optional |
| 147 | + If True, run doctests in module. Default is False. |
| 148 | + coverage : bool, optional |
| 149 | + If True, report coverage of NumPy code. Default is False. |
| 150 | + (This requires the `coverage module: |
| 151 | + <http://nedbatchelder.com/code/modules/coverage.html>`_). |
| 152 | + raise_warnings : str or sequence of warnings, optional |
| 153 | + This specifies which warnings to configure as 'raise' instead |
| 154 | + of 'warn' during the test execution. Valid strings are: |
| 155 | +
|
| 156 | + - "develop" : equals ``(DeprecationWarning, RuntimeWarning)`` |
| 157 | + - "release" : equals ``()``, don't raise on any warnings. |
| 158 | +
|
| 159 | + Returns |
| 160 | + ------- |
| 161 | + result : object |
| 162 | + Returns the result of running the tests as a |
| 163 | + ``nose.result.TextTestResult`` object. |
| 164 | + """ |
| 165 | + |
| 166 | + # cap verbosity at 3 because nose becomes *very* verbose beyond that |
| 167 | + verbose = min(verbose, 3) |
| 168 | + |
| 169 | + if doctests: |
| 170 | + print("Running unit tests and doctests for %s" % self.package_name) |
| 171 | + else: |
| 172 | + print("Running unit tests for %s" % self.package_name) |
| 173 | + |
| 174 | + self._show_system_info() |
| 175 | + |
| 176 | + # reset doctest state on every run |
| 177 | + import doctest |
| 178 | + doctest.master = None |
| 179 | + |
| 180 | + if raise_warnings is None: |
| 181 | + raise_warnings = 'release' |
| 182 | + |
| 183 | + _warn_opts = dict(develop=(DeprecationWarning, RuntimeWarning), |
| 184 | + release=()) |
| 185 | + if isinstance(raise_warnings, string_types): |
| 186 | + raise_warnings = _warn_opts[raise_warnings] |
| 187 | + |
| 188 | + with warnings.catch_warnings(): |
| 189 | + # Reset the warning filters to the default state, |
| 190 | + # so that running the tests is more repeatable. |
| 191 | + warnings.resetwarnings() |
| 192 | + # Set all warnings to 'warn', this is because the default 'once' |
| 193 | + # has the bad property of possibly shadowing later warnings. |
| 194 | + warnings.filterwarnings('always') |
| 195 | + # Force the requested warnings to raise |
| 196 | + for warningtype in raise_warnings: |
| 197 | + warnings.filterwarnings('error', category=warningtype) |
| 198 | + # Filter out annoying import messages. |
| 199 | + warnings.filterwarnings("ignore", category=FutureWarning) |
| 200 | + |
| 201 | + from numpy.testing.noseclasses import NumpyTestProgram |
| 202 | + |
| 203 | + argv, plugins = self.prepare_test_args( |
| 204 | + label, verbose, extra_argv, doctests, coverage) |
| 205 | + t = NumpyTestProgram(argv=argv, exit=False, plugins=plugins) |
| 206 | + |
| 207 | + return t.result |
0 commit comments