summaryrefslogtreecommitdiff
path: root/src/_pytest/main.py
diff options
context:
space:
mode:
authorRan Benita <ran@unusedvar.com>2020-08-22 11:35:54 +0300
committerRan Benita <ran@unusedvar.com>2020-08-24 18:15:11 +0300
commitc867452488659729c2caef82cd323c79a2a19b08 (patch)
tree5e9388c391989890343692d47396d2ff00245e1e /src/_pytest/main.py
parentd0e8b71404efc19554dbe5b38a226c31b7e281b9 (diff)
downloadpytest-c867452488659729c2caef82cd323c79a2a19b08.tar.gz
main: inline matchnodes() into collect()
Now all of the logic is in one place and may be simplified and refactored in more sensible way.
Diffstat (limited to 'src/_pytest/main.py')
-rw-r--r--src/_pytest/main.py101
1 files changed, 51 insertions, 50 deletions
diff --git a/src/_pytest/main.py b/src/_pytest/main.py
index a581cbe23..69ea46a40 100644
--- a/src/_pytest/main.py
+++ b/src/_pytest/main.py
@@ -707,8 +707,53 @@ class Session(nodes.FSCollector):
col = collect_root._collectfile(argpath, handle_dupes=False)
if col:
self._collection_node_cache1[argpath] = col
- m = self.matchnodes(col, names)
- if not m:
+
+ matching = []
+ work = [
+ (col, names)
+ ] # type: List[Tuple[Sequence[Union[nodes.Item, nodes.Collector]], Sequence[str]]]
+ while work:
+ self.trace("matchnodes", col, names)
+ self.trace.root.indent += 1
+
+ matchnodes, matchnames = work.pop()
+ for node in matchnodes:
+ if not matchnames:
+ matching.append(node)
+ continue
+ if not isinstance(node, nodes.Collector):
+ continue
+ key = (type(node), node.nodeid)
+ if key in self._collection_matchnodes_cache:
+ rep = self._collection_matchnodes_cache[key]
+ else:
+ rep = collect_one_node(node)
+ self._collection_matchnodes_cache[key] = rep
+ if rep.passed:
+ submatchnodes = []
+ for r in rep.result:
+ # TODO: Remove parametrized workaround once collection structure contains
+ # parametrization.
+ if (
+ r.name == matchnames[0]
+ or r.name.split("[")[0] == matchnames[0]
+ ):
+ submatchnodes.append(r)
+ if submatchnodes:
+ work.append((submatchnodes, matchnames[1:]))
+ # XXX Accept IDs that don't have "()" for class instances.
+ elif len(rep.result) == 1 and rep.result[0].name == "()":
+ work.append((rep.result, matchnames))
+ else:
+ # Report collection failures here to avoid failing to run some test
+ # specified in the command line because the module could not be
+ # imported (#134).
+ node.ihook.pytest_collectreport(report=rep)
+
+ self.trace("matchnodes finished -> ", len(matching), "nodes")
+ self.trace.root.indent -= 1
+
+ if not matching:
report_arg = "::".join((str(argpath), *names))
self._notfound.append((report_arg, col))
continue
@@ -718,16 +763,17 @@ class Session(nodes.FSCollector):
# Module itself, so just use that. If this special case isn't taken, then all
# the files in the package will be yielded.
if argpath.basename == "__init__.py":
- assert isinstance(m[0], nodes.Collector)
+ assert isinstance(matching[0], nodes.Collector)
try:
- yield next(iter(m[0].collect()))
+ yield next(iter(matching[0].collect()))
except StopIteration:
# The package collects nothing with only an __init__.py
# file in it, which gets ignored by the default
# "python_files" option.
pass
continue
- yield from m
+
+ yield from matching
self.trace.root.indent -= 1
self._collection_node_cache1.clear()
@@ -735,51 +781,6 @@ class Session(nodes.FSCollector):
self._collection_matchnodes_cache.clear()
self._collection_pkg_roots.clear()
- def matchnodes(
- self,
- matching: Sequence[Union[nodes.Item, nodes.Collector]],
- names: Sequence[str],
- ) -> Sequence[Union[nodes.Item, nodes.Collector]]:
- result = []
- work = [(matching, names)]
- while work:
- self.trace("matchnodes", matching, names)
- self.trace.root.indent += 1
-
- matching, names = work.pop()
- for node in matching:
- if not names:
- result.append(node)
- continue
- if not isinstance(node, nodes.Collector):
- continue
- key = (type(node), node.nodeid)
- if key in self._collection_matchnodes_cache:
- rep = self._collection_matchnodes_cache[key]
- else:
- rep = collect_one_node(node)
- self._collection_matchnodes_cache[key] = rep
- if rep.passed:
- submatching = []
- for x in rep.result:
- # TODO: Remove parametrized workaround once collection structure contains parametrization.
- if x.name == names[0] or x.name.split("[")[0] == names[0]:
- submatching.append(x)
- if submatching:
- work.append((submatching, names[1:]))
- # XXX Accept IDs that don't have "()" for class instances.
- elif len(rep.result) == 1 and rep.result[0].name == "()":
- work.append((rep.result, names))
- else:
- # Report collection failures here to avoid failing to run some test
- # specified in the command line because the module could not be
- # imported (#134).
- node.ihook.pytest_collectreport(report=rep)
-
- self.trace("matchnodes finished -> ", len(result), "nodes")
- self.trace.root.indent -= 1
- return result
-
def genitems(
self, node: Union[nodes.Item, nodes.Collector]
) -> Iterator[nodes.Item]: