diff options
author | Sebastian Berg <sebastian@sipsolutions.net> | 2016-01-29 01:17:55 +0100 |
---|---|---|
committer | Sebastian Berg <sebastian@sipsolutions.net> | 2016-09-02 16:39:17 +0200 |
commit | 4ec016784b02f69347c4429829b9eb8225ace5ee (patch) | |
tree | c058c5b7e4edec3ee0b5bc13dff55ded65cb5042 /numpy/tests | |
parent | 7884a8c9f5f5c6657413dbeaa59ad969280d38ea (diff) | |
download | numpy-4ec016784b02f69347c4429829b9eb8225ace5ee.tar.gz |
TST: Add tests for stacklevel in warnings and "ignore" filters.
Enforces that stacklevel is used in warnings.warn and "ignore"
is not used in filterwarnings or simplefilter for most of numpy.
Diffstat (limited to 'numpy/tests')
-rw-r--r-- | numpy/tests/test_warnings.py | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/numpy/tests/test_warnings.py b/numpy/tests/test_warnings.py new file mode 100644 index 000000000..dcae60a81 --- /dev/null +++ b/numpy/tests/test_warnings.py @@ -0,0 +1,86 @@ +""" +Tests which scan for certain occurances in the code, they may not find +all of these occurances but should catch almost all. +""" + + +from __future__ import division, absolute_import, print_function + + +import sys +if sys.version_info >= (3, 4): + from pathlib import Path + import ast + import tokenize + import numpy + from numpy.testing import run_module_suite + from numpy.testing.decorators import slow + + + class ParseCall(ast.NodeVisitor): + def __init__(self): + self.ls = [] + + def visit_Attribute(self, node): + ast.NodeVisitor.generic_visit(self, node) + self.ls.append(node.attr) + + def visit_Name(self, node): + self.ls.append(node.id) + + + class FindFuncs(ast.NodeVisitor): + def __init__(self, filename): + super().__init__() + self.__filename = filename + + def visit_Call(self, node): + p = ParseCall() + p.visit(node.func) + ast.NodeVisitor.generic_visit(self, node) + + if p.ls[-1] == 'simplefilter' or p.ls[-1] == 'filterwarnings': + if node.args[0].s == "ignore": + raise AssertionError( + "ignore filter should not be used; found in " + "{} on line {}".format(self.__filename, node.lineno)) + + if p.ls[-1] == 'warn' and ( + len(p.ls) == 1 or p.ls[-2] == 'warnings'): + + if "testing/tests/test_warnings.py" is self.__filename: + # This file + return + + # See if stacklevel exists: + if len(node.args) == 3: + return + args = {kw.arg for kw in node.keywords} + if "stacklevel" in args: + return + raise AssertionError( + "warnings should have an appropriate stacklevel; found in " + "{} on line {}".format(self.__filename, node.lineno)) + + + @slow + def test_warning_calls(): + # combined "ignore" and stacklevel error + base = Path(numpy.__file__).parent + + for path in base.rglob("*.py"): + if base / "testing" in path.parents: + continue + if path == base / "__init__.py": + continue + if path == base / "random" / "__init__.py": + continue + # use tokenize to auto-detect encoding on systems where no + # default encoding is defined (e.g. LANG='C') + with tokenize.open(str(path)) as file: + tree = ast.parse(file.read()) + FindFuncs(path).visit(tree) + + + if __name__ == "__main__": + run_module_suite() |