summaryrefslogtreecommitdiff
path: root/numpy/tests
diff options
context:
space:
mode:
authorSebastian Berg <sebastian@sipsolutions.net>2016-01-29 01:17:55 +0100
committerSebastian Berg <sebastian@sipsolutions.net>2016-09-02 16:39:17 +0200
commit4ec016784b02f69347c4429829b9eb8225ace5ee (patch)
treec058c5b7e4edec3ee0b5bc13dff55ded65cb5042 /numpy/tests
parent7884a8c9f5f5c6657413dbeaa59ad969280d38ea (diff)
downloadnumpy-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.py86
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()