Skip to content

Commit 655ab0b

Browse files
Address more review comments, fix massive bug I reintroduced in the node-splitting code :-/
1 parent a7199fa commit 655ab0b

File tree

4 files changed

+49
-45
lines changed

4 files changed

+49
-45
lines changed

_pytest/fixtures.py

Lines changed: 8 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
from __future__ import absolute_import, division, print_function
2-
import sys
32

4-
from py._code.code import FormattedExcinfo
3+
import inspect
4+
import sys
5+
import warnings
56

67
import py
7-
import warnings
8+
from py._code.code import FormattedExcinfo
89

9-
import inspect
1010
import _pytest
1111
from _pytest._code.code import TerminalRepr
1212
from _pytest.compat import (
@@ -15,9 +15,11 @@
1515
is_generator, isclass, getimfunc,
1616
getlocation, getfuncargnames,
1717
safe_getattr,
18+
FuncargnamesCompatAttr,
1819
)
20+
from _pytest.nodes import ischildnode
1921
from _pytest.outcomes import fail, TEST_OUTCOME
20-
from _pytest.compat import FuncargnamesCompatAttr
22+
2123

2224
if sys.version_info[:2] == (2, 6):
2325
from ordereddict import OrderedDict
@@ -1130,40 +1132,7 @@ def getfixturedefs(self, argname, nodeid):
11301132
else:
11311133
return tuple(self._matchfactories(fixturedefs, nodeid))
11321134

1133-
@classmethod
1134-
def _splitnode(cls, nodeid):
1135-
"""Split a nodeid into constituent 'parts'.
1136-
1137-
Node IDs are strings, and can be things like:
1138-
''
1139-
'testing/code'
1140-
'testing/code/test_excinfo.py'
1141-
'testing/code/test_excinfo.py::TestFormattedExcinfo::()'
1142-
1143-
Return values are lists e.g.
1144-
['']
1145-
['testing', 'code']
1146-
['testing', 'code', 'test_excinfo.py']
1147-
['testing', 'code', 'test_excinfo.py', 'TestFormattedExcinfo', '()']
1148-
"""
1149-
parts = nodeid.split(py.path.local.sep)
1150-
# Replace single last element 'test_foo.py::Bar::()' with multiple elements 'test_foo.py', 'Bar', '()'
1151-
parts[-1:] = parts[-1].split("::")
1152-
return parts
1153-
1154-
@classmethod
1155-
def _ischildnode(cls, baseid, nodeid):
1156-
"""Return True if the nodeid is a child node of the baseid.
1157-
1158-
E.g. 'foo/bar::Baz::()' is a child of 'foo', 'foo/bar' and 'foo/bar::Baz', but not of 'foo/blorp'
1159-
"""
1160-
base_parts = cls._splitnode(baseid)
1161-
node_parts = cls._splitnode(nodeid)
1162-
if len(node_parts) < len(base_parts):
1163-
return False
1164-
return node_parts[:len(base_parts)] == base_parts
1165-
11661135
def _matchfactories(self, fixturedefs, nodeid):
11671136
for fixturedef in fixturedefs:
1168-
if self._ischildnode(fixturedef.baseid, nodeid):
1137+
if ischildnode(fixturedef.baseid, nodeid):
11691138
yield fixturedef

_pytest/nodes.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import py
2+
3+
4+
def _splitnode(nodeid):
5+
"""Split a nodeid into constituent 'parts'.
6+
7+
Node IDs are strings, and can be things like:
8+
''
9+
'testing/code'
10+
'testing/code/test_excinfo.py'
11+
'testing/code/test_excinfo.py::TestFormattedExcinfo::()'
12+
13+
Return values are lists e.g.
14+
[]
15+
['testing', 'code']
16+
['testing', 'code', 'test_excinfo.py']
17+
['testing', 'code', 'test_excinfo.py', 'TestFormattedExcinfo', '()']
18+
"""
19+
if nodeid == '':
20+
# If there is no root node at all, return an empty list so the caller's logic can remain sane
21+
return []
22+
parts = nodeid.split(py.path.local.sep)
23+
# Replace single last element 'test_foo.py::Bar::()' with multiple elements 'test_foo.py', 'Bar', '()'
24+
parts[-1:] = parts[-1].split("::")
25+
return parts
26+
27+
28+
def ischildnode(baseid, nodeid):
29+
"""Return True if the nodeid is a child node of the baseid.
30+
31+
E.g. 'foo/bar::Baz::()' is a child of 'foo', 'foo/bar' and 'foo/bar::Baz', but not of 'foo/blorp'
32+
"""
33+
base_parts = _splitnode(baseid)
34+
node_parts = _splitnode(nodeid)
35+
if len(node_parts) < len(base_parts):
36+
return False
37+
return node_parts[:len(base_parts)] == base_parts

changelog/2836.bug

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1 @@
1-
Attempted fix for https://github.com/pytest-dev/pytest/issues/2836
2-
3-
Improves the handling of "nodeid"s to be more aware of path and class separators.
1+
Match fixture paths against actual path segments in order to avoid matching folders which share a prefix.

testing/test_fixtures.py renamed to testing/test_nodes.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import pytest
22

3-
from _pytest import fixtures
3+
from _pytest import nodes
44

55

66
@pytest.mark.parametrize("baseid, nodeid, expected", (
@@ -13,6 +13,6 @@
1313
('foo/bar::TestBaz::()', 'foo/bar::TestBop::()', False),
1414
('foo/bar', 'foo/bar::TestBop::()', True),
1515
))
16-
def test_fixturemanager_ischildnode(baseid, nodeid, expected):
17-
result = fixtures.FixtureManager._ischildnode(baseid, nodeid)
16+
def test_ischildnode(baseid, nodeid, expected):
17+
result = nodes.ischildnode(baseid, nodeid)
1818
assert result is expected

0 commit comments

Comments
 (0)