unify collection for finding items and for finding initial nodes.

--HG--
branch : trunk
This commit is contained in:
holger krekel 2010-10-25 23:08:41 +02:00
parent 603ff3a64f
commit a6f10a6d80
3 changed files with 44 additions and 40 deletions

View File

@ -272,7 +272,8 @@ class TmpTestdir:
def genitems(self, colitems): def genitems(self, colitems):
collection = colitems[0].collection collection = colitems[0].collection
result = [] result = []
collection.genitems(colitems, (), result) for colitem in colitems:
result.extend(collection.genitems(colitem))
return result return result
def inline_genitems(self, *args): def inline_genitems(self, *args):

View File

@ -105,6 +105,10 @@ class Session(object):
self.shouldstop = False self.shouldstop = False
self.collection = Collection(config) # XXX move elswehre self.collection = Collection(config) # XXX move elswehre
def pytest_collectstart(self):
if self.shouldstop:
raise self.Interrupted(self.shouldstop)
def pytest_runtest_logreport(self, report): def pytest_runtest_logreport(self, report):
if report.failed and 'xfail' not in getattr(report, 'keywords', []): if report.failed and 'xfail' not in getattr(report, 'keywords', []):
self._testsfailed += 1 self._testsfailed += 1
@ -112,7 +116,6 @@ class Session(object):
if maxfail and self._testsfailed >= maxfail: if maxfail and self._testsfailed >= maxfail:
self.shouldstop = "stopping after %d failures" % ( self.shouldstop = "stopping after %d failures" % (
self._testsfailed) self._testsfailed)
self.collection.shouldstop = self.shouldstop
pytest_collectreport = pytest_runtest_logreport pytest_collectreport = pytest_runtest_logreport
def main(self): def main(self):
@ -200,49 +203,32 @@ class Collection:
names = [x for x in id.split("::") if x] names = [x for x in id.split("::") if x]
if names and '/' in names[0]: if names and '/' in names[0]:
names[:1] = names[0].split("/") names[:1] = names[0].split("/")
return self._match([self._topcollector], names) return list(self.matchnodes([self._topcollector], names))
def _match(self, matching, names):
while names:
name = names.pop(0)
l = []
for current in matching:
for x in current._memocollect():
if x.name == name:
l.append(x)
elif x.name == "()":
names.insert(0, name)
l.append(x)
break
if not l:
raise ValueError("no node named %r below %r" %(name, current))
matching = l
return matching
def perform_collect(self): def perform_collect(self):
nodes = [] items = []
for arg in self.config.args: for arg in self.config.args:
names = self._parsearg(arg) names = self._parsearg(arg)
try: try:
self.genitems([self._topcollector], names, nodes) for node in self.matchnodes([self._topcollector], names):
items.extend(self.genitems(node))
except NoMatch: except NoMatch:
raise self.config.Error("can't collect: %s" % (arg,)) raise self.config.Error("can't collect: %s" % (arg,))
return nodes return items
def genitems(self, matching, names, result): def matchnodes(self, matching, names):
if not matching: if not matching:
assert not names
return return
if names: if not names:
name = names[0] for x in matching:
names = names[1:] yield x
else: return
name = None name = names[0]
names = names[1:]
for node in matching: for node in matching:
if isinstance(node, pytest.collect.Item): if isinstance(node, pytest.collect.Item):
if name is None: if not name:
node.ihook.pytest_log_itemcollect(item=node) yield node
result.append(node)
continue continue
assert isinstance(node, pytest.collect.Collector) assert isinstance(node, pytest.collect.Collector)
node.ihook.pytest_collectstart(collector=node) node.ihook.pytest_collectstart(collector=node)
@ -250,16 +236,19 @@ class Collection:
#print "matching", rep.result, "against name", name #print "matching", rep.result, "against name", name
if rep.passed: if rep.passed:
if not name: if not name:
self.genitems(rep.result, [], result) for x in rep.result:
yield x
else: else:
matched = False matched = False
for x in rep.result: for x in rep.result:
try: try:
if x.name == name or x.fspath.basename == name: if x.name == name or x.fspath.basename == name:
self.genitems([x], names, result) for x in self.matchnodes([x], names):
yield x
matched = True matched = True
elif x.name == "()": # XXX special Instance() case elif x.name == "()": # XXX special Instance() case
self.genitems([x], [name] + names, result) for x in self.matchnodes([x], [name] + names):
yield x
matched = True matched = True
except NoMatch: except NoMatch:
pass pass
@ -267,12 +256,23 @@ class Collection:
node.ihook.pytest_collectreport(report=rep) node.ihook.pytest_collectreport(report=rep)
raise NoMatch(name) raise NoMatch(name)
node.ihook.pytest_collectreport(report=rep) node.ihook.pytest_collectreport(report=rep)
x = getattr(self, 'shouldstop', None)
if x: def genitems(self, node):
raise Session.Interrupted(x) if isinstance(node, pytest.collect.Item):
node.ihook.pytest_log_itemcollect(item=node)
yield node
else:
assert isinstance(node, pytest.collect.Collector)
node.ihook.pytest_collectstart(collector=node)
rep = node.ihook.pytest_make_collect_report(collector=node)
if rep.passed:
for subnode in rep.result or []:
for x in self.genitems(subnode):
yield x
node.ihook.pytest_collectreport(report=rep)
class NoMatch(Exception): class NoMatch(Exception):
""" raised if genitems cannot locate a matching names. """ """ raised if matching 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.

View File

@ -8,6 +8,9 @@ rsyncdirs = ['conftest.py', '../pytest', '../doc', '.']
import os, py import os, py
def pytest_report_header():
return "pid: %s" % os.getpid()
def pytest_generate_tests(metafunc): def pytest_generate_tests(metafunc):
multi = getattr(metafunc.function, 'multi', None) multi = getattr(metafunc.function, 'multi', None)
if multi is not None: if multi is not None: