collection: performance: use optimized parts function

Time: 8.53s => 5.73s
This commit is contained in:
Anders Hovmöller 2018-10-25 15:09:14 +02:00 committed by Daniel Hahler
parent f2cebce2eb
commit a41820fbf0
3 changed files with 13 additions and 10 deletions

View File

@ -18,6 +18,7 @@ from _pytest.config import directory_arg
from _pytest.config import hookimpl from _pytest.config import hookimpl
from _pytest.config import UsageError from _pytest.config import UsageError
from _pytest.outcomes import exit from _pytest.outcomes import exit
from _pytest.pathlib import parts
from _pytest.runner import collect_one_node from _pytest.runner import collect_one_node
@ -469,8 +470,8 @@ class Session(nodes.FSCollector):
return items return items
def collect(self): def collect(self):
for parts in self._initialparts: for initialpart in self._initialparts:
arg = "::".join(map(str, parts)) arg = "::".join(map(str, initialpart))
self.trace("processing argument", arg) self.trace("processing argument", arg)
self.trace.root.indent += 1 self.trace.root.indent += 1
try: try:
@ -532,12 +533,12 @@ class Session(nodes.FSCollector):
fil=filter_, rec=self._recurse, bf=True, sort=True fil=filter_, rec=self._recurse, bf=True, sort=True
): ):
pkginit = path.dirpath().join("__init__.py") pkginit = path.dirpath().join("__init__.py")
if pkginit.exists() and not any(x in pkginit.parts() for x in paths): if pkginit.exists() and not any(x in parts(pkginit.strpath) for x in paths):
for x in root._collectfile(pkginit): for x in root._collectfile(pkginit):
yield x yield x
paths.append(x.fspath.dirpath()) paths.append(x.fspath.dirpath())
if not any(x in path.parts() for x in paths): if not any(x in parts(path.strpath) for x in paths):
for x in root._collectfile(path): for x in root._collectfile(path):
if (type(x), x.fspath) in self._node_cache: if (type(x), x.fspath) in self._node_cache:
yield self._node_cache[(type(x), x.fspath)] yield self._node_cache[(type(x), x.fspath)]

View File

@ -303,3 +303,8 @@ def fnmatch_ex(pattern, path):
else: else:
name = six.text_type(path) name = six.text_type(path)
return fnmatch.fnmatch(name, pattern) return fnmatch.fnmatch(name, pattern)
def parts(s):
parts = s.split(sep)
return [sep.join(parts[:i+1]) or sep for i in range(len(parts))]

View File

@ -41,6 +41,7 @@ from _pytest.mark.structures import get_unpacked_marks
from _pytest.mark.structures import normalize_mark_list from _pytest.mark.structures import normalize_mark_list
from _pytest.mark.structures import transfer_markers from _pytest.mark.structures import transfer_markers
from _pytest.outcomes import fail from _pytest.outcomes import fail
from _pytest.pathlib import parts
from _pytest.warning_types import PytestWarning from _pytest.warning_types import PytestWarning
from _pytest.warning_types import RemovedInPytest4Warning from _pytest.warning_types import RemovedInPytest4Warning
@ -562,14 +563,10 @@ class Package(Module):
yield Module(init_module, self) yield Module(init_module, self)
pkg_prefixes = set() pkg_prefixes = set()
for path in this_path.visit(rec=self._recurse, bf=True, sort=True): for path in this_path.visit(rec=self._recurse, bf=True, sort=True):
# We will visit our own __init__.py file, in which case we skip it.
if path.isfile():
if path.basename == "__init__.py" and path.dirpath() == this_path:
continue
parts = path.parts() parts_ = parts(path.strpath)
if any( if any(
pkg_prefix in parts and pkg_prefix.join("__init__.py") != path pkg_prefix in parts_ and pkg_prefix.join("__init__.py") != path
for pkg_prefix in pkg_prefixes for pkg_prefix in pkg_prefixes
): ):
continue continue