test_warnings.py 2.5 KB

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