[py-svn] r12006 - in py/dist/py/test: . terminal
hpk at codespeak.net
hpk at codespeak.net
Fri May 6 12:36:57 CEST 2005
Author: hpk
Date: Fri May 6 12:36:56 2005
New Revision: 12006
Modified:
py/dist/py/test/collect.py
py/dist/py/test/item.py
py/dist/py/test/terminal/remote.py
Log:
make building the collector's tree more persistent
by introducing "buildname2items()" which is responsible
for building a dictionary mapping names to collectors/items.
the default run()/join() methods now build this dictionary
and cache it.
The net result is that py lib's own and PyPy's test runs
run some 10% faster and are somewhat saner!
Modified: py/dist/py/test/collect.py
==============================================================================
--- py/dist/py/test/collect.py (original)
+++ py/dist/py/test/collect.py Fri May 6 12:36:56 2005
@@ -41,19 +41,17 @@
raise py.error.ENOENT(fspath)
pkgpath = fspath.pypkgpath()
if pkgpath is None:
- if fspath.check(file=1):
- clsname = 'Module'
- else:
- clsname = 'Directory'
+ clsname = fspath.check(file=1) and 'Module' or 'Directory'
fscol = py.test.Config.getvalue(clsname, fspath)
current = fscol(fspath)
else:
Directory = py.test.Config.getvalue('Directory', pkgpath)
current = Directory(pkgpath)
#print "pkgpath", pkgpath
- for name in filter(None, fspath.relto(pkgpath).split(fspath.sep)):
- #print "joining", name
+ names = fspath.relto(pkgpath).split(fspath.sep)
+ for name in names:
current = current.join(name)
+ assert current, "joining %r resulted in None!" % (names,)
top = current.listchain()[0]
#top._config = config
return current
@@ -104,6 +102,12 @@
except AttributeError:
return False
+ def __cmp__(self, other):
+ s1 = self.getsortvalue()
+ s2 = other.getsortvalue()
+ #print "cmp", s1, s2
+ return cmp(s1, s2)
+
def obj():
def fget(self):
try:
@@ -119,13 +123,6 @@
def _getobj(self):
return getattr(self.parent.obj, self.name)
- def sortvalue(self):
- """ sorting function helper to bring test methods in
- the same order as in their file.
- """
- for x in self.run():
- return self.join(x).sortvalue()
-
def multijoin(self, namelist):
""" return a list of colitems for the given namelist. """
return [self.join(name) for name in namelist]
@@ -184,6 +181,26 @@
for y in self.join(x).tryiter(stopitems):
yield y
+ def _prepare(self):
+ if not hasattr(self, 'name2items'):
+ self.name2items = self.buildname2items()
+
+ def buildname2items(self):
+ raise NotImplementedError, "abstract"
+
+ def getsortvalue(self):
+ return self.name
+
+ def run(self):
+ self._prepare()
+ itemlist = self.name2items.values()
+ itemlist.sort()
+ return [x.name for x in itemlist]
+
+ def join(self, name):
+ self._prepare()
+ return self.name2items.get(name, None)
+
captured_out = captured_err = None
def startcapture(self):
return None # by default collectors don't capture output
@@ -194,8 +211,7 @@
class FSCollector(Collector):
def __init__(self, fspath, parent=None):
- if isinstance(fspath, str):
- fspath = py.path.local(fspath)
+ fspath = py.path.local(fspath)
super(FSCollector, self).__init__(fspath.basename, parent)
self.fspath = fspath
@@ -209,20 +225,27 @@
return path.check(dotfile=0) and \
path.basename not in ('CVS', '_darcs', '{arch}')
- def run(self):
- l = self.fspath.listdir()
- l.sort()
- return [x.basename for x in l
- if (x.check(file=1) and self.filefilter(x) or
- x.check(dir=1) and self.recfilter(x))]
+ def buildname2items(self):
+ d = {}
+ for p in self.fspath.listdir():
+ x = self.makeitem(p.basename, self.filefilter, self.recfilter)
+ if x is not None:
+ d[p.basename] = x
+ return d
+
+ def makeitem(self, basename, filefilter=None, recfilter=None):
+ p = self.fspath.join(basename)
+ if p.check(file=1) and (not filefilter or filefilter(p)):
+ return self.Module(p, parent=self)
+ elif p.check(dir=1) and (not recfilter or recfilter(p)):
+ Directory = py.test.Config.getvalue('Directory', p)
+ return Directory(p, parent=self)
def join(self, name):
- x = self.fspath.join(name)
- if x.check(file=1):
- return self.Module(x, parent=self)
- elif x.check(dir=1):
- Directory = py.test.Config.getvalue('Directory', x)
- return Directory(x, parent=self)
+ x = super(Directory, self).join(name)
+ if x is None:
+ x = self.makeitem(name)
+ return x
class PyCollectorMixin(object):
def funcnamefilter(self, name):
@@ -230,28 +253,20 @@
def classnamefilter(self, name):
return name.startswith('Test')
- def run(self):
- l = []
+ def buildname2items(self):
+ d = {}
for name in dir(self.obj):
- if self.funcnamefilter(name) or self.classnamefilter(name):
- x = self.join(name)
- if x is not None:
- l.append((x.sortvalue(), name))
- l.sort()
- return [x[1] for x in l]
-
- def join(self, name):
- obj = getattr(self.obj, name)
- if isclass(obj):
- return self.Class(name, parent=self)
- elif callable(obj):
- if obj.func_code.co_flags & 32: # generator function
- return self.Generator(name, parent=self)
- else:
- return self.Function(name, parent=self)
+ obj = getattr(self.obj, name)
+ if self.classnamefilter(name) and isclass(obj):
+ d[name] = self.Class(name, parent=self)
+ elif self.funcnamefilter(name) and callable(obj):
+ if obj.func_code.co_flags & 32: # generator function
+ d[name] = self.Generator(name, parent=self)
+ else:
+ d[name] = self.Function(name, parent=self)
+ return d
class Module(PyCollectorMixin, FSCollector):
-
def startcapture(self):
if not self.option.nocapture and not self.option.usepdb:
self._capture = SimpleOutErrCapture()
@@ -289,6 +304,7 @@
if hasattr(self.obj, 'teardown_module'):
self.obj.teardown_module(self.obj)
+
class Class(PyCollectorMixin, Collector):
def run(self):
if getattr(self.obj, 'disabled', 0):
@@ -311,6 +327,10 @@
teardown_class = getattr(teardown_class, 'im_func', teardown_class)
teardown_class(self.obj)
+ def getsortvalue(self):
+ for x in self.tryiter((py.test.collect.Generator, py.test.Item)):
+ return x.getsortvalue()
+
class Instance(PyCollectorMixin, Collector):
def _getobj(self):
return self.parent.obj()
@@ -320,37 +340,16 @@
Function = property(Function)
class Generator(Collector):
- def run(self):
- #def iterator():
- # for i,x in py.builtin.enumerate(self.obj()):
- # yield self.join("[%d]" % i)
- #return py.builtin.collect(iterator())
- self._objlist = l = []
- namelist = []
+ def buildname2items(self):
+ d = {}
for i, x in py.builtin.enumerate(self.obj()):
- call,args = self.getcallargs(x)
+ call, args = self.getcallargs(x)
if not callable(call):
raise TypeError("yielded test %r not callable" %(call,))
- l.append(x)
- namelist.append("[%d]" % i)
- return namelist
-
- def join(self, name):
- if name[:1] != '[' or name[-1:] != ']':
- raise NameError("%r is not an index" %(name,))
- num = int(name[1:-1])
- try:
- objlist = self._objlist
- except AttributeError:
- self._objlist = objlist = list(self.obj())
- for i, x in py.builtin.enumerate(objlist):
- if i == num:
- if isinstance(x, (Collector, )):
- return x
- call, args = self.getcallargs(x)
- assert callable(call)
- return self.Function(name, self, args, obj=call)
-
+ name = "[%d]" % i
+ d[name] = self.Function(name, self, args, obj=call)
+ return d
+
def getcallargs(self, obj):
if isinstance(obj, (tuple, list)):
call, args = obj[0], obj[1:]
@@ -362,5 +361,5 @@
code = py.code.Code(self.obj)
return code.path, code.firstlineno
- def sortvalue(self):
+ def getsortvalue(self):
return self.getpathlineno()
Modified: py/dist/py/test/item.py
==============================================================================
--- py/dist/py/test/item.py (original)
+++ py/dist/py/test/item.py Fri May 6 12:36:56 2005
@@ -58,7 +58,7 @@
code = py.code.Code(self.obj)
return code.path, code.firstlineno
- def sortvalue(self):
+ def getsortvalue(self):
return self.getpathlineno()
def run(self):
Modified: py/dist/py/test/terminal/remote.py
==============================================================================
--- py/dist/py/test/terminal/remote.py (original)
+++ py/dist/py/test/terminal/remote.py Fri May 6 12:36:56 2005
@@ -97,17 +97,20 @@
channel.send((args, failures))
return waitfinish(channel)
+def generalize(p1, p2):
+ general = p1
+ for x, y in zip(p1.parts(), p2.parts()):
+ if x != y:
+ break
+ general = x
+ return general
+
def getrootdir(args):
- colitems = py.test.TerminalSession._map2colitems(args)
- tops = [x.listchain()[0].fspath for x in colitems]
- def generalize(p1, p2):
- general = p1
- for x, y in zip(p1.parts(), p2.parts()):
- if x != y:
- break
- general = x
- return general
- p =reduce(generalize, tops)
+ tops = []
+ for arg in args:
+ p = py.path.local(arg)
+ tops.append(p.pypkgpath() or p)
+ p = reduce(generalize, tops)
if p.check(file=1):
p = p.dirpath()
return p
More information about the pytest-commit
mailing list