From mscott at goldenspud.com Thu Mar 3 20:39:21 2005 From: mscott at goldenspud.com (Matthew Scott) Date: Thu, 03 Mar 2005 13:39:21 -0600 Subject: [py-dev] using Python profiler with py.test Message-ID: <422767E9.7030105@goldenspud.com> I'm having problems using the Python profiler with py.test If I write a simple one-liner as 'hello.py': import py; print py.path.local() Then run "python2.4 -m profile hello.py", I get a report from the profiler. However, if I run "python2.4 -m profile bin/py.test" from within the py directory, I get the output below. Any ideas or tips on using the Python profiler with py.test? inserting into sys.path: /home/gldnspud/s/py-dist ============================= test process starts ============================= testing-mode: inprocess executable : /usr/bin/python2.4 (2.4.1-alpha-0) using py lib: /home/gldnspud/s/py-dist/py Traceback (most recent call last): File "/usr/lib/python2.4/profile.py", line 611, in ? run('execfile(%r)' % (sys.argv[0],), options.outfile, options.sort) File "/usr/lib/python2.4/profile.py", line 72, in run prof = prof.run(statement) File "/usr/lib/python2.4/profile.py", line 448, in run return self.runctx(cmd, dict, dict) File "/usr/lib/python2.4/profile.py", line 454, in runctx exec cmd in globals, locals File "", line 1, in ? File "bin/py.test", line 5, in ? main() File "/home/gldnspud/s/py-dist/py/test/cmdline.py", line 32, in main run.inprocess(args, filenames) File "/home/gldnspud/s/py-dist/py/test/run.py", line 141, in inprocess driver.run(fncollectors) File "/home/gldnspud/s/py-dist/py/test/drive.py", line 41, in run self.reporter.start() File "/home/gldnspud/s/py-dist/py/test/report/text/reporter.py", line 53, in start self.out.line("initial testconfig %d: %s" %(i, x)) File "/home/gldnspud/s/py-dist/py/path/extpy/extpy.py", line 38, in __str__ def __str__(self): File "/usr/lib/python2.4/profile.py", line 238, in trace_dispatch_i if self.dispatch[event](self, frame, t): File "/usr/lib/python2.4/profile.py", line 295, in trace_dispatch_call assert (self.cur is None or \ AssertionError: ('Bad call', ('/home/gldnspud/s/py-dist/py/initpkg.py', 149, '__getattr__')) -- Matthew R. Scott From hpk at trillke.net Fri Mar 4 08:06:15 2005 From: hpk at trillke.net (holger krekel) Date: Fri, 4 Mar 2005 08:06:15 +0100 Subject: [py-dev] using Python profiler with py.test In-Reply-To: <422767E9.7030105@goldenspud.com> References: <422767E9.7030105@goldenspud.com> Message-ID: <20050304070615.GG3663@solar.trillke.net> Hi Matthew! On Thu, Mar 03, 2005 at 13:39 -0600, Matthew Scott wrote: > I'm having problems using the Python profiler with py.test > > If I write a simple one-liner as 'hello.py': > > import py; print py.path.local() > > Then run "python2.4 -m profile hello.py", I get a report from the profiler. > > However, if I run "python2.4 -m profile bin/py.test" from within the py > directory, I get the output below. > > Any ideas or tips on using the Python profiler with py.test? Hum, i can reproduce your problem but am not sure exactly what is going on. If i take out the triggering assertion in profile.py then it seems to work. Maybe the assertion somehow triggers because of the lazy module loading in py/initpkg.py. Forgive me, but I am not in the mood currently to examine how profile.py works ... Anyway, i think that we should rather try to incorporate hotshot rather than profile directly into py.test as this is the recommended way of doing profiling these days ASFAIK. (Btw, I assume we want to profile the tested application and not py.test itself ...) Do you have a suggestion for a cmdline-API? cheers, holger From mscott at goldenspud.com Fri Mar 4 12:30:48 2005 From: mscott at goldenspud.com (Matthew Scott) Date: Fri, 04 Mar 2005 05:30:48 -0600 Subject: [py-dev] using Python profiler with py.test In-Reply-To: <20050304070615.GG3663@solar.trillke.net> References: <422767E9.7030105@goldenspud.com> <20050304070615.GG3663@solar.trillke.net> Message-ID: <422846E8.3090505@goldenspud.com> holger krekel wrote: > Anyway, i think that we should rather try to incorporate > hotshot rather than profile directly into py.test as this is the > recommended way of doing profiling these days ASFAIK. (Btw, I assume > we want to profile the tested application and not py.test itself ...) > Do you have a suggestion for a cmdline-API? D'oh! I haven't tried hotshot yet. This was my first attempt at profiling something in Python so I just gravitated toward something that had was based on the same root word :) I'll check out hotshot, since I haven't yet... :) -- Matthew R. Scott From dialtone at divmod.com Sun Mar 6 01:44:51 2005 From: dialtone at divmod.com (Valentino Volonghi aka Dialtone) Date: Sun, 06 Mar 2005 01:44:51 +0100 Subject: [py-dev] py.test patches and problems Message-ID: <422A5283.60906@divmod.com> I think there is far too magic in py.test :). Since I need a markdown parser I've started a new project. Unfortunately the Markdown test suite is completely useless (whoever wrote it must have some problems with blank lines in html output). Hence I wanted to build my own test suite using py.test First problem: I'm under MacOSX and I'm using python built with the framework. This means _findpy.py is not ready to locate my py dir and fails (even if import py finishes without problems). I modified _findpy.py in this way: Index: py/bin/_findpy.py =================================================================== --- py/bin/_findpy.py (revision 9671) +++ py/bin/_findpy.py (working copy) @@ -27,6 +27,9 @@ if not searchpy(abspath(os.curdir)): if not searchpy(opd(abspath(sys.argv[0]))): if not searchpy(opd(__file__)): - raise SystemExit, "Could not find 'py' package!" + for path in sys.path: + if searchpy(path): + break + else: raise SystemExit, "Could not find 'py' package!" import py And now it works. Pythondir under MacOSX with framework is: /Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site-packages while python executable is under: /Library/Frameworks/Python.framework/Versions/2.4/bin/python But then there is another problem with other software that uses __import__() function. I'm working with Nevow and it uses a particular function: namedAny which loads a module from PYTHONPATH using the complete path to the module. This is one of the many error outputs that I have while running 'py.test'. def namedAny(name): """Get a fully named package, module, module-global object, or attribute. """ names = name.split('.') topLevelPackage = None moduleNames = names[:] while not topLevelPackage: try: trialname = '.'.join(moduleNames) E topLevelPackage = __import__(trialname) ~ ImportError: __import__('nevow.flat.flatstan.TagSerializer') << No module named TagSerializer Is there any way to fix this last behaviour? I fear that import hooks are too magic, for a py.test newbie like me, to dig in. -- Valentino Volonghi aka Dialtone Now Running MacOSX 10.3.8 Blog: http://vvolonghi.blogspot.com http://weever.berlios.de From hpk at trillke.net Sun Mar 6 11:10:54 2005 From: hpk at trillke.net (holger krekel) Date: Sun, 6 Mar 2005 11:10:54 +0100 Subject: [py-dev] py.test patches and problems In-Reply-To: <422A5283.60906@divmod.com> References: <422A5283.60906@divmod.com> Message-ID: <20050306101054.GP3663@solar.trillke.net> Hi Valentino, On Sun, Mar 06, 2005 at 01:44 +0100, Valentino Volonghi aka Dialtone wrote: > I think there is far too magic in py.test :). maybe. We try to keep it down and only do neccessary magic ... > Since I need a markdown parser I've started a new project. Unfortunately > the Markdown test suite is completely useless (whoever wrote it must > have some problems with blank lines in html output). > > Hence I wanted to build my own test suite using py.test > > First problem: I'm under MacOSX and I'm using python built with the > framework. This means _findpy.py is not ready to locate my py dir and > fails (even if import py finishes without problems). Hum, did you put "py.test" somewhere outside the py library? I am using MacOSX (both framework and non-framework installs), without any problems. > I modified _findpy.py in this way: > > Index: py/bin/_findpy.py > =================================================================== > --- py/bin/_findpy.py (revision 9671) > +++ py/bin/_findpy.py (working copy) > @@ -27,6 +27,9 @@ > if not searchpy(abspath(os.curdir)): > if not searchpy(opd(abspath(sys.argv[0]))): > if not searchpy(opd(__file__)): > - raise SystemExit, "Could not find 'py' package!" > + for path in sys.path: > + if searchpy(path): > + break > + else: raise SystemExit, "Could not find 'py' package!" I just committed a simpler "fix" where last 'if' just results in a "pass" so that "import py" will be executed either way. > But then there is another problem with other software that uses > __import__() function. strange. > I'm working with Nevow and it uses a particular function: namedAny which > loads a module from PYTHONPATH using the complete path to the module. > > This is one of the many error outputs that I have while running 'py.test'. > > def namedAny(name): > """Get a fully named package, module, module-global object, or > attribute. > """ > names = name.split('.') > topLevelPackage = None > moduleNames = names[:] > while not topLevelPackage: > try: > trialname = '.'.join(moduleNames) > E topLevelPackage = __import__(trialname) > ~ ImportError: > __import__('nevow.flat.flatstan.TagSerializer') << No module named > TagSerializer > > Is there any way to fix this last behaviour? I fear that import hooks > are too magic, for a py.test newbie like me, to dig in. I presume there must be a much larger traceback. I just looked at the nevow import logic and have the impression that it's at least as magic as the py lib's :-) Anyway, can you try to replace line 337 of py/path/common.py from mod.__file__ = PathStr(self) to mod.__file__ = str(self) and see if that fixes your problem? thanks, holger From jan at balster.info Mon Mar 14 15:48:59 2005 From: jan at balster.info (Jan Balster) Date: Mon, 14 Mar 2005 15:48:59 +0100 Subject: [py-dev] Bug in collect.Error Message-ID: <4235A45B.5070906@balster.info> Hello, this is my first post to py-dev. Thanks for py.test! I found an Bug in collect.Error.__repr__[line 27]: calling __repr__ raises an exception: def __repr__(self): E tb = list(self.excinfo)[-1] ~ TypeError: << iteration over non-sequence __repr__ should be changed to: def __repr__(self): tb = list(self.excinfo.traceback)[-1] ^^^^^^^^^ return '' % (tb.frame.code.path, tb.lineno+1) Testcase: import py def test_Error_repr_returns_string(): try: raise TypeError except: import sys error = py.test.collect.Error(sys.exc_info()) import types assert isinstance(repr(error), types.StringTypes) Jan Balster From edvard.majakari at staselog.com Tue Mar 15 14:07:25 2005 From: edvard.majakari at staselog.com (Edvard Majakari) Date: Tue, 15 Mar 2005 15:07:25 +0200 Subject: [py-dev] Creating test skeleton automatically from modules Message-ID: <87zmx5njle.fsf@titan.staselog.com> Hi, I wrote a simple program which uses Python's compiler module to parse given set of modules and writes a py.test unit test skeleton for each module. Currently it is not too clever, mostly because I don't have very clear ideas how unit testing should be done. However, it does create code for automatically generating test methods :) Say, if you have module bar and therein method named foo, pytestgen will automatically create TestBar: ... def test_foo(self): known_values(,) for arg1, arg2, expected in known_values: yield self.foo, arg1, arg2, expected def foo(self, arg1, arg2, expectd): assert bar.foo(arg1, arg2) == expected I intend to develop the program further, hopefully integrate it to Eclipse pydev plugin :) If you're interested in trying it out, see http://majakari.net/dl/pytestgen-0.11.tar.bz2 It's not too advanced (yet), but I already use it myself for my own purposes. -- # Edvard Majakari Software Engineer # PGP PUBLIC KEY available Soli Deo Gloria! $_ = '456476617264204d616a616b6172692c20612043687269737469616e20'; print join('',map{chr hex}(split/(\w{2})/)),uc substr(crypt(60281449,'es'),2,4),"\n"; From hpk at trillke.net Tue Mar 15 14:21:45 2005 From: hpk at trillke.net (holger krekel) Date: Tue, 15 Mar 2005 14:21:45 +0100 Subject: [py-dev] Bug in collect.Error In-Reply-To: <4235A45B.5070906@balster.info> References: <4235A45B.5070906@balster.info> Message-ID: <20050315132145.GI17456@solar.trillke.net> Hi Jan, On Mon, Mar 14, 2005 at 15:48 +0100, Jan Balster wrote: > Hello, > > this is my first post to py-dev. > Thanks for py.test! > > I found an Bug in collect.Error.__repr__[line 27]: thanks for pointing it out along with the test! i just committed this to the trunk although this will likely become obsolete soon when the "py-collect" branch is merged back into the trunk (intended to unify and clean up the test collection process) ... cheers, holger From jan at balster.info Tue Mar 15 20:02:07 2005 From: jan at balster.info (Jan Balster) Date: Tue, 15 Mar 2005 20:02:07 +0100 Subject: [py-dev] Bug in collect.Error In-Reply-To: <20050315132145.GI17456@solar.trillke.net> References: <4235A45B.5070906@balster.info> <20050315132145.GI17456@solar.trillke.net> Message-ID: <4237312F.3070906@balster.info> hi Holger, holger krekel wrote: > i just committed this to the trunk although this will > likely become obsolete soon when the "py-collect" branch is > merged back into the trunk (intended to unify and clean up > the test collection process) ... i just finished a small tkinter gui for py.test with a tree view for all collectors and items. the main part is a gui-reporter, which sends information through a extpy.channel to the gui. i think, i have to use a subclass of driver now. the new FailureCollector in run.py is great. i had a problem to get the right name (like collector.listnames()) for a failed item returned by the old FailureCollector. thats much easier now, thank you. what kind of object is root in FailureCollector: "for root, names in failures"? i think, it should be a collect.Directory or collect.Module, but sending them through a extpy.channel doesn't work: eval(repr(directory_object)) != directory_object terminaldriver.run() (--> driver.run()) returns nothing (None), so i can't deduce the object type from the source. cheers, jan From hpk at trillke.net Tue Mar 15 21:29:07 2005 From: hpk at trillke.net (holger krekel) Date: Tue, 15 Mar 2005 21:29:07 +0100 Subject: [py-dev] Bug in collect.Error In-Reply-To: <4237312F.3070906@balster.info> References: <4235A45B.5070906@balster.info> <20050315132145.GI17456@solar.trillke.net> <4237312F.3070906@balster.info> Message-ID: <20050315202907.GA30690@solar.trillke.net> Hi Jan, On Tue, Mar 15, 2005 at 20:02 +0100, Jan Balster wrote: > holger krekel wrote: > > i just committed this to the trunk although this will > > likely become obsolete soon when the "py-collect" branch is > > merged back into the trunk (intended to unify and clean up > > the test collection process) ... > > i just finished a small tkinter gui for py.test with a tree view for all > collectors and items. Cool! > the main part is a gui-reporter, which sends information through a > extpy.channel to the gui. i think, i have to use a subclass of driver now. > > the new FailureCollector in run.py is great. i had a problem to get the > right name (like collector.listnames()) for a failed item returned by > the old FailureCollector. thats much easier now, thank you. hey, you are using the collect branch already? Nice! and crazy :-) > what kind of object is root in FailureCollector: > "for root, names in failures"? Well, this particular bit is not fully spelled out yet, to be honest. > i think, it should be a collect.Directory or collect.Module, but sending > them through a extpy.channel doesn't work: > > eval(repr(directory_object)) != directory_object yip, you are right. Probably it will be "implicitely" encoded so that the FrontendDriver and the remote end will agree that "root" is e.g. a filesystem path (as a string) which has to be wrapped by (indeed) a collect.Directory object. So the channel would only see lists and strings basically from which the "collect/item tree" can be constructed. > terminaldriver.run() (--> driver.run()) returns nothing (None), so i > can't deduce the object type from the source. Yes, that return value is one of the missing bits in the branch! I'll try to finish that up asap. cheers! holger From jan at balster.info Wed Mar 16 15:59:19 2005 From: jan at balster.info (Jan Balster) Date: Wed, 16 Mar 2005 15:59:19 +0100 Subject: [py-dev] branch py-collect was: Bug in collect.Error Message-ID: <423849C7.4070104@balster.info> hi holger, > Yes, that return value is one of the missing bits in the branch! > I'll try to finish that up asap. > may i help? below a diff for run.py and drive.py. FrontendDriver(run.py) and Driver(drive.py) communicate only with lists and tuples of strings. hope this helps. Jan output of "svn diff run.py": Index: run.py =================================================================== --- run.py (Revision 9787) +++ run.py (Arbeitskopie) @@ -94,7 +94,7 @@ args, failures = channel.receive() driver, paths = py.test.config.init(args, ignoreremote=True) if failures: - cols = [FailureCollector(failures)] + cols = FailureCollector(failures) else: cols = list(getcollectors(paths)) driver.shouldclose = channel.isclosed @@ -105,8 +105,15 @@ def __init__(self, failures): self.failures = failures def __iter__(self): - for root, names in self.failures: - current = root + for rootpath, names in self.failures: + root = py.path.local(rootpath) + if root.check(dir=1): + current = py.test.Directory(root).Directory(root) + elif root.check(file=1): + current = py.test.Module(root).Module(root) + # root is fspath of names[0] -> pop names[0] + # slicing works with empty lists + names = names[1:] while names: name = names.pop(0) try: @@ -143,8 +150,8 @@ break print "#" * 60 print "# session mode: %d failures remaining" % len(failures) - for x in failures: - name = ":".join(x) # XXX + for root, names in failures: + name = ":".join(names) # XXX print "Failure at: %r" % (name,) print "# watching py files below %s" % rootdir - print "# ", "^" * len(rootdir) + print "# ", "^" * len(str(rootdir)) output of "svn diff drive.py": Index: drive.py =================================================================== --- drive.py (Revision 9787) +++ drive.py (Arbeitskopie) @@ -54,6 +54,11 @@ except Exit, ex: pass + # return [(fspath as string, [names as string])] + return [(str(item.listchain()[0].fspath), item.listnames()) + for item, res in self.getresults(py.test.Item.Failed)] + + def runone(self, colitem): if self.shouldclose(): raise SystemExit, "received external close signal" From hpk at trillke.net Wed Mar 16 17:01:43 2005 From: hpk at trillke.net (holger krekel) Date: Wed, 16 Mar 2005 17:01:43 +0100 Subject: [py-dev] branch py-collect was: Bug in collect.Error In-Reply-To: <423849C7.4070104@balster.info> References: <423849C7.4070104@balster.info> Message-ID: <20050316160143.GH30690@solar.trillke.net> Hi Jan, On Wed, Mar 16, 2005 at 15:59 +0100, Jan Balster wrote: > hi holger, > > Yes, that return value is one of the missing bits in the branch! > > I'll try to finish that up asap. > > > > may i help? Sure :-) > below a diff for run.py and drive.py. > FrontendDriver(run.py) and Driver(drive.py) communicate only with lists > and tuples of strings. applied, thanks! Btw, if you want to get an account with checkin rights just drop me a private mail with your desired user name and public ssh key. I think that your perspective from a GUI side of things could help to get py.test more mature and flexible! cheers, holger From jan at balster.info Wed Mar 16 14:38:48 2005 From: jan at balster.info (Jan Balster) Date: Wed, 16 Mar 2005 14:38:48 +0100 Subject: [py-dev] branch py-collect was: Bug in collect.Error Message-ID: <423836E8.8000402@balster.info> hi holger, > Yes, that return value is one of the missing bits in the branch! > I'll try to finish that up asap. > may i help? below a diff for run.py and drive.py. FrontendDriver(run.py) and Driver(drive.py) communicate only with lists and tuples of strings. hope this helps. Jan output of "svn diff run.py": Index: run.py =================================================================== --- run.py (Revision 9787) +++ run.py (Arbeitskopie) @@ -94,7 +94,7 @@ args, failures = channel.receive() driver, paths = py.test.config.init(args, ignoreremote=True) if failures: - cols = [FailureCollector(failures)] + cols = FailureCollector(failures) else: cols = list(getcollectors(paths)) driver.shouldclose = channel.isclosed @@ -105,8 +105,15 @@ def __init__(self, failures): self.failures = failures def __iter__(self): - for root, names in self.failures: - current = root + for rootpath, names in self.failures: + root = py.path.local(rootpath) + if root.check(dir=1): + current = py.test.Directory(root).Directory(root) + elif root.check(file=1): + current = py.test.Module(root).Module(root) + # root is fspath of names[0] -> pop names[0] + # slicing works with empty lists + names = names[1:] while names: name = names.pop(0) try: @@ -143,8 +150,8 @@ break print "#" * 60 print "# session mode: %d failures remaining" % len(failures) - for x in failures: - name = ":".join(x) # XXX + for root, names in failures: + name = ":".join(names) # XXX print "Failure at: %r" % (name,) print "# watching py files below %s" % rootdir - print "# ", "^" * len(rootdir) + print "# ", "^" * len(str(rootdir)) output of "svn diff drive.py": Index: drive.py =================================================================== --- drive.py (Revision 9787) +++ drive.py (Arbeitskopie) @@ -54,6 +54,11 @@ except Exit, ex: pass + # return [(fspath as string, [names as string])] + return [(str(item.listchain()[0].fspath), item.listnames()) + for item, res in self.getresults(py.test.Item.Failed)] + + def runone(self, colitem): if self.shouldclose(): raise SystemExit, "received external close signal"