From brian at dorseys.org Thu Jan 11 19:52:21 2007 From: brian at dorseys.org (Brian Dorsey) Date: Thu, 11 Jan 2007 10:52:21 -0800 Subject: [py-dev] py lib tests looking good on Windows. Message-ID: <66e877b70701111052t541ba7a2m9d124159a1c3148e@mail.gmail.com> Happy Sprinting everyone! I just wanted to mention that py lib tests are looking pretty clean on Windows right now. I've attached the output of running them on my machine, if anyone is interested. Good luck with the release! Take care, -Brian -------------- next part -------------- ============================= test process starts ============================= testing-mode: inprocess executable: c:\python24\python.exe (2.4.2-final-0) using py lib: C:\Python24\Lib\site-packages\py apigen\rest\testing\test_htmlhandlers.py[1] . apigen\rest\testing\test_rest.py[22] ...................... apigen\source\testing\test_browser.py[3] ... apigen\source\testing\test_color.py[10] .......s.. apigen\source\testing\test_html.py[8] ........ apigen\testing\test_apigen_example.py[1] . apigen\testing\test_linker.py[2] .. apigen\tracer\testing\test_desc.py[2] .. apigen\tracer\testing\test_docgen.py[14] .............. apigen\tracer\testing\test_magic.py - skipped apigen\tracer\testing\test_model.py[4] .... apigen\tracer\testing\test_package.py[3] ... builtin\testing\test_enumerate.py[1] . builtin\testing\test_exception.py[1] . builtin\testing\test_reversed.py[1] . builtin\testing\test_sorted.py[2] .. c-extension\greenlet\test_generator.py - skipped c-extension\greenlet\test_generator_nested.py - skipped c-extension\greenlet\test_greenlet.py - skipped c-extension\greenlet\test_remote.py - skipped c-extension\greenlet\test_throw.py - skipped code\testing\test_code.py[4] .... code\testing\test_cpython_features.py[1] . code\testing\test_excinfo.py[15] ............... code\testing\test_frame.py[2] .. code\testing\test_safe_repr.py[5] ..... code\testing\test_source.py[28] ............................ documentation\apigen\api-docs.txt[2] s. documentation\apigen\assumptions.txt[2] s. documentation\apigen\first-implementation.txt[2] s. documentation\apigen\source-viewer.txt[2] .. documentation\example\pytest\test_failures.py[1] . documentation\example\pytest\test_setup_flow_example.py[2] .. documentation\future\code_template.txt[2] .. documentation\future\future.txt[7] ....... documentation\future\planning.txt[2] .. documentation\future\rsession_todo.txt[2] .. documentation\talk\execnet-overview.txt[2] s. documentation\talk\pytest-overview.txt[5] s.... documentation\test_conftest.py[2] .. documentation\TODO.txt[2] .. documentation\api.txt[3] s.. documentation\apigen.txt[2] .. documentation\binary.txt[3] ... documentation\coding-style.txt[3] ... documentation\contact.txt[2] s. documentation\execnet.txt[3] s.. documentation\getting-started.txt[7] ....... documentation\greenlet.txt[2] s. documentation\home.txt[2] .. documentation\index.txt[12] ............ documentation\links.txt[2] s. documentation\log.txt[2] .. documentation\maciej-implementation-notes.txt[2] s. documentation\misc.txt[5] ..... documentation\releaseplan.txt[3] s.. documentation\releasescheme.txt[3] s.. documentation\test-distributed.txt[2] .. documentation\test.txt[5] ..... documentation\why_py.txt[8] ........ documentation\xml.txt[4] s... execnet\testing\test_gateway.py[105] .........................................................................ssssssssssssssssssssssssssssssss execnet\testing\test_pickle.py[2] .. io\test\test_capture.py[12] ............ io\test\test_dupfile.py[1] . log\testing\test_log.py[16] ................ log\testing\test_logger.py[8] ........ magic\testing\test_assertion.py[8] ........ magic\testing\test_autopath.py[5] ..... magic\testing\test_exprinfo.py[8] ........ magic\testing\test_invoke.py[2] .. magic\testing\test_patch.py[3] ... magic\testing\test_viewtype.py[2] .. misc\testing\test_api.py[3] ... misc\testing\test_cache.py[11] ........... misc\testing\test_error.py[2] .. misc\testing\test_initpkg.py[228] .........................................................................................s.........................................................................s..........................s..............s.s.s..sss.sss......... misc\testing\test_simplecapture.py[13] ............s misc\testing\test_std.py[3] ... misc\testing\test_svnlook.py[1] . path\extpy\testing\test_extpy.py[53] ..................................................... path\local\testing\test_local.py[85] ..................................................................................... path\local\testing\test_posix.py[0] path\local\testing\test_win.py[2] .. path\svn\testing\test_test_repo.py[2] .. path\svn\testing\test_urlcommand.py[86] ..............s....................................................................... path\svn\testing\test_wccommand.py[93] ............................................................................................. path\testing\test_api.py[4] .... process\testing\test_cmdexec.py[4] .... rest\testing\test_convert.py[2] ss rest\testing\test_directive.py[3] .s. rest\testing\test_htmlrest.py[0] rest\testing\test_rst.py[46] .............................................. rest\testing\test_rst2pdf.py[2] ss rest\testing\test_transform.py[3] ... test\rsession\testing\test_boxing.py - skipped test\rsession\testing\test_config.py[1] . test\rsession\testing\test_executor.py - skipped test\rsession\testing\test_lsession.py[9] s..ss..s. test\rsession\testing\test_master.py - skipped test\rsession\testing\test_outcome.py[2] .. test\rsession\testing\test_report.py[3] ... test\rsession\testing\test_reporter.py - skipped test\rsession\testing\test_rest.py - skipped test\rsession\testing\test_rsession.py - skipped test\rsession\testing\test_rsync.py[3] .s. test\rsession\testing\test_slave.py - skipped test\rsession\testing\test_web.py - skipped test\rsession\testing\test_webjs.py - skipped test\testing\import_test\package\test_import.py[1] . test\testing\test_collect.py[31] ............................... test\testing\test_compat.py[18] .................. test\testing\test_config.py[2] .. test\testing\test_deprecated.py[5] ..... test\testing\test_doctest.py[3] ... test\testing\test_raises.py[4] .... test\testing\test_session.py[22] ...................... test\testing\test_setup_nested.py[10] .......... test\tkinter\testing\test_backend.py[18] .................. test\tkinter\testing\test_capture_out_err.py[1] . test\tkinter\testing\test_reportsession.py[2] .. test\tkinter\testing\test_repository.py[20] .................... test\tkinter\testing\test_util.py[17] ................. thread\testing\test_io.py[4] .... thread\testing\test_pool.py[7] ....... tool\testing\test_utestconvert.py[1] . xmlobj\testing\test_html.py[5] ..... xmlobj\testing\test_xml.py[9] ......... __________________________ reasons for skipped tests __________________________ Skipped in C:\Python24\Lib\site-packages\py\documentation\conftest.py:53 reason: Skipped: html file is up to date, use --forcegen to regenerate Skipped in C:\Python24\Lib\site-packages\py\execnet\testing\test_gateway.py:452 reason: Skipped: no known ssh target, use -S to set one Skipped in C:\Python24\Lib\site-packages\py\path\svn\testing\test_urlcommand.py:40 reason: Skipped: XXX fixme win32 Skipped in C:\Python24\Lib\site-packages\py\apigen\source\testing\test_color.py:55 reason: Skipped: not yet implemented Skipped in C:\Python24\Lib\site-packages\py\apigen\source\server.py:9 Skipped in C:\Python24\Lib\site-packages\py\test\rsession\testing\test_webjs.py:5 Skipped in C:\Python24\Lib\site-packages\py\test\rsession\webjs.py:12 Skipped in C:\Python24\Lib\site-packages\py\test\rsession\testing\test_web.py:13 reason: Skipped: PyPy not found Skipped in C:\Python24\Lib\site-packages\py\misc\testing\test_simplecapture.py:89 reason: Skipped: Hangs in py.test --session=R Skipped in C:\Python24\Lib\site-packages\py\compat\testing\conftest.py:5 reason: Skipped: compat tests currently need to be run manually Skipped in C:\Python24\Lib\site-packages\py\test\rsession\testing\test_boxing.py:8 Skipped in C:\Python24\Lib\site-packages\py\test\rsession\testing\test_slave.py:11 Skipped in C:\Python24\Lib\site-packages\py\test\rsession\testing\test_master.py:10 reason: Skipped: rsession is unsupported on Windows. Skipped in C:\Python24\Lib\site-packages\py\test\rsession\testing\test_lsession.py:135 Skipped in C:\Python24\Lib\site-packages\py\test\rsession\testing\test_lsession.py:66 Skipped in C:\Python24\Lib\site-packages\py\test\rsession\testing\test_lsession.py:104 Skipped in C:\Python24\Lib\site-packages\py\test\rsession\testing\test_lsession.py:225 reason: Skipped: operating system not supported Skipped in C:\Python24\Lib\site-packages\py\c-extension\greenlet\test_remote.py:5 Skipped in C:\Python24\Lib\site-packages\py\c-extension\greenlet\test_generator.py:5 Skipped in C:\Python24\Lib\site-packages\py\c-extension\greenlet\test_throw.py:5 Skipped in C:\Python24\Lib\site-packages\py\c-extension\greenlet\test_generator_nested.py:6 Skipped in C:\Python24\Lib\site-packages\py\c-extension\greenlet\test_greenlet.py:5 reason: Skipped: cannot compile C:\Python24\Lib\site-packages\py\c-extension\greenlet\greenlet.c: error: The .NET Framework SDK needs to be installed before building extensions for Python. Skipped in C:\Python24\Lib\site-packages\py\test\rsession\testing\test_rsync.py:49 reason: Skipped: symlinks are unsupported on Windows. Skipped in C:\Python24\Lib\site-packages\py\rest\testing\test_directive.py:34 reason: Skipped: graphviz and latex needed Skipped in C:\Python24\Lib\site-packages\py\rest\testing\test_convert.py:10 Skipped in C:\Python24\Lib\site-packages\py\rest\testing\test_htmlrest.py:10 Skipped in C:\Python24\Lib\site-packages\py\rest\testing\test_rst2pdf.py:14 reason: Skipped: ghostscript, graphviz and latex needed Skipped in C:\Python24\Lib\site-packages\py\apigen\tracer\testing\test_magic.py:6 reason: Skipped: These features has been disabled ========== tests finished: 1185 passed, 89 skipped in 245.48 seconds ========== From holger at merlinux.de Sun Jan 14 22:24:16 2007 From: holger at merlinux.de (holger krekel) Date: Sun, 14 Jan 2007 22:24:16 +0100 Subject: [py-dev] from dist to trunk / release TODO Message-ID: <20070114212416.GW16915@solar.trillke> Hi folks, ahead of the release i'd like to move development works to http://codespeak.net/svn/py/trunk and have svn/py/dist carry stable snapshots or maybe only the last released version. I probably implement that policy tomorrow or so and will likely dis-allow commits to dist/ at the same time to avoid random commits still going there. moreover, you may want to have a look at the evolving http://codespeak.net/svn/py/dist/py/doc/TODO.txt file which lists a number of intended changes for 0.9, particularly regarding namespaces ... in Switzerland/Leysin (where some of us sprinted on py lib release topics) we decided to be avoid exposing 'alpha' API because we don't want to impose a support burden for already-known-to-change code. E.g. 'py.log' is going to become 'py._log'. I hope that this doesn't cause too much pain to the current usages of the py lib. Oh, and if you'd like to comment, add or work on the TODO file, you are most welcome! best & greetings, holger From holger at merlinux.de Mon Jan 15 08:19:32 2007 From: holger at merlinux.de (holger krekel) Date: Mon, 15 Jan 2007 08:19:32 +0100 Subject: [py-dev] Failing to manage test state of a module with py.test In-Reply-To: <5c1d522d0611161322t3bfa2ed7od4dc838b14487261@mail.gmail.com> References: <5c1d522d0611161254n33f5c0adyf7cbc82029ce4298@mail.gmail.com> <455CD242.8080507@genesilico.pl> <5c1d522d0611161322t3bfa2ed7od4dc838b14487261@mail.gmail.com> Message-ID: <20070115071932.GY16915@solar.trillke> Hi Pierre, On Thu, Nov 16, 2006 at 16:22 -0500, Pierre Rouleau wrote: > The setup_module I have looks like this: > > def setup_module(roman): > print 'SETTING UP........................' > > global knownValues > knownValues = ( (1, 'I'), > (2, 'II'), > (3, 'III'), > (4, 'IV'), > (5, 'V'), > (6, 'VI'), > (7, 'VII'), > .... > > > I wanted to know if the values set up by the setup_module function > would be available to the test functions. The test function that > fails is failing because knownValues is not accessible to the check > inside test_known_values. > > def test_known_values() : > """Test all known values.""" > > def check(number, roman_numeral): > print 'test_known_values Testing: ', roman_numeral > assert roman.toRoman(number) == roman_numeral > assert roman.fromRoman(roman_numeral) == number > # all Roman numerals should be in upper case > assert roman_numeral.upper() == roman_numeral > # lower case Roman numerals are not accepted > raises(roman.InvalidRomanNumeralError, roman.fromRoman, > roman_numeral.lower()) > > tested_numbers = [] > > # test the numbers in the table above > for number, roman_numeral in knownValues: > yield check, number, roman_numeral > tested_numbers.append(number) > > # test the others > for number in xrange(1,5000): > if number not in tested_numbers: > yield check, number, roman.toRoman(number) > > > > Note that nose is able to recover the global variable and the test > succeeds in nosetests. py.test does not seem able to do it. It's not > that I absolutely want to use global variables, but I wanted to checks > the module setup mechanism. So last week i tweaked py.test (rev 36386) to invoke setup/teardown procedures before calling a "test generator". Generative tests are a bit of an edge case in that the generator already gets invoked during the collection process. The collection process (in contrast to executing the tests) usually does not invoke the setup/teardown logic but i think it makes sense to regard test generators enough of a special case. (the other issue regarding working with the 'mod' argument properly within setup_module(mod) has been clarified in another subthread of your posting). best & thanks for reporting! holger From grig at agilistas.org Mon Jan 15 19:16:00 2007 From: grig at agilistas.org (Grig Gheorghiu) Date: Mon, 15 Jan 2007 10:16:00 -0800 Subject: [py-dev] Test failures for py lib in Pybots (on Ubuntu Breezy) Message-ID: My Ubuntu Breezy Pybots buildslave is getting lots of failures when running the unit tests for the py lib. See details here: http://www.python.org/dev/buildbot/community/all/x86%20Ubuntu%20Breezy%20trunk/builds/269/step-py.lib/0 Grig From holger at merlinux.de Tue Jan 16 22:47:22 2007 From: holger at merlinux.de (holger krekel) Date: Tue, 16 Jan 2007 22:47:22 +0100 Subject: [py-dev] dist failing ... conftest cleanup branch emerging Message-ID: <20070116214722.GN16915@solar.trillke> Hi folks, cf pointed me to the fact that 'dist' currently fails some 90 tests due to some weird option handling problem. I can't investigate what caused it but i think i'd like to merge the conftest cleanup branch tomorrow anyway (i need to talk to Maciej about rsession related option handling mainly, i think) and then the problems should have gone away. (and yes, i didn't yet do the dist -> trunk switch, i'll send another mail when i actually do that) best, holger -- merlinux GmbH Steinbergstr. 42 31139 Hildesheim http://merlinux.de tel +49 5121 20800 75 (fax 77) From grig at agilistas.org Tue Jan 16 22:51:55 2007 From: grig at agilistas.org (Grig Gheorghiu) Date: Tue, 16 Jan 2007 13:51:55 -0800 Subject: [py-dev] dist failing ... conftest cleanup branch emerging In-Reply-To: <20070116214722.GN16915@solar.trillke> References: <20070116214722.GN16915@solar.trillke> Message-ID: Hi, Holger This is also happening on my Pybots buildslave -- see my message to the list from yesterday... Grig On 1/16/07, holger krekel wrote: > Hi folks, > > cf pointed me to the fact that 'dist' currently > fails some 90 tests due to some weird option handling > problem. I can't investigate what caused it but > i think i'd like to merge the conftest cleanup > branch tomorrow anyway (i need to talk to Maciej > about rsession related option handling mainly, i think) > and then the problems should have gone away. > (and yes, i didn't yet do the dist -> trunk switch, > i'll send another mail when i actually do that) > > best, > > holger > > -- > merlinux GmbH Steinbergstr. 42 31139 Hildesheim > http://merlinux.de tel +49 5121 20800 75 (fax 77) > _______________________________________________ > py-dev mailing list > py-dev at codespeak.net > http://codespeak.net/mailman/listinfo/py-dev > From holger at merlinux.de Tue Jan 16 22:57:41 2007 From: holger at merlinux.de (holger krekel) Date: Tue, 16 Jan 2007 22:57:41 +0100 Subject: [py-dev] dist failing ... conftest cleanup branch emerging In-Reply-To: References: <20070116214722.GN16915@solar.trillke> Message-ID: <20070116215741.GO16915@solar.trillke> Hi Grig! On Tue, Jan 16, 2007 at 13:51 -0800, Grig Gheorghiu wrote: > Hi, Holger > > This is also happening on my Pybots buildslave -- see my message to > the list from yesterday... ah good to know - admittedly i didn't check that yet but it shows that the buildslaves are working nicely :) greetings and thanks, holger > Grig > > On 1/16/07, holger krekel wrote: > > Hi folks, > > > > cf pointed me to the fact that 'dist' currently > > fails some 90 tests due to some weird option handling > > problem. I can't investigate what caused it but > > i think i'd like to merge the conftest cleanup > > branch tomorrow anyway (i need to talk to Maciej > > about rsession related option handling mainly, i think) > > and then the problems should have gone away. > > (and yes, i didn't yet do the dist -> trunk switch, > > i'll send another mail when i actually do that) > > > > best, > > > > holger > > > > -- > > merlinux GmbH Steinbergstr. 42 31139 Hildesheim > > http://merlinux.de tel +49 5121 20800 75 (fax 77) > > _______________________________________________ > > py-dev mailing list > > py-dev at codespeak.net > > http://codespeak.net/mailman/listinfo/py-dev > > > _______________________________________________ > py-dev mailing list > py-dev at codespeak.net > http://codespeak.net/mailman/listinfo/py-dev > -- merlinux GmbH Steinbergstr. 42 31139 Hildesheim http://merlinux.de tel +49 5121 20800 75 (fax 77) From holger at merlinux.de Thu Jan 18 08:07:21 2007 From: holger at merlinux.de (holger krekel) Date: Thu, 18 Jan 2007 08:07:21 +0100 Subject: [py-dev] merge of conftest branch / 0.9 todos Message-ID: <20070118070721.GD16915@solar.trillke> Hi folks, i just merged my conftest cleanup works, see the below commit and log message. Regarding configuration and option handling there still is more work to do, particularly for configuring remote sessions (both the terminal based one and the rssession ones). In this vein, currently --looponfailing is not working properly thanks to my conftest merge but that was expected and will receive fixing. For the 0.9 release i'd like to have the configuration/option handling as seen from user-level (so including command line options and conftest.py options and possibilities) be transparent, systematic and documented because changing it later is cumbersome. This issue and also the API documentation generation which is "in-progress" make it likely that the release will drag on a bit still. I'd be glad if some of you can check from time to time if things break badly for you and report here as soon as possible. If you look into py/doc/todo.txt you'll notice that there are some changes pending that might affect your usages of the py lib. best & thanks, holger ----- Forwarded message from hpk at codespeak.net ----- From: hpk at codespeak.net To: py-svn at codespeak.net Date: Thu, 18 Jan 2007 08:00:50 +0100 (CET) Subject: [py-svn] r36902 - in py/dist/py: . apigen apigen/testing doc doc/example/pytest test test/rsession test/rsession/testing test/terminal test/testing test/testing/data test/tkinter test/tkinter/testing X-Spambayes-Classification: ham; 0.00 Author: hpk Date: Thu Jan 18 08:00:43 2007 New Revision: 36902 Added: py/dist/py/test/conftesthandle.py - copied unchanged from r36901, py/branch/conftest/py/test/conftesthandle.py py/dist/py/test/testing/setupdata.py - copied unchanged from r36901, py/branch/conftest/py/test/testing/setupdata.py py/dist/py/test/testing/test_conftesthandle.py - copied unchanged from r36901, py/branch/conftest/py/test/testing/test_conftesthandle.py py/dist/py/test/todo-cleanup.txt - copied unchanged from r36901, py/branch/conftest/py/test/todo-cleanup.txt Removed: py/dist/py/test/testing/data/ Modified: py/dist/py/__init__.py py/dist/py/apigen/conftest.py py/dist/py/apigen/testing/test_apigen_functional.py py/dist/py/conftest.py py/dist/py/doc/conftest.py py/dist/py/doc/example/pytest/test_failures.py py/dist/py/doc/test.txt py/dist/py/doc/test_conftest.py py/dist/py/test/cmdline.py py/dist/py/test/collect.py py/dist/py/test/config.py py/dist/py/test/defaultconftest.py py/dist/py/test/item.py py/dist/py/test/rsession/conftest.py py/dist/py/test/rsession/rest.py py/dist/py/test/rsession/rsession.py py/dist/py/test/rsession/testing/test_config.py py/dist/py/test/rsession/testing/test_executor.py py/dist/py/test/rsession/testing/test_lsession.py py/dist/py/test/rsession/testing/test_master.py py/dist/py/test/rsession/testing/test_reporter.py py/dist/py/test/rsession/testing/test_rest.py py/dist/py/test/rsession/testing/test_rsession.py py/dist/py/test/rsession/testing/test_slave.py py/dist/py/test/rsession/testing/test_web.py py/dist/py/test/rsession/testing/test_webjs.py py/dist/py/test/session.py py/dist/py/test/terminal/remote.py py/dist/py/test/terminal/terminal.py py/dist/py/test/testing/test_collect.py py/dist/py/test/testing/test_config.py py/dist/py/test/testing/test_session.py py/dist/py/test/tkinter/backend.py py/dist/py/test/tkinter/reportsession.py py/dist/py/test/tkinter/testing/test_backend.py py/dist/py/test/tkinter/testing/test_capture_out_err.py Log: * svn merge -r 36833:36901 http://codespeak.net/svn/py/branch/conftest/py * merging in the first bunch of cleanups from the conftest branch, main visible changes: * implemented and localized conftest handling code (in py/test/conftesthandle.py) * removed redundancies while setting up config and session objects * refactored config objects methods and attributes, you now use 'py.test.config' instead of 'py.test.Config' as you are now dealing with an instance and not a class anymore. py.test.config is a singleton-per-process (tests have the _reparse() method to get to additional config instances in a someone safe manner) * cleaned up documentation, added some docstrings to py.test objects Modified: py/dist/py/__init__.py ============================================================================== --- py/dist/py/__init__.py (original) +++ py/dist/py/__init__.py Thu Jan 18 08:00:43 2007 @@ -32,7 +32,7 @@ 'test.compat.TestCase' : ('./test/compat.py', 'TestCase'), # configuration/initialization related test api - 'test.Config' : ('./test/config.py', 'Config'), + 'test.config' : ('./test/config.py', 'config'), 'test.ensuretemp' : ('./test/config.py', 'ensuretemp'), 'test.cmdline.main' : ('./test/cmdline.py', 'main'), Modified: py/dist/py/apigen/conftest.py ============================================================================== --- py/dist/py/apigen/conftest.py (original) +++ py/dist/py/apigen/conftest.py Thu Jan 18 08:00:43 2007 @@ -1,7 +1,7 @@ import py -Option = py.test.Config.Option -option = py.test.Config.addoptions("apigen test options", +Option = py.test.config.Option +option = py.test.config.addoptions("apigen test options", Option('', '--webcheck', action="store_true", dest="webcheck", default=False, help="run XHTML validation tests" Modified: py/dist/py/apigen/testing/test_apigen_functional.py ============================================================================== --- py/dist/py/apigen/testing/test_apigen_functional.py (original) +++ py/dist/py/apigen/testing/test_apigen_functional.py Thu Jan 18 08:00:43 2007 @@ -7,6 +7,7 @@ from test_apigen_example import setup_fs_project def test_apigen_functional(): + py.test.skip("needs fixing with respect to rev 36800 and probably other problems") fs_root, package_name = setup_fs_project( 'test_apigen_functional') tempdir = py.test.ensuretemp('test_apigen_functional_results') Modified: py/dist/py/conftest.py ============================================================================== --- py/dist/py/conftest.py (original) +++ py/dist/py/conftest.py Thu Jan 18 08:00:43 2007 @@ -17,9 +17,9 @@ nomagic = False import py -Option = py.test.Config.Option +Option = py.test.config.Option -option = py.test.Config.addoptions("execnet options", +option = py.test.config.addoptions("execnet options", Option('-S', '', action="store", dest="sshtarget", default=None, help=("target to run tests requiring ssh, e.g. " Modified: py/dist/py/doc/conftest.py ============================================================================== --- py/dist/py/doc/conftest.py (original) +++ py/dist/py/doc/conftest.py Thu Jan 18 08:00:43 2007 @@ -2,8 +2,8 @@ import py from py.__.misc import rest -Option = py.test.Config.Option -option = py.test.Config.addoptions("documentation check options", +Option = py.test.config.Option +option = py.test.config.addoptions("documentation check options", Option('-R', '--checkremote', action="store_true", dest="checkremote", default=False, help="check remote links in ReST files" Modified: py/dist/py/doc/example/pytest/test_failures.py ============================================================================== --- py/dist/py/doc/example/pytest/test_failures.py (original) +++ py/dist/py/doc/example/pytest/test_failures.py Thu Jan 18 08:00:43 2007 @@ -3,9 +3,9 @@ failure_demo = py.magic.autopath().dirpath('failure_demo.py') def test_failure_demo_fails_properly(): - config, args = py.test.Config.parse([]) + config = py.test.config._reparse([failure_demo]) session = config.getsessionclass()(config, py.std.sys.stdout) - session.main([failure_demo]) + session.main() l = session.getitemoutcomepairs(py.test.Item.Failed) assert len(l) == 21 l = session.getitemoutcomepairs(py.test.Item.Passed) Modified: py/dist/py/doc/test.txt ============================================================================== --- py/dist/py/doc/test.txt (original) +++ py/dist/py/doc/test.txt Thu Jan 18 08:00:43 2007 @@ -358,6 +358,7 @@ .. _`basicpicture`: + Collecting and running tests / implementation remarks ====================================================== @@ -396,7 +397,7 @@ ------------------------------------------ The collecting process is iterative, i.e. the session -traverses the *collector tree*. Here is an example of such +traverses and generates a *collector tree*. Here is an example of such a tree, generated with the command ``py.test --collectonly py/xmlobj``:: @@ -421,38 +422,6 @@ .. _`collector API`: -collector API invoked by sessions ---------------------------------- - -Apart from initialization the default session object invokes -a very uniform API on collectors and test items: - -*colitem.run()* - - returns a list of names available from this collector. - You can return an empty list. Callers of this method - must take care to catch exceptions properly. The session - object guards its calls to ``colitem.run()`` in its - ``session.runtraced(colitem)`` method, including - catching of stdout. - -*colitem.join(name)* - - return a child item from the given name. Usually the - session feeds the join method with each name obtained - from ``colitem.run()``. If the return value is None - it means the ``colitem`` was not able to resolve - with the given name. - -*colitem.parent* - - attribute pointing to the parent collector. - -*colitem.name* - - name of this sub item. This is the name that is - passed to ``colitem.join()`` above. - test items are collectors as well --------------------------------- @@ -477,7 +446,8 @@ on a path object (which returns the parent directory as a path object). -* insert this base directory into sys.path as its first item +* insert this base directory into the sys.path list + as its first element * import the root package @@ -485,10 +455,11 @@ at ``path`` ... * if the imported root package has a __package__ object - then call its ``getimportname(path)`` + then call ``__package__.getimportname(path)`` * otherwise use the relative path of the module path to - the base dir and turn slashes into dots. + the base dir and turn slashes into dots and strike + the trailing ``.py``. The Module collector will eventually trigger ``__import__(mod_fqdnname, ...)`` to finally get to @@ -504,48 +475,16 @@ and test classes and methods. Test functions and methods are prefixed ``test`` by default. Test classes must start with a capitalized ``Test`` prefix. - -Reporting hooks of the session object -------------------------------------- - -Part of the default session API deals with reporting -test outcomes and collection details. These methods -are reponsible for representing the testing process -to the user or other programs: - -*session.header()* - - invoked once by ``session.run()`` before the whole - test session starts. -*session.footer()* - - invoked once by ``session.run()`` after the collection - and running process finished. - - -*session.start(colitem)* - - invoked before each ``colitem.run()`` invocation - - -*session.finish(colitem, outcome)* - - invoked after each ``colitem.run()`` invocation +Customizing the testing process +=============================== +writing conftest.py files +----------------------------------- -XXX the names of these session objects are likely to change -soon because the session object now has too many names that -aren't easily distinguishable regarding their purposes. It is -also likely that collectors/test items will become more -self-responsible for presenting outcomes in textual ways. -Currently, session object have to know too much about the -representation of failures/successes to the user which makes -it harder than neccessary to write custom test items. +XXX -Customizing the testing process -=============================== customizing the collecting and running process ----------------------------------------------- @@ -666,33 +605,17 @@ machines accessible through SSH, ``py.test`` can distribute tests across the machines. It does not require any particular installation on the remote machine sides as it uses `py.execnet`_ -mechanisms to distribute execution. - -*Warning*: support for distributed testing is in alpha state -and its mechanics and configuration options may change without -prior notice. - -Benefits --------- - -The main benefit for using distributed testing is speed. There -is some runtime overhead required to setup the test environment on the -remote machines, but if the project has a lot of tests and -several machines available, the speed up should be significant -in most cases. The more machines available, the better results -you will get. - -Automatically distributing the tests can be also be useful if you -need to use remote resouces which you do not have locally (perhaps -a server has much more RAM or disk available). -Of course, you could also just ssh into the remote server, -rsync or checkout your source code and run py.test -but that is obviously more cumbersome for the development -process. - -The distributed testing part of ``py.test`` also provides -a web server interface which tells you about the progress -of your distributed test run interactively. +mechanisms to distribute execution. Using distributed testing +can speed up your development process considerably and it +may also be useful where you need to use a remote server +that has more resources (e.g. RAM/diskspace) than your +local machine. + +*WARNING*: support for distributed testing is experimental, +its mechanics and configuration options may change without +prior notice. Particularly, not all reporting features +of the in-process py.test have been integrated into +the distributed testing approach. Requirements ------------ @@ -702,23 +625,23 @@ * ssh client * python -Remote requirements: +requirements for remote machines: * ssh daemon running * ssh keys setup to allow login without a password * python (2.3 or 2.4 should work) -* unix like machine (``os.fork``) +* unix like machine (reliance on ``os.fork``) -How it works ------------- +Hot to use it +----------------------- When you issue ``py.test --session=R`` then your computer becomes -the distributor of tests ("master") and will start distributing tests -to several machines which need to be specified in a ``conftest.py`` -file. +the distributor of tests ("master") and will start collecting +and distributing tests to several machines. The machines +need to be specified in a ``conftest.py`` file. -At start up, the master connects to each node using `py.execnet`_ and -its SSHGateways and *rsyncs* all specified python packages to all nodes. +At start up, the master connects to each node using `py.execnet.SshGateway`_ +and *rsyncs* all specified python packages to all nodes. Then the master collects all of the tests and immediately sends test item descriptions to its connected nodes. Each node has a local queue of tests to run and begins to execute the tests, following the setup and teardown @@ -730,6 +653,7 @@ from the testing nodes: command line, rest output and ajaxy web based. .. _`py.execnet`: execnet.html +.. _`py.execnet.SshGateway`: execnet.html Differences from local tests ---------------------------- @@ -745,19 +669,21 @@ The options that you need to specify in that conftest.py file are: -* `disthosts` - a list of ssh addresses (including a specific path if it +* `dist_hosts` - a list of ssh addresses (including a specific path if it should be different than the default: ``$HOME/pytestcache-hostname``) -* `distrsync_roots` - a list of packages to copy to the remote machines. +* `dist_rsync_roots` - a list of packages to copy to the remote machines. * `dist_remotepython` - the remote python to run. * `SessionOptions` - containing some specific tuning options Sample configuration:: - disthosts = ['localhost', 'user at someserver:/tmp/somedir'] - distrsync_roots = ['pypy', 'py'] + dist_hosts = ['localhost', 'user at someserver:/tmp/somedir'] + dist_rsync_roots = ['pypy', 'py'] dist_remotepython = 'python2.4' - class SessionOptions: - nice_level = 10 + dist_nicelevel = 10 + dist_boxing = True + dist_maxwait = 100 + dist_taskspernode = 10 Running server is done by ``-w`` command line option or ``--startserver`` (the former might change at some point due to conflicts). @@ -767,8 +693,8 @@ * `nice_level` - Level of nice under which tests are run * `runner_policy` - (for `LSession` only) - contains policy for the test boxig. `"plain_runner"` means no boxing, `"box_runner"` means boxing. -* `waittime` - Default waiting time for remote host to finish tests (after - that period we consider node as dead, default to 100s). +* `waittime` - Default maximum waiting time for remote host to execute + one test. * `max_tasks_per_node` - Maximum number of tasks which can be send to one node. * `import_pypy` - Flag to control pypy importing for js regeneration (defaults to False) Modified: py/dist/py/doc/test_conftest.py ============================================================================== --- py/dist/py/doc/test_conftest.py (original) +++ py/dist/py/doc/test_conftest.py Thu Jan 18 08:00:43 2007 @@ -28,9 +28,9 @@ end """)) - config, args = py.test.Config.parse([str(xtxt)]) + config = py.test.config._reparse([xtxt]) session = config.getsessionclass()(config, py.std.sys.stdout) - session.main([xtxt]) + session.main() l = session.getitemoutcomepairs(py.test.Item.Failed) assert len(l) == 0 l = session.getitemoutcomepairs(py.test.Item.Passed) @@ -46,9 +46,9 @@ .. _`blah`: javascript:some_function() """)) - config, args = py.test.Config.parse([str(xtxt)]) + config = py.test.config._reparse([xtxt]) session = config.getsessionclass()(config, py.std.sys.stdout) - session.main([xtxt]) + session.main() l = session.getitemoutcomepairs(py.test.Item.Failed) assert len(l) == 0 l = session.getitemoutcomepairs(py.test.Item.Passed) Modified: py/dist/py/test/cmdline.py ============================================================================== --- py/dist/py/test/cmdline.py (original) +++ py/dist/py/test/cmdline.py Thu Jan 18 08:00:43 2007 @@ -10,7 +10,8 @@ args = py.std.sys.argv[1:] elif isinstance(args, basestring): args = args.split(" ") - config, args = py.test.Config.parse(args) + config = py.test.config + config.parse(args) sessionclass = config.getsessionclass() # ok, some option checks @@ -31,17 +32,8 @@ session = sessionclass(config) - if config.option.runbrowser and not config.option.startserver: - print "Cannot point browser when not starting server" - config.option.startserver = True - try: - if config.getinitialvalue('startserver'): - py.std.warnings.warn("Startserver flag in config is deprecated, use commandline option instead") - except ValueError: - pass - try: - failures = session.main(args) + failures = session.main() if failures: raise SystemExit, 1 except KeyboardInterrupt: Modified: py/dist/py/test/collect.py ============================================================================== --- py/dist/py/test/collect.py (original) +++ py/dist/py/test/collect.py Thu Jan 18 08:00:43 2007 @@ -29,7 +29,7 @@ def configproperty(name): def fget(self): #print "retrieving %r property from %s" %(name, self.fspath) - return py.test.Config.getvalue(name, self.fspath) + return py.test.config.getvalue(name, self.fspath) return property(fget) def getfscollector(fspath): @@ -43,7 +43,7 @@ pkgpath = fspath else: pkgpath = fspath.dirpath() - Directory = py.test.Config.getvalue('Directory', pkgpath) + Directory = py.test.config.getvalue('Directory', pkgpath) current = Directory(pkgpath) #print "pkgpath", pkgpath names = filter(None, fspath.relto(pkgpath).split(fspath.sep)) @@ -55,6 +55,14 @@ return current class Collector(object): + """ Collector instances are iteratively generated + (through their run() and join() methods) + and form a tree. attributes:: + + parent: attribute pointing to the parent collector + (or None if it is the root collector) + name: basename of this collector object + """ def __init__(self, name, parent=None): self.name = name self.parent = parent @@ -113,6 +121,25 @@ #print "cmp", s1, s2 return cmp(s1, s2) + + def run(self): + """ returns a list of names available from this collector. + You can return an empty list. Callers of this method + must take care to catch exceptions properly. The session + object guards its calls to ``colitem.run()`` in its + ``session.runtraced(colitem)`` method, including + catching of stdout. + """ + raise NotImplementedError("abstract") + + def join(self, name): + """ return a child item for the given name. Usually the + session feeds the join method with each name obtained + from ``colitem.run()``. If the return value is None + it means the ``colitem`` was not able to resolve + with the given name. + """ + def obj(): def fget(self): try: @@ -287,7 +314,7 @@ elif p.ext == '.txt': res = self.DoctestFile(p, parent=self) elif p.check(dir=1): - Directory = py.test.Config.getvalue('Directory', p) + Directory = py.test.config.getvalue('Directory', p) res = Directory(p, parent=self) name2items[name] = res return res @@ -364,7 +391,7 @@ return res def startcapture(self): - if not self.option.nocapture and not self.option.usepdb: + if not self.option.nocapture: assert not hasattr(self, '_capture') #self._capture = py.io.OutErrCapture() # XXX integrate this into py.io / refactor @@ -454,7 +481,7 @@ Collector.Function.__get__(self)) # XXX for python 2.2 Function = property(Function) -class Generator(Collector, PyCollectorMixin): +class Generator(PyCollectorMixin, Collector): def run(self): self._prepare() itemlist = self._name2items Modified: py/dist/py/test/config.py ============================================================================== --- py/dist/py/test/config.py (original) +++ py/dist/py/test/config.py Thu Jan 18 08:00:43 2007 @@ -1,16 +1,9 @@ from __future__ import generators import py -optparse = py.compat.optparse - -defaultconfig = py.magic.autopath().dirpath('defaultconftest.py') -dummy = object() - -# -# configuration file handling -# -configbasename = 'conftest.py' +from conftesthandle import Conftest +optparse = py.compat.optparse # XXX move to Config class basetemp = None @@ -22,113 +15,90 @@ if basetemp is None: basetemp = py.path.local.make_numbered_dir(prefix='pytest-') return basetemp.ensure(string, dir=dir) - + +class CmdOptions(object): + """ pure container instance for holding cmdline options + as attributes. + """ + def __repr__(self): + return "" %(self.__dict__,) + class Config(object): """ central hub for dealing with configuration/initialization data. """ Option = optparse.Option - _configs_cache = {} + conftest = Conftest() def __init__(self): - self.option = optparse.Values() - self._parser = optparse.OptionParser(usage="usage: %prog [options] [query] [filenames of tests]") - self._initialconfigmodules = [] - - # class level attributes - def _reset(cls): - cls._config = cls() - _reset = classmethod(_reset) - - def getvalue(cls, name, path=None, default=dummy, trydefaultconfig=True): - """ return 'name' value looked up from the first conftest file - found up the path (including the path itself). - """ - configpaths = guessconfigpaths(path) - if trydefaultconfig: - configpaths.append(defaultconfig) - for p in configpaths: - try: - mod = cls._configs_cache[p] - except (KeyError, IndexError): - mod = importconfig(p) - cls._configs_cache[p] = mod - try: - return getattr(mod, name) - except AttributeError: - pass - if default is not dummy: - return default - raise ValueError("config value not found: %r, path=%r" % (name, path)) - getvalue = classmethod(getvalue) - - def parse(cls, args): - """ return Config object and remaining arguments from parsing - command line arguments. + self.option = CmdOptions() + self._parser = optparse.OptionParser( + usage="usage: %prog [options] [query] [filenames of tests]") + self._parsed = False + + def parse(self, args): + """ parse cmdline arguments into this config object. + Note that this can only be called once per testing process. """ - configpaths = guessconfigpaths(*getanchorpaths(args)) - config = bootstrapconfig(configpaths) - config._origargs = args - cmdlineoption, remaining = config._parser.parse_args(args) - for name, value in vars(cmdlineoption).items(): - setattr(config.option, name, value) - fixoptions(config.option) + assert not self._parsed, ( + "can only parse cmdline args once per Config object") + self._parsed = True + self.conftest.setinitial(args) + self.conftest.lget('adddefaultoptions')() + args = [str(x) for x in args] + self._origargs = args + cmdlineoption, remaining = self._parser.parse_args(args) + self.option.__dict__.update(vars(cmdlineoption)) + fixoptions(self.option) # XXX fixing should be moved to sessions if not remaining: remaining.append(py.std.os.getcwd()) - config.remaining = remaining - return config, remaining - parse = classmethod(parse) + self.remaining = remaining - def addoptions(cls, groupname, *specs): + def addoptions(self, groupname, *specs): """ add a named group of options to the current testing session. This function gets invoked during testing session initialization. """ - parser = cls._config._parser - optgroup = optparse.OptionGroup(parser, groupname) + optgroup = optparse.OptionGroup(self._parser, groupname) optgroup.add_options(specs) - parser.add_option_group(optgroup) + self._parser.add_option_group(optgroup) for opt in specs: if hasattr(opt, 'default') and opt.dest: - setattr(cls._config.option, opt.dest, opt.default) - return cls._config.option - addoptions = classmethod(addoptions) - - # instance methods dealing with initial config module handling - - def loadconfig(self, configpath): - """ load configpath as an initial config module. """ - mod = importconfig(configpath) - self._initialconfigmodules.append(mod) - return mod - - def getinitialvalue(self, name, default=dummy): - """ return first value found in initial config modules. """ - for confmodule in self._initialconfigmodules: - if hasattr(confmodule, name): - return getattr(confmodule, name) - if default is not dummy: - return default - raise ValueError("initial config value not found: %r" % name) + setattr(self.option, opt.dest, opt.default) + return self.option + + def getvalue(self, name, path=None): + """ return 'name' value looked up from the first conftest file + found up the path (including the path itself). + if path is None, lookup the value in the initial + conftest modules found during command line parsing. + """ + return self.conftest.rget(name, path) def getsessionclass(self): """ return Session class determined from cmdline options and looked up in initial config modules. """ - # we need to import all the sessions here - from py.__.test.session import Session - from py.__.test.rsession.rsession import RSession, LSession - from py.__.test.terminal.terminal import TerminalSession - from py.__.test.tkinter.reportsession import ReportSession - sessions = {'RSession':RSession, 'LSession':LSession, - 'TerminalSession':TerminalSession, - 'TkinterSession':ReportSession} - - name = self.option.session - name += 'Session' - try: - return self.getinitialvalue(name) - except ValueError: - return sessions[name] + sessionname = self.option.session + 'Session' + try: + return self.conftest.lget(sessionname) + except KeyError: + pass + sessionimportpaths = self.conftest.lget('sessionimportpaths') + importpath = sessionimportpaths[sessionname] + mod = __import__(importpath, None, None, ['__doc__']) + return getattr(mod, sessionname) + + def _reparse(self, args): + """ this is used from tests that want to re-invoke parse(). """ + global config + oldconfig = py.test.config + try: + config = py.test.config = Config() + config.parse(args) + return config + finally: + config = py.test.config = oldconfig -Config._reset() +# this is the one per-process instance of py.test configuration +config = Config() # # helpers @@ -153,6 +123,11 @@ else: option.executable = py.std.sys.executable + if option.usepdb: + if not option.nocapture: + print "--usepdb currently implies --nocapture" + option.nocapture = True + # make information available about wether we should/will be remote option._remote = remote or option.looponfailing option._fromremote = False @@ -167,75 +142,7 @@ name = name.capitalize() option.session = name -def bootstrapconfig(configpaths): - """ return 'current' config object, after initializing - it with the given configpaths. - """ - # XXX Config._config holds all options that are added from - # conftest's py.test.Config.addoptions() invocations. This "global state" - # manipulation is unfortunate but how else could we allow - # applications to add cmdline options and provide them - # access to the resulting config values? - - config = Config._config - # trigger loading conftest files which might add options! - config.loadconfig(defaultconfig).adddefaultoptions() - for configpath in configpaths: - config.loadconfig(configpath) - # each time we make a config object (which assembled cmdline - # options through py.test.addoptions() invocations) - # we want to reset and clean up the global state - Config._reset() - return config - -_config_paths_cache = {} - -def guessconfigpaths(*paths): - """ return test configuration paths from skimming the args. """ - key = tuple(paths) - try: - return _config_paths_cache[key] - except KeyError: - pass - d = {} - l = [] - for anchor in paths: - if anchor: - for p in anchor.parts(): - x = p.join(configbasename) - if x not in d and x.check(file=1): - d[x] = True - l.append(x) - l.reverse() - _config_paths_cache[key] = l - return l - -def getanchorpaths(args): - """ yield "anchors" from skimming the args for existing files/dirs. """ - current = py.path.local() - l = [] - for arg in args: - anchor = current.join(arg, abs=1) - if anchor.check(): - l.append(anchor) - if not l: - l = [current] - return l - -def importconfig(configpath): - if not configpath.dirpath('__init__.py').check(file=1): - # HACK: we don't want a "globally" imported conftest.py, - # prone to conflicts and subtle problems - modname = str(configpath).replace('.', configpath.sep) - return configpath.pyimport(modname=modname) - else: - return configpath.pyimport() + if option.runbrowser and not option.startserver: + print "Cannot point browser when not starting server" + option.startserver = True - -#XXX was needed for extracting defaults, not needed anymore? -#def flattenoptions(parser): -# for group in parser.option_groups: -# for y in group.option_list: -# yield y -# for x in parser.option_list: -# yield x Modified: py/dist/py/test/defaultconftest.py ============================================================================== --- py/dist/py/test/defaultconftest.py (original) +++ py/dist/py/test/defaultconftest.py Thu Jan 18 08:00:43 2007 @@ -10,9 +10,17 @@ additionalinfo = None +Option = py.test.config.Option + +sessionimportpaths = { + 'RSession': 'py.__.test.rsession.rsession', + 'LSession': 'py.__.test.rsession.rsession', + 'TerminalSession': 'py.__.test.terminal.terminal', + 'TkinterSession': 'py.__.test.tkinter.reportsession', +} + def adddefaultoptions(): - Option = py.test.Config.Option - py.test.Config.addoptions('general options', + py.test.config.addoptions('general options', Option('-v', '--verbose', action="count", dest="verbose", default=0, help="increase verbosity."), @@ -53,7 +61,8 @@ help="generate api documentation while testing (requires" "argument pointing to a script)."), ) - py.test.Config.addoptions('test-session related options', + + py.test.config.addoptions('test-session related options', Option('', '--tkinter', action="store_true", dest="tkinter", default=False, help="use tkinter test session frontend."), Modified: py/dist/py/test/item.py ============================================================================== --- py/dist/py/test/item.py (original) +++ py/dist/py/test/item.py Thu Jan 18 08:00:43 2007 @@ -31,7 +31,7 @@ class Item(py.test.collect.Collector): def startcapture(self): - if not self.option.nocapture and not self.option.usepdb: + if not self.option.nocapture: # XXX refactor integrate capturing #self._capture = py.io.OutErrCapture() from py.__.misc.simplecapture import SimpleOutErrCapture Modified: py/dist/py/test/rsession/conftest.py ============================================================================== --- py/dist/py/test/rsession/conftest.py (original) +++ py/dist/py/test/rsession/conftest.py Thu Jan 18 08:00:43 2007 @@ -1,7 +1,7 @@ import py -Option = py.test.Config.Option +Option = py.test.config.Option -option = py.test.Config.addoptions("boxing test options", +option = py.test.config.addoptions("boxing test options", Option('', '--skip-kill-test', action='store_true', default=False, dest='skip_kill_test', help='skip a certain test that checks for os.kill results, this ' Modified: py/dist/py/test/rsession/rest.py ============================================================================== --- py/dist/py/test/rsession/rest.py (original) +++ py/dist/py/test/rsession/rest.py Thu Jan 18 08:00:43 2007 @@ -19,7 +19,7 @@ def get_linkwriter(self): if self.linkwriter is None: - self.linkwriter = self.config.getinitialvalue('linkwriter') + self.linkwriter = self.config.getvalue('linkwriter') return self.linkwriter def report_unknown(self, what): Modified: py/dist/py/test/rsession/rsession.py ============================================================================== --- py/dist/py/test/rsession/rsession.py (original) +++ py/dist/py/test/rsession/rsession.py Thu Jan 18 08:00:43 2007 @@ -45,8 +45,8 @@ def getvalue(self, opt): try: - return getattr(self.config.getinitialvalue('SessionOptions'), opt) - except (ValueError, AttributeError): + return getattr(self.config.getvalue('SessionOptions'), opt) + except (KeyError, AttributeError): try: return self.defaults[opt] except KeyError: @@ -56,8 +56,8 @@ self.config = config # copy to remote session options try: - ses_opt = self.config.getinitialvalue('SessionOptions').__dict__ - except ValueError: + ses_opt = self.config.getvalue('SessionOptions').__dict__ + except KeyError: ses_opt = self.defaults for key in self.defaults: try: @@ -184,10 +184,9 @@ class RSession(AbstractSession): """ Remote version of session """ - def main(self, args, reporter=None): + def main(self, reporter=None): """ main loop for running tests. """ - if not args: - args = [py.path.local()] + args = self.config.remaining session_options.bind_config(self.config) sshhosts, remotepython, rsync_roots = self.read_distributed_config() @@ -216,14 +215,14 @@ def read_distributed_config(self): try: - rsync_roots = self.config.getinitialvalue("distrsync_roots") + rsync_roots = self.config.getvalue("distrsync_roots") except: rsync_roots = None # all files and directories in the pkgdir sshhosts = [HostInfo(i) for i in - self.config.getinitialvalue("disthosts")] + self.config.getvalue("disthosts")] parse_directories(sshhosts) try: - remotepython = self.config.getinitialvalue("dist_remotepython") + remotepython = self.config.getvalue("dist_remotepython") except: remotepython = None return sshhosts, remotepython, rsync_roots @@ -246,11 +245,9 @@ class LSession(AbstractSession): """ Local version of session """ - def main(self, args, reporter=None, runner=None): + def main(self, reporter=None, runner=None): # check out if used options makes any sense - - if not args: - args = [py.path.local()] + args = self.config.remaining sshhosts = [HostInfo('localhost')] # this is just an info to reporter Modified: py/dist/py/test/rsession/testing/test_config.py ============================================================================== --- py/dist/py/test/rsession/testing/test_config.py (original) +++ py/dist/py/test/rsession/testing/test_config.py Thu Jan 18 08:00:43 2007 @@ -14,11 +14,11 @@ """) tmp2 = py.test.ensuretemp("xxx") args = [str(tmpdir)] - config, args = py.test.Config.parse(args) + config = py.test.config._reparse(args) session_options.bind_config(config) assert session_options.max_tasks_per_node == 5 assert remote_options.nice_level == 10 - config, args = py.test.Config.parse([str(tmp2)]) + config = py.test.config._reparse([str(tmp2)]) session_options.bind_config(config) assert session_options.max_tasks_per_node == \ SessionOptions.defaults['max_tasks_per_node'] Modified: py/dist/py/test/rsession/testing/test_executor.py ============================================================================== --- py/dist/py/test/rsession/testing/test_executor.py (original) +++ py/dist/py/test/rsession/testing/test_executor.py Thu Jan 18 08:00:43 2007 @@ -100,7 +100,7 @@ outcome_repr = ex.execute() outcome = ReprOutcome(outcome_repr) assert outcome.passed - assert outcome.stdout == "samfing\n" + assert outcome.stdout.find("samfing") != -1 def test_box_executor_stdout_error(): rootcol = py.test.collect.Directory(rootdir) @@ -109,7 +109,7 @@ outcome_repr = ex.execute() outcome = ReprOutcome(outcome_repr) assert not outcome.passed - assert outcome.stdout == "samfing elz\n" + assert outcome.stdout.find("samfing elz") != -1 def test_cont_executor(): rootcol = py.test.collect.Directory(rootdir) @@ -120,4 +120,4 @@ outcome_repr = cont() outcome = ReprOutcome(outcome_repr) assert not outcome.passed - assert outcome.stdout == "samfing elz\n" + assert outcome.stdout.find("samfing elz") != -1 Modified: py/dist/py/test/rsession/testing/test_lsession.py ============================================================================== --- py/dist/py/test/rsession/testing/test_lsession.py (original) +++ py/dist/py/test/rsession/testing/test_lsession.py Thu Jan 18 08:00:43 2007 @@ -32,10 +32,10 @@ # os.kill(os.getpid(), 11) """)) args = [str(tmpdir.join(dirname))] - config, args = py.test.Config.parse(args) + config = py.test.config._reparse(args) lsession = LSession(config) allevents = [] - lsession.main(args, reporter=allevents.append, runner=runner) + lsession.main(reporter=allevents.append, runner=runner) testevents = [x for x in allevents if isinstance(x, report.ReceivedItemOutcome)] assert len(testevents) @@ -85,11 +85,11 @@ pdb.post_mortem = some_fun args = [str(tmpdir.join(subdir)), '--pdb'] - config, args = py.test.Config.parse(args) + config = py.test.config._reparse(args) lsession = LSession(config) allevents = [] try: - lsession.main(args, reporter=allevents.append, runner=plain_runner) + lsession.main(reporter=allevents.append, runner=plain_runner) except SystemExit: pass else: @@ -116,12 +116,12 @@ pass """)) args = [str(tmpdir.join(subdir)), '-x'] - config, args = py.test.Config.parse(args) + config = py.test.config._reparse(args) assert config.option.exitfirst lsession = LSession(config) allevents = [] - lsession.main(args, reporter=allevents.append, runner=box_runner) + lsession.main(reporter=allevents.append, runner=box_runner) testevents = [x for x in allevents if isinstance(x, report.ReceivedItemOutcome)] assert len(testevents) @@ -146,11 +146,11 @@ pass """)) args = [str(tmpdir.join("sub3")), '-k', 'test_one'] - config, args = py.test.Config.parse(args) + config = py.test.config._reparse(args) lsession = LSession(config) allevents = [] - lsession.main(args, reporter=allevents.append, runner=box_runner) + lsession.main(reporter=allevents.append, runner=box_runner) testevents = [x for x in allevents if isinstance(x, report.ReceivedItemOutcome)] assert len(testevents) @@ -174,7 +174,7 @@ """)) args = [str(tmpdir.join("sub4"))] - config, args = py.test.Config.parse(args) + config = py.test.config._reparse(args) lsession = LSession(config) allevents = [] allruns = [] @@ -182,7 +182,7 @@ allruns.append(item) item.passed = True return item - lsession.main(args, reporter=allevents.append, runner=dummy_runner) + lsession.main(reporter=allevents.append, runner=dummy_runner) assert len(allruns) == 4 testevents = [x for x in allevents @@ -205,10 +205,10 @@ """)) args = [str(tmpdir.join("sub5"))] - config, args = py.test.Config.parse(args) + config = py.test.config._reparse(args) lsession = LSession(config) allevents = [] - lsession.main(args, reporter=allevents.append, runner=box_runner) + lsession.main(reporter=allevents.append, runner=box_runner) testevents = [x for x in allevents if isinstance(x, report.ReceivedItemOutcome)] assert len(testevents) == 0 @@ -231,10 +231,10 @@ assert [0] == x """)) args = [str(tmpdir.join("sub6"))] - config, args = py.test.Config.parse(args) + config = py.test.config._reparse(args) lsession = LSession(config) allevents = [] - lsession.main(args, reporter=allevents.append, runner=box_runner) + lsession.main(reporter=allevents.append, runner=box_runner) testevents = [x for x in allevents if isinstance(x, report.ReceivedItemOutcome)] failevents = [i for i in testevents if i.outcome.excinfo] @@ -252,10 +252,10 @@ print 3 """)) args = [str(tmpdir.join("sub7"))] - config, args = py.test.Config.parse(args) + config = py.test.config._reparse(args) lsession = LSession(config) allevents = [] - lsession.main(args, reporter=allevents.append, runner=plain_runner) + lsession.main(reporter=allevents.append, runner=plain_runner) testevents = [x for x in allevents if isinstance(x, report.ReceivedItemOutcome)] assert len(testevents) == 1 Modified: py/dist/py/test/rsession/testing/test_master.py ============================================================================== --- py/dist/py/test/rsession/testing/test_master.py (original) +++ py/dist/py/test/rsession/testing/test_master.py Thu Jan 18 08:00:43 2007 @@ -18,7 +18,7 @@ def setup_module(mod): # bind an empty config - config, args = py.test.Config.parse([]) + config = py.test.config._reparse([]) config.option.max_tasks_per_node = 10 session_options.bind_config(config) #assert not remote_options.exitfirst Modified: py/dist/py/test/rsession/testing/test_reporter.py ============================================================================== --- py/dist/py/test/rsession/testing/test_reporter.py (original) +++ py/dist/py/test/rsession/testing/test_reporter.py Thu Jan 18 08:00:43 2007 @@ -61,7 +61,7 @@ return outcomes def report_received_item_outcome(self): - config, args = py.test.Config.parse(["some_sub"]) + config = py.test.config._reparse(["some_sub"]) # we just go... rootcol = py.test.collect.Directory(self.pkgdir.dirpath()) item = rootcol.getitembynames(funcpass_spec) @@ -81,7 +81,7 @@ return out def _test_module(self): - config, args = py.test.Config.parse(["some_sub"]) + config = py.test.config._reparse(["some_sub"]) # we just go... rootcol = py.test.collect.Directory(self.pkgdir.dirpath()) funcitem = rootcol.getitembynames(funcpass_spec) @@ -119,7 +119,7 @@ """)) def boxfun(): - config, args = py.test.Config.parse([str(tmpdir)]) + config = py.test.config._reparse([str(tmpdir)]) rootcol = py.test.collect.Directory(tmpdir) hosts = [HostInfo('localhost')] r = self.reporter(config, hosts) @@ -138,7 +138,7 @@ sadsadsa """)) def boxfun(): - config, args = py.test.Config.parse([str(tmpdir)]) + config = py.test.config._reparse([str(tmpdir)]) rootcol = py.test.collect.Directory(tmpdir) host = HostInfo('localhost') r = self.reporter(config, [host]) @@ -157,7 +157,7 @@ tmpdir = py.test.ensuretemp("stilltogo") tmpdir.ensure("__init__.py") cap = py.io.OutErrCapture() - config, args = py.test.Config.parse([str(tmpdir)]) + config = py.test.config._reparse([str(tmpdir)]) hosts = [HostInfo(i) for i in ["host1", "host2", "host3"]] r = self.reporter(config, hosts) r.report(report.TestStarted(hosts)) @@ -170,7 +170,7 @@ host1: READY (still 2 to go) host2: READY (still 1 to go) host3: READY""" - assert out.startswith(expected) + assert out.find(expected) != -1 class TestLocalReporter(AbstractTestReporter): reporter = LocalReporter @@ -191,7 +191,7 @@ repmod/test_one.py[1] repmod/test_three.py[0] - FAILED TO LOAD MODULE repmod/test_two.py[0] - skipped (reason)""" - assert received == expected + assert received.find(expected) != -1 class TestRemoteReporter(AbstractTestReporter): reporter = RemoteReporter @@ -207,7 +207,7 @@ localhost: FAILED py test rsession testing test_slave.py funcpass localhost: PASSED py test rsession testing test_slave.py funcpass """ - assert val == expected + assert val.find(expected) != -1 def test_module(self): val = self._test_module() @@ -217,10 +217,10 @@ localhost: FAILED py test rsession testing test_slave.py funcpass localhost: PASSED py test rsession testing test_slave.py funcpass """ - assert val == expected + assert val.find(expected) != -1 def test_full_module(self): #py.test.skip("XXX rewrite test to not rely on exact formatting") val = self._test_full_module() - assert val == 'FAILED TO LOAD MODULE: repmod/test_three.py\n'\ - '\nSkipped (reason) repmod/test_two.py\n\n' + assert val.find('FAILED TO LOAD MODULE: repmod/test_three.py\n'\ + '\nSkipped (reason) repmod/test_two.py') != -1 Modified: py/dist/py/test/rsession/testing/test_rest.py ============================================================================== --- py/dist/py/test/rsession/testing/test_rest.py (original) +++ py/dist/py/test/rsession/testing/test_rest.py Thu Jan 18 08:00:43 2007 @@ -27,7 +27,7 @@ class TestRestUnits(object): def setup_method(self, method): - config, args = py.test.Config.parse(["some_sub"]) + config = py.test.config._reparse(["some_sub"]) config.option.verbose = False self.config = config hosts = [HostInfo('localhost')] Modified: py/dist/py/test/rsession/testing/test_rsession.py ============================================================================== --- py/dist/py/test/rsession/testing/test_rsession.py (original) +++ py/dist/py/test/rsession/testing/test_rsession.py Thu Jan 18 08:00:43 2007 @@ -91,10 +91,10 @@ pass """)) args = [str(tmpdir.join("sub")), "-x"] - config, args = py.test.Config.parse(args) + config = py.test.config._reparse(args) rsession = RSession(config) allevents = [] - rsession.main(args, reporter=allevents.append) + rsession.main(reporter=allevents.append) testevents = [x for x in allevents if isinstance(x, report.ReceivedItemOutcome)] assert len(testevents) == 3 @@ -121,10 +121,10 @@ assert __file__ != '%s' """ % str(tmpdir.join(subdir)))) args = [str(tmpdir.join(subdir))] - config, args = py.test.Config.parse(args) + config = py.test.config._reparse(args) rsession = RSession(config, optimise_localhost=False) allevents = [] - rsession.main(args, reporter=allevents.append) + rsession.main(reporter=allevents.append) testevents = [x for x in allevents if isinstance(x, report.ReceivedItemOutcome)] assert len(testevents) @@ -154,7 +154,7 @@ setup_events = [] teardown_events = [] - config, args = py.test.Config.parse([]) + config = py.test.config._reparse([]) session_options.bind_config(config) nodes = init_hosts(setup_events.append, hosts, pkgdir, rsync_roots=["py"], optimise_localhost=False, remote_options=remote_options.d) @@ -181,7 +181,7 @@ parse_directories(hosts) allevents = [] - config, args = py.test.Config.parse([]) + config = py.test.config._reparse([]) session_options.bind_config(config) nodes = init_hosts(allevents.append, hosts, pkgdir, rsync_roots=["py"], optimise_localhost=False, remote_options=remote_options.d) @@ -214,7 +214,7 @@ assert len(skipped) == len(nodes) assert len(events) == 4 * len(nodes) # one of passed for each node has non-empty stdout - passed_stdout = [i for i in passed if i.outcome.stdout == 'samfing\n'] + passed_stdout = [i for i in passed if i.outcome.stdout.find('samfing') != -1] assert len(passed_stdout) == len(nodes), passed def test_config_pass(self): @@ -223,7 +223,7 @@ allevents = [] hosts = [HostInfo('localhost')] parse_directories(hosts) - config, args = py.test.Config.parse([]) + config = py.test.config._reparse([]) session_options.bind_config(config) d = remote_options.d.copy() d['custom'] = 'custom' @@ -264,11 +264,11 @@ assert os.nice(0) == 10 """) - config, args = py.test.Config.parse([str(tmpdir)]) + config = py.test.config._reparse([tmpdir]) config.option.nice_level = 10 rsession = RSession(config) allevents = [] - rsession.main(args, reporter=allevents.append) + rsession.main(reporter=allevents.append) testevents = [x for x in allevents if isinstance(x, report.ReceivedItemOutcome)] passevents = [x for x in testevents if x.outcome.passed] Modified: py/dist/py/test/rsession/testing/test_slave.py ============================================================================== --- py/dist/py/test/rsession/testing/test_slave.py (original) +++ py/dist/py/test/rsession/testing/test_slave.py Thu Jan 18 08:00:43 2007 @@ -13,7 +13,7 @@ def setup_module(module): from py.__.test.rsession.rsession import session_options module.rootdir = py.path.local(py.__file__).dirpath().dirpath() - config, args = py.test.Config.parse([]) + config = py.test.config._reparse([]) session_options.bind_config(config) # ---------------------------------------------------------------------- Modified: py/dist/py/test/rsession/testing/test_web.py ============================================================================== --- py/dist/py/test/rsession/testing/test_web.py (original) +++ py/dist/py/test/rsession/testing/test_web.py Thu Jan 18 08:00:43 2007 @@ -13,7 +13,7 @@ py.test.skip("PyPy not found") def setup_module(mod): - config, args = py.test.Config.parse([]) + config = py.test.config._reparse([]) from py.__.test.rsession.rsession import session_options session_options.bind_config(config) session_options.import_pypy = True Modified: py/dist/py/test/rsession/testing/test_webjs.py ============================================================================== --- py/dist/py/test/rsession/testing/test_webjs.py (original) +++ py/dist/py/test/rsession/testing/test_webjs.py Thu Jan 18 08:00:43 2007 @@ -15,7 +15,7 @@ mod.dom = dom dom.window = dom.Window(html) dom.document = dom.window.document - config, args = py.test.Config.parse([]) + config = py.test.config._reparse([]) from py.__.test.rsession.rsession import session_options session_options.bind_config(config) session_options.import_pypy = True Modified: py/dist/py/test/session.py ============================================================================== --- py/dist/py/test/session.py (original) +++ py/dist/py/test/session.py Thu Jan 18 08:00:43 2007 @@ -13,20 +13,21 @@ return False def header(self, colitems): - """ setup any neccessary resources. """ + """ setup any neccessary resources ahead of the test run. """ if not self.config.option.nomagic: py.magic.invoke(assertion=1) def footer(self, colitems): - """ teardown any resources we know about. """ + """ teardown any resources after a test run. """ py.test.Function.state.teardown_all() if not self.config.option.nomagic: py.magic.revoke(assertion=1) def start(self, colitem): - pass + """ hook invoked before each colitem.run() invocation. """ def finish(self, colitem, outcome): + """ hook invoked after each colitem.run() invocation. """ self._memo.append((colitem, outcome)) def startiteration(self, colitem, subitems): @@ -35,9 +36,9 @@ def getitemoutcomepairs(self, cls): return [x for x in self._memo if isinstance(x[1], cls)] - def main(self, args): + def main(self): """ main loop for running tests. """ - colitems = self._map2colitems(args) + colitems = self._map2colitems(self.config.remaining) try: self.header(colitems) try: Modified: py/dist/py/test/terminal/remote.py ============================================================================== --- py/dist/py/test/terminal/remote.py (original) +++ py/dist/py/test/terminal/remote.py Thu Jan 18 08:00:43 2007 @@ -53,7 +53,7 @@ def failure_slave(channel): """ we run this on the other side. """ args, failures = channel.receive() - config, args = py.test.Config.parse(args) + config = py.test.config._reparse(args) # making this session definitely non-remote config.option.executable = py.std.sys.executable config.option.looponfailing = False @@ -66,7 +66,7 @@ #print "processing", cols session = config.getsessionclass()(config) session.shouldclose = channel.isclosed - failures = session.main(cols) + failures = session.main() channel.send(failures) def getfailureitems(failures): Modified: py/dist/py/test/terminal/terminal.py ============================================================================== --- py/dist/py/test/terminal/terminal.py (original) +++ py/dist/py/test/terminal/terminal.py Thu Jan 18 08:00:43 2007 @@ -28,12 +28,12 @@ self._started = {} self._opencollectors = [] - def main(self, args): + def main(self): if self.config.option._remote: from py.__.test.terminal import remote return remote.main(self.config, self._file, self.config._origargs) else: - return super(TerminalSession, self).main(args) + return super(TerminalSession, self).main() # --------------------- # PROGRESS information @@ -145,7 +145,8 @@ for x in colitems: self.out.line("test target: %s" %(x.fspath,)) - for i,x in py.builtin.enumerate(self.config._initialconfigmodules): + conftestmodules = self.config.conftest.getconftestmodules(None) + for i,x in py.builtin.enumerate(conftestmodules): self.out.line("initial conf %d: %s" %(i, x.__file__)) #for i, x in py.builtin.enumerate(py.test.config.configpaths): Modified: py/dist/py/test/testing/test_collect.py ============================================================================== --- py/dist/py/test/testing/test_collect.py (original) +++ py/dist/py/test/testing/test_collect.py Thu Jan 18 08:00:43 2007 @@ -1,13 +1,13 @@ from __future__ import generators import py -datadir = py.magic.autopath().dirpath('data') +from setupdata import setupdatadir -tmpdir = py.test.ensuretemp('test_collect') +def setup_module(mod): + mod.datadir = setupdatadir() + mod.tmpdir = py.test.ensuretemp('test_collect') def test_failing_import_execfile(): - fn = datadir / 'failingimport.py' - dest = tmpdir.join('failing_import.py') - fn.copy(dest) + dest = datadir / 'failingimport.py' col = py.test.collect.Module(dest) py.test.raises(ImportError, col.run) py.test.raises(ImportError, col.run) @@ -213,20 +213,20 @@ # test that running a session works from the directories old = o.chdir() try: - config, args = py.test.Config.parse([]) + config = py.test.config._reparse([]) out = py.std.cStringIO.StringIO() session = config.getsessionclass()(config, out) - session.main(args) + session.main() l = session.getitemoutcomepairs(py.test.Item.Passed) assert len(l) == 2 finally: old.chdir() # test that running the file directly works - config, args = py.test.Config.parse([str(checkfile)]) + config = py.test.config._reparse([str(checkfile)]) out = py.std.cStringIO.StringIO() session = config.getsessionclass()(config, out) - session.main(args) + session.main() l = session.getitemoutcomepairs(py.test.Item.Passed) assert len(l) == 2 @@ -260,20 +260,20 @@ # test that running a session works from the directories old = o.chdir() try: - config, args = py.test.Config.parse([]) + config = py.test.config._reparse([]) out = py.std.cStringIO.StringIO() session = config.getsessionclass()(config, out) - session.main(args) + session.main() l = session.getitemoutcomepairs(py.test.Item.Passed) assert len(l) == 1 finally: old.chdir() # test that running the file directly works - config, args = py.test.Config.parse([str(checkfile)]) + config = py.test.config._reparse([str(checkfile)]) out = py.std.cStringIO.StringIO() session = config.getsessionclass()(config, out) - session.main(args) + session.main() l = session.getitemoutcomepairs(py.test.Item.Passed) assert len(l) == 1 Modified: py/dist/py/test/testing/test_config.py ============================================================================== --- py/dist/py/test/testing/test_config.py (original) +++ py/dist/py/test/testing/test_config.py Thu Jan 18 08:00:43 2007 @@ -1,26 +1,5 @@ from __future__ import generators import py -from py.__.test import config - -class MyClass: - def getoptions(self): - yield config.Option('-v', action="count", dest="verbose", help="verbose") - -def xtest_verbose(): - obj = MyClass() - args = config.parseargs(['-v', 'hello'], obj) - assert args == ['hello'] - assert hasattr(obj, 'option') - assert hasattr(obj.option, 'verbose') - assert obj.option.verbose - -def xtest_verbose_default(): - obj = MyClass() - args = config.parseargs(['hello'], obj) - assert args, ['hello'] - assert hasattr(obj, 'option') - assert hasattr(obj.option, 'verbose') - assert not obj.option.verbose def test_tmpdir(): d1 = py.test.ensuretemp('hello') @@ -28,14 +7,14 @@ assert d1 == d2 assert d1.check(dir=1) -def test_config_options(): +def test_config_cmdline_options(): o = py.test.ensuretemp('configoptions') o.ensure("conftest.py").write(py.code.Source(""" import py def _callback(option, opt_str, value, parser, *args, **kwargs): option.tdest = True - Option = py.test.Config.Option - option = py.test.Config.addoptions("testing group", + Option = py.test.config.Option + option = py.test.config.addoptions("testing group", Option('-g', '--glong', action="store", default=42, type="int", dest="gdest", help="g value."), # XXX note: special case, option without a destination @@ -45,35 +24,30 @@ """)) old = o.chdir() try: - config, args = py.test.Config.parse(['-g', '17']) - assert config.option.gdest == 17 + config = py.test.config._reparse(['-g', '17']) finally: old.chdir() - -#def test_config_order(): -# from py.__.test import config -# o = py.test.ensuretemp('configorder') -# o.ensure('conftest.py').write('x=1 ; import py ; py._x = [x]') -# o.ensure('a/conftest.py').write('x=2 ; import py ; py._x.append(x)') -# o.ensure('a/b/c/conftest.py').write('x=3 ; import py ; py._x.append(x)') -# cfg = config.Config() -# cfg.readconfiguration(o) -# assert cfg.getfirst('x') == 1 -# assert py._x == [1] -# -# cfg = config.Config() -# cfg.readconfiguration(o.join('a/b/c')) -# assert cfg.getfirst('x') == 1 -# assert py._x == [1,2,3] -# -#def test_getconfigvalue(): -# from py.__.test import config -# cfg = config.Config() -# o = py.test.ensuretemp('configtest') -# o.ensure('conftest.py').write('x=1') -# assert cfg.getconfigvalue(o, 'x') == 1 -# py.test.raises(ValueError, "cfg.getconfigvalue(o, 'y')") -# + assert config.option.gdest == 17 + +def test_parsing_again_fails(): + dir = py.test.ensuretemp("parsing_again_fails") + config = py.test.config._reparse([str(dir)]) + py.test.raises(AssertionError, "config.parse([])") + +def test_config_getvalue_honours_conftest(): + o = py.test.ensuretemp('testconfigget') + o.ensure("conftest.py").write("x=1") + o.ensure("sub", "conftest.py").write("x=2 ; y = 3") + config = py.test.config._reparse([str(o)]) + assert config.getvalue("x") == 1 + assert config.getvalue("x", o.join('sub')) == 2 + py.test.raises(KeyError, "config.getvalue('y')") + config = py.test.config._reparse([str(o.join('sub'))]) + assert config.getvalue("x") == 2 + assert config.getvalue("y") == 3 + assert config.getvalue("x", o) == 1 + py.test.raises(KeyError, 'config.getvalue("y", o)') + def test_siblingconftest_fails_maybe(): from py.__.test import config Modified: py/dist/py/test/testing/test_session.py ============================================================================== --- py/dist/py/test/testing/test_session.py (original) +++ py/dist/py/test/testing/test_session.py Thu Jan 18 08:00:43 2007 @@ -1,32 +1,35 @@ import py -datadir = py.magic.autopath().dirpath('data') -from cStringIO import StringIO +from setupdata import setupdatadir -tmpdir = py.test.ensuretemp('test_drive') +def setup_module(mod): + mod.datadir = setupdatadir() + mod.tmpdir = py.test.ensuretemp(mod.__name__) class TestDefaultSession: def test_simple(self): - config, args = py.test.Config.parse([]) + config = py.test.config._reparse([datadir/'filetest.py']) session = config.getsessionclass()(config, py.std.sys.stdout) - session.main([datadir / 'filetest.py']) + session.main() l = session.getitemoutcomepairs(py.test.Item.Failed) assert len(l) == 2 l = session.getitemoutcomepairs(py.test.Item.Passed) assert not l def test_simple_verbose(self): - config, args = py.test.Config.parse(['--verbose']) + config = py.test.config._reparse([datadir/'filetest.py', + '--verbose']) session = config.getsessionclass()(config, py.std.sys.stdout) - session.main([datadir / 'filetest.py']) + session.main() l = session.getitemoutcomepairs(py.test.Item.Failed) assert len(l) == 2 l = session.getitemoutcomepairs(py.test.Item.Passed) assert not l def test_simple_verbose_verbose(self): - config, args = py.test.Config.parse(['-v', '-v']) + config = py.test.config._reparse([datadir/'filetest.py', + '-v', '-v']) session = config.getsessionclass()(config, py.std.sys.stdout) - session.main([datadir / 'filetest.py']) + session.main() l = session.getitemoutcomepairs(py.test.Item.Failed) assert len(l) == 2 l = session.getitemoutcomepairs(py.test.Item.Passed) @@ -35,19 +38,20 @@ def test_session_parsing(self): from py.__.test.terminal.terminal import TerminalSession from py.__.test.tkinter.reportsession import ReportSession - config, args = py.test.Config.parse(['--session=terminal']) + config = py.test.config._reparse(['--session=terminal']) assert issubclass(config.getsessionclass(), TerminalSession) - config, args = py.test.Config.parse(['--session=tkinter']) + config = py.test.config._reparse(['--session=tkinter']) assert issubclass(config.getsessionclass(), ReportSession) - config, args = py.test.Config.parse(['--tkinter']) + config = py.test.config._reparse(['--tkinter']) assert issubclass(config.getsessionclass(), ReportSession) class TestKeywordSelection: def test_select_simple(self): for keyword in ['test_one', 'est_on']: - config, args = py.test.Config.parse(['-k', keyword]) + config = py.test.config._reparse([datadir/'filetest.py', + '-k', keyword]) session = config.getsessionclass()(config, py.std.sys.stdout) - session.main([datadir / 'filetest.py']) + session.main() l = session.getitemoutcomepairs(py.test.Item.Failed) assert len(l) == 1 item = l[0][0] @@ -73,10 +77,10 @@ """)) for keyword in ('xxx', 'xxx test_2', 'TestClass', 'xxx -test_1', 'TestClass test_2', 'xxx TestClass test_2',): - f = StringIO() - config, args = py.test.Config.parse(['-k', keyword]) + f = py.std.StringIO.StringIO() + config = py.test.config._reparse([o, '-k', keyword]) session = config.getsessionclass()(config, f) - session.main([o]) + session.main() print "keyword", repr(keyword) l = session.getitemoutcomepairs(py.test.Item.Passed) assert len(l) == 1 @@ -93,33 +97,23 @@ def teardown_class(cls): (datadir / 'syntax_error.py').remove() - def setup_method(self, method): + def mainsession(self, *args): from py.__.test.terminal.terminal import TerminalSession - self.file = StringIO() - config, args = py.test.Config.parse([]) - self.session = TerminalSession(config, file=self.file) - #print >>f, "session %r is setup for %r" %(self.session, method) - #f.flush() - #print "session is setup", self.session - - #def teardown_method(self, method): - #print >>f, "session %r finished method %r" % (self.session, method) - #f.flush() + self.file = py.std.StringIO.StringIO() + config = py.test.config._reparse(list(args)) + session = TerminalSession(config, file=self.file) + session.main() + return session def test_terminal(self): - self.session.main([datadir / 'filetest.py']) + session = self.mainsession(datadir / 'filetest.py') out = self.file.getvalue() - #print "memo" - #print self.session._memo - #print "out" - #print out - l = self.session.getitemoutcomepairs(py.test.Item.Failed) + l = session.getitemoutcomepairs(py.test.Item.Failed) assert len(l) == 2 assert out.find('2 failed') != -1 def test_syntax_error_module(self): - session = self.session - session.main([str(datadir / 'syntax_error.py')]) + session = self.mainsession(datadir / 'syntax_error.py') l = session.getitemoutcomepairs(py.test.Item.Failed) assert len(l) == 1 out = self.file.getvalue() @@ -127,18 +121,18 @@ assert out.find(str('not python')) != -1 def test_exit_first_problem(self): - session = self.session - session.config.option.exitfirst = True - session.main([str(datadir / 'filetest.py')]) + session = self.mainsession("--exitfirst", + datadir / 'filetest.py') + assert session.config.option.exitfirst l = session.getitemoutcomepairs(py.test.Item.Failed) assert len(l) == 1 l = session.getitemoutcomepairs(py.test.Item.Passed) assert not l def test_collectonly(self): - session = self.session - session.config.option.collectonly = True - session.main([str(datadir / 'filetest.py')]) + session = self.mainsession("--collectonly", + datadir / 'filetest.py') + assert session.config.option.collectonly out = self.file.getvalue() #print out l = session.getitemoutcomepairs(py.test.Item.Failed) @@ -162,11 +156,7 @@ f() f() """)) - #print "hello" - session = self.session - #session.config.option.nocapture = True - print "calling main", o - session.main([str(o)]) + session = self.mainsession(o) print "back from main", o out = self.file.getvalue() #print out @@ -180,8 +170,7 @@ def test_1(): yield None """)) - session = self.session - session.main([o]) + session = self.mainsession(o) out = self.file.getvalue() #print out i = out.find('TypeError') @@ -209,8 +198,7 @@ def finishcapture(self): self._testmycapture = self._mycapture.reset() """)) - session = self.session - session.main([o]) + session = self.mainsession(o) l = session.getitemoutcomepairs(py.test.Item.Passed) assert len(l) == 1 item = l[0][0] @@ -236,8 +224,7 @@ def test_raises_doesnt(): py.test.raises(ValueError, int, "3") """)) - session = self.session - session.main([o]) + session = self.mainsession(o) out = self.file.getvalue() if not out.find("DID NOT RAISE") != -1: print out @@ -266,8 +253,7 @@ assert self.reslist == [1,2,1,2,3] """)) - session = self.session - session.main([o]) + session = self.mainsession(o) l = session.getitemoutcomepairs(py.test.Item.Failed) assert len(l) == 0 l = session.getitemoutcomepairs(py.test.Item.Passed) @@ -290,16 +276,14 @@ import does_not_work a = 1 """)) - session = self.session - session.main([o]) + session = self.mainsession(o) l = session.getitemoutcomepairs(py.test.Item.Failed) assert len(l) == 1 item, outcome = l[0] assert str(outcome.excinfo).find('does_not_work') != -1 def test_safe_repr(self): - session = self.session - session.main([str(datadir / 'brokenrepr.py')]) + session = self.mainsession(datadir/'brokenrepr.py') out = self.file.getvalue() print 'Output of simulated "py.test brokenrepr.py":' print out @@ -321,8 +305,7 @@ 'c']) """) tfile.write(source) - session = self.session - session.main([o]) + session = self.mainsession(o) out = self.file.getvalue() print 'Output of simulated "py.test test_correct_line.py":' print out @@ -362,14 +345,14 @@ assert 1 == 0 """)) print py.std.sys.executable - config, args = py.test.Config.parse( + config = py.test.config._reparse( ['--exec=' + py.std.sys.executable, - str(o)]) + o]) assert config.option._remote cls = config.getsessionclass() out = [] # out = py.std.Queue.Queue() session = cls(config, out.append) - session.main([o]) + session.main() for s in out: if s.find('1 failed') != -1: break @@ -384,13 +367,13 @@ assert 1 == 0 """)) print py.std.sys.executable - config, args = py.test.Config.parse(['--looponfailing', str(o)]) + config = py.test.config._reparse(['--looponfailing', str(o)]) assert config.option._remote cls = config.getsessionclass() out = py.std.Queue.Queue() session = cls(config, out.put) pool = py._thread.WorkerPool() - reply = pool.dispatch(session.main, [str(o)]) + reply = pool.dispatch(session.main) while 1: s = out.get() if s.find('1 failed') != -1: Modified: py/dist/py/test/tkinter/backend.py ============================================================================== --- py/dist/py/test/tkinter/backend.py (original) +++ py/dist/py/test/tkinter/backend.py Thu Jan 18 08:00:43 2007 @@ -229,12 +229,12 @@ from py.__.test.tkinter.reportsession import ReportSession from py.__.test.terminal.remote import getfailureitems - config, testfiles = py.test.Config.parse(args) + config = py.test.config._reparse(args) if tests: cols = getfailureitems(tests) else: - cols = testfiles + cols = config.remaining session = ReportSession(config = config, channel=channel) session.shouldclose = channel.isclosed - session.main(cols) + session.main() Modified: py/dist/py/test/tkinter/reportsession.py ============================================================================== --- py/dist/py/test/tkinter/reportsession.py (original) +++ py/dist/py/test/tkinter/reportsession.py Thu Jan 18 08:00:43 2007 @@ -44,4 +44,5 @@ def sendreport(self, report): self.channel.send(report.to_channel()) +TkinterSession = ReportSession Modified: py/dist/py/test/tkinter/testing/test_backend.py ============================================================================== --- py/dist/py/test/tkinter/testing/test_backend.py (original) +++ py/dist/py/test/tkinter/testing/test_backend.py Thu Jan 18 08:00:43 2007 @@ -178,7 +178,7 @@ assert l[0] is None def test_start_tests(self): - config, args = py.test.Config.parse([]) + config = py.test.config._reparse([]) self.backend.start_tests(config = config, args = [str(datadir / 'filetest.py')], tests = []) Modified: py/dist/py/test/tkinter/testing/test_capture_out_err.py ============================================================================== --- py/dist/py/test/tkinter/testing/test_capture_out_err.py (original) +++ py/dist/py/test/tkinter/testing/test_capture_out_err.py Thu Jan 18 08:00:43 2007 @@ -5,10 +5,10 @@ datadir = py.magic.autopath().dirpath('data') def test_capture_out_err(): - config, args = py.test.Config.parse([]) + config = py.test.config._reparse([datadir/'filetest.py']) backend = ReportBackend() backend.start_tests(config = config, - args = [str(datadir / 'filetest.py')], + args = config.remaining, tests = []) while backend.running: backend.update() _______________________________________________ py-svn mailing list py-svn at codespeak.net http://codespeak.net/mailman/listinfo/py-svn ----- End forwarded message ----- -- merlinux GmbH Steinbergstr. 42 31139 Hildesheim http://merlinux.de tel +49 5121 20800 75 (fax 77) From grig at agilistas.org Fri Jan 19 17:53:54 2007 From: grig at agilistas.org (Grig Gheorghiu) Date: Fri, 19 Jan 2007 08:53:54 -0800 Subject: [py-dev] py lib tests all pass in Pybots buildbot for rev 36977 Message-ID: Details here: http://www.python.org/dev/buildbot/community/all/x86%20Ubuntu%20Breezy%20trunk/builds/277/step-py.lib/0 Grig From grig at agilistas.org Mon Jan 22 22:49:00 2007 From: grig at agilistas.org (Grig Gheorghiu) Date: Mon, 22 Jan 2007 13:49:00 -0800 Subject: [py-dev] Buildbot failure in test_apigen_example.py Message-ID: _______________________________________________________________________________ __________ entrypoint: TestApiPageBuilder().test_build_callable_view __________ def test_build_callable_view(self): ds, dsa = get_dsa(self.fs_root, self.pkg_name) t = Tracer(ds) t.start_tracing() pkg = __import__(self.pkg_name) pkg.main.sub.func(10) pkg.main.sub.func(pkg.main.SomeClass(10)) t.end_tracing() apb = ApiPageBuilder(self.base, self.linker, dsa) snippet = apb.build_callable_view('main.sub.func') html = snippet.unicode() print html > run_string_sequence_test(html, [ 'arg1 :: AnyOf(', 'href="', 'Class SomeClass', 'Int>', 'return value :: <None>', 'source:', 'def func(arg1):', ]) [/tmp/pylib/py/apigen/testing/test_apigen_example.py:130] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def run_string_sequence_test(data, seq): currpos = -1 for s in seq: newpos = data.find(s) if currpos >= newpos: if newpos == -1: message = 'not found' else: message = 'unexpected position: %s' % (newpos,) E py.test.fail('string %r: %s' % (s, message)) > Failed: string 'Int>': unexpected position: 123 [/tmp/pylib/py/apigen/testing/test_apigen_example.py:20] - - - - - - - - - test_build_callable_view: recorded stdout - - - - - - - - -

