Skip to content

Commit 4dba778

Browse files
committed
main: inline matchnodes() into collect()
Now all of the logic is in one place and may be simplified and refactored in more sensible way.
1 parent cb66aa3 commit 4dba778

File tree

1 file changed

+51
-50
lines changed

1 file changed

+51
-50
lines changed

src/_pytest/main.py

Lines changed: 51 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -693,8 +693,53 @@ def collect(self) -> Iterator[Union[nodes.Item, nodes.Collector]]:
693693
col = collect_root._collectfile(argpath, handle_dupes=False)
694694
if col:
695695
self._collection_node_cache1[argpath] = col
696-
m = self.matchnodes(col, names)
697-
if not m:
696+
697+
matching = []
698+
work = [
699+
(col, names)
700+
] # type: List[Tuple[Sequence[Union[nodes.Item, nodes.Collector]], Sequence[str]]]
701+
while work:
702+
self.trace("matchnodes", col, names)
703+
self.trace.root.indent += 1
704+
705+
matchnodes, matchnames = work.pop()
706+
for node in matchnodes:
707+
if not matchnames:
708+
matching.append(node)
709+
continue
710+
if not isinstance(node, nodes.Collector):
711+
continue
712+
key = (type(node), node.nodeid)
713+
if key in self._collection_matchnodes_cache:
714+
rep = self._collection_matchnodes_cache[key]
715+
else:
716+
rep = collect_one_node(node)
717+
self._collection_matchnodes_cache[key] = rep
718+
if rep.passed:
719+
submatchnodes = []
720+
for r in rep.result:
721+
# TODO: Remove parametrized workaround once collection structure contains
722+
# parametrization.
723+
if (
724+
r.name == matchnames[0]
725+
or r.name.split("[")[0] == matchnames[0]
726+
):
727+
submatchnodes.append(r)
728+
if submatchnodes:
729+
work.append((submatchnodes, matchnames[1:]))
730+
# XXX Accept IDs that don't have "()" for class instances.
731+
elif len(rep.result) == 1 and rep.result[0].name == "()":
732+
work.append((rep.result, matchnames))
733+
else:
734+
# Report collection failures here to avoid failing to run some test
735+
# specified in the command line because the module could not be
736+
# imported (#134).
737+
node.ihook.pytest_collectreport(report=rep)
738+
739+
self.trace("matchnodes finished -> ", len(matching), "nodes")
740+
self.trace.root.indent -= 1
741+
742+
if not matching:
698743
report_arg = "::".join((str(argpath), *names))
699744
self._notfound.append((report_arg, col))
700745
continue
@@ -704,68 +749,24 @@ def collect(self) -> Iterator[Union[nodes.Item, nodes.Collector]]:
704749
# Module itself, so just use that. If this special case isn't taken, then all
705750
# the files in the package will be yielded.
706751
if argpath.basename == "__init__.py":
707-
assert isinstance(m[0], nodes.Collector)
752+
assert isinstance(matching[0], nodes.Collector)
708753
try:
709-
yield next(iter(m[0].collect()))
754+
yield next(iter(matching[0].collect()))
710755
except StopIteration:
711756
# The package collects nothing with only an __init__.py
712757
# file in it, which gets ignored by the default
713758
# "python_files" option.
714759
pass
715760
continue
716-
yield from m
761+
762+
yield from matching
717763

718764
self.trace.root.indent -= 1
719765
self._collection_node_cache1.clear()
720766
self._collection_node_cache2.clear()
721767
self._collection_matchnodes_cache.clear()
722768
self._collection_pkg_roots.clear()
723769

724-
def matchnodes(
725-
self,
726-
matching: Sequence[Union[nodes.Item, nodes.Collector]],
727-
names: Sequence[str],
728-
) -> Sequence[Union[nodes.Item, nodes.Collector]]:
729-
result = []
730-
work = [(matching, names)]
731-
while work:
732-
self.trace("matchnodes", matching, names)
733-
self.trace.root.indent += 1
734-
735-
matching, names = work.pop()
736-
for node in matching:
737-
if not names:
738-
result.append(node)
739-
continue
740-
if not isinstance(node, nodes.Collector):
741-
continue
742-
key = (type(node), node.nodeid)
743-
if key in self._collection_matchnodes_cache:
744-
rep = self._collection_matchnodes_cache[key]
745-
else:
746-
rep = collect_one_node(node)
747-
self._collection_matchnodes_cache[key] = rep
748-
if rep.passed:
749-
submatching = []
750-
for x in rep.result:
751-
# TODO: Remove parametrized workaround once collection structure contains parametrization.
752-
if x.name == names[0] or x.name.split("[")[0] == names[0]:
753-
submatching.append(x)
754-
if submatching:
755-
work.append((submatching, names[1:]))
756-
# XXX Accept IDs that don't have "()" for class instances.
757-
elif len(rep.result) == 1 and rep.result[0].name == "()":
758-
work.append((rep.result, names))
759-
else:
760-
# Report collection failures here to avoid failing to run some test
761-
# specified in the command line because the module could not be
762-
# imported (#134).
763-
node.ihook.pytest_collectreport(report=rep)
764-
765-
self.trace("matchnodes finished -> ", len(result), "nodes")
766-
self.trace.root.indent -= 1
767-
return result
768-
769770
def genitems(
770771
self, node: Union[nodes.Item, nodes.Collector]
771772
) -> Iterator[nodes.Item]:

0 commit comments

Comments
 (0)