Skip to content

Commit c867452

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 d0e8b71 commit c867452

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
@@ -707,8 +707,53 @@ def collect(self) -> Iterator[Union[nodes.Item, nodes.Collector]]:
707707
col = collect_root._collectfile(argpath, handle_dupes=False)
708708
if col:
709709
self._collection_node_cache1[argpath] = col
710-
m = self.matchnodes(col, names)
711-
if not m:
710+
711+
matching = []
712+
work = [
713+
(col, names)
714+
] # type: List[Tuple[Sequence[Union[nodes.Item, nodes.Collector]], Sequence[str]]]
715+
while work:
716+
self.trace("matchnodes", col, names)
717+
self.trace.root.indent += 1
718+
719+
matchnodes, matchnames = work.pop()
720+
for node in matchnodes:
721+
if not matchnames:
722+
matching.append(node)
723+
continue
724+
if not isinstance(node, nodes.Collector):
725+
continue
726+
key = (type(node), node.nodeid)
727+
if key in self._collection_matchnodes_cache:
728+
rep = self._collection_matchnodes_cache[key]
729+
else:
730+
rep = collect_one_node(node)
731+
self._collection_matchnodes_cache[key] = rep
732+
if rep.passed:
733+
submatchnodes = []
734+
for r in rep.result:
735+
# TODO: Remove parametrized workaround once collection structure contains
736+
# parametrization.
737+
if (
738+
r.name == matchnames[0]
739+
or r.name.split("[")[0] == matchnames[0]
740+
):
741+
submatchnodes.append(r)
742+
if submatchnodes:
743+
work.append((submatchnodes, matchnames[1:]))
744+
# XXX Accept IDs that don't have "()" for class instances.
745+
elif len(rep.result) == 1 and rep.result[0].name == "()":
746+
work.append((rep.result, matchnames))
747+
else:
748+
# Report collection failures here to avoid failing to run some test
749+
# specified in the command line because the module could not be
750+
# imported (#134).
751+
node.ihook.pytest_collectreport(report=rep)
752+
753+
self.trace("matchnodes finished -> ", len(matching), "nodes")
754+
self.trace.root.indent -= 1
755+
756+
if not matching:
712757
report_arg = "::".join((str(argpath), *names))
713758
self._notfound.append((report_arg, col))
714759
continue
@@ -718,68 +763,24 @@ def collect(self) -> Iterator[Union[nodes.Item, nodes.Collector]]:
718763
# Module itself, so just use that. If this special case isn't taken, then all
719764
# the files in the package will be yielded.
720765
if argpath.basename == "__init__.py":
721-
assert isinstance(m[0], nodes.Collector)
766+
assert isinstance(matching[0], nodes.Collector)
722767
try:
723-
yield next(iter(m[0].collect()))
768+
yield next(iter(matching[0].collect()))
724769
except StopIteration:
725770
# The package collects nothing with only an __init__.py
726771
# file in it, which gets ignored by the default
727772
# "python_files" option.
728773
pass
729774
continue
730-
yield from m
775+
776+
yield from matching
731777

732778
self.trace.root.indent -= 1
733779
self._collection_node_cache1.clear()
734780
self._collection_node_cache2.clear()
735781
self._collection_matchnodes_cache.clear()
736782
self._collection_pkg_roots.clear()
737783

738-
def matchnodes(
739-
self,
740-
matching: Sequence[Union[nodes.Item, nodes.Collector]],
741-
names: Sequence[str],
742-
) -> Sequence[Union[nodes.Item, nodes.Collector]]:
743-
result = []
744-
work = [(matching, names)]
745-
while work:
746-
self.trace("matchnodes", matching, names)
747-
self.trace.root.indent += 1
748-
749-
matching, names = work.pop()
750-
for node in matching:
751-
if not names:
752-
result.append(node)
753-
continue
754-
if not isinstance(node, nodes.Collector):
755-
continue
756-
key = (type(node), node.nodeid)
757-
if key in self._collection_matchnodes_cache:
758-
rep = self._collection_matchnodes_cache[key]
759-
else:
760-
rep = collect_one_node(node)
761-
self._collection_matchnodes_cache[key] = rep
762-
if rep.passed:
763-
submatching = []
764-
for x in rep.result:
765-
# TODO: Remove parametrized workaround once collection structure contains parametrization.
766-
if x.name == names[0] or x.name.split("[")[0] == names[0]:
767-
submatching.append(x)
768-
if submatching:
769-
work.append((submatching, names[1:]))
770-
# XXX Accept IDs that don't have "()" for class instances.
771-
elif len(rep.result) == 1 and rep.result[0].name == "()":
772-
work.append((rep.result, names))
773-
else:
774-
# Report collection failures here to avoid failing to run some test
775-
# specified in the command line because the module could not be
776-
# imported (#134).
777-
node.ihook.pytest_collectreport(report=rep)
778-
779-
self.trace("matchnodes finished -> ", len(result), "nodes")
780-
self.trace.root.indent -= 1
781-
return result
782-
783784
def genitems(
784785
self, node: Union[nodes.Item, nodes.Collector]
785786
) -> Iterator[nodes.Item]:

0 commit comments

Comments
 (0)