123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112 |
- """
- invent a quick version of pytest autouse fixtures as pytest's unacceptably slow
- collection/high memory use in pytest 4.6.11, which is the highest version that
- works in py2k.
- by "too-slow" we mean the test suite can't even manage to be collected for a
- single process in less than 70 seconds or so and memory use seems to be very
- high as well. for two or four workers the job just times out after ten
- minutes.
- so instead we have invented a very limited form of these fixtures, as our
- current use of "autouse" fixtures are limited to those in fixtures.py.
- assumptions for these fixtures:
- 1. we are only using "function" or "class" scope
- 2. the functions must be associated with a test class
- 3. the fixture functions cannot themselves use pytest fixtures
- 4. the fixture functions must use yield, not return
- When py2k support is removed and we can stay on a modern pytest version, this
- can all be removed.
- """
- import collections
- _py2k_fixture_fn_names = collections.defaultdict(set)
- _py2k_class_fixtures = collections.defaultdict(
- lambda: collections.defaultdict(set)
- )
- _py2k_function_fixtures = collections.defaultdict(
- lambda: collections.defaultdict(set)
- )
- _py2k_cls_fixture_stack = []
- _py2k_fn_fixture_stack = []
- def add_fixture(fn, fixture):
- assert fixture.scope in ("class", "function")
- _py2k_fixture_fn_names[fn.__name__].add((fn, fixture.scope))
- def scan_for_fixtures_to_use_for_class(item):
- test_class = item.parent.parent.obj
- for name in _py2k_fixture_fn_names:
- for fixture_fn, scope in _py2k_fixture_fn_names[name]:
- meth = getattr(test_class, name, None)
- if meth and meth.im_func is fixture_fn:
- for sup in test_class.__mro__:
- if name in sup.__dict__:
- if scope == "class":
- _py2k_class_fixtures[test_class][sup].add(meth)
- elif scope == "function":
- _py2k_function_fixtures[test_class][sup].add(meth)
- break
- break
- def run_class_fixture_setup(request):
- cls = request.cls
- self = cls.__new__(cls)
- fixtures_for_this_class = _py2k_class_fixtures.get(cls)
- if fixtures_for_this_class:
- for sup_ in cls.__mro__:
- for fn in fixtures_for_this_class.get(sup_, ()):
- iter_ = fn(self)
- next(iter_)
- _py2k_cls_fixture_stack.append(iter_)
- def run_class_fixture_teardown(request):
- while _py2k_cls_fixture_stack:
- iter_ = _py2k_cls_fixture_stack.pop(-1)
- try:
- next(iter_)
- except StopIteration:
- pass
- def run_fn_fixture_setup(request):
- cls = request.cls
- self = request.instance
- fixtures_for_this_class = _py2k_function_fixtures.get(cls)
- if fixtures_for_this_class:
- for sup_ in reversed(cls.__mro__):
- for fn in fixtures_for_this_class.get(sup_, ()):
- iter_ = fn(self)
- next(iter_)
- _py2k_fn_fixture_stack.append(iter_)
- def run_fn_fixture_teardown(request):
- while _py2k_fn_fixture_stack:
- iter_ = _py2k_fn_fixture_stack.pop(-1)
- try:
- next(iter_)
- except StopIteration:
- pass
|