diff options
author | Ran Benita <ran@unusedvar.com> | 2020-08-22 11:35:54 +0300 |
---|---|---|
committer | Ran Benita <ran@unusedvar.com> | 2020-08-24 18:15:11 +0300 |
commit | c867452488659729c2caef82cd323c79a2a19b08 (patch) | |
tree | 5e9388c391989890343692d47396d2ff00245e1e /src/_pytest/main.py | |
parent | d0e8b71404efc19554dbe5b38a226c31b7e281b9 (diff) | |
download | pytest-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.py | 101 |
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]: |