diff --git a/ISSUES.txt b/ISSUES.txt index 4474b4a29..415ed8b9a 100644 --- a/ISSUES.txt +++ b/ISSUES.txt @@ -4,6 +4,8 @@ tags: bug 1.4 core xdist * reportinfo -> location in hooks and items * check oejskit plugin compatibility +* terminal reporting - dot-printing +* some simple profiling refine session initialization / fix custom collect crash --------------------------------------------------------------- diff --git a/py/_test/session.py b/py/_test/session.py index db9bcc1f8..4d40908d0 100644 --- a/py/_test/session.py +++ b/py/_test/session.py @@ -138,15 +138,14 @@ class Collection: def getbyid(self, id): """ return one or more nodes matching the id. """ - matching = [self._topcollector] - if not id: - return matching - names = id.split("::") + names = filter(None, id.split("::")) + if names and '/' in names[0]: + names[:1] = names[0].split("/") + return self._match([self._topcollector], names) + + def _match(self, matching, names): while names: name = names.pop(0) - newnames = name.split("/") - name = newnames[0] - names[:0] = newnames[1:] l = [] for current in matching: for x in current._memocollect(): @@ -169,22 +168,28 @@ class Collection: return nodes def perform_collect(self): - idlist = [self._parsearg(arg) for arg in self.config.args] nodes = [] - for names in idlist: - self.genitems([self._topcollector], names, nodes) + for arg in self.config.args: + names = self._parsearg(arg) + try: + self.genitems([self._topcollector], names, nodes) + except NoMatch: + raise self.config.Error("can't collect: %s" % (arg,)) return nodes def genitems(self, matching, names, result): if not matching: assert not names - return result - names = list(names) - name = names and names.pop(0) or None + return + if names: + name = names[0] + names = names[1:] + else: + name = None for node in matching: if isinstance(node, py.test.collect.Item): if name is None: - self.config.hook.pytest_log_itemcollect(item=node) + node.ihook.pytest_log_itemcollect(item=node) result.append(node) continue assert isinstance(node, py.test.collect.Collector) @@ -192,27 +197,31 @@ class Collection: rep = node.ihook.pytest_make_collect_report(collector=node) #print "matching", rep.result, "against name", name if rep.passed: - if 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: + if not name: 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) x = getattr(self, 'shouldstop', None) if x: raise Session.Interrupted(x) +class NoMatch(Exception): + """ raised if genitems cannot locate a matching names. """ + def gettopdir(args): """ return the top directory for the given paths. if the common base dir resides in a python package diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index faf27ea12..0b521eef8 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -191,3 +191,23 @@ class TestGeneralUsage: for dirname, other_dirname in [('a', 'b'), ('b', 'a')]: result = testdir.runpytest(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*", + ]) +