Don't stop at the first package when looking up package-scoped fixtures.
Example: package1.subpackage1 package1.subpackage2 package1's setup/teardown were executed again when exiting subpackage1 and entering subpackage2.
This commit is contained in:
parent
7d923c389e
commit
c416b1d935
|
@ -2,6 +2,7 @@ from __future__ import absolute_import, division, print_function
|
|||
|
||||
import functools
|
||||
import inspect
|
||||
import os
|
||||
import sys
|
||||
import warnings
|
||||
from collections import OrderedDict, deque, defaultdict
|
||||
|
@ -70,6 +71,17 @@ def scopeproperty(name=None, doc=None):
|
|||
return decoratescope
|
||||
|
||||
|
||||
def get_scope_package(node, fixturedef):
|
||||
cls = node.Package
|
||||
current = node
|
||||
fixture_package_name = os.path.join(fixturedef.baseid, '__init__.py')
|
||||
while current and type(current) is not cls or \
|
||||
fixture_package_name != current.nodeid:
|
||||
current = current.parent
|
||||
assert current
|
||||
return current
|
||||
|
||||
|
||||
def get_scope_node(node, scope):
|
||||
cls = scopename2class.get(scope)
|
||||
if cls is None:
|
||||
|
@ -558,7 +570,10 @@ class FixtureRequest(FuncargnamesCompatAttr):
|
|||
if scope == "function":
|
||||
# this might also be a non-function Item despite its attribute name
|
||||
return self._pyfuncitem
|
||||
node = get_scope_node(self._pyfuncitem, scope)
|
||||
if scope == 'package':
|
||||
node = get_scope_package(self._pyfuncitem, self._fixturedef)
|
||||
else:
|
||||
node = get_scope_node(self._pyfuncitem, scope)
|
||||
if node is None and scope == "class":
|
||||
# fallback to function item itself
|
||||
node = self._pyfuncitem
|
||||
|
|
|
@ -116,6 +116,7 @@ class Node(object):
|
|||
Function = _CompatProperty("Function")
|
||||
File = _CompatProperty("File")
|
||||
Item = _CompatProperty("Item")
|
||||
Package = _CompatProperty("Package")
|
||||
|
||||
def _getcustomclass(self, name):
|
||||
maybe_compatprop = getattr(type(self), name)
|
||||
|
|
|
@ -13,11 +13,11 @@ from itertools import count
|
|||
|
||||
import py
|
||||
import six
|
||||
from _pytest.main import FSHookProxy
|
||||
from _pytest.mark import MarkerError
|
||||
from _pytest.config import hookimpl
|
||||
|
||||
import _pytest
|
||||
from _pytest.main import Session
|
||||
import pluggy
|
||||
from _pytest import fixtures
|
||||
from _pytest import nodes
|
||||
|
@ -490,7 +490,7 @@ class Module(nodes.File, PyCollector):
|
|||
self.addfinalizer(teardown_module)
|
||||
|
||||
|
||||
class Package(Session, Module):
|
||||
class Package(Module):
|
||||
|
||||
def __init__(self, fspath, parent=None, config=None, session=None, nodeid=None):
|
||||
session = parent.session
|
||||
|
@ -503,7 +503,38 @@ class Package(Session, Module):
|
|||
for path in list(session.config.pluginmanager._duplicatepaths):
|
||||
if path.dirname == fspath.dirname and path != fspath:
|
||||
session.config.pluginmanager._duplicatepaths.remove(path)
|
||||
pass
|
||||
|
||||
def _recurse(self, path):
|
||||
ihook = self.gethookproxy(path.dirpath())
|
||||
if ihook.pytest_ignore_collect(path=path, config=self.config):
|
||||
return
|
||||
for pat in self._norecursepatterns:
|
||||
if path.check(fnmatch=pat):
|
||||
return False
|
||||
ihook = self.gethookproxy(path)
|
||||
ihook.pytest_collect_directory(path=path, parent=self)
|
||||
return True
|
||||
|
||||
def gethookproxy(self, fspath):
|
||||
# check if we have the common case of running
|
||||
# hooks with all conftest.py filesall conftest.py
|
||||
pm = self.config.pluginmanager
|
||||
my_conftestmodules = pm._getconftestmodules(fspath)
|
||||
remove_mods = pm._conftest_plugins.difference(my_conftestmodules)
|
||||
if remove_mods:
|
||||
# one or more conftests are not in use at this fspath
|
||||
proxy = FSHookProxy(fspath, pm, remove_mods)
|
||||
else:
|
||||
# all plugis are active for this fspath
|
||||
proxy = self.config.hook
|
||||
return proxy
|
||||
|
||||
def _collectfile(self, path):
|
||||
ihook = self.gethookproxy(path)
|
||||
if not self.isinitpath(path):
|
||||
if ihook.pytest_ignore_collect(path=path, config=self.config):
|
||||
return ()
|
||||
return ihook.pytest_collect_file(path=path, parent=self)
|
||||
|
||||
def isinitpath(self, path):
|
||||
return path in self.session._initialpaths
|
||||
|
|
Loading…
Reference in New Issue