func (arg1)

    where:
  • arg1 :: AnyOf(<Int>, <Instance of Class SomeClass>)
  • return value :: <None>
docstring

source:
def func(arg1):
_______________________________________________________________________________ ===== tests finished: 1375 passed, 1 failed, 64 skipped in 135.67 seconds ===== The full log is here: http://www.python.org/dev/buildbot/community/all/x86%20Ubuntu%20Breezy%20trunk/builds/291/step-py.lib/0 Grig From holger at merlinux.de Fri Jan 26 19:25:45 2007 From: holger at merlinux.de (holger krekel) Date: Fri, 26 Jan 2007 19:25:45 +0100 Subject: [py-dev] from dist to trunk / release TODO In-Reply-To: <20070114212416.GW16915@solar.trillke> References: <20070114212416.GW16915@solar.trillke> Message-ID: <20070126182545.GO16146@solar.trillke> Hi again, so we have switched to use https://codespeak.net/svn/py/trunk for development. Now /svn/py/dist is meant to contain stable snapshosts before and after the release. Speaking of which: Guido, Maciej and me are still cleaning up option/configuration handling, ad-hoc distributed testing and bringing the API documentation generator to release-state. Release still drags on a bit, thus. best, holger On Sun, Jan 14, 2007 at 22:24 +0100, holger krekel wrote: > Hi folks, > > ahead of the release i'd like to move development works to > http://codespeak.net/svn/py/trunk and have svn/py/dist carry > stable snapshots or maybe only the last released version. > I probably implement that policy tomorrow or so and will > likely dis-allow commits to dist/ at the same time > to avoid random commits still going there. > > moreover, you may want to have a look at the evolving > > http://codespeak.net/svn/py/dist/py/doc/TODO.txt > > file which lists a number of intended changes for 0.9, > particularly regarding namespaces ... in Switzerland/Leysin > (where some of us sprinted on py lib release topics) > we decided to be avoid exposing 'alpha' API > because we don't want to impose a support burden > for already-known-to-change code. E.g. 'py.log' is going > to become 'py._log'. I hope that this doesn't cause too > much pain to the current usages of the py lib. > > Oh, and if you'd like to comment, add or work on the TODO file, > you are most welcome! > > best & greetings, > > holger > _______________________________________________ > py-dev mailing list > py-dev at codespeak.net > http://codespeak.net/mailman/listinfo/py-dev > -- merlinux GmbH Steinbergstr. 42 31139 Hildesheim http://merlinux.de tel +49 5121 20800 75 (fax 77) From holger at merlinux.de Sat Jan 27 13:53:40 2007 From: holger at merlinux.de (holger krekel) Date: Sat, 27 Jan 2007 13:53:40 +0100 Subject: [py-dev] win32: restarting socketserver cleanly? Message-ID: <20070127125340.GU16146@solar.trillke> Hi Brian, i am trying to get a regular socketserver (service) running on win32 in order to drive win32 test runs remotely. I am wondering how i could have a socketserver run one (without looping) and restarting always - and without having socket/closing issues (address already in use). Do you know how to do that? i am also on IRC (#pylib) this GMT+1 afternoon/early evening. best, holger From brian at dorseys.org Sat Jan 27 16:39:11 2007 From: brian at dorseys.org (Brian Dorsey) Date: Sat, 27 Jan 2007 07:39:11 -0800 Subject: [py-dev] win32: restarting socketserver cleanly? In-Reply-To: <20070127125340.GU16146@solar.trillke> References: <20070127125340.GU16146@solar.trillke> Message-ID: <66e877b70701270739j65f2e05cm5fddc4701c9d0a1a@mail.gmail.com> Hi Holger! I'm heading out to class now, so I can't lookup the details at the moment, but I believe you can pass a flag in when opening the socket which will allow 'reuse' when the same app is using the same socket over and over. I'll lookup the details later today. Take care, -Brian On 1/27/07, holger krekel wrote: > Hi Brian, > > i am trying to get a regular socketserver (service) > running on win32 in order to drive win32 test runs remotely. > > I am wondering how i could have a socketserver run one (without > looping) and restarting always - and without having socket/closing > issues (address already in use). Do you know how to do that? > i am also on IRC (#pylib) this GMT+1 afternoon/early evening. > > best, > > holger > From holger at merlinux.de Sun Jan 28 12:09:34 2007 From: holger at merlinux.de (holger krekel) Date: Sun, 28 Jan 2007 12:09:34 +0100 Subject: [py-dev] win32 ad-hoc testing from linux Message-ID: <20070128110934.GV16146@solar.trillke> Hi Folks, so py-trunk revision 37463 passes for both on win32 (with english locale) and linux for me. Thanks to Brian for bouncing things back and forth a bit. Note that you may now run remote Windows pylib tests in an ad-hoc way from your linux/osx machine: windows/remote: * get py/execnet/script/loop_socketserver.py and socketserver.py to the windows machine * run loop_socketserver.py local/driving side: * go to a clean checkout of http://codespeak.net/svn/py/trunk * copy "py/misc/conftest-socketgatewayrun.py" to "conftest.py" somewhere above your py-trunk hierarchy * edit the new conftest.py file to contain the correct 'socketserveradr' (the one, where loop_socketserver.py was started on) * start py.test to do ad-hoc testing of your WC, using the custom Session found in the new conftest.py: py.test --session=MySession py/path/local Most options should just work (not e.g. --pdb though). There are a few rough edges partly because i don't manage some win32 process/socket details correctly, i guess. have fun, holger From fijal at genesilico.pl Mon Jan 29 14:10:42 2007 From: fijal at genesilico.pl (Maciek Fijalkowski) Date: Mon, 29 Jan 2007 14:10:42 +0100 Subject: [py-dev] RSession and py-trunk users Message-ID: <45BDF252.5030207@genesilico.pl> I've implemented recently an addition, which allows to have cleanur conftest.py setup. Basically, conftest.py's dist_rsyncroots affects only directory where it is located, so in let's say pypy's parent dir you might have conftest.py with dist_rsyncroots = ['py', 'pypy', 'lib-python'] and in pypy's dir dist_rsyncroots = # all files except _cache and should work. There were different ideas how to solve that problem and from my POV this on is the simplest, but I'm open to different ones.