aboutsummaryrefslogtreecommitdiffstats
path: root/library/python/pytest/plugins/collection.py
diff options
context:
space:
mode:
authorDevtools Arcadia <arcadia-devtools@yandex-team.ru>2022-02-07 18:08:42 +0300
committerDevtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net>2022-02-07 18:08:42 +0300
commit1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch)
treee26c9fed0de5d9873cce7e00bc214573dc2195b7 /library/python/pytest/plugins/collection.py
downloadydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'library/python/pytest/plugins/collection.py')
-rw-r--r--library/python/pytest/plugins/collection.py128
1 files changed, 128 insertions, 0 deletions
diff --git a/library/python/pytest/plugins/collection.py b/library/python/pytest/plugins/collection.py
new file mode 100644
index 0000000000..e36f47a78f
--- /dev/null
+++ b/library/python/pytest/plugins/collection.py
@@ -0,0 +1,128 @@
+import os
+import sys
+from six import reraise
+
+import py
+
+import pytest # noqa
+import _pytest.python
+import _pytest.doctest
+import json
+import library.python.testing.filter.filter as test_filter
+
+
+class LoadedModule(_pytest.python.Module):
+ def __init__(self, parent, name, **kwargs):
+ self.name = name + '.py'
+ self.session = parent
+ self.parent = parent
+ self.config = parent.config
+ self.keywords = {}
+ self.own_markers = []
+ self.fspath = py.path.local()
+
+ @classmethod
+ def from_parent(cls, **kwargs):
+ namespace = kwargs.pop('namespace', True)
+ kwargs.setdefault('fspath', py.path.local())
+
+ loaded_module = getattr(super(LoadedModule, cls), 'from_parent', cls)(**kwargs)
+ loaded_module.namespace = namespace
+
+ return loaded_module
+
+ @property
+ def _nodeid(self):
+ if os.getenv('CONFTEST_LOAD_POLICY') == 'LOCAL':
+ return self._getobj().__file__
+ else:
+ return self.name
+
+ @property
+ def nodeid(self):
+ return self._nodeid
+
+ def _getobj(self):
+ module_name = self.name[:-len('.py')]
+ if self.namespace:
+ module_name = '__tests__.' + module_name
+ __import__(module_name)
+ return sys.modules[module_name]
+
+
+class DoctestModule(LoadedModule):
+
+ def collect(self):
+ import doctest
+
+ module = self._getobj()
+ # uses internal doctest module parsing mechanism
+ finder = doctest.DocTestFinder()
+ optionflags = _pytest.doctest.get_optionflags(self)
+ runner = doctest.DebugRunner(verbose=0, optionflags=optionflags)
+
+ try:
+ for test in finder.find(module, self.name[:-len('.py')]):
+ if test.examples: # skip empty doctests
+ yield getattr(_pytest.doctest.DoctestItem, 'from_parent', _pytest.doctest.DoctestItem)(
+ name=test.name,
+ parent=self,
+ runner=runner,
+ dtest=test)
+ except Exception:
+ import logging
+ logging.exception('DoctestModule failed, probably you can add NO_DOCTESTS() macro to ya.make')
+ etype, exc, tb = sys.exc_info()
+ msg = 'DoctestModule failed, probably you can add NO_DOCTESTS() macro to ya.make'
+ reraise(etype, type(exc)('{}\n{}'.format(exc, msg)), tb)
+
+
+# NOTE: Since we are overriding collect method of pytest session, pytest hooks are not invoked during collection.
+def pytest_ignore_collect(module, session, filenames_from_full_filters, accept_filename_predicate):
+ if session.config.option.mode == 'list':
+ return not accept_filename_predicate(module.name)
+
+ if filenames_from_full_filters is not None and module.name not in filenames_from_full_filters:
+ return True
+
+ test_file_filter = getattr(session.config.option, 'test_file_filter', None)
+ if test_file_filter is None:
+ return False
+ if module.name != test_file_filter.replace('/', '.'):
+ return True
+ return False
+
+
+class CollectionPlugin(object):
+ def __init__(self, test_modules, doctest_modules):
+ self._test_modules = test_modules
+ self._doctest_modules = doctest_modules
+
+ def pytest_sessionstart(self, session):
+
+ def collect(*args, **kwargs):
+ accept_filename_predicate = test_filter.make_py_file_filter(session.config.option.test_filter)
+ full_test_names_file_path = session.config.option.test_list_path
+ filenames_filter = None
+
+ if full_test_names_file_path and os.path.exists(full_test_names_file_path):
+ with open(full_test_names_file_path, 'r') as afile:
+ # in afile stored 2 dimensional array such that array[modulo_index] contains tests which should be run in this test suite
+ full_names_filter = set(json.load(afile)[int(session.config.option.modulo_index)])
+ filenames_filter = set(map(lambda x: x.split('::')[0], full_names_filter))
+
+ for test_module in self._test_modules:
+ module = LoadedModule.from_parent(name=test_module, parent=session)
+ if not pytest_ignore_collect(module, session, filenames_filter, accept_filename_predicate):
+ yield module
+
+ if os.environ.get('YA_PYTEST_DISABLE_DOCTEST', 'no') == 'no':
+ module = DoctestModule.from_parent(name=test_module, parent=session)
+ if not pytest_ignore_collect(module, session, filenames_filter, accept_filename_predicate):
+ yield module
+
+ if os.environ.get('YA_PYTEST_DISABLE_DOCTEST', 'no') == 'no':
+ for doctest_module in self._doctest_modules:
+ yield DoctestModule.from_parent(name=doctest_module, parent=session, namespace=False)
+
+ session.collect = collect