Skip to content

Commit 5e59357

Browse files
make nodeids precalculated, there is no sane reason to commpute lazyly
1 parent 45b6b7d commit 5e59357

File tree

3 files changed

+31
-30
lines changed

3 files changed

+31
-30
lines changed

_pytest/main.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ class Session(nodes.FSCollector):
300300
def __init__(self, config):
301301
nodes.FSCollector.__init__(
302302
self, config.rootdir, parent=None,
303-
config=config, session=self)
303+
config=config, session=self, nodeid="")
304304
self.testsfailed = 0
305305
self.testscollected = 0
306306
self.shouldstop = False
@@ -311,9 +311,6 @@ def __init__(self, config):
311311

312312
self.config.pluginmanager.register(self, name="session")
313313

314-
def _makeid(self):
315-
return ""
316-
317314
@hookimpl(tryfirst=True)
318315
def pytest_collectstart(self):
319316
if self.shouldfail:

_pytest/nodes.py

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import attr
77

88
import _pytest
9+
import _pytest._code
10+
911
from _pytest.mark.structures import NodeKeywords
1012

1113
SEP = "/"
@@ -69,7 +71,7 @@ class Node(object):
6971
""" base class for Collector and Item the test collection tree.
7072
Collector subclasses have children, Items are terminal nodes."""
7173

72-
def __init__(self, name, parent=None, config=None, session=None):
74+
def __init__(self, name, parent=None, config=None, session=None, fspath=None, nodeid=None):
7375
#: a unique name within the scope of the parent node
7476
self.name = name
7577

@@ -83,7 +85,7 @@ def __init__(self, name, parent=None, config=None, session=None):
8385
self.session = session or parent.session
8486

8587
#: filesystem path where this node was collected from (can be None)
86-
self.fspath = getattr(parent, 'fspath', None)
88+
self.fspath = fspath or getattr(parent, 'fspath', None)
8789

8890
#: keywords/markers collected from all scopes
8991
self.keywords = NodeKeywords(self)
@@ -94,6 +96,12 @@ def __init__(self, name, parent=None, config=None, session=None):
9496
# used for storing artificial fixturedefs for direct parametrization
9597
self._name2pseudofixturedef = {}
9698

99+
if nodeid is not None:
100+
self._nodeid = nodeid
101+
else:
102+
assert parent is not None
103+
self._nodeid = self.parent.nodeid + "::" + self.name
104+
97105
@property
98106
def ihook(self):
99107
""" fspath sensitive hook proxy used to call pytest hooks"""
@@ -137,14 +145,7 @@ def warn(self, code, message):
137145
@property
138146
def nodeid(self):
139147
""" a ::-separated string denoting its collection tree address. """
140-
try:
141-
return self._nodeid
142-
except AttributeError:
143-
self._nodeid = x = self._makeid()
144-
return x
145-
146-
def _makeid(self):
147-
return self.parent.nodeid + "::" + self.name
148+
return self._nodeid
148149

149150
def __hash__(self):
150151
return hash(self.nodeid)
@@ -281,31 +282,34 @@ def _prunetraceback(self, excinfo):
281282
excinfo.traceback = ntraceback.filter()
282283

283284

285+
def _check_initialpaths_for_relpath(session, fspath):
286+
for initial_path in session._initialpaths:
287+
if fspath.common(initial_path) == initial_path:
288+
return fspath.relto(initial_path.dirname)
289+
290+
284291
class FSCollector(Collector):
285-
def __init__(self, fspath, parent=None, config=None, session=None):
292+
def __init__(self, fspath, parent=None, config=None, session=None, nodeid=None):
286293
fspath = py.path.local(fspath) # xxx only for test_resultlog.py?
287294
name = fspath.basename
288295
if parent is not None:
289296
rel = fspath.relto(parent.fspath)
290297
if rel:
291298
name = rel
292299
name = name.replace(os.sep, SEP)
293-
super(FSCollector, self).__init__(name, parent, config, session)
294300
self.fspath = fspath
295301

296-
def _check_initialpaths_for_relpath(self):
297-
for initialpath in self.session._initialpaths:
298-
if self.fspath.common(initialpath) == initialpath:
299-
return self.fspath.relto(initialpath.dirname)
302+
session = session or parent.session
303+
304+
if nodeid is None:
305+
nodeid = self.fspath.relto(session.config.rootdir)
300306

301-
def _makeid(self):
302-
relpath = self.fspath.relto(self.config.rootdir)
307+
if not nodeid:
308+
nodeid = _check_initialpaths_for_relpath(session, fspath)
309+
if os.sep != SEP:
310+
nodeid = nodeid.replace(os.sep, SEP)
303311

304-
if not relpath:
305-
relpath = self._check_initialpaths_for_relpath()
306-
if os.sep != SEP:
307-
relpath = relpath.replace(os.sep, SEP)
308-
return relpath
312+
super(FSCollector, self).__init__(name, parent, config, session, nodeid=nodeid, fspath=fspath)
309313

310314

311315
class File(FSCollector):
@@ -318,8 +322,8 @@ class Item(Node):
318322
"""
319323
nextitem = None
320324

321-
def __init__(self, name, parent=None, config=None, session=None):
322-
super(Item, self).__init__(name, parent, config, session)
325+
def __init__(self, name, parent=None, config=None, session=None, nodeid=None):
326+
super(Item, self).__init__(name, parent, config, session, nodeid=nodeid)
323327
self._report_sections = []
324328

325329
#: user properties is a list of tuples (name, value) that holds user

testing/test_resultlog.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ def test_generic_path(testdir):
1313
from _pytest.main import Session
1414
config = testdir.parseconfig()
1515
session = Session(config)
16-
p1 = Node('a', config=config, session=session)
16+
p1 = Node('a', config=config, session=session, nodeid='a')
1717
# assert p1.fspath is None
1818
p2 = Node('B', parent=p1)
1919
p3 = Node('()', parent=p2)

0 commit comments

Comments
 (0)