Skip to content

Commit 8b39c75

Browse files
committed
Move common code between Session and Package to FSCollector
1 parent 7490488 commit 8b39c75

File tree

3 files changed

+46
-72
lines changed

3 files changed

+46
-72
lines changed

src/_pytest/main.py

Lines changed: 5 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
import _pytest._code
1414
from _pytest import nodes
15+
from _pytest.config import Config
1516
from _pytest.config import directory_arg
1617
from _pytest.config import hookimpl
1718
from _pytest.config import UsageError
@@ -339,18 +340,6 @@ def pytest_collection_modifyitems(items, config):
339340
items[:] = remaining
340341

341342

342-
class FSHookProxy:
343-
def __init__(self, fspath, pm, remove_mods):
344-
self.fspath = fspath
345-
self.pm = pm
346-
self.remove_mods = remove_mods
347-
348-
def __getattr__(self, name):
349-
x = self.pm.subset_hook_caller(name, remove_plugins=self.remove_mods)
350-
self.__dict__[name] = x
351-
return x
352-
353-
354343
class NoMatch(Exception):
355344
""" raised if matching cannot locate a matching names. """
356345

@@ -381,7 +370,7 @@ class Session(nodes.FSCollector):
381370
_setupstate = None # type: SetupState
382371
_fixturemanager = None # type: FixtureManager
383372

384-
def __init__(self, config):
373+
def __init__(self, config: Config) -> None:
385374
nodes.FSCollector.__init__(
386375
self, config.rootdir, parent=None, config=config, session=self, nodeid=""
387376
)
@@ -390,16 +379,15 @@ def __init__(self, config):
390379
self.shouldstop = False
391380
self.shouldfail = False
392381
self.trace = config.trace.root.get("collection")
393-
self._norecursepatterns = config.getini("norecursedirs")
394382
self.startdir = config.invocation_dir
395-
self._initialpaths = frozenset()
383+
self._initialpaths = frozenset() # type: ignore
396384
# Keep track of any collected nodes in here, so we don't duplicate fixtures
397-
self._node_cache = {}
385+
self._node_cache = {} # type: ignore
398386
self._bestrelpathcache = _bestrelpath_cache(
399387
config.rootdir
400388
) # type: Dict[str, str]
401389
# Dirnames of pkgs with dunder-init files.
402-
self._pkg_roots = {}
390+
self._pkg_roots = {} # type: ignore
403391

404392
self.config.pluginmanager.register(self, name="session")
405393

@@ -440,20 +428,6 @@ def pytest_runtest_logreport(self, report):
440428
def isinitpath(self, path):
441429
return path in self._initialpaths
442430

443-
def gethookproxy(self, fspath):
444-
# check if we have the common case of running
445-
# hooks with all conftest.py files
446-
pm = self.config.pluginmanager
447-
my_conftestmodules = pm._getconftestmodules(fspath)
448-
remove_mods = pm._conftest_plugins.difference(my_conftestmodules)
449-
if remove_mods:
450-
# one or more conftests are not in use at this fspath
451-
proxy = FSHookProxy(fspath, pm, remove_mods)
452-
else:
453-
# all plugins are active for this fspath
454-
proxy = self.config.hook
455-
return proxy
456-
457431
def perform_collect(self, args=None, genitems=True):
458432
hook = self.config.hook
459433
try:
@@ -616,19 +590,6 @@ def _collectfile(self, path, handle_dupes=True):
616590

617591
return ihook.pytest_collect_file(path=path, parent=self)
618592

619-
def _recurse(self, dirpath: py.path.local) -> bool:
620-
if dirpath.basename == "__pycache__":
621-
return False
622-
ihook = self.gethookproxy(dirpath.dirpath())
623-
if ihook.pytest_ignore_collect(path=dirpath, config=self.config):
624-
return False
625-
for pat in self._norecursepatterns:
626-
if dirpath.check(fnmatch=pat):
627-
return False
628-
ihook = self.gethookproxy(dirpath)
629-
ihook.pytest_collect_directory(path=dirpath, parent=self)
630-
return True
631-
632593
@staticmethod
633594
def _visit_filter(f):
634595
return f.check(file=1)

