6
6
import os
7
7
import sys
8
8
from typing import Dict
9
+ from typing import FrozenSet
10
+ from typing import List
9
11
10
12
import attr
11
13
import py
12
14
13
15
import _pytest ._code
14
16
from _pytest import nodes
17
+ from _pytest .compat import TYPE_CHECKING
15
18
from _pytest .config import directory_arg
16
19
from _pytest .config import hookimpl
17
20
from _pytest .config import UsageError
18
21
from _pytest .fixtures import FixtureManager
22
+ from _pytest .nodes import Node
19
23
from _pytest .outcomes import exit
20
24
from _pytest .runner import collect_one_node
21
25
from _pytest .runner import SetupState
22
26
23
27
28
+ if TYPE_CHECKING :
29
+ from _pytest .python import Package
30
+
31
+
24
32
class ExitCode (enum .IntEnum ):
25
33
"""
26
34
.. versionadded:: 5.0
@@ -381,7 +389,7 @@ class Session(nodes.FSCollector):
381
389
_setupstate = None # type: SetupState
382
390
_fixturemanager = None # type: FixtureManager
383
391
384
- def __init__ (self , config ):
392
+ def __init__ (self , config ) -> None :
385
393
nodes .FSCollector .__init__ (
386
394
self , config .rootdir , parent = None , config = config , session = self , nodeid = ""
387
395
)
@@ -392,14 +400,16 @@ def __init__(self, config):
392
400
self .trace = config .trace .root .get ("collection" )
393
401
self ._norecursepatterns = config .getini ("norecursedirs" )
394
402
self .startdir = config .invocation_dir
395
- self ._initialpaths = frozenset ()
403
+ self ._initialpaths = frozenset () # type: FrozenSet[py.path.local]
404
+
396
405
# Keep track of any collected nodes in here, so we don't duplicate fixtures
397
- self ._node_cache = {}
406
+ self ._collection_node_cache = {} # type: Dict[str, List[Node]]
407
+ # Dirnames of pkgs with dunder-init files.
408
+ self ._collection_pkg_roots = {} # type: Dict[py.path.local, Package]
409
+
398
410
self ._bestrelpathcache = _bestrelpath_cache (
399
411
config .rootdir
400
412
) # type: Dict[str, str]
401
- # Dirnames of pkgs with dunder-init files.
402
- self ._pkg_roots = {}
403
413
404
414
self .config .pluginmanager .register (self , name = "session" )
405
415
@@ -511,6 +521,8 @@ def collect(self):
511
521
self ._notfound .append ((report_arg , sys .exc_info ()[1 ]))
512
522
513
523
self .trace .root .indent -= 1
524
+ self ._collection_node_cache .clear ()
525
+ self ._collection_pkg_roots .clear ()
514
526
515
527
def _collect (self , arg ):
516
528
from _pytest .python import Package
@@ -530,13 +542,13 @@ def _collect(self, arg):
530
542
if parent .isdir ():
531
543
pkginit = parent .join ("__init__.py" )
532
544
if pkginit .isfile ():
533
- if pkginit not in self ._node_cache :
545
+ if pkginit not in self ._collection_node_cache :
534
546
col = self ._collectfile (pkginit , handle_dupes = False )
535
547
if col :
536
548
if isinstance (col [0 ], Package ):
537
- self ._pkg_roots [parent ] = col [0 ]
549
+ self ._collection_pkg_roots [parent ] = col [0 ]
538
550
# always store a list in the cache, matchnodes expects it
539
- self ._node_cache [col [0 ].fspath ] = [col [0 ]]
551
+ self ._collection_node_cache [col [0 ].fspath ] = [col [0 ]]
540
552
541
553
# If it's a directory argument, recurse and look for any Subpackages.
542
554
# Let the Package collector deal with subnodes, don't collect here.
@@ -556,28 +568,28 @@ def _collect(self, arg):
556
568
for x in self ._collectfile (pkginit ):
557
569
yield x
558
570
if isinstance (x , Package ):
559
- self ._pkg_roots [dirpath ] = x
560
- if dirpath in self ._pkg_roots :
571
+ self ._collection_pkg_roots [dirpath ] = x
572
+ if dirpath in self ._collection_pkg_roots :
561
573
# Do not collect packages here.
562
574
continue
563
575
564
576
for x in self ._collectfile (path ):
565
577
key = (type (x ), x .fspath )
566
- if key in self ._node_cache :
567
- yield self ._node_cache [key ]
578
+ if key in self ._collection_node_cache :
579
+ yield self ._collection_node_cache [key ]
568
580
else :
569
- self ._node_cache [key ] = x
581
+ self ._collection_node_cache [key ] = x
570
582
yield x
571
583
else :
572
584
assert argpath .check (file = 1 )
573
585
574
- if argpath in self ._node_cache :
575
- col = self ._node_cache [argpath ]
586
+ if argpath in self ._collection_node_cache :
587
+ col = self ._collection_node_cache [argpath ]
576
588
else :
577
- collect_root = self ._pkg_roots .get (argpath .dirname , self )
589
+ collect_root = self ._collection_pkg_roots .get (argpath .dirname , self )
578
590
col = collect_root ._collectfile (argpath , handle_dupes = False )
579
591
if col :
580
- self ._node_cache [argpath ] = col
592
+ self ._collection_node_cache [argpath ] = col
581
593
m = self .matchnodes (col , names )
582
594
# If __init__.py was the only file requested, then the matched node will be
583
595
# the corresponding Package, and the first yielded item will be the __init__
@@ -690,11 +702,11 @@ def _matchnodes(self, matching, names):
690
702
continue
691
703
assert isinstance (node , nodes .Collector )
692
704
key = (type (node ), node .nodeid )
693
- if key in self ._node_cache :
694
- rep = self ._node_cache [key ]
705
+ if key in self ._collection_node_cache :
706
+ rep = self ._collection_node_cache [key ]
695
707
else :
696
708
rep = collect_one_node (node )
697
- self ._node_cache [key ] = rep
709
+ self ._collection_node_cache [key ] = rep
698
710
if rep .passed :
699
711
has_matched = False
700
712
for x in rep .result :
0 commit comments