conftest.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. import re
  2. import tempfile
  3. import shutil
  4. import logging
  5. import sys
  6. import os
  7. import pytest
  8. import yatest.common
  9. import parso
  10. from parso import cache
  11. from parso.utils import parse_version_string
  12. collect_ignore = ["setup.py"]
  13. VERSIONS_2 = '2.7',
  14. VERSIONS_3 = '3.4', '3.5', '3.6', '3.7', '3.8'
  15. @pytest.fixture(scope='session')
  16. def clean_parso_cache():
  17. """
  18. Set the default cache directory to a temporary directory during tests.
  19. Note that you can't use built-in `tmpdir` and `monkeypatch`
  20. fixture here because their scope is 'function', which is not used
  21. in 'session' scope fixture.
  22. This fixture is activated in ../pytest.ini.
  23. """
  24. old = cache._default_cache_path
  25. tmp = tempfile.mkdtemp(prefix='parso-test-')
  26. cache._default_cache_path = tmp
  27. yield
  28. cache._default_cache_path = old
  29. shutil.rmtree(tmp)
  30. def pytest_addoption(parser):
  31. parser.addoption("--logging", "-L", action='store_true',
  32. help="Enables the logging output.")
  33. def pytest_generate_tests(metafunc):
  34. if 'normalizer_issue_case' in metafunc.fixturenames:
  35. base_dir = os.path.join(yatest.common.test_source_path(), 'normalizer_issue_files')
  36. cases = list(colllect_normalizer_tests(base_dir))
  37. metafunc.parametrize(
  38. 'normalizer_issue_case',
  39. cases,
  40. ids=[c.name for c in cases]
  41. )
  42. elif 'each_version' in metafunc.fixturenames:
  43. metafunc.parametrize('each_version', VERSIONS_2 + VERSIONS_3)
  44. elif 'each_py2_version' in metafunc.fixturenames:
  45. metafunc.parametrize('each_py2_version', VERSIONS_2)
  46. elif 'each_py3_version' in metafunc.fixturenames:
  47. metafunc.parametrize('each_py3_version', VERSIONS_3)
  48. elif 'version_ge_py36' in metafunc.fixturenames:
  49. metafunc.parametrize('version_ge_py36', ['3.6', '3.7', '3.8'])
  50. elif 'version_ge_py38' in metafunc.fixturenames:
  51. metafunc.parametrize('version_ge_py38', ['3.8'])
  52. class NormalizerIssueCase(object):
  53. """
  54. Static Analysis cases lie in the static_analysis folder.
  55. The tests also start with `#!`, like the goto_definition tests.
  56. """
  57. def __init__(self, path):
  58. self.path = path
  59. self.name = os.path.basename(path)
  60. match = re.search(r'python([\d.]+)\.py', self.name)
  61. self.python_version = match and match.group(1)
  62. def colllect_normalizer_tests(base_dir):
  63. for f_name in os.listdir(base_dir):
  64. if f_name.endswith(".py"):
  65. path = os.path.join(base_dir, f_name)
  66. yield NormalizerIssueCase(path)
  67. def pytest_configure(config):
  68. if config.option.logging:
  69. root = logging.getLogger()
  70. root.setLevel(logging.DEBUG)
  71. #ch = logging.StreamHandler(sys.stdout)
  72. #ch.setLevel(logging.DEBUG)
  73. #formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
  74. #ch.setFormatter(formatter)
  75. #root.addHandler(ch)
  76. class Checker():
  77. def __init__(self, version, is_passing):
  78. self.version = version
  79. self._is_passing = is_passing
  80. self.grammar = parso.load_grammar(version=self.version)
  81. def parse(self, code):
  82. if self._is_passing:
  83. return parso.parse(code, version=self.version, error_recovery=False)
  84. else:
  85. self._invalid_syntax(code)
  86. def _invalid_syntax(self, code):
  87. with pytest.raises(parso.ParserSyntaxError):
  88. module = parso.parse(code, version=self.version, error_recovery=False)
  89. # For debugging
  90. print(module.children)
  91. def get_error(self, code):
  92. errors = list(self.grammar.iter_errors(self.grammar.parse(code)))
  93. assert bool(errors) != self._is_passing
  94. if errors:
  95. return errors[0]
  96. def get_error_message(self, code):
  97. error = self.get_error(code)
  98. if error is None:
  99. return
  100. return error.message
  101. def assert_no_error_in_passing(self, code):
  102. if self._is_passing:
  103. module = self.grammar.parse(code)
  104. assert not list(self.grammar.iter_errors(module))
  105. @pytest.fixture
  106. def works_not_in_py(each_version):
  107. return Checker(each_version, False)
  108. @pytest.fixture
  109. def works_in_py2(each_version):
  110. return Checker(each_version, each_version.startswith('2'))
  111. @pytest.fixture
  112. def works_ge_py27(each_version):
  113. version_info = parse_version_string(each_version)
  114. return Checker(each_version, version_info >= (2, 7))
  115. @pytest.fixture
  116. def works_ge_py3(each_version):
  117. version_info = parse_version_string(each_version)
  118. return Checker(each_version, version_info >= (3, 0))
  119. @pytest.fixture
  120. def works_ge_py35(each_version):
  121. version_info = parse_version_string(each_version)
  122. return Checker(each_version, version_info >= (3, 5))
  123. @pytest.fixture
  124. def works_ge_py36(each_version):
  125. version_info = parse_version_string(each_version)
  126. return Checker(each_version, version_info >= (3, 6))
  127. @pytest.fixture
  128. def works_ge_py38(each_version):
  129. version_info = parse_version_string(each_version)
  130. return Checker(each_version, version_info >= (3, 8))
  131. @pytest.fixture
  132. def works_ge_py39(each_version):
  133. version_info = parse_version_string(each_version)
  134. return Checker(each_version, version_info >= (3, 9))