test_warnings.py 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. """
  2. Tests which scan for certain occurrences in the code, they may not find
  3. all of these occurrences but should catch almost all.
  4. """
  5. import pytest
  6. from pathlib import Path
  7. import ast
  8. import tokenize
  9. import numpy
  10. class ParseCall(ast.NodeVisitor):
  11. def __init__(self):
  12. self.ls = []
  13. def visit_Attribute(self, node):
  14. ast.NodeVisitor.generic_visit(self, node)
  15. self.ls.append(node.attr)
  16. def visit_Name(self, node):
  17. self.ls.append(node.id)
  18. class FindFuncs(ast.NodeVisitor):
  19. def __init__(self, filename):
  20. super().__init__()
  21. self.__filename = filename
  22. def visit_Call(self, node):
  23. p = ParseCall()
  24. p.visit(node.func)
  25. ast.NodeVisitor.generic_visit(self, node)
  26. if p.ls[-1] == 'simplefilter' or p.ls[-1] == 'filterwarnings':
  27. if node.args[0].s == "ignore":
  28. raise AssertionError(
  29. "warnings should have an appropriate stacklevel; found in "
  30. "{} on line {}".format(self.__filename, node.lineno))
  31. if p.ls[-1] == 'warn' and (
  32. len(p.ls) == 1 or p.ls[-2] == 'warnings'):
  33. if "testing/tests/test_warnings.py" == self.__filename:
  34. # This file
  35. return
  36. # See if stacklevel exists:
  37. if len(node.args) == 3:
  38. return
  39. args = {kw.arg for kw in node.keywords}
  40. if "stacklevel" in args:
  41. return
  42. raise AssertionError(
  43. "warnings should have an appropriate stacklevel; found in "
  44. "{} on line {}".format(self.__filename, node.lineno))
  45. @pytest.mark.slow
  46. def test_warning_calls():
  47. # combined "ignore" and stacklevel error
  48. base = Path(numpy.__file__).parent
  49. for path in base.rglob("*.py"):
  50. if base / "testing" in path.parents:
  51. continue
  52. if path == base / "__init__.py":
  53. continue
  54. if path == base / "random" / "__init__.py":
  55. continue
  56. # use tokenize to auto-detect encoding on systems where no
  57. # default encoding is defined (e.g. LANG='C')
  58. with tokenize.open(str(path)) as file:
  59. tree = ast.parse(file.read())
  60. FindFuncs(path).visit(tree)