fix a collection bug where a:🅱️:c could not be resolved properly if

there are multiple 'b' nodes.

--HG--
branch : trunk
This commit is contained in:
holger krekel 2010-09-28 15:24:36 +02:00
parent f779d3f863
commit a60e470573
3 changed files with 60 additions and 29 deletions

View File

@ -4,6 +4,8 @@ tags: bug 1.4 core xdist
* reportinfo -> location in hooks and items * reportinfo -> location in hooks and items
* check oejskit plugin compatibility * check oejskit plugin compatibility
* terminal reporting - dot-printing
* some simple profiling
refine session initialization / fix custom collect crash refine session initialization / fix custom collect crash
--------------------------------------------------------------- ---------------------------------------------------------------

View File

@ -138,15 +138,14 @@ class Collection:
def getbyid(self, id): def getbyid(self, id):
""" return one or more nodes matching the id. """ """ return one or more nodes matching the id. """
matching = [self._topcollector] names = filter(None, id.split("::"))
if not id: if names and '/' in names[0]:
return matching names[:1] = names[0].split("/")
names = id.split("::") return self._match([self._topcollector], names)
def _match(self, matching, names):
while names: while names:
name = names.pop(0) name = names.pop(0)
newnames = name.split("/")
name = newnames[0]
names[:0] = newnames[1:]
l = [] l = []
for current in matching: for current in matching:
for x in current._memocollect(): for x in current._memocollect():
@ -169,22 +168,28 @@ class Collection:
return nodes return nodes
def perform_collect(self): def perform_collect(self):
idlist = [self._parsearg(arg) for arg in self.config.args]
nodes = [] nodes = []
for names in idlist: for arg in self.config.args:
self.genitems([self._topcollector], names, nodes) names = self._parsearg(arg)
try:
self.genitems([self._topcollector], names, nodes)
except NoMatch:
raise self.config.Error("can't collect: %s" % (arg,))
return nodes return nodes
def genitems(self, matching, names, result): def genitems(self, matching, names, result):
if not matching: if not matching:
assert not names assert not names
return result return
names = list(names) if names:
name = names and names.pop(0) or None name = names[0]
names = names[1:]
else:
name = None
for node in matching: for node in matching:
if isinstance(node, py.test.collect.Item): if isinstance(node, py.test.collect.Item):
if name is None: if name is None:
self.config.hook.pytest_log_itemcollect(item=node) node.ihook.pytest_log_itemcollect(item=node)
result.append(node) result.append(node)
continue continue
assert isinstance(node, py.test.collect.Collector) assert isinstance(node, py.test.collect.Collector)
@ -192,27 +197,31 @@ class Collection:
rep = node.ihook.pytest_make_collect_report(collector=node) rep = node.ihook.pytest_make_collect_report(collector=node)
#print "matching", rep.result, "against name", name #print "matching", rep.result, "against name", name
if rep.passed: if rep.passed:
if name: if not name:
matched = False
for subcol in rep.result:
if subcol.name != name and subcol.name == "()":
names.insert(0, name)
name = "()"
# see doctests/custom naming XXX
if subcol.name == name or subcol.fspath.basename == name:
self.genitems([subcol], names, result)
matched = True
if not matched:
raise self.config.Error(
"can't collect: %s" % (name,))
else:
self.genitems(rep.result, [], result) self.genitems(rep.result, [], result)
else:
matched = False
for x in rep.result:
try:
if x.name == name or x.fspath.basename == name:
self.genitems([x], names, result)
matched = True
elif x.name == "()": # XXX special Instance() case
self.genitems([x], [name] + names, result)
matched = True
except NoMatch:
pass
if not matched:
node.ihook.pytest_collectreport(report=rep)
raise NoMatch(name)
node.ihook.pytest_collectreport(report=rep) node.ihook.pytest_collectreport(report=rep)
x = getattr(self, 'shouldstop', None) x = getattr(self, 'shouldstop', None)
if x: if x:
raise Session.Interrupted(x) raise Session.Interrupted(x)
class NoMatch(Exception):
""" raised if genitems cannot locate a matching names. """
def gettopdir(args): def gettopdir(args):
""" return the top directory for the given paths. """ return the top directory for the given paths.
if the common base dir resides in a python package if the common base dir resides in a python package

View File

@ -191,3 +191,23 @@ class TestGeneralUsage:
for dirname, other_dirname in [('a', 'b'), ('b', 'a')]: for dirname, other_dirname in [('a', 'b'), ('b', 'a')]:
result = testdir.runpytest(dirname) result = testdir.runpytest(dirname)
assert result.ret == 0, "test_sibling_conftest: py.test run for '%s', but '%s/conftest.py' loaded." % (dirname, other_dirname) assert result.ret == 0, "test_sibling_conftest: py.test run for '%s', but '%s/conftest.py' loaded." % (dirname, other_dirname)
def test_multiple_items_per_collector_byid(self, testdir):
c = testdir.makeconftest("""
import py
class MyItem(py.test.collect.Item):
def runtest(self):
pass
class MyCollector(py.test.collect.File):
def collect(self):
return [MyItem(name="xyz", parent=self)]
def pytest_collect_file(path, parent):
if path.basename.startswith("conftest"):
return MyCollector(path, parent)
""")
result = testdir.runpytest(c.basename+"::"+"xyz")
assert result.ret == 0
result.stdout.fnmatch_lines([
"*1 pass*",
])