src/_pytest/nodes.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,18 @@ def _check_initialpaths_for_relpath(session, fspath):
408408
return fspath.relto(initial_path)
409409

410410

411+
class FSHookProxy:
412+
def __init__(self, fspath, pm, remove_mods):
413+
self.fspath = fspath
414+
self.pm = pm
415+
self.remove_mods = remove_mods
416+
417+
def __getattr__(self, name):
418+
x = self.pm.subset_hook_caller(name, remove_plugins=self.remove_mods)
419+
self.__dict__[name] = x
420+
return x
421+
422+
411423
class FSCollector(Collector):
412424
def __init__(
413425
self, fspath: py.path.local, parent=None, config=None, session=None, nodeid=None
@@ -432,10 +444,39 @@ def __init__(
432444

433445
super().__init__(name, parent, config, session, nodeid=nodeid, fspath=fspath)
434446

447+
self._norecursepatterns = self.config.getini("norecursedirs")
448+
435449
@classmethod
436450
def from_parent(cls, parent, *, fspath):
437451
return cls._create(parent=parent, fspath=fspath)
438452

453+
def gethookproxy(self, fspath):
454+
# check if we have the common case of running
455+
# hooks with all conftest.py files
456+
pm = self.config.pluginmanager
457+
my_conftestmodules = pm._getconftestmodules(fspath)
458+
remove_mods = pm._conftest_plugins.difference(my_conftestmodules)
459+
if remove_mods:
460+
# one or more conftests are not in use at this fspath
461+
proxy = FSHookProxy(fspath, pm, remove_mods)
462+
else:
463+
# all plugins are active for this fspath
464+
proxy = self.config.hook
465+
return proxy
466+
467+
def _recurse(self, dirpath: py.path.local) -> bool:
468+
if dirpath.basename == "__pycache__":
469+
return False
470+
ihook = self.gethookproxy(dirpath.dirpath())
471+
if ihook.pytest_ignore_collect(path=dirpath, config=self.config):
472+
return False
473+
for pat in self._norecursepatterns:
474+
if dirpath.check(fnmatch=pat):
475+
return False
476+
ihook = self.gethookproxy(dirpath)
477+
ihook.pytest_collect_directory(path=dirpath, parent=self)
478+
return True
479+
439480

440481
class File(FSCollector):
441482
""" base class for collecting tests from a file. """

src/_pytest/python.py

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
from _pytest.compat import STRING_TYPES
3636
from _pytest.config import hookimpl
3737
from _pytest.deprecated import FUNCARGNAMES
38-
from _pytest.main import FSHookProxy
3938
from _pytest.mark import MARK_GEN
4039
from _pytest.mark.structures import get_unpacked_marks
4140
from _pytest.mark.structures import Mark
@@ -561,33 +560,6 @@ def setup(self):
561560
func = partial(_call_with_optional_argument, teardown_module, self.obj)
562561
self.addfinalizer(func)
563562

564-
def _recurse(self, dirpath: py.path.local) -> bool:
565-
if dirpath.basename == "__pycache__":
566-
return False
567-
ihook = self.gethookproxy(dirpath.dirpath())
568-
if ihook.pytest_ignore_collect(path=dirpath, config=self.config):
569-
return False
570-
for pat in self._norecursepatterns:
571-
if dirpath.check(fnmatch=pat):
572-
return False
573-
ihook = self.gethookproxy(dirpath)
574-
ihook.pytest_collect_directory(path=dirpath, parent=self)
575-
return True
576-
577-
def gethookproxy(self, fspath):
578-
# check if we have the common case of running
579-
# hooks with all conftest.py files
580-
pm = self.config.pluginmanager
581-
my_conftestmodules = pm._getconftestmodules(fspath)
582-
remove_mods = pm._conftest_plugins.difference(my_conftestmodules)
583-
if remove_mods:
584-
# one or more conftests are not in use at this fspath
585-
proxy = FSHookProxy(fspath, pm, remove_mods)
586-
else:
587-
# all plugins are active for this fspath
588-
proxy = self.config.hook
589-
return proxy
590-
591563
def _collectfile(self, path, handle_dupes=True):
592564
assert (
593565
path.isfile()

0 commit comments

Comments
 (0)