diff --git a/py/__init__.py b/py/__init__.py index c4bebf997..6f5a8b437 100644 --- a/py/__init__.py +++ b/py/__init__.py @@ -9,8 +9,8 @@ version = "0.8.80-alpha2" initpkg(__name__, description = "py.test and the py lib", - revision = int('$LastChangedRevision: 37056 $'.split(':')[1][:-1]), - lastchangedate = '$LastChangedDate: 2007-01-20 13:11:01 +0100 (Sat, 20 Jan 2007) $', + revision = int('$LastChangedRevision: 37278 $'.split(':')[1][:-1]), + lastchangedate = '$LastChangedDate: 2007-01-24 17:46:46 +0100 (Wed, 24 Jan 2007) $', version = version, url = "http://codespeak.net/py", download_url = "http://codespeak.net/download/py/%s.tar.gz" %(version,), @@ -32,7 +32,7 @@ initpkg(__name__, 'test.compat.TestCase' : ('./test/compat.py', 'TestCase'), # configuration/initialization related test api - 'test.config' : ('./test/config.py', 'config'), + 'test.config' : ('./test/config.py', 'config_per_process'), 'test.ensuretemp' : ('./test/config.py', 'ensuretemp'), 'test.cmdline.main' : ('./test/cmdline.py', 'main'), @@ -93,6 +93,9 @@ initpkg(__name__, 'execnet.PopenGateway' : ('./execnet/register.py', 'PopenGateway'), 'execnet.SshGateway' : ('./execnet/register.py', 'SshGateway'), + # execnet scripts + 'execnet.RSync' : ('./execnet/rsync.py', 'RSync'), + # input-output helping 'io.dupfile' : ('./io/dupfile.py', 'dupfile'), 'io.FDCapture' : ('./io/capture.py', 'FDCapture'), diff --git a/py/__init__.py.merge.tmp b/py/__init__.py.merge.tmp deleted file mode 100644 index e7ea87a46..000000000 --- a/py/__init__.py.merge.tmp +++ /dev/null @@ -1,132 +0,0 @@ -"""\ -the py lib is a development support library featuring -py.test, an interactive testing tool which supports -unit-testing with practically no boilerplate. -""" -from initpkg import initpkg - -version = "0.8.80-alpha2" - -initpkg(__name__, - description = "py.test and the py lib", - revision = int('$LastChangedRevision: 37268 $'.split(':')[1][:-1]), - lastchangedate = '$LastChangedDate: 2007-01-24 17:39:40 +0100 (Wed, 24 Jan 2007) $', - version = version, - url = "http://codespeak.net/py", - download_url = "http://codespeak.net/download/py/%s.tar.gz" %(version,), - license = "MIT license", - platforms = ['unix', 'linux', 'cygwin'], - author = "holger krekel & others", - author_email = "py-dev@codespeak.net", - long_description = globals()['__doc__'], - - exportdefs = { - '_dist.setup' : ('./misc/_dist.py', 'setup'), - - # helpers for use from test functions or collectors - 'test.raises' : ('./test/raises.py', 'raises'), - 'test.deprecated_call' : ('./test/deprecate.py', 'deprecated_call'), - 'test.skip' : ('./test/item.py', 'skip'), - 'test.fail' : ('./test/item.py', 'fail'), - 'test.exit' : ('./test/session.py', 'exit'), - 'test.compat.TestCase' : ('./test/compat.py', 'TestCase'), - - # configuration/initialization related test api - 'test.config' : ('./test/config.py', 'config_per_process'), - 'test.ensuretemp' : ('./test/config.py', 'ensuretemp'), - 'test.cmdline.main' : ('./test/cmdline.py', 'main'), - - # for customization of collecting/running tests - 'test.collect.Collector' : ('./test/collect.py', 'Collector'), - 'test.collect.Directory' : ('./test/collect.py', 'Directory'), - 'test.collect.Module' : ('./test/collect.py', 'Module'), - 'test.collect.DoctestFile' : ('./test/collect.py', 'DoctestFile'), - 'test.collect.Class' : ('./test/collect.py', 'Class'), - 'test.collect.Instance' : ('./test/collect.py', 'Instance'), - 'test.collect.Generator' : ('./test/collect.py', 'Generator'), - 'test.Item' : ('./test/item.py', 'Item'), - 'test.Function' : ('./test/item.py', 'Function'), - - # thread related API (still in early design phase) - '_thread.WorkerPool' : ('./thread/pool.py', 'WorkerPool'), - '_thread.NamedThreadPool' : ('./thread/pool.py', 'NamedThreadPool'), - '_thread.ThreadOut' : ('./thread/io.py', 'ThreadOut'), - - # hook into the top-level standard library - 'std' : ('./misc/std.py', 'std'), - - 'process.cmdexec' : ('./process/cmdexec.py', 'cmdexec'), - - # path implementations - 'path.svnwc' : ('./path/svn/wccommand.py', 'SvnWCCommandPath'), - 'path.svnurl' : ('./path/svn/urlcommand.py', 'SvnCommandPath'), - 'path.local' : ('./path/local/local.py', 'LocalPath'), - 'path.extpy' : ('./path/extpy/extpy.py', 'Extpy'), - - # some nice slightly magic APIs - 'magic.greenlet' : ('./magic/greenlet.py', 'greenlet'), - 'magic.invoke' : ('./magic/invoke.py', 'invoke'), - 'magic.revoke' : ('./magic/invoke.py', 'revoke'), - 'magic.patch' : ('./magic/patch.py', 'patch'), - 'magic.revert' : ('./magic/patch.py', 'revert'), - 'magic.autopath' : ('./magic/autopath.py', 'autopath'), - 'magic.AssertionError' : ('./magic/assertion.py', 'AssertionError'), - - # python inspection/code-generation API - 'code.compile' : ('./code/source.py', 'compile_'), - 'code.Source' : ('./code/source.py', 'Source'), - 'code.Code' : ('./code/code.py', 'Code'), - 'code.Frame' : ('./code/frame.py', 'Frame'), - 'code.ExceptionInfo' : ('./code/excinfo.py', 'ExceptionInfo'), - 'code.Traceback' : ('./code/traceback2.py', 'Traceback'), - - # backports and additions of builtins - 'builtin.enumerate' : ('./builtin/enumerate.py', 'enumerate'), - 'builtin.reversed' : ('./builtin/reversed.py', 'reversed'), - 'builtin.sorted' : ('./builtin/sorted.py', 'sorted'), - 'builtin.BaseException' : ('./builtin/exception.py', 'BaseException'), - 'builtin.set' : ('./builtin/set.py', 'set'), - 'builtin.frozenset' : ('./builtin/set.py', 'frozenset'), - - # gateways into remote contexts - 'execnet.SocketGateway' : ('./execnet/register.py', 'SocketGateway'), - 'execnet.PopenGateway' : ('./execnet/register.py', 'PopenGateway'), - 'execnet.SshGateway' : ('./execnet/register.py', 'SshGateway'), - - # execnet scripts - 'execnet.RSync' : ('./execnet/rsync.py', 'RSync'), - - # input-output helping - 'io.dupfile' : ('./io/dupfile.py', 'dupfile'), - 'io.FDCapture' : ('./io/capture.py', 'FDCapture'), - 'io.OutErrCapture' : ('./io/capture.py', 'OutErrCapture'), - 'io.callcapture' : ('./io/capture.py', 'callcapture'), - - # error module, defining all errno's as Classes - 'error' : ('./misc/error.py', 'error'), - - # small and mean xml/html generation - 'xml.html' : ('./xmlobj/html.py', 'html'), - 'xml.Tag' : ('./xmlobj/xml.py', 'Tag'), - 'xml.raw' : ('./xmlobj/xml.py', 'raw'), - 'xml.Namespace' : ('./xmlobj/xml.py', 'Namespace'), - 'xml.escape' : ('./xmlobj/misc.py', 'escape'), - - # logging API ('producers' and 'consumers' connected via keywords) - 'log.Producer' : ('./log/producer.py', 'Producer'), - 'log.default' : ('./log/producer.py', 'default'), - 'log._getstate' : ('./log/producer.py', '_getstate'), - 'log._setstate' : ('./log/producer.py', '_setstate'), - 'log.setconsumer' : ('./log/consumer.py', 'setconsumer'), - 'log.Path' : ('./log/consumer.py', 'Path'), - 'log.STDOUT' : ('./log/consumer.py', 'STDOUT'), - 'log.STDERR' : ('./log/consumer.py', 'STDERR'), - 'log.Syslog' : ('./log/consumer.py', 'Syslog'), - 'log.get' : ('./log/logger.py', 'get'), - - # compatibility modules (taken from 2.4.4) - 'compat.doctest' : ('./compat/doctest.py', '*'), - 'compat.optparse' : ('./compat/optparse.py', '*'), - 'compat.textwrap' : ('./compat/textwrap.py', '*'), - 'compat.subprocess' : ('./compat/subprocess.py', '*'), -}) diff --git a/py/apigen/testing/test_apigen_functional.py b/py/apigen/testing/test_apigen_functional.py index c2af8a298..2e0f5752b 100644 --- a/py/apigen/testing/test_apigen_functional.py +++ b/py/apigen/testing/test_apigen_functional.py @@ -76,7 +76,7 @@ def test_apigen_functional(): parentdir = py.magic.autopath().dirpath().dirpath() pkgdir = fs_root.join('pkg') try: - output = py.process.cmdexec('APIGEN_TARGET="%s" py.test --session=L ' + output = py.process.cmdexec('APIGEN_TARGET="%s" py.test ' '--apigen="%s/apigen.py" "%s"' % ( tempdir, parentdir, pkgdir)) except py.error.Error, e: diff --git a/py/apigen/testing/test_apigen_functional.py.merge.tmp b/py/apigen/testing/test_apigen_functional.py.merge.tmp deleted file mode 100644 index 2e0f5752b..000000000 --- a/py/apigen/testing/test_apigen_functional.py.merge.tmp +++ /dev/null @@ -1,116 +0,0 @@ -""" functional test for apigen.py - - script to build api + source docs from py.test -""" - -import py - -def setup_fs_project(): - temp = py.test.ensuretemp('apigen_functional') - temp.ensure("pkg/func.py").write(py.code.Source("""\ - def func(arg1): - "docstring" - - def func_2(arg1, arg2): - return arg1(arg2) - """)) - temp.ensure('pkg/sometestclass.py').write(py.code.Source("""\ - class SomeTestClass(object): - " docstring sometestclass " - def __init__(self, somevar): - self.somevar = somevar - - def get_somevar(self): - " get_somevar docstring " - return self.somevar - """)) - temp.ensure('pkg/sometestsubclass.py').write(py.code.Source("""\ - from sometestclass import SomeTestClass - class SomeTestSubClass(SomeTestClass): - " docstring sometestsubclass " - def get_somevar(self): - return self.somevar + 1 - """)) - temp.ensure('pkg/somenamespace.py').write(py.code.Source("""\ - def foo(): - return 'bar' - def baz(qux): - return qux - """)) - temp.ensure("pkg/__init__.py").write(py.code.Source("""\ - from py.initpkg import initpkg - initpkg(__name__, exportdefs = { - 'main.sub.func': ("./func.py", "func"), - 'main.func': ("./func.py", "func_2"), - 'main.SomeTestClass': ('./sometestclass.py', 'SomeTestClass'), - 'main.SomeTestSubClass': ('./sometestsubclass.py', - 'SomeTestSubClass'), - }) - """)) - temp.ensure('pkg/test/test_pkg.py').write(py.code.Source("""\ - import py - py.std.sys.path.insert(0, - py.magic.autopath().dirpath().dirpath().dirpath().strpath) - import pkg - - # this mainly exists to provide some data to the tracer - def test_pkg(): - s = pkg.main.SomeTestClass(10) - assert s.get_somevar() == 10 - s = pkg.main.SomeTestClass('10') - assert s.get_somevar() == '10' - s = pkg.main.SomeTestSubClass(10) - assert s.get_somevar() == 11 - s = pkg.main.SomeTestSubClass('10') - py.test.raises(TypeError, 's.get_somevar()') - assert pkg.main.sub.func(10) is None - assert pkg.main.sub.func(20) is None - s = pkg.main.func(pkg.main.SomeTestClass, 10) - assert isinstance(s, pkg.main.SomeTestClass) - """)) - return temp, 'pkg' - -def test_apigen_functional(): - fs_root, package_name = setup_fs_project() - tempdir = py.test.ensuretemp('test_apigen_functional_results') - parentdir = py.magic.autopath().dirpath().dirpath() - pkgdir = fs_root.join('pkg') - try: - output = py.process.cmdexec('APIGEN_TARGET="%s" py.test ' - '--apigen="%s/apigen.py" "%s"' % ( - tempdir, parentdir, pkgdir)) - except py.error.Error, e: - print e.out - raise - assert output.lower().find('traceback') == -1 - - # just some quick content checks - apidir = tempdir.join('api') - assert apidir.check(dir=True) - sometestclass_api = apidir.join('main.SomeTestClass.html') - assert sometestclass_api.check(file=True) - html = sometestclass_api.read() - assert 'SomeTestClass' in html - # XXX not linking to method files anymore - #sometestclass_init_api = apidir.join('main.SomeTestClass.__init__.html') - #assert sometestclass_init_api.check(file=True) - #assert sometestclass_init_api.read().find( - # '__init__') > -1 - namespace_api = apidir.join('main.html') - assert namespace_api.check(file=True) - html = namespace_api.read() - assert 'SomeTestClass' in html - - sourcedir = tempdir.join('source') - assert sourcedir.check(dir=True) - sometestclass_source = sourcedir.join('sometestclass.py.html') - assert sometestclass_source.check(file=True) - html = sometestclass_source.read() - assert '
sources for sometestclass.py
' in html - - # XXX later... - #index = sourcedir.join('index.html') - #assert index.check(file=True) - #html = index.read() - #assert 'main' in html - diff --git a/py/code/traceback2.py b/py/code/traceback2.py index 6b72a069e..5acdf3e6c 100644 --- a/py/code/traceback2.py +++ b/py/code/traceback2.py @@ -23,6 +23,10 @@ class TracebackEntry(object): return self.frame.code.path path = property(path, None, None, "path to the full source code") + def getlocals(self): + return self.frame.f_locals + locals = property(getlocals, None, None, "locals of underlaying frame") + def reinterpret(self): """Reinterpret the failing statement and returns a detailed information about what operations are performed.""" @@ -78,6 +82,10 @@ class TracebackEntry(object): line = "" return " File %r:%d in %s\n %s\n" %(fn, self.lineno+1, name, line) + def name(self): + return self.frame.code.raw.co_name + name = property(name, None, None, "co_name of underlaying code") + class Traceback(list): """ Traceback objects encapsulate and offer higher level access to Traceback entries. diff --git a/py/doc/TODO.txt b/py/doc/TODO.txt index efa24b0aa..56e231a9d 100644 --- a/py/doc/TODO.txt +++ b/py/doc/TODO.txt @@ -94,7 +94,7 @@ testing - running "py.test --looponfailing" - running "py.test" distributed on some hosts -* fix --box on config branch (XXX guido - find tests that depend on each other) +* consider --box on trunk (XXX guido - find tests that depend on each other) * tests should not create any tempdirectories in the source code base @@ -109,15 +109,6 @@ testing distributed testing ---------------------- -* the main rsession methods should have docstrings - explaining the purpose - - (done) - -* move RSync class to py.execnet.RSync, document its usage and - features in the class and method docstrings - - (done) code quality ----------------- diff --git a/py/doc/TODO.txt.merge.tmp b/py/doc/TODO.txt.merge.tmp deleted file mode 100644 index 56e231a9d..000000000 --- a/py/doc/TODO.txt.merge.tmp +++ /dev/null @@ -1,561 +0,0 @@ -Things to do before 0.9.0 -========================= - - - -py/bin ------------ - -* review py/bin scripts abit - py.test - py.rest - py.lookup - py.cleanup - py.countloc - -review all py lib documentation -------------------------------------- - -* (hpk, in-progress) rename py/documentation to py/doc - (check web page and pypy usage of it) - -streamline exported API -------------------------------------- - -* (hpk, should be done) move not-to-be-exported Gateway() methods to _ - methods. -* docstrings for all exported API - -* remove: - test.compat.TestCAse - -* check and likely remove already deprecated API - -* remove from public namespace: - XXX consider py.magic. invoke/revoke/patch/revert - -* make "_" namespace: - py.path.extpy -> py.path._extpy - py.log -> py._log (pypy!) - -* review py.io and write py.io.dupfile docstring (XXX guido) - -* re-consider what to do with read and write methods of py.path classes (since - there are places that check for file-ness by doing hasattr(... 'write')) - - (XXX guido talk to holger) - -packaging -------------------------------------- - -* debian and TAR/zip packages for py lib, - particularly look into C module issues (greenlet most importantly) - -* do something about c-extensions both on unix-ish - versus win32 systems - -* ensure compatibility with Python 2.3 - 2.5, - see what is missing for 2.2 - -* optional: support setuptools (eggs?) installs, and instally - from pypi (and register pylib there) - -* see if things work on Win32 (partially done) - -* refine and implement `releasescheme`_ - -.. _releasescheme: releasescheme.html - -APIGEN / source viewer -------------------------------------- - -* make py.test --apigen=PATH_TO_SCRIPT - collect tracing information and call the apigen - script to produce api and source code documentation - - (done) - -* deploy the above "py.test --apigen" run on codespeak - regularly, determine directory locations and URL namespace design. - -* integrate rest directive into py/documentation/conftest.py - with help code from py.__.rest.directive.... - make sure that the txt files in py/documentation/ use it - - (done XXX functions/methods) - -testing ------------ - -* windows tests (rev 36514 passes without errors, many skips) (XXX guido) - -* these should all work on 0.9 and on the py lib and pypy: - - running "py.test -s" - - running "py.test --pdb" - - running "py.test --looponfailing" - - running "py.test" distributed on some hosts - -* consider --box on trunk (XXX guido - find tests that depend on each other) - -* tests should not create any tempdirectories in the source code base - - - (done) - -* try to be as 2.2 compatible as possible - (use e.g. py.builtin.enumerate instead of "enumerate" directly) - - (done) - -distributed testing ----------------------- - - -code quality ------------------ - -* no function implementation longer than 30 lines - -* no lines longer than 80 characters - -* review the pylib issue tracker - (cfbolz: done: what has a 0.8.0 or a 0.9.0 tag should be looked at again) - - -py.test -------- - -* adjust py.test documentation to reflect new - collector/session architecture (mostly done) - -* document py.test's conftest.py approach (somewhat done) - -* py.test fails to parse strangely formatted code after assertion failure - -Missing docstrings ------------------- - -:: - - code.Traceback.recursionindex misses a docstring - code.Traceback.filter misses a docstring - code.Traceback.cut misses a docstring - code.Traceback.__getitem__ misses a docstring - code.Traceback.Entry misses a docstring - code.Traceback.Entry.ishidden misses a docstring - code.Traceback.Entry.getfirstlinesource misses a docstring - code.Traceback.Entry.__str__ misses a docstring - code.Traceback.Entry.__repr__ misses a docstring - code.Traceback.Entry.__init__ misses a docstring - code.Source.getblockend misses a docstring - code.Source.__str__ misses a docstring - code.Source.__len__ misses a docstring - code.Source.__init__ misses a docstring - code.Source.__getslice__ misses a docstring - code.Source.__getitem__ misses a docstring - code.Source.__eq__ misses a docstring - code.Frame.repr misses a docstring - code.Frame.is_true misses a docstring - code.Frame.getargs misses a docstring - code.Frame.exec_ misses a docstring - code.Frame.eval misses a docstring - code.Frame.__init__ misses a docstring - code.ExceptionInfo.exconly misses a docstring - code.ExceptionInfo.errisinstance misses a docstring - code.ExceptionInfo.__str__ misses a docstring - code.ExceptionInfo.__init__ misses a docstring - code.Code misses a docstring - code.Code.source misses a docstring - code.Code.getargs misses a docstring - code.Code.__init__ misses a docstring - code.Code.__eq__ misses a docstring - execnet.SshGateway misses a docstring - execnet.SshGateway.join misses a docstring - execnet.SshGateway.exit misses a docstring - execnet.SshGateway.__repr__ misses a docstring - execnet.SshGateway.__init__ misses a docstring - execnet.SshGateway.ThreadOut.write misses a docstring - execnet.SshGateway.ThreadOut.setwritefunc misses a docstring - execnet.SshGateway.ThreadOut.setdefaultwriter misses a docstring - execnet.SshGateway.ThreadOut.resetdefault misses a docstring - execnet.SshGateway.ThreadOut.isatty misses a docstring - execnet.SshGateway.ThreadOut.flush misses a docstring - execnet.SshGateway.ThreadOut.delwritefunc misses a docstring - execnet.SshGateway.ThreadOut.deinstall misses a docstring - execnet.SocketGateway misses a docstring - execnet.SocketGateway.join misses a docstring - execnet.SocketGateway.exit misses a docstring - execnet.SocketGateway.__repr__ misses a docstring - execnet.SocketGateway.__init__ misses a docstring - execnet.PopenGateway misses a docstring - execnet.PopenGateway.remote_bootstrap_gateway misses a docstring - execnet.PopenGateway.join misses a docstring - execnet.PopenGateway.exit misses a docstring - execnet.PopenGateway.__repr__ misses a docstring - execnet.PopenGateway.__init__ misses a docstring - initpkg misses a docstring - io.dupfile misses a docstring - log.setconsumer misses a docstring - log.get misses a docstring - log.Syslog misses a docstring - log.STDOUT misses a docstring - log.STDERR misses a docstring - log.Producer.set_consumer misses a docstring - log.Producer.get_consumer misses a docstring - log.Producer.__repr__ misses a docstring - log.Producer.__init__ misses a docstring - log.Producer.__getattr__ misses a docstring - log.Producer.__call__ misses a docstring - log.Producer.Message misses a docstring - log.Producer.Message.prefix misses a docstring - log.Producer.Message.content misses a docstring - log.Producer.Message.__str__ misses a docstring - log.Producer.Message.__init__ misses a docstring - log.Path misses a docstring - log.Path.__init__ misses a docstring - log.Path.__call__ misses a docstring - magic.View.__viewkey__ misses a docstring - magic.View.__repr__ misses a docstring - magic.View.__new__ misses a docstring - magic.View.__matchkey__ misses a docstring - magic.View.__getattr__ misses a docstring - magic.AssertionError misses a docstring - path.svnwc.visit misses a docstring - path.svnwc.mkdir misses a docstring - path.svnwc.dump misses a docstring - path.svnwc.check misses a docstring - path.svnwc.add misses a docstring - path.svnwc.__str__ misses a docstring - path.svnwc.__repr__ misses a docstring - path.svnwc.__new__ misses a docstring - path.svnwc.__iter__ misses a docstring - path.svnwc.__hash__ misses a docstring - path.svnwc.__eq__ misses a docstring - path.svnwc.__div__ misses a docstring - path.svnwc.__contains__ misses a docstring - path.svnwc.__cmp__ misses a docstring - path.svnwc.__add__ misses a docstring - path.svnwc.Checkers misses a docstring - path.svnurl.visit misses a docstring - path.svnurl.check misses a docstring - path.svnurl.__repr__ misses a docstring - path.svnurl.__new__ misses a docstring - path.svnurl.__ne__ misses a docstring - path.svnurl.__iter__ misses a docstring - path.svnurl.__hash__ misses a docstring - path.svnurl.__div__ misses a docstring - path.svnurl.__contains__ misses a docstring - path.svnurl.__cmp__ misses a docstring - path.svnurl.__add__ misses a docstring - path.svnurl.Checkers misses a docstring - path.local.visit misses a docstring - path.local.sysexec has an 'XXX' in its docstring - path.local.check misses a docstring - path.local.__repr__ misses a docstring - path.local.__iter__ misses a docstring - path.local.__hash__ misses a docstring - path.local.__eq__ misses a docstring - path.local.__div__ misses a docstring - path.local.__contains__ misses a docstring - path.local.__cmp__ misses a docstring - path.local.__add__ misses a docstring - path.local.Checkers misses a docstring - path.extpy.visit misses a docstring - path.extpy.samefile misses a docstring - path.extpy.relto misses a docstring - path.extpy.listobj misses a docstring - path.extpy.listdir misses a docstring - path.extpy.join misses a docstring - path.extpy.getpymodule misses a docstring - path.extpy.getfilelineno misses a docstring - path.extpy.dirpath misses a docstring - path.extpy.check misses a docstring - path.extpy.__str__ misses a docstring - path.extpy.__repr__ misses a docstring - path.extpy.__new__ misses a docstring - path.extpy.__iter__ misses a docstring - path.extpy.__hash__ misses a docstring - path.extpy.__contains__ misses a docstring - path.extpy.__cmp__ misses a docstring - path.extpy.__add__ misses a docstring - path.extpy.Checkers misses a docstring - test.rest.RestReporter misses a docstring - test.rest.RestReporter.summary misses a docstring - test.rest.RestReporter.skips misses a docstring - test.rest.RestReporter.repr_traceback misses a docstring - test.rest.RestReporter.repr_source misses a docstring - test.rest.RestReporter.repr_signal misses a docstring - test.rest.RestReporter.repr_failure misses a docstring - test.rest.RestReporter.report_unknown misses a docstring - test.rest.RestReporter.report_TestStarted misses a docstring - test.rest.RestReporter.report_TestFinished misses a docstring - test.rest.RestReporter.report_SkippedTryiter misses a docstring - test.rest.RestReporter.report_SendItem misses a docstring - test.rest.RestReporter.report_RsyncFinished misses a docstring - test.rest.RestReporter.report_ReceivedItemOutcome misses a docstring - test.rest.RestReporter.report_Nodes misses a docstring - test.rest.RestReporter.report_ItemStart misses a docstring - test.rest.RestReporter.report_ImmediateFailure misses a docstring - test.rest.RestReporter.report_HostReady misses a docstring - test.rest.RestReporter.report_HostRSyncing misses a docstring - test.rest.RestReporter.report_FailedTryiter misses a docstring - test.rest.RestReporter.report misses a docstring - test.rest.RestReporter.print_summary misses a docstring - test.rest.RestReporter.prepare_source misses a docstring - test.rest.RestReporter.hangs misses a docstring - test.rest.RestReporter.get_rootpath misses a docstring - test.rest.RestReporter.get_path_from_item misses a docstring - test.rest.RestReporter.get_linkwriter misses a docstring - test.rest.RestReporter.get_item_name misses a docstring - test.rest.RestReporter.get_host misses a docstring - test.rest.RestReporter.failures misses a docstring - test.rest.RestReporter.add_rest misses a docstring - test.rest.RestReporter.__init__ misses a docstring - test.rest.RelLinkWriter misses a docstring - test.rest.RelLinkWriter.get_link misses a docstring - test.rest.NoLinkWriter misses a docstring - test.rest.NoLinkWriter.get_link misses a docstring - test.rest.LinkWriter misses a docstring - test.rest.LinkWriter.get_link misses a docstring - test.rest.LinkWriter.__init__ misses a docstring - test.exit misses a docstring - test.deprecated_call misses a docstring - test.collect.Module misses a docstring - test.collect.Module.tryiter has an 'XXX' in its docstring - test.collect.Module.teardown misses a docstring - test.collect.Module.startcapture misses a docstring - test.collect.Module.skipbykeyword misses a docstring - test.collect.Module.setup misses a docstring - test.collect.Module.run misses a docstring - test.collect.Module.makeitem misses a docstring - test.collect.Module.listnames misses a docstring - test.collect.Module.join misses a docstring - test.collect.Module.haskeyword misses a docstring - test.collect.Module.getsortvalue misses a docstring - test.collect.Module.getpathlineno misses a docstring - test.collect.Module.getouterr misses a docstring - test.collect.Module.getitembynames misses a docstring - test.collect.Module.funcnamefilter misses a docstring - test.collect.Module.finishcapture misses a docstring - test.collect.Module.classnamefilter misses a docstring - test.collect.Module.buildname2items misses a docstring - test.collect.Module.__repr__ misses a docstring - test.collect.Module.__ne__ misses a docstring - test.collect.Module.__init__ misses a docstring - test.collect.Module.__hash__ misses a docstring - test.collect.Module.__eq__ misses a docstring - test.collect.Module.__cmp__ misses a docstring - test.collect.Module.Skipped misses a docstring - test.collect.Module.Passed misses a docstring - test.collect.Module.Outcome misses a docstring - test.collect.Module.Failed misses a docstring - test.collect.Module.ExceptionFailure misses a docstring - test.collect.Instance misses a docstring - test.collect.Instance.tryiter has an 'XXX' in its docstring - test.collect.Instance.teardown misses a docstring - test.collect.Instance.startcapture misses a docstring - test.collect.Instance.skipbykeyword misses a docstring - test.collect.Instance.setup misses a docstring - test.collect.Instance.run misses a docstring - test.collect.Instance.makeitem misses a docstring - test.collect.Instance.listnames misses a docstring - test.collect.Instance.join misses a docstring - test.collect.Instance.haskeyword misses a docstring - test.collect.Instance.getsortvalue misses a docstring - test.collect.Instance.getpathlineno misses a docstring - test.collect.Instance.getouterr misses a docstring - test.collect.Instance.getitembynames misses a docstring - test.collect.Instance.funcnamefilter misses a docstring - test.collect.Instance.finishcapture misses a docstring - test.collect.Instance.classnamefilter misses a docstring - test.collect.Instance.buildname2items misses a docstring - test.collect.Instance.__repr__ misses a docstring - test.collect.Instance.__ne__ misses a docstring - test.collect.Instance.__init__ misses a docstring - test.collect.Instance.__hash__ misses a docstring - test.collect.Instance.__eq__ misses a docstring - test.collect.Instance.__cmp__ misses a docstring - test.collect.Generator misses a docstring - test.collect.Generator.tryiter has an 'XXX' in its docstring - test.collect.Generator.teardown misses a docstring - test.collect.Generator.startcapture misses a docstring - test.collect.Generator.skipbykeyword misses a docstring - test.collect.Generator.setup misses a docstring - test.collect.Generator.run misses a docstring - test.collect.Generator.listnames misses a docstring - test.collect.Generator.join misses a docstring - test.collect.Generator.haskeyword misses a docstring - test.collect.Generator.getsortvalue misses a docstring - test.collect.Generator.getpathlineno misses a docstring - test.collect.Generator.getouterr misses a docstring - test.collect.Generator.getitembynames misses a docstring - test.collect.Generator.getcallargs misses a docstring - test.collect.Generator.finishcapture misses a docstring - test.collect.Generator.buildname2items misses a docstring - test.collect.Generator.__repr__ misses a docstring - test.collect.Generator.__ne__ misses a docstring - test.collect.Generator.__init__ misses a docstring - test.collect.Generator.__hash__ misses a docstring - test.collect.Generator.__eq__ misses a docstring - test.collect.Generator.__cmp__ misses a docstring - test.collect.DoctestFile misses a docstring - test.collect.DoctestFile.tryiter has an 'XXX' in its docstring - test.collect.DoctestFile.teardown misses a docstring - test.collect.DoctestFile.startcapture misses a docstring - test.collect.DoctestFile.skipbykeyword misses a docstring - test.collect.DoctestFile.setup misses a docstring - test.collect.DoctestFile.run misses a docstring - test.collect.DoctestFile.makeitem misses a docstring - test.collect.DoctestFile.listnames misses a docstring - test.collect.DoctestFile.join misses a docstring - test.collect.DoctestFile.haskeyword misses a docstring - test.collect.DoctestFile.getsortvalue misses a docstring - test.collect.DoctestFile.getpathlineno misses a docstring - test.collect.DoctestFile.getouterr misses a docstring - test.collect.DoctestFile.getitembynames misses a docstring - test.collect.DoctestFile.funcnamefilter misses a docstring - test.collect.DoctestFile.finishcapture misses a docstring - test.collect.DoctestFile.classnamefilter misses a docstring - test.collect.DoctestFile.buildname2items misses a docstring - test.collect.DoctestFile.__repr__ misses a docstring - test.collect.DoctestFile.__ne__ misses a docstring - test.collect.DoctestFile.__init__ misses a docstring - test.collect.DoctestFile.__hash__ misses a docstring - test.collect.DoctestFile.__eq__ misses a docstring - test.collect.DoctestFile.__cmp__ misses a docstring - test.collect.Directory misses a docstring - test.collect.Directory.tryiter has an 'XXX' in its docstring - test.collect.Directory.teardown misses a docstring - test.collect.Directory.startcapture misses a docstring - test.collect.Directory.skipbykeyword misses a docstring - test.collect.Directory.setup misses a docstring - test.collect.Directory.run misses a docstring - test.collect.Directory.recfilter misses a docstring - test.collect.Directory.makeitem misses a docstring - test.collect.Directory.listnames misses a docstring - test.collect.Directory.join misses a docstring - test.collect.Directory.haskeyword misses a docstring - test.collect.Directory.getsortvalue misses a docstring - test.collect.Directory.getpathlineno misses a docstring - test.collect.Directory.getouterr misses a docstring - test.collect.Directory.getitembynames misses a docstring - test.collect.Directory.finishcapture misses a docstring - test.collect.Directory.filefilter misses a docstring - test.collect.Directory.buildname2items misses a docstring - test.collect.Directory.__repr__ misses a docstring - test.collect.Directory.__ne__ misses a docstring - test.collect.Directory.__init__ misses a docstring - test.collect.Directory.__hash__ misses a docstring - test.collect.Directory.__eq__ misses a docstring - test.collect.Directory.__cmp__ misses a docstring - test.collect.Collector misses a docstring - test.collect.Collector.tryiter has an 'XXX' in its docstring - test.collect.Collector.teardown misses a docstring - test.collect.Collector.startcapture misses a docstring - test.collect.Collector.skipbykeyword misses a docstring - test.collect.Collector.setup misses a docstring - test.collect.Collector.run misses a docstring - test.collect.Collector.listnames misses a docstring - test.collect.Collector.join misses a docstring - test.collect.Collector.haskeyword misses a docstring - test.collect.Collector.getsortvalue misses a docstring - test.collect.Collector.getpathlineno misses a docstring - test.collect.Collector.getouterr misses a docstring - test.collect.Collector.getitembynames misses a docstring - test.collect.Collector.finishcapture misses a docstring - test.collect.Collector.buildname2items misses a docstring - test.collect.Collector.__repr__ misses a docstring - test.collect.Collector.__ne__ misses a docstring - test.collect.Collector.__init__ misses a docstring - test.collect.Collector.__hash__ misses a docstring - test.collect.Collector.__eq__ misses a docstring - test.collect.Collector.__cmp__ misses a docstring - test.collect.Class misses a docstring - test.collect.Class.tryiter has an 'XXX' in its docstring - test.collect.Class.teardown misses a docstring - test.collect.Class.startcapture misses a docstring - test.collect.Class.skipbykeyword misses a docstring - test.collect.Class.setup misses a docstring - test.collect.Class.run misses a docstring - test.collect.Class.makeitem misses a docstring - test.collect.Class.listnames misses a docstring - test.collect.Class.join misses a docstring - test.collect.Class.haskeyword misses a docstring - test.collect.Class.getsortvalue misses a docstring - test.collect.Class.getpathlineno misses a docstring - test.collect.Class.getouterr misses a docstring - test.collect.Class.getitembynames misses a docstring - test.collect.Class.funcnamefilter misses a docstring - test.collect.Class.finishcapture misses a docstring - test.collect.Class.classnamefilter misses a docstring - test.collect.Class.buildname2items misses a docstring - test.collect.Class.__repr__ misses a docstring - test.collect.Class.__ne__ misses a docstring - test.collect.Class.__init__ misses a docstring - test.collect.Class.__hash__ misses a docstring - test.collect.Class.__eq__ misses a docstring - test.collect.Class.__cmp__ misses a docstring - test.cmdline.main misses a docstring - test.Item misses a docstring - test.Item.tryiter has an 'XXX' in its docstring - test.Item.teardown misses a docstring - test.Item.startcapture misses a docstring - test.Item.skipbykeyword misses a docstring - test.Item.setup misses a docstring - test.Item.run misses a docstring - test.Item.listnames misses a docstring - test.Item.join misses a docstring - test.Item.haskeyword misses a docstring - test.Item.getsortvalue misses a docstring - test.Item.getpathlineno misses a docstring - test.Item.getouterr misses a docstring - test.Item.getitembynames misses a docstring - test.Item.finishcapture misses a docstring - test.Item.buildname2items misses a docstring - test.Item.__repr__ misses a docstring - test.Item.__ne__ misses a docstring - test.Item.__init__ misses a docstring - test.Item.__hash__ misses a docstring - test.Item.__eq__ misses a docstring - test.Item.__cmp__ misses a docstring - test.Function.tryiter has an 'XXX' in its docstring - test.Function.teardown misses a docstring - test.Function.startcapture misses a docstring - test.Function.skipbykeyword misses a docstring - test.Function.setup misses a docstring - test.Function.run misses a docstring - test.Function.listnames misses a docstring - test.Function.join misses a docstring - test.Function.haskeyword misses a docstring - test.Function.getsortvalue misses a docstring - test.Function.getpathlineno misses a docstring - test.Function.getouterr misses a docstring - test.Function.getitembynames misses a docstring - test.Function.finishcapture misses a docstring - test.Function.buildname2items misses a docstring - test.Function.__repr__ misses a docstring - test.Function.__ne__ misses a docstring - test.Function.__init__ misses a docstring - test.Function.__hash__ misses a docstring - test.Function.__eq__ misses a docstring - test.Function.__cmp__ misses a docstring - test.Config.__init__ misses a docstring - xml.raw.__init__ misses a docstring - xml.html misses a docstring - xml.html.__tagclass__ misses a docstring - xml.html.__tagclass__.unicode misses a docstring - xml.html.__tagclass__.__unicode__ misses a docstring - xml.html.__tagclass__.__repr__ misses a docstring - xml.html.__tagclass__.__init__ misses a docstring - xml.html.__tagclass__.Attr misses a docstring - xml.html.__tagclass__.Attr.__init__ misses a docstring - xml.html.__metaclass__ misses a docstring - xml.html.__metaclass__.__getattr__ misses a docstring - xml.html.Style misses a docstring - xml.html.Style.__init__ misses a docstring - xml.escape misses a docstring - xml.Tag misses a docstring - xml.Tag.unicode misses a docstring - xml.Tag.__unicode__ misses a docstring - xml.Tag.__repr__ misses a docstring - xml.Tag.__init__ misses a docstring - xml.Namespace misses a docstring diff --git a/py/doc/example/pytest/test_failures.py b/py/doc/example/pytest/test_failures.py index f9ce18099..4427af02b 100644 --- a/py/doc/example/pytest/test_failures.py +++ b/py/doc/example/pytest/test_failures.py @@ -4,7 +4,7 @@ failure_demo = py.magic.autopath().dirpath('failure_demo.py') def test_failure_demo_fails_properly(): config = py.test.config._reparse([failure_demo]) - session = config.getsessionclass()(config, py.std.sys.stdout) + session = config.initsession() session.main() l = session.getitemoutcomepairs(py.test.Item.Failed) assert len(l) == 21 diff --git a/py/doc/test.txt b/py/doc/test.txt index 196c532db..0771e9ad0 100644 --- a/py/doc/test.txt +++ b/py/doc/test.txt @@ -669,11 +669,14 @@ You must create a conftest.py in any parent directory above your tests. The options that you need to specify in that conftest.py file are: -* `dist_hosts` - a list of ssh addresses (including a specific path if it - should be different than the default: ``$HOME/pytestcache-hostname``) +* **`dist_hosts`**: a required list of ssh addresses (which each may + include a path, default path is: ``$HOME/pytestcache-HOSTNAME``) * `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 +* `dist_remotepython` - the remote python executable to run. +* `dist_nicelevel` - process priority of remote nodes. +* `dist_boxing` - will run each single test in a separate process + (allowing to survive segfaults for example) +* `dist_taskspernode` - Maximum number of tasks being queued to remote nodes Sample configuration:: @@ -688,17 +691,6 @@ Sample configuration:: Running server is done by ``-w`` command line option or ``--startserver`` (the former might change at some point due to conflicts). -Possible `SessionOptions` arguments: - -* `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 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) - Development Notes ----------------- diff --git a/py/doc/test_conftest.py b/py/doc/test_conftest.py index 7b94e8596..4c71bde92 100644 --- a/py/doc/test_conftest.py +++ b/py/doc/test_conftest.py @@ -7,7 +7,6 @@ def setup_module(mod): def test_doctest_basic(): # XXX get rid of the next line: py.magic.autopath().dirpath('conftest.py').copy(tmpdir.join('conftest.py')) - tmpdir.ensure('__init__.py') xtxt = tmpdir.join('x.txt') xtxt.write(py.code.Source(""" @@ -29,7 +28,7 @@ def test_doctest_basic(): end """)) config = py.test.config._reparse([xtxt]) - session = config.getsessionclass()(config, py.std.sys.stdout) + session = config.initsession() session.main() l = session.getitemoutcomepairs(py.test.Item.Failed) assert len(l) == 0 @@ -47,7 +46,7 @@ def test_js_ignore(): .. _`blah`: javascript:some_function() """)) config = py.test.config._reparse([xtxt]) - session = config.getsessionclass()(config, py.std.sys.stdout) + session = config.initsession() session.main() l = session.getitemoutcomepairs(py.test.Item.Failed) assert len(l) == 0 diff --git a/py/doc/test_conftest.py.merge.tmp b/py/doc/test_conftest.py.merge.tmp deleted file mode 100644 index 4c71bde92..000000000 --- a/py/doc/test_conftest.py.merge.tmp +++ /dev/null @@ -1,73 +0,0 @@ - -import py - -def setup_module(mod): - mod.tmpdir = py.test.ensuretemp('docdoctest') - -def test_doctest_basic(): - # XXX get rid of the next line: - py.magic.autopath().dirpath('conftest.py').copy(tmpdir.join('conftest.py')) - - xtxt = tmpdir.join('x.txt') - xtxt.write(py.code.Source(""" - .. - >>> from os.path import abspath - - hello world - - >>> assert abspath - >>> i=3 - >>> print i - 3 - - yes yes - - >>> i - 3 - - end - """)) - config = py.test.config._reparse([xtxt]) - session = config.initsession() - session.main() - l = session.getitemoutcomepairs(py.test.Item.Failed) - assert len(l) == 0 - l = session.getitemoutcomepairs(py.test.Item.Passed) - l2 = session.getitemoutcomepairs(py.test.Item.Skipped) - assert len(l+l2) == 2 - -def test_js_ignore(): - py.magic.autopath().dirpath('conftest.py').copy(tmpdir.join('conftest.py')) - tmpdir.ensure('__init__.py') - xtxt = tmpdir.join('x.txt') - xtxt.write(py.code.Source(""" - `blah`_ - - .. _`blah`: javascript:some_function() - """)) - config = py.test.config._reparse([xtxt]) - session = config.initsession() - session.main() - l = session.getitemoutcomepairs(py.test.Item.Failed) - assert len(l) == 0 - l = session.getitemoutcomepairs(py.test.Item.Passed) - l2 = session.getitemoutcomepairs(py.test.Item.Skipped) - assert len(l+l2) == 3 - -def test_resolve_linkrole(): - from py.__.doc.conftest import resolve_linkrole - assert resolve_linkrole('api', 'py.foo.bar') == ( - 'py.foo.bar', '../../apigen/api/foo.bar.html') - assert resolve_linkrole('api', 'py.foo.bar()') == ( - 'py.foo.bar()', '../../apigen/api/foo.bar.html') - assert resolve_linkrole('api', 'py') == ( - 'py', '../../apigen/api/index.html') - py.test.raises(AssertionError, 'resolve_linkrole("api", "foo.bar")') - assert resolve_linkrole('source', 'py/foo/bar.py') == ( - 'py/foo/bar.py', '../../apigen/source/foo/bar.py.html') - assert resolve_linkrole('source', 'py/foo/') == ( - 'py/foo/', '../../apigen/source/foo/index.html') - assert resolve_linkrole('source', 'py/') == ( - 'py/', '../../apigen/source/index.html') - py.test.raises(AssertionError, 'resolve_linkrole("source", "/foo/bar/")') - diff --git a/py/execnet/rsync.py b/py/execnet/rsync.py index 88b3687e1..b4feb0c5f 100644 --- a/py/execnet/rsync.py +++ b/py/execnet/rsync.py @@ -1,162 +1,153 @@ -import py, md5 +import py, os, stat, md5 +from Queue import Queue -def rsync(gw, sourcedir, destdir, **options): - for name in options: - assert name in ('delete',) +class RSync(object): + """ This is an example usage of py.execnet - a sample RSync + protocol, which can perform syncing 1-to-n. - channel = gw.remote_exec(""" - import os, stat, shutil, md5 - destdir, options = channel.receive() - modifiedfiles = [] + Sample usage: you instantiate this class, eventually providing a + callback when rsyncing is done, than add some targets + (gateway + destdir) by running add_target and finally + invoking send() which will send provided source tree remotely. - def remove(path): - assert path.startswith(destdir) - try: - os.unlink(path) - except OSError: - # assume it's a dir - shutil.rmtree(path) + There is limited support for symlinks, which means that symlinks + pointing to the sourcetree will be send "as is" while external + symlinks will be just copied (regardless of existance of such + a path on remote side) + """ + def __init__(self, callback=None, **options): + for name in options: + assert name in ('delete') + self.options = options + self.callback = callback + self.channels = {} + self.receivequeue = Queue() + self.links = [] - def receive_directory_structure(path, relcomponents): - #print "receive directory structure", path - try: - st = os.lstat(path) - except OSError: - st = None - msg = channel.receive() - if isinstance(msg, list): - if st and not stat.S_ISDIR(st.st_mode): - os.unlink(path) - st = None - if not st: - os.mkdir(path) - entrynames = {} - for entryname in msg: - receive_directory_structure(os.path.join(path, entryname), - relcomponents + [entryname]) - entrynames[entryname] = True - if options.get('delete'): - for othername in os.listdir(path): - if othername not in entrynames: - otherpath = os.path.join(path, othername) - remove(otherpath) + def filter(self, path): + return True + + def add_target(self, gateway, destdir, finishedcallback=None): + """ Adds a target for to-be-send data + """ + def itemcallback(req): + self.receivequeue.put((channel, req)) + channel = gateway.remote_exec(REMOTE_SOURCE) + channel.setcallback(itemcallback, endmarker = None) + channel.send((str(destdir), self.options)) + self.channels[channel] = finishedcallback + + def send(self, sourcedir): + """ Sends a sourcedir to previously prepared targets + """ + self.sourcedir = str(sourcedir) + # normalize a trailing '/' away + self.sourcedir = os.path.dirname(os.path.join(self.sourcedir, 'x')) + # send directory structure and file timestamps/sizes + self._send_directory_structure(self.sourcedir) + + # paths and to_send are only used for doing + # progress-related callbacks + self.paths = {} + self.to_send = {} + + # send modified file to clients + while self.channels: + channel, req = self.receivequeue.get() + if req is None: + # end-of-channel + if channel in self.channels: + # too early! we must have got an error + channel.waitclose() + # or else we raise one + raise IOError('connection unexpectedly closed: %s ' % ( + channel.gateway,)) else: - if st and stat.S_ISREG(st.st_mode): - f = file(path, 'rb') + command, data = req + if command == "links": + for link in self.links: + channel.send(link) + # completion marker, this host is done + channel.send(42) + elif command == "done": + finishedcallback = self.channels.pop(channel) + if finishedcallback: + finishedcallback() + elif command == "ack": + if self.callback: + self.callback("ack", self.paths[data], channel) + elif command == "list_done": + # sum up all to send + if self.callback: + s = sum([self.paths[i] for i in self.to_send[channel]]) + self.callback("list", s, channel) + elif command == "send": + modified_rel_path, checksum = data + modifiedpath = os.path.join(self.sourcedir, *modified_rel_path) + f = open(modifiedpath, 'rb') data = f.read() - f.close() - mychecksum = md5.md5(data).digest() - else: - if st: - remove(path) - mychecksum = None - if mychecksum != msg: - channel.send(relcomponents) - modifiedfiles.append(path) - receive_directory_structure(destdir, []) - channel.send(None) # end marker - for path in modifiedfiles: - data = channel.receive() - f = open(path, 'wb') - f.write(data) - f.close() - """) - - channel.send((str(destdir), options)) - def send_directory_structure(path): - if path.check(dir=1): - subpaths = path.listdir() - print "sending directory structure", path - channel.send([p.basename for p in subpaths]) + # provide info to progress callback function + modified_rel_path = "/".join(modified_rel_path) + self.paths[modified_rel_path] = len(data) + if channel not in self.to_send: + self.to_send[channel] = [] + self.to_send[channel].append(modified_rel_path) + + f.close() + if checksum is not None and checksum == md5.md5(data).digest(): + data = None # not really modified + else: + # ! there is a reason for the interning: + # sharing multiple copies of the file's data + data = intern(data) + print '%s <= %s' % ( + channel.gateway._getremoteaddress(), + modified_rel_path) + channel.send(data) + del data + else: + assert "Unknown command %s" % command + + def _broadcast(self, msg): + for channel in self.channels: + channel.send(msg) + + def _send_link(self, basename, linkpoint): + self.links.append(("link", basename, linkpoint)) + + def _send_directory_structure(self, path): + st = os.lstat(path) + if stat.S_ISREG(st.st_mode): + # regular file: send a timestamp/size pair + self._broadcast((st.st_mtime, st.st_size)) + elif stat.S_ISDIR(st.st_mode): + # dir: send a list of entries + names = [] + subpaths = [] + for name in os.listdir(path): + p = os.path.join(path, name) + if self.filter(p): + names.append(name) + subpaths.append(p) + self._broadcast(names) for p in subpaths: - send_directory_structure(p) - elif path.check(file=1): - data = path.read() - checksum = md5.md5(data).digest() - channel.send(checksum) + self._send_directory_structure(p) + elif stat.S_ISLNK(st.st_mode): + linkpoint = os.readlink(path) + basename = path[len(self.sourcedir) + 1:] + if not linkpoint.startswith(os.sep): + # relative link, just send it + self._send_link(basename, linkpoint) + elif linkpoint.startswith(self.sourcedir): + self._send_link(basename, linkpoint[len(self.sourcedir) + 1:]) + else: + self._send_link(basename, linkpoint) + self._broadcast(None) else: raise ValueError, "cannot sync %r" % (path,) - send_directory_structure(sourcedir) - while True: - modified_rel_path = channel.receive() - if modified_rel_path is None: - break - modifiedpath = sourcedir.join(*modified_rel_path) - data = modifiedpath.read() - channel.send(data) - channel.waitclose() -def copy(gw, source, dest): - channel = gw.remote_exec(""" - import md5 - localfilename = channel.receive() - try: - f = file(localfilename, 'rb') - existingdata = f.read() - f.close() - except (IOError, OSError): - mycrc = None - else: - mycrc = md5.md5(existingdata).digest() - remotecrc = channel.receive() - if remotecrc == mycrc: - channel.send(None) - else: - channel.send(localfilename) - newdata = channel.receive() - f = file(localfilename, 'wb') - f.write(newdata) - f.close() - """) - channel.send(str(dest)) - f = file(str(source), 'rb') - localdata = f.read() - f.close() - channel.send(md5.md5(localdata).digest()) - status = channel.receive() - if status is not None: - assert status == str(dest) # for now - channel.send(localdata) - channel.waitclose() - - -def setup_module(mod): - mod.gw = py.execnet.PopenGateway() - -def teardown_module(mod): - mod.gw.exit() - - -def test_filecopy(): - dir = py.test.ensuretemp('filecopy') - source = dir.ensure('source') - dest = dir.join('dest') - source.write('hello world') - copy(gw, source, dest) - assert dest.check(file=1) - assert dest.read() == 'hello world' - source.write('something else') - copy(gw, source, dest) - assert dest.check(file=1) - assert dest.read() == 'something else' - -def test_dirsync(): - base = py.test.ensuretemp('dirsync') - dest = base.join('dest') - source = base.mkdir('source') - - for s in ('content1', 'content2'): - source.ensure('subdir', 'file1').write(s) - rsync(gw, source, dest) - assert dest.join('subdir').check(dir=1) - assert dest.join('subdir', 'file1').check(file=1) - assert dest.join('subdir', 'file1').read() == s - - source.join('subdir').remove('file1') - rsync(gw, source, dest) - assert dest.join('subdir', 'file1').check(file=1) - rsync(gw, source, dest, delete=True) - assert not dest.join('subdir', 'file1').check() +REMOTE_SOURCE = py.path.local(__file__).dirpath().\ + join('rsync_remote.py').open().read() + "\nf()" diff --git a/py/test/rsession/rsync_remote.py b/py/execnet/rsync_remote.py similarity index 99% rename from py/test/rsession/rsync_remote.py rename to py/execnet/rsync_remote.py index 72793ef3c..bb770ebc7 100644 --- a/py/test/rsession/rsync_remote.py +++ b/py/execnet/rsync_remote.py @@ -76,7 +76,7 @@ def f(): assert _type == "link" path = os.path.join(destdir, relpath) try: - os.unlink(path) + remove(path) except OSError: pass diff --git a/py/test/rsession/testing/test_rsync.py b/py/execnet/testing/test_rsync.py similarity index 98% rename from py/test/rsession/testing/test_rsync.py rename to py/execnet/testing/test_rsync.py index ae682118c..7b01c3ae3 100644 --- a/py/test/rsession/testing/test_rsync.py +++ b/py/execnet/testing/test_rsync.py @@ -1,5 +1,5 @@ import py -from py.__.test.rsession.rsync import RSync +from py.execnet import RSync def setup_module(mod): diff --git a/py/misc/terminal_helper.py b/py/misc/terminal_helper.py index ba95d4bf6..26920cc87 100644 --- a/py/misc/terminal_helper.py +++ b/py/misc/terminal_helper.py @@ -1,6 +1,19 @@ import sys, os -terminal_width = int(os.environ.get('COLUMNS', 80))-1 +def get_terminal_width(): + try: + import termios,fcntl,struct + call = fcntl.ioctl(0,termios.TIOCGWINSZ,"\000"*8) + height,width = struct.unpack( "hhhh", call ) [:2] + terminal_width = width + except (SystemExit, KeyboardInterrupt), e: + raise + except: + # FALLBACK + terminal_width = int(os.environ.get('COLUMNS', 80))-1 + return terminal_width + +terminal_width = get_terminal_width() def ansi_print(text, esc, file=None, newline=True, flush=False): if file is None: diff --git a/py/misc/testing/test_terminal.py b/py/misc/testing/test_terminal.py new file mode 100644 index 000000000..daba8351d --- /dev/null +++ b/py/misc/testing/test_terminal.py @@ -0,0 +1,21 @@ + +import os +from py.__.misc.terminal_helper import get_terminal_width + +def test_terminal_width(): + """ Dummy test for get_terminal_width + """ + assert get_terminal_width() + try: + def f(*args): + raise ValueError + import fcntl + ioctl = fcntl.ioctl + fcntl.ioctl = f + cols = os.environ.get('COLUMNS', None) + os.environ['COLUMNS'] = '42' + assert get_terminal_width() == 41 + finally: + fcntl.ioctl = ioctl + if cols: + os.environ['COLUMNS'] = cols diff --git a/py/path/local/local.py b/py/path/local/local.py index e53df774a..90d990207 100644 --- a/py/path/local/local.py +++ b/py/path/local/local.py @@ -189,7 +189,7 @@ class LocalPath(common.FSPathBase, PlatformMixin): strpath += sep strpath += arg obj = self.new() - obj.strpath = strpath + obj.strpath = os.path.normpath(strpath) return obj def __eq__(self, other): diff --git a/py/path/local/testing/test_local.py b/py/path/local/testing/test_local.py index b22122a52..d3496c5e8 100644 --- a/py/path/local/testing/test_local.py +++ b/py/path/local/testing/test_local.py @@ -17,6 +17,13 @@ class LocalSetup: class TestLocalPath(LocalSetup, CommonFSTests): + def test_join_normpath(self): + assert self.tmpdir.join(".") == self.tmpdir + p = self.tmpdir.join("../%s" % self.tmpdir.basename) + assert p == self.tmpdir + p = self.tmpdir.join("..//%s/" % self.tmpdir.basename) + assert p == self.tmpdir + def test_gethash(self): import md5 import sha diff --git a/py/test/cmdline.py b/py/test/cmdline.py index 8ade642fd..18f4cffc1 100644 --- a/py/test/cmdline.py +++ b/py/test/cmdline.py @@ -8,30 +8,9 @@ def main(args=None): warn_about_missing_assertion() if args is None: args = py.std.sys.argv[1:] - elif isinstance(args, basestring): - args = args.split(" ") config = py.test.config config.parse(args) - sessionclass = config.getsessionclass() - - # ok, some option checks - if config.option.startserver or config.option.runbrowser: - from py.__.test.rsession.rsession import AbstractSession, LSession - if not issubclass(sessionclass, AbstractSession): - print "Cannot use web server without (R|L)Session, using lsession" - sessionclass = LSession - if config.option.apigen: - from py.__.test.rsession.rsession import AbstractSession, LSession - if not issubclass(sessionclass, AbstractSession): - sessionclass = LSession - print "Cannot generate API without (R|L)Session, using lsession" - if config.option.restreport: - from py.__.test.rsession.rsession import AbstractSession, LSession - if not issubclass(sessionclass, AbstractSession): - sessionclass = LSession - - session = sessionclass(config) - + session = config.initsession() try: failures = session.main() if failures: diff --git a/py/test/collect.py b/py/test/collect.py index 60fdb4073..c4a7a9861 100644 --- a/py/test/collect.py +++ b/py/test/collect.py @@ -29,31 +29,9 @@ import py def configproperty(name): def fget(self): #print "retrieving %r property from %s" %(name, self.fspath) - return py.test.config.getvalue(name, self.fspath) + return self.config.getvalue(name, self.fspath) return property(fget) -def getfscollector(fspath): - if isinstance(fspath, str): - fspath = py.path.local(fspath) - if not fspath.check(): - raise py.error.ENOENT(fspath) - pkgpath = fspath.pypkgpath() - if pkgpath is None: - if fspath.check(dir=1): - pkgpath = fspath - else: - pkgpath = fspath.dirpath() - Directory = py.test.config.getvalue('Directory', pkgpath) - current = Directory(pkgpath) - #print "pkgpath", pkgpath - names = filter(None, fspath.relto(pkgpath).split(fspath.sep)) - for name in names: - current = current.join(name) - assert current, "joining %r resulted in None!" % (names,) - top = current.listchain()[0] - #top._config = config - return current - class Collector(object): """ Collector instances are iteratively generated (through their run() and join() methods) @@ -63,10 +41,10 @@ class Collector(object): (or None if it is the root collector) name: basename of this collector object """ - def __init__(self, name, parent=None): + def __init__(self, name, parent=None): self.name = name self.parent = parent - self.option = getattr(parent, 'option', None) + self.config = getattr(parent, 'config', py.test.config) self.fspath = getattr(parent, 'fspath', None) Module = configproperty('Module') @@ -187,9 +165,10 @@ class Collector(object): namelist = namelist.split("/") cur = self for name in namelist: - next = cur.join(name) - assert next is not None, (cur, name, namelist) - cur = next + if name: + next = cur.join(name) + assert next is not None, (cur, name, namelist) + cur = next return cur def haskeyword(self, keyword): @@ -211,8 +190,10 @@ class Collector(object): newl.append(x.name) return ".".join(newl) - # XXX: Copied from session def skipbykeyword(self, keyword): + """ raise Skipped() exception if the given keyword + matches for this collector. + """ if not keyword: return chain = self.listchain() @@ -342,15 +323,15 @@ class PyCollectorMixin(object): d[name] = res return d - def makeitem(self, name, obj, usefilters=True): + def makeitem(self, name, obj, usefilters=True): if (not usefilters or self.classnamefilter(name)) and \ - py.std.inspect.isclass(obj): - return self.Class(name, parent=self) + py.std.inspect.isclass(obj): + return self.Class(name, parent=self) elif (not usefilters or self.funcnamefilter(name)) and callable(obj): if obj.func_code.co_flags & 32: # generator function - return self.Generator(name, parent=self) + return self.Generator(name, parent=self) else: - return self.Function(name, parent=self) + return self.Function(name, parent=self) def _prepare(self): if not hasattr(self, '_name2items'): @@ -391,7 +372,7 @@ class Module(FSCollector, PyCollectorMixin): return res def startcapture(self): - if not self.option.nocapture: + if not self.config.option.nocapture: assert not hasattr(self, '_capture') #self._capture = py.io.OutErrCapture() # XXX integrate this into py.io / refactor diff --git a/py/test/config.py b/py/test/config.py index 1ae49fe89..91cccee86 100644 --- a/py/test/config.py +++ b/py/test/config.py @@ -26,32 +26,65 @@ class CmdOptions(object): class Config(object): """ central hub for dealing with configuration/initialization data. """ Option = optparse.Option - conftest = Conftest() def __init__(self): self.option = CmdOptions() self._parser = optparse.OptionParser( usage="usage: %prog [options] [query] [filenames of tests]") - self._parsed = False + self.conftest = Conftest() + self._initialized = False + self._overwrite_dict = {} def parse(self, args): """ parse cmdline arguments into this config object. Note that this can only be called once per testing process. """ - assert not self._parsed, ( + assert not self._initialized, ( "can only parse cmdline args once per Config object") - self._parsed = True + self._initialized = True self.conftest.setinitial(args) - self.conftest.lget('adddefaultoptions')() + self.conftest.rget('adddefaultoptions')() args = [str(x) for x in args] - self._origargs = args - cmdlineoption, remaining = self._parser.parse_args(args) + cmdlineoption, args = 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()) - self.remaining = remaining + if not args: + args.append(py.std.os.getcwd()) + self.topdir = gettopdir(args) + self.args = args + def initdirect(self, topdir, repr, coltrails=None): + assert not self._initialized + self._initialized = True + self.topdir = py.path.local(topdir) + self.merge_repr(repr) + self._coltrails = coltrails + + def getcolitems(self): + """ return initial collectors. """ + trails = getattr(self, '_coltrails', None) + return [self._getcollector(path) for path in (trails or self.args)] + + def _getcollector(self, path): + if isinstance(path, tuple): + relpath, names = path + fspath = self.topdir.join(relpath) + col = self._getcollector(fspath) + else: + path = py.path.local(path) + assert path.check(), "%s: path does not exist" %(path,) + col = self._getrootcollector(path) + names = path.relto(col.fspath).split(path.sep) + return col.getitembynames(names) + + def _getrootcollector(self, path): + pkgpath = path.pypkgpath() + if pkgpath is None: + pkgpath = path.check(file=1) and path.dirpath() or path + col = self.conftest.rget("Directory", pkgpath)(pkgpath) + col.config = self + return col + def addoptions(self, groupname, *specs): """ add a named group of options to the current testing session. This function gets invoked during testing session initialization. @@ -70,79 +103,186 @@ class Config(object): if path is None, lookup the value in the initial conftest modules found during command line parsing. """ - return self.conftest.rget(name, path) + try: + return self._overwrite_dict[name] + except KeyError: + return self.conftest.rget(name, path) - def getsessionclass(self): + def initsession(self): + """ return an initialized session object. """ + cls = self._getsessionclass() + session = cls(self) + #session.fixoptions() + return session + + def _getsessionclass(self): """ return Session class determined from cmdline options and looked up in initial config modules. """ - sessionname = self.option.session + 'Session' - try: - return self.conftest.rget(sessionname) - except KeyError: - pass - sessionimportpaths = self.conftest.lget('sessionimportpaths') - importpath = sessionimportpaths[sessionname] - mod = __import__(importpath, None, None, ['__doc__']) - return getattr(mod, sessionname) + if self.option.session is not None: + return self.conftest.rget(self.option.session) + else: + name = self._getsessionname() + importpath = globals()[name] + mod = __import__(importpath, None, None, '__doc__') + return getattr(mod, name) + + def _getsessionname(self): + """ return default session name as determined from options. """ + name = 'TerminalSession' + if self.option.dist: + name = 'RSession' + elif self.option.tkinter: + name = 'TkinterSession' + else: + optnames = 'startserver runbrowser apigen restreport boxing'.split() + for opt in optnames: + if getattr(self.option, opt, False): + name = 'LSession' + break + else: + if self.getvalue('dist_boxing'): + name = 'LSession' + if self.option.looponfailing: + name = 'RemoteTerminalSession' + elif self.option.executable: + name = 'RemoteTerminalSession' + return name + + def is_boxed(self): + # XXX probably not a good idea to have this special function ... + return self.option.boxing or self.getvalue("dist_boxing") def _reparse(self, args): """ this is used from tests that want to re-invoke parse(). """ - global config - oldconfig = py.test.config + global config_per_process + oldconfig = py.test.config try: - config = py.test.config = Config() - config.parse(args) - return config + config_per_process = py.test.config = Config() + config_per_process.parse(args) + return config_per_process finally: - config = py.test.config = oldconfig + config_per_process = py.test.config = oldconfig + + def _overwrite(self, name, value): + """ this is used from tests to overwrite values irrespectives of conftests. + """ + self._overwrite_dict[name] = value + + def make_repr(self, conftestnames, optnames=None): + """ return a marshallable representation + of conftest and cmdline options. + if optnames is None, all options + on self.option will be transferred. + """ + conftestdict = {} + for name in conftestnames: + value = self.getvalue(name) + checkmarshal(name, value) + conftestdict[name] = value + cmdlineopts = {} + if optnames is None: + optnames = dir(self.option) + for name in optnames: + if not name.startswith("_"): + value = getattr(self.option, name) + checkmarshal(name, value) + cmdlineopts[name] = value + l = [] + for path in self.args: + path = py.path.local(path) + l.append(path.relto(self.topdir)) + return l, conftestdict, cmdlineopts + + def merge_repr(self, repr): + """ merge in the conftest and cmdline option values + found in the given representation (produced + by make_repr above). + + The repr-contained conftest values are + stored on the default conftest module (last + priority) and the cmdline options on self.option. + """ + class override: + def __init__(self, d): + self.__dict__.update(d) + args, conftestdict, cmdlineopts = repr + self.args = [self.topdir.join(x) for x in args] + self.conftest.setinitial(self.args) + self.conftest._path2confmods[None].append(override(conftestdict)) + for name, val in cmdlineopts.items(): + setattr(self.option, name, val) + + def get_collector_trail(self, collector): + """ provide a trail relative to the topdir, + which can be used to reconstruct the + collector (possibly on a different host + starting from a different topdir). + """ + chain = collector.listchain() + relpath = chain[0].fspath.relto(self.topdir) + if not relpath: + if chain[0].fspath == self.topdir: + relpath = "." + else: + raise ValueError("%r not relative to %s" + %(chain[0], self.topdir)) + return relpath, tuple([x.name for x in chain[1:]]) # this is the one per-process instance of py.test configuration -config = Config() +config_per_process = Config() + +# default import paths for sessions + +TkinterSession = 'py.__.test.tkinter.reportsession' +TerminalSession = 'py.__.test.terminal.terminal' +TerminalSession = 'py.__.test.terminal.terminal' +RemoteTerminalSession = 'py.__.test.terminal.remote' +RSession = 'py.__.test.rsession.rsession' +LSession = 'py.__.test.rsession.rsession' # # helpers # +def checkmarshal(name, value): + try: + py.std.marshal.dumps(value) + except ValueError: + raise ValueError("%s=%r is not marshallable" %(name, value)) + def fixoptions(option): """ sanity checks and making option values canonical. """ - if option.looponfailing and option.usepdb: - raise ValueError, "--looponfailing together with --pdb not supported yet." - if option.executable and option.usepdb: - raise ValueError, "--exec together with --pdb not supported yet." - - # setting a correct executable - remote = False - if option.executable is not None: - remote = True - exe = py.path.local(py.std.os.path.expanduser(option.executable)) - if not exe.check(): - exe = py.path.local.sysfind(option.executable) - assert exe.check() - option.executable = exe - else: - option.executable = py.std.sys.executable + # implied options if option.usepdb: if not option.nocapture: - print "--usepdb currently implies --nocapture" + #print "--pdb implies --nocapture" option.nocapture = True - # make information available about wether we should/will be remote - option._remote = remote or option.looponfailing - option._fromremote = False - - # setting a correct frontend session - if option.session: - name = option.session - elif option.tkinter: - name = 'tkinter' - else: - name = 'terminal' - name = name.capitalize() - option.session = name - if option.runbrowser and not option.startserver: - print "Cannot point browser when not starting server" + #print "--runbrowser implies --startserver" option.startserver = True - + + # conflicting options + if option.looponfailing and option.usepdb: + raise ValueError, "--looponfailing together with --pdb not supported." + if option.looponfailing and option.dist: + raise ValueError, "--looponfailing together with --dist not supported." + if option.executable and option.usepdb: + raise ValueError, "--exec together with --pdb not supported." + + +def gettopdir(args): + """ return the top directory for the given paths. + if the common base dir resides in a python package + parent directory of the root package is returned. + """ + args = [py.path.local(arg) for arg in args] + p = reduce(py.path.local.common, args) + assert p, "cannot determine common basedir of %s" %(args,) + pkgdir = p.pypkgpath() + if pkgdir is None: + return p + else: + return pkgdir.dirpath() diff --git a/py/test/config.py.merge.tmp b/py/test/config.py.merge.tmp deleted file mode 100644 index 91cccee86..000000000 --- a/py/test/config.py.merge.tmp +++ /dev/null @@ -1,288 +0,0 @@ -from __future__ import generators - -import py -from conftesthandle import Conftest - -optparse = py.compat.optparse - -# XXX move to Config class -basetemp = None -def ensuretemp(string, dir=1): - """ return temporary directory path with - the given string as the trailing part. - """ - global basetemp - 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 - - def __init__(self): - self.option = CmdOptions() - self._parser = optparse.OptionParser( - usage="usage: %prog [options] [query] [filenames of tests]") - self.conftest = Conftest() - self._initialized = False - self._overwrite_dict = {} - - def parse(self, args): - """ parse cmdline arguments into this config object. - Note that this can only be called once per testing process. - """ - assert not self._initialized, ( - "can only parse cmdline args once per Config object") - self._initialized = True - self.conftest.setinitial(args) - self.conftest.rget('adddefaultoptions')() - args = [str(x) for x in args] - cmdlineoption, args = self._parser.parse_args(args) - self.option.__dict__.update(vars(cmdlineoption)) - fixoptions(self.option) # XXX fixing should be moved to sessions - if not args: - args.append(py.std.os.getcwd()) - self.topdir = gettopdir(args) - self.args = args - - def initdirect(self, topdir, repr, coltrails=None): - assert not self._initialized - self._initialized = True - self.topdir = py.path.local(topdir) - self.merge_repr(repr) - self._coltrails = coltrails - - def getcolitems(self): - """ return initial collectors. """ - trails = getattr(self, '_coltrails', None) - return [self._getcollector(path) for path in (trails or self.args)] - - def _getcollector(self, path): - if isinstance(path, tuple): - relpath, names = path - fspath = self.topdir.join(relpath) - col = self._getcollector(fspath) - else: - path = py.path.local(path) - assert path.check(), "%s: path does not exist" %(path,) - col = self._getrootcollector(path) - names = path.relto(col.fspath).split(path.sep) - return col.getitembynames(names) - - def _getrootcollector(self, path): - pkgpath = path.pypkgpath() - if pkgpath is None: - pkgpath = path.check(file=1) and path.dirpath() or path - col = self.conftest.rget("Directory", pkgpath)(pkgpath) - col.config = self - return col - - def addoptions(self, groupname, *specs): - """ add a named group of options to the current testing session. - This function gets invoked during testing session initialization. - """ - optgroup = optparse.OptionGroup(self._parser, groupname) - optgroup.add_options(specs) - self._parser.add_option_group(optgroup) - for opt in specs: - if hasattr(opt, 'default') and opt.dest: - 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. - """ - try: - return self._overwrite_dict[name] - except KeyError: - return self.conftest.rget(name, path) - - def initsession(self): - """ return an initialized session object. """ - cls = self._getsessionclass() - session = cls(self) - #session.fixoptions() - return session - - def _getsessionclass(self): - """ return Session class determined from cmdline options - and looked up in initial config modules. - """ - if self.option.session is not None: - return self.conftest.rget(self.option.session) - else: - name = self._getsessionname() - importpath = globals()[name] - mod = __import__(importpath, None, None, '__doc__') - return getattr(mod, name) - - def _getsessionname(self): - """ return default session name as determined from options. """ - name = 'TerminalSession' - if self.option.dist: - name = 'RSession' - elif self.option.tkinter: - name = 'TkinterSession' - else: - optnames = 'startserver runbrowser apigen restreport boxing'.split() - for opt in optnames: - if getattr(self.option, opt, False): - name = 'LSession' - break - else: - if self.getvalue('dist_boxing'): - name = 'LSession' - if self.option.looponfailing: - name = 'RemoteTerminalSession' - elif self.option.executable: - name = 'RemoteTerminalSession' - return name - - def is_boxed(self): - # XXX probably not a good idea to have this special function ... - return self.option.boxing or self.getvalue("dist_boxing") - - def _reparse(self, args): - """ this is used from tests that want to re-invoke parse(). """ - global config_per_process - oldconfig = py.test.config - try: - config_per_process = py.test.config = Config() - config_per_process.parse(args) - return config_per_process - finally: - config_per_process = py.test.config = oldconfig - - def _overwrite(self, name, value): - """ this is used from tests to overwrite values irrespectives of conftests. - """ - self._overwrite_dict[name] = value - - def make_repr(self, conftestnames, optnames=None): - """ return a marshallable representation - of conftest and cmdline options. - if optnames is None, all options - on self.option will be transferred. - """ - conftestdict = {} - for name in conftestnames: - value = self.getvalue(name) - checkmarshal(name, value) - conftestdict[name] = value - cmdlineopts = {} - if optnames is None: - optnames = dir(self.option) - for name in optnames: - if not name.startswith("_"): - value = getattr(self.option, name) - checkmarshal(name, value) - cmdlineopts[name] = value - l = [] - for path in self.args: - path = py.path.local(path) - l.append(path.relto(self.topdir)) - return l, conftestdict, cmdlineopts - - def merge_repr(self, repr): - """ merge in the conftest and cmdline option values - found in the given representation (produced - by make_repr above). - - The repr-contained conftest values are - stored on the default conftest module (last - priority) and the cmdline options on self.option. - """ - class override: - def __init__(self, d): - self.__dict__.update(d) - args, conftestdict, cmdlineopts = repr - self.args = [self.topdir.join(x) for x in args] - self.conftest.setinitial(self.args) - self.conftest._path2confmods[None].append(override(conftestdict)) - for name, val in cmdlineopts.items(): - setattr(self.option, name, val) - - def get_collector_trail(self, collector): - """ provide a trail relative to the topdir, - which can be used to reconstruct the - collector (possibly on a different host - starting from a different topdir). - """ - chain = collector.listchain() - relpath = chain[0].fspath.relto(self.topdir) - if not relpath: - if chain[0].fspath == self.topdir: - relpath = "." - else: - raise ValueError("%r not relative to %s" - %(chain[0], self.topdir)) - return relpath, tuple([x.name for x in chain[1:]]) - -# this is the one per-process instance of py.test configuration -config_per_process = Config() - -# default import paths for sessions - -TkinterSession = 'py.__.test.tkinter.reportsession' -TerminalSession = 'py.__.test.terminal.terminal' -TerminalSession = 'py.__.test.terminal.terminal' -RemoteTerminalSession = 'py.__.test.terminal.remote' -RSession = 'py.__.test.rsession.rsession' -LSession = 'py.__.test.rsession.rsession' - -# -# helpers -# - -def checkmarshal(name, value): - try: - py.std.marshal.dumps(value) - except ValueError: - raise ValueError("%s=%r is not marshallable" %(name, value)) - -def fixoptions(option): - """ sanity checks and making option values canonical. """ - - # implied options - if option.usepdb: - if not option.nocapture: - #print "--pdb implies --nocapture" - option.nocapture = True - - if option.runbrowser and not option.startserver: - #print "--runbrowser implies --startserver" - option.startserver = True - - # conflicting options - if option.looponfailing and option.usepdb: - raise ValueError, "--looponfailing together with --pdb not supported." - if option.looponfailing and option.dist: - raise ValueError, "--looponfailing together with --dist not supported." - if option.executable and option.usepdb: - raise ValueError, "--exec together with --pdb not supported." - - -def gettopdir(args): - """ return the top directory for the given paths. - if the common base dir resides in a python package - parent directory of the root package is returned. - """ - args = [py.path.local(arg) for arg in args] - p = reduce(py.path.local.common, args) - assert p, "cannot determine common basedir of %s" %(args,) - pkgdir = p.pypkgpath() - if pkgdir is None: - return p - else: - return pkgdir.dirpath() diff --git a/py/test/conftesthandle.py b/py/test/conftesthandle.py index e482af7f4..0548f53e6 100644 --- a/py/test/conftesthandle.py +++ b/py/test/conftesthandle.py @@ -51,9 +51,10 @@ class Conftest(object): # affect us by always returning a copy of the actual list return clist[:] - def lget(self, name, path=None): - modules = self.getconftestmodules(path) - return self._get(name, modules) + # XXX no real use case, may probably go + #def lget(self, name, path=None): + # modules = self.getconftestmodules(path) + # return self._get(name, modules) def rget(self, name, path=None): modules = self.getconftestmodules(path) diff --git a/py/test/defaultconftest.py b/py/test/defaultconftest.py index 94e3ba906..69db1b1c1 100644 --- a/py/test/defaultconftest.py +++ b/py/test/defaultconftest.py @@ -10,15 +10,25 @@ Instance = py.test.collect.Instance additionalinfo = None + +# =================================================== +# Distributed testing specific options + +#dist_hosts: needs to be provided by user +#dist_rsync_roots: might be provided by user, if not present or None, +# whole pkgdir will be rsynced +dist_remotepython = "python" +dist_taskspernode = 15 +dist_boxing = False +if hasattr(py.std.os, 'nice'): + dist_nicelevel = py.std.os.nice(0) # nice py.test works +else: + dist_nicelevel = 0 +_dist_import_pypy = False # used for regenerating JS application + +# =================================================== + 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(): py.test.config.addoptions('general options', Option('-v', '--verbose', @@ -56,35 +66,41 @@ def adddefaultoptions(): Option('', '--traceconfig', action="store_true", dest="traceconfig", default=False, help="trace considerations of conftest.py files."), + ) + + py.test.config.addoptions('EXPERIMENTAL options', + Option('-f', '--looponfailing', + action="store_true", dest="looponfailing", default=False, + help="loop on failing test set."), + Option('', '--exec', + action="store", dest="executable", default=None, + help="python executable to run the tests with."), + Option('-d', '--dist', + action="store_true", dest="dist", default=False, + help="ad-hoc distribute tests across machines (requires conftest settings)"), + Option('-w', '--startserver', + action="store_true", dest="startserver", default=False, + help="starts local web server for displaying test progress.", + ), + Option('-r', '--runbrowser', + action="store_true", dest="runbrowser", default=False, + help="run browser (implies --startserver)." + ), + Option('', '--tkinter', + action="store_true", dest="tkinter", default=False, + help="use tkinter test session frontend."), + Option('', '--box', + action="store_true", dest="boxing", + help="use boxing (running each test in external process)"), + Option('', '--rest', + action='store_true', dest="restreport", default=False, + help="restructured text output reporting."), Option('', '--apigen', action="store", dest="apigen", help="generate api documentation while testing (requires" "argument pointing to a script)."), - ) - - py.test.config.addoptions('test-session related options', - Option('', '--tkinter', - action="store_true", dest="tkinter", default=False, - help="use tkinter test session frontend."), - Option('', '--looponfailing', - action="store_true", dest="looponfailing", default=False, - help="loop on failing test set."), Option('', '--session', action="store", dest="session", default=None, - help="use given sessionclass, default is terminal."), - Option('', '--exec', - action="store", dest="executable", default=None, - help="python executable to run the tests with."), - Option('-w', '--startserver', - action="store_true", dest="startserver", default=False, - help="start HTTP server listening on localhost:8000 for test." - ), - Option('', '--runbrowser', - action="store_true", dest="runbrowser", default=False, - help="run browser to point to your freshly started web server." - ), - Option('-r', '--rest', - action='store_true', dest="restreport", default=False, - help="restructured text output reporting."), + help="lookup given sessioname in conftest.py files and use it."), ) diff --git a/py/test/item.py b/py/test/item.py index f34b7a988..dd5e16a06 100644 --- a/py/test/item.py +++ b/py/test/item.py @@ -31,7 +31,7 @@ class SetupState(object): class Item(py.test.collect.Collector): def startcapture(self): - if not self.option.nocapture: + if not self.config.option.nocapture: # XXX refactor integrate capturing #self._capture = py.io.OutErrCapture() from py.__.misc.simplecapture import SimpleOutErrCapture diff --git a/py/test/representation.py b/py/test/representation.py new file mode 100644 index 000000000..08f45e139 --- /dev/null +++ b/py/test/representation.py @@ -0,0 +1,177 @@ + +""" This file intends to gather all methods of representing +failures/tracebacks etc. which should be used among +all terminal-based reporters. This methods should be general, +to allow further use outside the pylib +""" + +import py + +class Presenter(object): + """ Class used for presentation of various objects, + sharing common output style + """ + def __init__(self, out, config): + """ out is a file-like object (we can write to it) + """ + assert hasattr(out, 'write') + self.out = out + self.config = config + + def repr_source(self, source, marker=">", marker_location=-1): + """ This one represents piece of source with possible + marker at requested position + """ + if isinstance(source, str): + # why the hell, string is iterable? + source = source.split("\n") + if marker_location < 0: + marker_location += len(source) + if marker_location < 0: + marker_location = 0 + if marker_location >= len(source): + marker_location = len(source) - 1 + for i in range(len(source)): + if i == marker_location: + prefix = marker + " " + else: + prefix = " " + self.out.line(prefix + source[i]) + + def repr_item_info(self, item): + """ This method represents py.test.Item info (path and module) + """ + root = item.fspath + modpath = item.getmodpath() + try: + fn, lineno = item.getpathlineno() + except TypeError: + assert isinstance(item.parent, py.test.collect.Generator) + # a generative test yielded a non-callable + fn, lineno = item.parent.getpathlineno() + if root == fn: + self.out.sep("_", "entrypoint: %s" %(modpath)) + else: + self.out.sep("_", "entrypoint: %s %s" %(root.basename, modpath)) + + def repr_failure_explanation(self, excinfo, source): + try: + s = str(source.getstatement(len(source)-1)) + except KeyboardInterrupt: + raise + except: + s = str(source[-1]) + indent = " " * (4 + (len(s) - len(s.lstrip()))) + # get the real exception information out + lines = excinfo.exconly(tryshort=True).split('\n') + self.out.line('>' + indent[:-1] + lines.pop(0)) + for x in lines: + self.out.line(indent + x) + + def getentrysource(self, entry): + try: + source = entry.getsource() + except py.error.ENOENT: + source = py.code.Source("[failure to get at sourcelines from %r]\n" % entry) + return source.deindent() + + def repr_locals(self, f_locals): + if self.config.option.showlocals: + self.out.sep('- ', 'locals') + for name, value in f_locals.items(): + if name == '__builtins__': + self.out.line("__builtins__ = ") + else: + # This formatting could all be handled by the _repr() function, which is + # only repr.Repr in disguise, so is very configurable. + str_repr = py.__.code.safe_repr._repr(value) + if len(str_repr) < 70 or not isinstance(value, + (list, tuple, dict)): + self.out.line("%-10s = %s" %(name, str_repr)) + else: + self.out.line("%-10s =\\" % (name,)) + py.std.pprint.pprint(value, stream=self.out) + + def repr_failure_tblong(self, item, excinfo, traceback, out_err_reporter): + if not self.config.option.nomagic and excinfo.errisinstance(RuntimeError): + recursionindex = traceback.recursionindex() + else: + recursionindex = None + last = traceback[-1] + first = traceback[0] + for index, entry in py.builtin.enumerate(traceback): + if entry == first: + if item: + self.repr_item_info(item) + self.out.line() + else: + self.out.line("") + source = self.getentrysource(entry) + firstsourceline = entry.getfirstlinesource() + marker_location = entry.lineno - firstsourceline + if entry == last: + self.repr_source(source, 'E', marker_location) + self.repr_failure_explanation(excinfo, source) + else: + self.repr_source(source, '>', marker_location) + self.out.line("") + self.out.line("[%s:%d]" %(entry.path, entry.lineno+1)) + self.repr_locals(entry.locals) + + # trailing info + if entry == last: + out_err_reporter() + self.out.sep("_") + else: + self.out.sep("_ ") + if index == recursionindex: + self.out.line("Recursion detected (same locals & position)") + self.out.sep("!") + break + + def repr_failure_tbshort(self, item, excinfo, traceback, out_err_reporter): + # print a Python-style short traceback + if not self.config.option.nomagic and excinfo.errisinstance(RuntimeError): + recursionindex = traceback.recursionindex() + else: + recursionindex = None + last = traceback[-1] + first = traceback[0] + self.out.line() + for index, entry in py.builtin.enumerate(traceback): + path = entry.path.basename + firstsourceline = entry.getfirstlinesource() + relline = entry.lineno - firstsourceline + self.out.line(' File "%s", line %d, in %s' % ( + path, entry.lineno+1, entry.name)) + try: + source = entry.getsource().lines + except py.error.ENOENT: + source = ["?"] + else: + try: + if len(source) > 1: + source = source[relline] + except IndexError: + source = [] + if entry == last: + if source: + self.repr_source(source, 'E') + self.repr_failure_explanation(excinfo, source) + else: + if source: + self.repr_source(source, ' ') + self.repr_locals(entry.locals) + + # trailing info + if entry == last: + out_err_reporter() + self.out.sep("_") + else: + if index == recursionindex: + self.out.line("Recursion detected (same locals & position)") + self.out.sep("!") + break + + # the following is only used by the combination '--pdb --tb=no' + repr_failure_tbno = repr_failure_tbshort diff --git a/py/test/rsession/box.py b/py/test/rsession/box.py index fb04e9175..e58431514 100644 --- a/py/test/rsession/box.py +++ b/py/test/rsession/box.py @@ -18,12 +18,14 @@ from StringIO import StringIO class FileBox(object): count = 0 - def __init__(self, fun, args=None, kwargs=None): + def __init__(self, fun, args=None, kwargs=None, config=None): if args is None: args = [] if kwargs is None: kwargs = {} self.fun = fun + self.config = config + assert self.config self.args = args self.kwargs = kwargs @@ -35,8 +37,7 @@ class FileBox(object): self.PYTESTSTDOUT = tempdir.join('stdout') self.PYTESTSTDERR = tempdir.join('stderr') - from py.__.test.rsession.rsession import remote_options - nice_level = remote_options.nice_level + nice_level = self.config.getvalue('dist_nicelevel') pid = os.fork() if pid: if not continuation: @@ -48,10 +49,12 @@ class FileBox(object): outcome = self.children(nice_level) except: excinfo = py.code.ExceptionInfo() - print "Internal box error" + x = open("/tmp/traceback", "w") + print >>x, "Internal box error" for i in excinfo.traceback: - print str(i)[2:-1] - print excinfo + print >>x, str(i)[2:-1] + print >>x, excinfo + x.close() os._exit(1) os.close(1) os.close(2) @@ -83,8 +86,8 @@ class FileBox(object): retvalf.close() os._exit(0) - def parent(self, pid): - pid, exitstat = os.waitpid(pid, 0) + def parent(self, pid, waiter=os.waitpid): + pid, exitstat = waiter(pid, 0) self.signal = exitstat & 0x7f self.exitstat = exitstat & 0xff00 diff --git a/py/test/rsession/conftest.py b/py/test/rsession/conftest.py deleted file mode 100644 index 9e83701f9..000000000 --- a/py/test/rsession/conftest.py +++ /dev/null @@ -1,10 +0,0 @@ -import py -Option = py.test.config.Option - -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 ' - 'should be used when kill() is not allowed for the current ' - 'user'), -) diff --git a/py/test/rsession/executor.py b/py/test/rsession/executor.py index 5d82bd4aa..8c3ff174a 100644 --- a/py/test/rsession/executor.py +++ b/py/test/rsession/executor.py @@ -12,10 +12,12 @@ class RunExecutor(object): """ wraps = False - def __init__(self, item, usepdb=False, reporter=None): + def __init__(self, item, usepdb=False, reporter=None, config=None): self.item = item self.usepdb = usepdb self.reporter = reporter + self.config = config + assert self.config def execute(self): try: @@ -36,7 +38,8 @@ class RunExecutor(object): if self.usepdb: if self.reporter is not None: self.reporter(report.ImmediateFailure(self.item, - ReprOutcome(outcome.make_repr()))) + ReprOutcome(outcome.make_repr + (self.config.option.tbstyle)))) import pdb pdb.post_mortem(excinfo._excinfo[2]) # XXX hmm, we probably will not like to continue from that @@ -54,8 +57,8 @@ class BoxExecutor(RunExecutor): def execute(self): def fun(): outcome = RunExecutor.execute(self) - return outcome.make_repr() - b = Box(fun) + return outcome.make_repr(self.config.option.tbstyle) + b = Box(fun, config=self.config) pid = b.run() assert pid if b.retval is not None: @@ -76,13 +79,13 @@ class AsyncExecutor(RunExecutor): def execute(self): def fun(): outcome = RunExecutor.execute(self) - return outcome.make_repr() + return outcome.make_repr(self.config.option.tbstyle) - b = Box(fun) + b = Box(fun, config=self.config) parent, pid = b.run(continuation=True) - def cont(): - parent(pid) + def cont(waiter=os.waitpid): + parent(pid, waiter=waiter) if b.retval is not None: passed, setupfailure, excinfo, skipped,\ critical, _, _, _ = b.retval diff --git a/py/test/rsession/hostmanage.py b/py/test/rsession/hostmanage.py index 98338bfd3..0a28e0fc1 100644 --- a/py/test/rsession/hostmanage.py +++ b/py/test/rsession/hostmanage.py @@ -5,7 +5,6 @@ import thread, threading from py.__.test.rsession.master import \ setup_slave, MasterNode from py.__.test.rsession import report -from py.__.test.rsession.rsync import RSync class HostInfo(object): """ Class trying to store all necessary attributes @@ -39,11 +38,11 @@ class HostInfo(object): def __ne__(self, other): return not self == other -class HostRSync(RSync): +class HostRSync(py.execnet.RSync): """ An rsync wrapper which filters out *~, .svn/ and *.pyc """ def __init__(self, rsync_roots): - RSync.__init__(self, delete=True) + py.execnet.RSync.__init__(self, delete=True) self.rsync_roots = rsync_roots def filter(self, path): @@ -60,104 +59,143 @@ class HostRSync(RSync): class DummyGateway(object): pass -def prepare_gateway(sshosts, optimise_localhost, - remote_python, pkgdir, real_create=True): - hosts = [] - for host in sshosts: - if host.hostname != 'localhost' or not optimise_localhost: - if real_create: - # for tests we want to use somtehing different - if host.hostname == 'localhost' and optimise_localhost is False: - from py.__.execnet.register import PopenCmdGateway - gw = PopenCmdGateway("cd ~; python -u -c 'exec input()'") - if not host.relpath.startswith("/"): - host.relpath = os.environ['HOME'] + '/' + host.relpath - else: - if remote_python is None: - gw = py.execnet.SshGateway(host.hostname) - else: - gw = py.execnet.SshGateway(host.hostname, - remotepython=remote_python) - else: - gw = DummyGateway() - else: - if remote_python is None: - gw = py.execnet.PopenGateway() - else: - gw = py.execnet.PopenGateway(remotepython=remote_python) - host.relpath = str(pkgdir.dirpath()) - host.gw = gw - gw.host = host - return sshosts +class HostOptions(object): + """ Dummy container for host options, not to keep that + as different function parameters, mostly related to + tests only + """ + def __init__(self, rsync_roots=None, remote_python="python", + optimise_localhost=True, do_sync=True, + create_gateways=True): + self.rsync_roots = rsync_roots + self.remote_python = remote_python + self.optimise_localhost = optimise_localhost + self.do_sync = do_sync + self.create_gateways = create_gateways -def init_hosts(reporter, sshhosts, pkgdir, rsync_roots=None, - remote_python=None, \ - remote_options={}, optimise_localhost=True,\ - do_sync=True, done_dict=None): - if done_dict is None: - done_dict = {} - assert pkgdir.join("__init__.py").check(), ( +class HostManager(object): + def __init__(self, sshhosts, config, pkgdir, options=HostOptions()): + self.sshhosts = sshhosts + self.pkgdir = pkgdir + self.config = config + self.options = options + if not options.create_gateways: + self.prepare_gateways = self.prepare_dummy_gateways + assert pkgdir.join("__init__.py").check(), ( "%s probably wrong" %(pkgdir,)) - exc_info = [None] - hosts = prepare_gateway(sshhosts, optimise_localhost, - remote_python, pkgdir, real_create=do_sync) - - # rsyncing - rsynced = {} + def prepare_dummy_gateways(self): + for host in self.sshhosts: + gw = DummyGateway() + host.gw = gw + gw.host = host + return self.sshhosts - if do_sync: - rsync = HostRSync(rsync_roots) - for host in hosts: - #for num, host, gw, remoterootpath in hosts: - remoterootpath = host.relpath - if (host.hostname, remoterootpath) in rsynced or\ - (host.hostname == 'localhost' and optimise_localhost): - reporter(report.HostReady(host)) - continue - rsynced[(host.hostname, host.relpath)] = True - def done(host=host): - reporter(report.HostReady(host)) - reporter(report.HostRSyncing(host)) - if do_sync: - rsync.add_target(host.gw, remoterootpath, done) - if not do_sync: - return # for testing only - rsync.send(pkgdir.dirpath()) + def prepare_ssh_gateway(self, host): + if self.options.remote_python is None: + gw = py.execnet.SshGateway(host.hostname) + else: + gw = py.execnet.SshGateway(host.hostname, + remotepython=self.options.remote_python) + return gw - # hosts ready - return setup_nodes(hosts, pkgdir, remote_options, reporter, done_dict) + def prepare_popen_rsync_gateway(self, host): + """ Popen gateway, but with forced rsync + """ + from py.__.execnet.register import PopenCmdGateway + gw = PopenCmdGateway("cd ~; python -u -c 'exec input()'") + if not host.relpath.startswith("/"): + host.relpath = os.environ['HOME'] + '/' + host.relpath + return gw -def setup_nodes(hosts, pkgdir, remote_options, reporter, done_dict): - nodes = [] - for host in hosts: - ch = setup_slave(host.gw, os.path.join(host.relpath,\ - pkgdir.basename), remote_options) - nodes.append(MasterNode(ch, reporter, done_dict)) - - return nodes + def prepare_popen_gateway(self, host): + if self.options.remote_python is None: + gw = py.execnet.PopenGateway() + else: + gw = py.execnet.PopenGateway(python=self.options.remote_python) + host.relpath = str(self.pkgdir.dirpath()) + return gw -def teardown_hosts(reporter, channels, nodes, waiter=lambda : time.sleep(.1), - exitfirst=False): - for channel in channels: - channel.send(None) - - from py.__.test.rsession.rsession import session_options + def prepare_gateways(self): + for host in self.sshhosts: + if host.hostname == 'localhost': + if not self.options.optimise_localhost: + gw = self.prepare_popen_rsync_gateway(host) + else: + gw = self.prepare_popen_gateway(host) + else: + gw = self.prepare_ssh_gateway(host) + host.gw = gw + gw.host = host + return self.sshhosts - clean = exitfirst - while not clean: - clean = True - for node in nodes: - if node.pending: - clean = False - waiter() + def need_rsync(self, rsynced, hostname, remoterootpath): + if (hostname, remoterootpath) in rsynced: + return False + if hostname == 'localhost' and self.options.optimise_localhost: + return False + return True + + def init_hosts(self, reporter, done_dict={}): + if done_dict is None: + done_dict = {} + + hosts = self.prepare_gateways() + # rsyncing + rsynced = {} - for channel in channels: - try: - report.wrapcall(reporter, channel.waitclose, int(session_options.waittime)) - except KeyboardInterrupt, SystemExit: - raise - except: - pass - channel.gateway.exit() + if self.options.do_sync: + rsync = HostRSync(self.options.rsync_roots) + for host in hosts: + if not self.need_rsync(rsynced, host.hostname, host.relpath): + reporter(report.HostReady(host)) + continue + rsynced[(host.hostname, host.relpath)] = True + def done(host=host): + reporter(report.HostReady(host)) + reporter(report.HostRSyncing(host)) + if self.options.do_sync: + rsync.add_target(host.gw, host.relpath, done) + if not self.options.do_sync: + return # for testing only + rsync.send(self.pkgdir.dirpath()) + # hosts ready + return self.setup_nodes(reporter, done_dict) + + def setup_nodes(self, reporter, done_dict): + nodes = [] + for host in self.sshhosts: + ch = setup_slave(host.gw, os.path.join(host.relpath,\ + self.pkgdir.basename), self.config) + nodes.append(MasterNode(ch, reporter, done_dict)) + + return nodes + + def teardown_hosts(self, reporter, channels, nodes, + waiter=lambda : time.sleep(.1), exitfirst=False): + for channel in channels: + channel.send(None) + + clean = exitfirst + while not clean: + clean = True + for node in nodes: + if node.pending: + clean = False + waiter() + self.teardown_gateways(reporter, channels) + + def kill_channels(self, channels): + for channel in channels: + channel.send(42) + + def teardown_gateways(self, reporter, channels): + for channel in channels: + try: + report.wrapcall(reporter, channel.waitclose) + except KeyboardInterrupt, SystemExit: + raise + except: + pass + channel.gateway.exit() diff --git a/py/test/rsession/local.py b/py/test/rsession/local.py index 78e15b42c..b1d2cb106 100644 --- a/py/test/rsession/local.py +++ b/py/test/rsession/local.py @@ -21,23 +21,18 @@ def finishcapture(session): return "", "" def box_runner(item, session, reporter): - r = BoxExecutor(item) + r = BoxExecutor(item, config=session.config) return ReprOutcome(r.execute()) def plain_runner(item, session, reporter): # box executor is doing stdout/err catching for us, let's do it here startcapture(session) - r = RunExecutor(item, usepdb=session.config.option.usepdb, reporter=reporter) + r = RunExecutor(item, usepdb=session.config.option.usepdb, reporter=reporter, config=session.config) outcome = r.execute() - outcome = ReprOutcome(outcome.make_repr()) + outcome = ReprOutcome(outcome.make_repr(session.config.option.tbstyle)) outcome.stdout, outcome.stderr = finishcapture(session) return outcome -RunnerPolicy = { - 'plain_runner':plain_runner, - 'box_runner':box_runner -} - def benchmark_runner(item, session, reporter): raise NotImplementedError() diff --git a/py/test/rsession/master.py b/py/test/rsession/master.py index 5f2ef5f8d..9183fcf5e 100644 --- a/py/test/rsession/master.py +++ b/py/test/rsession/master.py @@ -35,7 +35,7 @@ class MasterNode(object): self.reporter(report.SendItem(self.channel, item)) def itemgen(colitems, reporter, keyword, reporterror): - for x in colitems: + for x in colitems: for y in x.tryiter(reporterror = lambda x: reporterror(reporter, x), keyword = keyword): yield y @@ -56,9 +56,7 @@ def dispatch_loop(masternodes, itemgenerator, shouldstop, waiter = lambda: py.std.time.sleep(0.1), max_tasks_per_node=None): if not max_tasks_per_node: - from py.__.test.rsession.rsession import session_options - - max_tasks_per_node = session_options.max_tasks_per_node + max_tasks_per_node = py.test.config.getvalue("dist_taskspernode") all_tests = {} while 1: try: @@ -76,12 +74,14 @@ def dispatch_loop(masternodes, itemgenerator, shouldstop, waiter() return all_tests -def setup_slave(gateway, pkgpath, options): +def setup_slave(gateway, pkgpath, config): from py.__.test.rsession import slave import os ch = gateway.remote_exec(str(py.code.Source(slave.setup, "setup()"))) #if hasattr(gateway, 'sshaddress'): # assert not os.path.isabs(pkgpath) ch.send(str(pkgpath)) - ch.send(options) + ch.send(config.make_repr(defaultconftestnames)) return ch + +defaultconftestnames = ['dist_nicelevel'] diff --git a/py/test/rsession/outcome.py b/py/test/rsession/outcome.py index e5c573898..35e4b1d5d 100644 --- a/py/test/rsession/outcome.py +++ b/py/test/rsession/outcome.py @@ -20,51 +20,82 @@ class Outcome(object): self.signal = 0 assert bool(self.passed) + bool(excinfo) + bool(skipped) == 1 - def make_excinfo_repr(self): + def make_excinfo_repr(self, tbstyle): if self.excinfo is None: return None excinfo = self.excinfo - tb_info = [self.traceback_entry_repr(x) for x in excinfo.traceback] - return (excinfo.type.__name__, str(excinfo.value), tb_info) + tb_info = [self.traceback_entry_repr(x, tbstyle) + for x in excinfo.traceback] + rec_index = excinfo.traceback.recursionindex() + return (excinfo.type.__name__, str(excinfo.value), (tb_info, rec_index)) - def traceback_entry_repr(self, tb_entry): + def traceback_entry_repr(self, tb_entry, tb_style): lineno = tb_entry.lineno relline = lineno - tb_entry.frame.code.firstlineno path = str(tb_entry.path) - try: - from py.__.test.rsession.rsession import remote_options - if remote_options.tbstyle == 'long': - source = str(tb_entry.getsource()) - else: - source = str(tb_entry.getsource()).split("\n")[relline] - except: - source = "" - return (relline, lineno, source, path) + #try: + if tb_style == 'long': + source = str(tb_entry.getsource()) + else: + source = str(tb_entry.getsource()).split("\n")[relline] + name = tb_entry.frame.code.raw.co_name + # XXX: Bare except. What can getsource() raise anyway? + # SyntaxError, AttributeError, IndentationError for sure, check it + #except: + # source = "" + return (relline, lineno, source, path, name) - def make_repr(self): + def make_repr(self, tbstyle="long"): return (self.passed, self.setupfailure, - self.make_excinfo_repr(), + self.make_excinfo_repr(tbstyle), self.skipped, self.is_critical, 0, "", "") class TracebackEntryRepr(object): def __init__(self, tbentry): - relline, lineno, self.source, self.path = tbentry + relline, lineno, self.source, self.path, self.name = tbentry self.relline = int(relline) + self.path = py.path.local(self.path) self.lineno = int(lineno) + self.locals = {} def __repr__(self): return "line %s in %s\n %s" %(self.lineno, self.path, self.source[100:]) + def getsource(self): + return py.code.Source(self.source).strip() + + def getfirstlinesource(self): + return self.lineno - self.relline + +class TracebackRepr(list): + def recursionindex(self): + return self.recursion_index + class ExcInfoRepr(object): def __init__(self, excinfo): - self.typename, self.value, tb = excinfo - self.traceback = [TracebackEntryRepr(x) for x in tb] + self.typename, self.value, tb_i = excinfo + tb, rec_index = tb_i + self.traceback = TracebackRepr([TracebackEntryRepr(x) for x in tb]) + self.traceback.recursion_index = rec_index def __repr__(self): l = ["%s=%s" %(x, getattr(self, x)) for x in "typename value traceback".split()] return "" %(" ".join(l),) + def exconly(self, tryshort=False): + """ Somehow crippled version of original one + """ + return "%s: %s" % (self.typename, self.value) + + def errisinstance(self, exc_t): + if not isinstance(exc_t, tuple): + exc_t = (exc_t,) + for exc in exc_t: + if self.typename == str(exc).split('.')[-1]: + return True + return False + class ReprOutcome(object): def __init__(self, repr_tuple): (self.passed, self.setupfailure, excinfo, self.skipped, diff --git a/py/test/rsession/report.py b/py/test/rsession/report.py index 71d1cfc90..951cfe399 100644 --- a/py/test/rsession/report.py +++ b/py/test/rsession/report.py @@ -124,3 +124,9 @@ class PongReceived(ReportEvent): def __init__(self, hostid, result): self.hostid = hostid self.result = result + +class InterruptedExecution(ReportEvent): + pass + +class CrashedExecution(ReportEvent): + pass diff --git a/py/test/rsession/reporter.py b/py/test/rsession/reporter.py index 6273dc458..1562692e5 100644 --- a/py/test/rsession/reporter.py +++ b/py/test/rsession/reporter.py @@ -2,7 +2,7 @@ """ reporter - different reporter for different purposes ;-) Still lacks: - 1. Hanging nodes are not good done + 1. Hanging nodes are not done well """ import py @@ -10,6 +10,10 @@ import py from py.__.test.terminal.out import getout from py.__.test.rsession import report from py.__.test.rsession import outcome +from py.__.misc.terminal_helper import ansi_print, get_terminal_width +from py.__.test.representation import Presenter + +import sys class AbstractReporter(object): def __init__(self, config, hosts, pkgdir=py.path.local(py.__file__)): @@ -19,6 +23,7 @@ class AbstractReporter(object): self.failed_tests_outcome = [] self.skipped_tests_outcome = [] self.out = getout(py.std.sys.stdout) + self.presenter = Presenter(self.out, config) self.failed = dict([(host, 0) for host in hosts]) self.skipped = dict([(host, 0) for host in hosts]) self.passed = dict([(host, 0) for host in hosts]) @@ -46,6 +51,7 @@ class AbstractReporter(object): def report_SendItem(self, item): address = item.host.hostname + assert isinstance(item.host.hostname, str) if self.config.option.verbose: print "Sending %s to %s" % (item.item, address) @@ -108,6 +114,7 @@ class AbstractReporter(object): self.out.sep('_', "%s on %s" % (" ".join(event.item.listnames()), host)) if event.outcome.signal: + self.presenter.repr_item_info(event.item) self.repr_signal(event.item, event.outcome) else: self.repr_failure(event.item, event.outcome) @@ -119,7 +126,7 @@ class AbstractReporter(object): def gethost(self, event): return event.host.hostname - def repr_failure(self, item, outcome): + def repr_failure(self, item, outcome): excinfo = outcome.excinfo traceback = excinfo.traceback #if item and not self.config.option.fulltrace: @@ -127,18 +134,11 @@ class AbstractReporter(object): if not traceback: self.out.line("empty traceback from item %r" % (item,)) return - #handler = getattr(self, 'repr_failure_tb%s' % self.config.option.tbstyle) - self.repr_traceback(item, excinfo, traceback) - if outcome.stdout: - self.out.sep('-', " Captured process stdout: ") - self.out.write(outcome.stdout) - if outcome.stderr: - self.out.sep('-', " Captured process stderr: ") - self.out.write(outcome.stderr) - - def repr_signal(self, item, outcome): - signal = outcome.signal - self.out.line("Received signal: %d" % outcome.signal) + + handler = getattr(self.presenter, 'repr_failure_tb%s' % self.config.option.tbstyle) + handler(item, excinfo, traceback, lambda: self.repr_out_err(outcome)) + + def repr_out_err(self, outcome): if outcome.stdout: self.out.sep('-', " Captured process stdout: ") self.out.write(outcome.stdout) @@ -146,25 +146,11 @@ class AbstractReporter(object): self.out.sep('-', " Captured process stderr: ") self.out.write(outcome.stderr) - def repr_traceback(self, item, excinfo, traceback): - if self.config.option.tbstyle == 'long': - for index, entry in py.builtin.enumerate(traceback): - self.out.sep('-') - self.out.line("%s: %s" % (entry.path, entry.lineno)) - self.repr_source(entry.relline, str(entry.source)) - elif self.config.option.tbstyle == 'short': - for index, entry in py.builtin.enumerate(traceback): - self.out.line("%s: %s" % (entry.path, entry.lineno)) - self.out.line(entry.source) - self.out.line("%s: %s" % (excinfo.typename, excinfo.value)) + def repr_signal(self, item, outcome): + signal = outcome.signal + self.out.line("Received signal: %d" % outcome.signal) + self.repr_out_err(outcome) - def repr_source(self, relline, source): - for num, line in enumerate(source.split("\n")): - if num == relline: - self.out.line(">>>>" + line) - else: - self.out.line(" " + line) - def skips(self): texts = {} for event in self.skipped_tests_outcome: @@ -225,19 +211,30 @@ class AbstractReporter(object): def report_ReceivedItemOutcome(self, event): host = event.host if event.outcome.passed: - status = "PASSED " self.passed[host] += 1 + sys.stdout.write("%10s: PASSED " % host.hostname[:10]) elif event.outcome.skipped: - status = "SKIPPED" self.skipped_tests_outcome.append(event) self.skipped[host] += 1 + sys.stdout.write("%10s: SKIPPED " % host.hostname[:10]) else: - status = "FAILED " self.failed[host] += 1 self.failed_tests_outcome.append(event) - # we'll take care of them later - itempath = " ".join(event.item.listnames()[1:]) - print "%10s: %s %s" %(host.hostname[:10], status, itempath) + sys.stdout.write("%10s: " % host.hostname[:10]) + ansi_print("FAILED", esc=(31,1), newline=False, file=sys.stdout) + sys.stdout.write(" ") + # we should have printed 20 characters to this point + itempath = ".".join(event.item.listnames()[1:-1]) + funname = event.item.listnames()[-1] + lgt = get_terminal_width() - 20 + # mark the function name, to be sure + to_display = len(itempath) + len(funname) + 1 + if to_display > lgt: + sys.stdout.write("..." + itempath[to_display-lgt+4:]) + else: + sys.stdout.write(itempath) + sys.stdout.write(" ") + ansi_print(funname, esc=32, file=sys.stdout) def report_Nodes(self, event): self.nodes = event.nodes diff --git a/py/test/rsession/rest.py b/py/test/rsession/rest.py index 9df4003ec..caaa4f3a8 100644 --- a/py/test/rsession/rest.py +++ b/py/test/rsession/rest.py @@ -31,18 +31,23 @@ class RestReporter(AbstractReporter): if self.config.option.verbose: self.add_rest(Paragraph("Unknown report: %s" % what)) + def gethost(self, item): + if item.channel: + return item.channel.gateway.host + return self.hosts[0] + def report_SendItem(self, item): - address = item.channel.gateway.host.hostname + address = self.gethost(item) if self.config.option.verbose: self.add_rest(Paragraph('sending item %s to %s' % (item.item, address))) def report_HostRSyncing(self, item): - self.add_rest(LiteralBlock('%10s: RSYNC ==> %s' % (item.hostname[:10], + self.add_rest(LiteralBlock('%10s: RSYNC ==> %s' % (item.host.hostname[:10], item.remoterootpath))) def report_HostReady(self, item): - self.add_rest(LiteralBlock('%10s: READY' % (item.hostname[:10],))) + self.add_rest(LiteralBlock('%10s: READY' % (item.host.hostname[:10],))) def report_TestStarted(self, event): txt = "Running tests on hosts: %s" % ", ".join(event.hosts) @@ -91,7 +96,7 @@ class RestReporter(AbstractReporter): self.out.write(self.rest.render_links()) def report_ReceivedItemOutcome(self, event): - host = event.channel.gateway.host + host = self.gethost(event) if event.outcome.passed: status = [Strong("PASSED")] self.passed[host] += 1 diff --git a/py/test/rsession/rest.py.merge.tmp b/py/test/rsession/rest.py.merge.tmp deleted file mode 100644 index caaa4f3a8..000000000 --- a/py/test/rsession/rest.py.merge.tmp +++ /dev/null @@ -1,276 +0,0 @@ - -""" Rest reporting stuff -""" - -import py -import sys -from StringIO import StringIO -from py.__.test.rsession.reporter import AbstractReporter -from py.__.test.rsession import report -from py.__.rest.rst import * - -class RestReporter(AbstractReporter): - linkwriter = None - - def __init__(self, *args, **kwargs): - super(RestReporter, self).__init__(*args, **kwargs) - self.rest = Rest() - self.traceback_num = 0 - - def get_linkwriter(self): - if self.linkwriter is None: - try: - self.linkwriter = self.config.getvalue('linkwriter') - except KeyError: - print >>sys.stderr, ('no linkwriter configured, using default ' - 'one') - self.linkwriter = RelLinkWriter() - return self.linkwriter - - def report_unknown(self, what): - if self.config.option.verbose: - self.add_rest(Paragraph("Unknown report: %s" % what)) - - def gethost(self, item): - if item.channel: - return item.channel.gateway.host - return self.hosts[0] - - def report_SendItem(self, item): - address = self.gethost(item) - if self.config.option.verbose: - self.add_rest(Paragraph('sending item %s to %s' % (item.item, - address))) - - def report_HostRSyncing(self, item): - self.add_rest(LiteralBlock('%10s: RSYNC ==> %s' % (item.host.hostname[:10], - item.remoterootpath))) - - def report_HostReady(self, item): - self.add_rest(LiteralBlock('%10s: READY' % (item.host.hostname[:10],))) - - def report_TestStarted(self, event): - txt = "Running tests on hosts: %s" % ", ".join(event.hosts) - self.add_rest(Title(txt, abovechar='=', belowchar='=')) - self.timestart = event.timestart - - def report_TestFinished(self, item): - self.timeend = item.timeend - self.summary() - return len(self.failed_tests_outcome) > 0 - - def report_ImmediateFailure(self, item): - pass - - def report_ItemStart(self, event): - item = event.item - if isinstance(item, py.test.collect.Module): - lgt = len(list(item.tryiter())) - lns = item.listnames()[1:] - name = "/".join(lns) - link = self.get_linkwriter().get_link(self.get_rootpath(item), - item.fspath) - if link: - name = Link(name, link) - txt = 'Testing module %s (%d items)' % (name, lgt) - self.add_rest(Title('Testing module', name, '(%d items)' % (lgt,), - belowchar='-')) - - def get_rootpath(self, item): - root = item.parent - while root.parent is not None: - root = root.parent - return root.fspath - - def print_summary(self, total, skipped_str, failed_str): - self.skips() - self.failures() - - txt = "%d tests run%s%s in %.2fs (rsync: %.2f)" % \ - (total, skipped_str, failed_str, self.timeend - self.timestart, - self.timersync - self.timestart) - self.add_rest(Title(txt, belowchar='-')) - - # since we're rendering each item, the links haven't been rendered - # yet - self.out.write(self.rest.render_links()) - - def report_ReceivedItemOutcome(self, event): - host = self.gethost(event) - if event.outcome.passed: - status = [Strong("PASSED")] - self.passed[host] += 1 - elif event.outcome.skipped: - status = [Strong("SKIPPED")] - self.skipped_tests_outcome.append(event) - self.skipped[host] += 1 - else: - status = [Strong("FAILED"), - InternalLink("traceback%d" % self.traceback_num)] - self.traceback_num += 1 - self.failed[host] += 1 - self.failed_tests_outcome.append(event) - # we'll take care of them later - itempath = self.get_path_from_item(event.item) - status.append(Text(itempath)) - hostname = host.hostname - self.add_rest(ListItem(Text("%10s:" % (hostname[:10],)), *status)) - - def skips(self): - # XXX hrmph, copied code - texts = {} - for event in self.skipped_tests_outcome: - colitem = event.item - if isinstance(event, report.ReceivedItemOutcome): - outcome = event.outcome - text = outcome.skipped - itemname = self.get_item_name(event, colitem) - elif isinstance(event, report.SkippedTryiter): - text = str(event.excinfo.value) - itemname = "/".join(colitem.listnames()) - if text not in texts: - texts[text] = [itemname] - else: - texts[text].append(itemname) - if texts: - self.add_rest(Title('Reasons for skipped tests:', belowchar='+')) - for text, items in texts.items(): - for item in items: - self.add_rest(ListItem('%s: %s' % (item, text))) - - def get_host(self, event): - return event.channel.gateway.host - - def failures(self): - self.traceback_num = 0 - tbstyle = self.config.option.tbstyle - if self.failed_tests_outcome: - self.add_rest(Title('Exceptions:', belowchar='+')) - for i, event in enumerate(self.failed_tests_outcome): - if i > 0: - self.add_rest(Transition()) - if isinstance(event, report.ReceivedItemOutcome): - host = self.get_host(event) - itempath = self.get_path_from_item(event.item) - root = self.get_rootpath(event.item) - link = self.get_linkwriter().get_link(root, event.item.fspath) - t = Title(belowchar='+') - if link: - t.add(Link(itempath, link)) - else: - t.add(Text(itempath)) - t.add(Text('on %s' % (host.hostname,))) - self.add_rest(t) - if event.outcome.signal: - self.repr_signal(event.item, event.outcome) - else: - self.repr_failure(event.item, event.outcome, tbstyle) - else: - itempath = self.get_path_from_item(event.item) - root = self.get_rootpath(event.item) - link = self.get_linkwriter().get_link(root, event.item.fspath) - t = Title(abovechar='+', belowchar='+') - if link: - t.add(Link(itempath, link)) - else: - t.add(Text(itempath)) - out = outcome.Outcome(excinfo=event.excinfo) - self.repr_failure(event.item, - outcome.ReprOutcome(out.make_repr()), - tbstyle) - - def repr_signal(self, item, outcome): - signal = outcome.signal - self.add_rest(Title('Received signal: %d' % (outcome.signal,), - abovechar='+', belowchar='+')) - if outcome.stdout.strip(): - self.add_rest(Paragraph('Captured process stdout:')) - self.add_rest(LiteralBlock(outcome.stdout)) - if outcome.stderr.strip(): - self.add_rest(Paragraph('Captured process stderr:')) - self.add_rest(LiteralBlock(outcome.stderr)) - - def repr_failure(self, item, outcome, style): - excinfo = outcome.excinfo - traceback = excinfo.traceback - if not traceback: - self.add_rest(Paragraph('empty traceback from item %r' % (item,))) - return - self.repr_traceback(item, excinfo, traceback, style) - if outcome.stdout: - self.add_rest(Title('Captured process stdout:', abovechar='+', - belowchar='+')) - self.add_rest(LiteralBlock(outcome.stdout)) - if outcome.stderr: - self.add_rest(Title('Captured process stderr:', abovechar='+', - belowchar='+')) - self.add_rest(LiteralBlock(outcome.stderr)) - - def repr_traceback(self, item, excinfo, traceback, style): - root = self.get_rootpath(item) - self.add_rest(LinkTarget('traceback%d' % self.traceback_num, "")) - self.traceback_num += 1 - if style == 'long': - for entry in traceback: - link = self.get_linkwriter().get_link(root, - py.path.local(entry.path)) - if link: - self.add_rest(Title(Link(entry.path, link), - 'line %d' % (entry.lineno,), - belowchar='+', abovechar='+')) - else: - self.add_rest(Title('%s line %d' % (entry.path, - entry.lineno,), - belowchar='+', abovechar='+')) - self.add_rest(LiteralBlock(self.prepare_source(entry.relline, - entry.source))) - elif style == 'short': - text = [] - for entry in traceback: - text.append('%s line %d' % (entry.path, entry.lineno)) - text.append(' %s' % (entry.source.strip(),)) - self.add_rest(LiteralBlock('\n'.join(text))) - self.add_rest(Title(excinfo.typename, belowchar='+')) - self.add_rest(LiteralBlock(excinfo.value)) - - def prepare_source(self, relline, source): - text = [] - for num, line in enumerate(source.split('\n')): - if num == relline: - text.append('>>> %s' % (line,)) - else: - text.append(' %s' % (line,)) - return '\n'.join(text) - - def add_rest(self, item): - self.rest.add(item) - self.out.write('%s\n\n' % (item.text(),)) - - def get_path_from_item(self, item): - lns = item.listnames()[1:] - for i, ln in enumerate(lns): - if i > 0 and ln != '()': - lns[i] = '/%s' % (ln,) - itempath = ''.join(lns) - return itempath - -class AbstractLinkWriter(object): - def get_link(self, base, path): - pass - -class NoLinkWriter(AbstractLinkWriter): - def get_link(self, base, path): - return '' - -class LinkWriter(AbstractLinkWriter): - def __init__(self, baseurl): - self.baseurl = baseurl - - def get_link(self, base, path): - relpath = path.relto(base) - return self.baseurl + relpath - -class RelLinkWriter(AbstractLinkWriter): - def get_link(self, base, path): - return path.relto(base) - diff --git a/py/test/rsession/rsession.py b/py/test/rsession/rsession.py index 700e20afe..ec2750504 100644 --- a/py/test/rsession/rsession.py +++ b/py/test/rsession/rsession.py @@ -11,74 +11,12 @@ import time from py.__.test.rsession import report from py.__.test.rsession.master import \ setup_slave, MasterNode, dispatch_loop, itemgen, randomgen -from py.__.test.rsession.hostmanage import init_hosts, teardown_hosts, HostInfo +from py.__.test.rsession.hostmanage import HostInfo, HostOptions, HostManager from py.__.test.rsession.local import local_loop, plain_runner, apigen_runner,\ - box_runner, RunnerPolicy + box_runner from py.__.test.rsession.reporter import LocalReporter, RemoteReporter -class RemoteOptions(object): - def __init__(self, d): - self.d = d - - def __getattr__(self, attr): - if attr == 'd': - return self.__dict__['d'] - return self.d[attr] - - def __setitem__(self, item, val): - self.d[item] = val - -# XXX: Must be initialised somehow -remote_options = RemoteOptions({'we_are_remote':False}) - -class SessionOptions: - defaults = { - 'max_tasks_per_node' : 15, - 'runner_policy' : 'plain_runner', - 'nice_level' : 0, - 'waittime' : 100.0, - 'import_pypy' : False, - } - - config = None - - def getvalue(self, opt): - try: - return getattr(self.config.getvalue('SessionOptions'), opt) - except (KeyError, AttributeError): - try: - return self.defaults[opt] - except KeyError: - raise AttributeError("Option %s undeclared" % opt) - - def bind_config(self, config): - self.config = config - # copy to remote session options - try: - ses_opt = self.config.getvalue('SessionOptions').__dict__ - except KeyError: - ses_opt = self.defaults - for key in self.defaults: - try: - val = ses_opt[key] - except KeyError: - val = self.defaults[key] - remote_options[key] = val - # copy to remote all options - for item, val in config.option.__dict__.items(): - remote_options[item] = val - - def __repr__(self): - return "" % self.config - - def __getattr__(self, attr): - if self.config is None: - raise AttributeError("Need to set up config first") - return self.getvalue(attr) - -session_options = SessionOptions() - class AbstractSession(object): """ An abstract session executes collectors/items through a runner. @@ -114,17 +52,29 @@ class AbstractSession(object): getpkgdir = staticmethod(getpkgdir) def init_reporter(self, reporter, sshhosts, reporter_class, arg=""): + """ This initialises so called `reporter` class, which will + handle all event presenting to user. Does not get called + if main received custom reporter + """ startserverflag = self.config.option.startserver restflag = self.config.option.restreport if startserverflag and reporter is None: from py.__.test.rsession.web import start_server, exported_methods + if self.config.option.runbrowser: + from socket import INADDR_ANY + port = INADDR_ANY # pick a random port when starting browser + else: + port = 8000 # stick to a fixed port otherwise reporter = exported_methods.report - start_server() + httpd = start_server(server_address = ('', port)) + port = httpd.server_port if self.config.option.runbrowser: - import webbrowser - webbrowser.open("http://localhost:8000") + import webbrowser, thread + # webbrowser.open() may block until the browser finishes or not + url = "http://localhost:%d" % (port,) + thread.start_new_thread(webbrowser.open, (url,)) elif reporter is None: if restflag: from py.__.test.rsession.rest import RestReporter @@ -150,6 +100,8 @@ class AbstractSession(object): reporterror = staticmethod(reporterror) def kill_server(self, startserverflag): + """ Kill web server + """ if startserverflag: from py.__.test.rsession.web import kill_server kill_server() @@ -172,6 +124,8 @@ class AbstractSession(object): return new_reporter, checkfun def parse_directories(sshhosts): + """ Parse sshadresses of hosts to have distinct hostname/hostdir + """ directories = {} for host in sshhosts: m = re.match("^(.*?):(.*)$", host.hostname) @@ -186,9 +140,8 @@ class RSession(AbstractSession): """ def main(self, reporter=None): """ main loop for running tests. """ - args = self.config.remaining + args = self.config.args - session_options.bind_config(self.config) sshhosts, remotepython, rsync_roots = self.read_distributed_config() reporter, startserverflag = self.init_reporter(reporter, sshhosts, RemoteReporter) @@ -198,22 +151,42 @@ class RSession(AbstractSession): pkgdir = self.getpkgdir(args[0]) done_dict = {} - nodes = init_hosts(reporter, sshhosts, pkgdir, - rsync_roots, remotepython, remote_options=remote_options.d, - optimise_localhost=self.optimise_localhost, done_dict=done_dict) - reporter(report.RsyncFinished()) - + hostopts = HostOptions(rsync_roots=rsync_roots, + remote_python=remotepython, + optimise_localhost=self.optimise_localhost) + hostmanager = HostManager(sshhosts, self.config, pkgdir, hostopts) try: - self.dispatch_tests(nodes, args, pkgdir, reporter, checkfun, done_dict) - finally: - teardown_hosts(reporter, [node.channel for node in nodes], nodes, + nodes = hostmanager.init_hosts(reporter, done_dict) + reporter(report.RsyncFinished()) + try: + self.dispatch_tests(nodes, args, pkgdir, reporter, checkfun, done_dict) + except (KeyboardInterrupt, SystemExit): + print >>sys.stderr, "C-c pressed waiting for gateways to teardown..." + channels = [node.channel for node in nodes] + hostmanager.kill_channels(channels) + hostmanager.teardown_gateways(reporter, channels) + print >>sys.stderr, "... Done" + raise + + channels = [node.channel for node in nodes] + hostmanager.teardown_hosts(reporter, channels, nodes, exitfirst=self.config.option.exitfirst) - reporter(report.Nodes(nodes)) - retval = reporter(report.TestFinished()) - self.kill_server(startserverflag) - return retval + reporter(report.Nodes(nodes)) + retval = reporter(report.TestFinished()) + self.kill_server(startserverflag) + return retval + except (KeyboardInterrupt, SystemExit): + reporter(report.InterruptedExecution()) + self.kill_server(startserverflag) + raise + except: + reporter(report.CrashedExecution()) + self.kill_server(startserverflag) + raise def read_distributed_config(self): + """ Read from conftest file the configuration of distributed testing + """ try: rsync_roots = self.config.getvalue("distrsync_roots") except: @@ -221,10 +194,7 @@ class RSession(AbstractSession): sshhosts = [HostInfo(i) for i in self.config.getvalue("disthosts")] parse_directories(sshhosts) - try: - remotepython = self.config.getvalue("dist_remotepython") - except: - remotepython = None + remotepython = self.config.getvalue("dist_remotepython") return sshhosts, remotepython, rsync_roots def dispatch_tests(self, nodes, args, pkgdir, reporter, checkfun, done_dict): @@ -247,14 +217,13 @@ class LSession(AbstractSession): """ def main(self, reporter=None, runner=None): # check out if used options makes any sense - args = self.config.remaining + args = self.config.args sshhosts = [HostInfo('localhost')] # this is just an info to reporter if not self.config.option.nomagic: py.magic.invoke(assertion=1) - session_options.bind_config(self.config) reporter, startserverflag = self.init_reporter(reporter, sshhosts, LocalReporter, args[0]) reporter, checkfun = self.wrap_reporter(reporter) @@ -321,4 +290,8 @@ class LSession(AbstractSession): self.tracer = Tracer(self.docstorage) return apigen_runner else: - return RunnerPolicy[session_options.runner_policy] + if (self.config.getvalue('dist_boxing') or self.config.option.boxing)\ + and not self.config.option.nocapture: + return box_runner + return plain_runner + diff --git a/py/test/rsession/rsession.py.merge.tmp b/py/test/rsession/rsession.py.merge.tmp deleted file mode 100644 index ec2750504..000000000 --- a/py/test/rsession/rsession.py.merge.tmp +++ /dev/null @@ -1,297 +0,0 @@ - -""" Remote session base class -""" - -import os -import py -import sys -import re -import time - -from py.__.test.rsession import report -from py.__.test.rsession.master import \ - setup_slave, MasterNode, dispatch_loop, itemgen, randomgen -from py.__.test.rsession.hostmanage import HostInfo, HostOptions, HostManager - -from py.__.test.rsession.local import local_loop, plain_runner, apigen_runner,\ - box_runner -from py.__.test.rsession.reporter import LocalReporter, RemoteReporter - -class AbstractSession(object): - """ - An abstract session executes collectors/items through a runner. - - """ - def __init__(self, config, optimise_localhost=True): - self.config = config - self.optimise_localhost = optimise_localhost - - def make_colitems(paths, baseon): - # we presume that from the base we can simply get to - # the target paths by joining the basenames - res = [] - for x in paths: - x = py.path.local(x) - current = py.test.collect.Directory(baseon) - relparts = x.relto(baseon).split(x.sep) - assert relparts - for part in relparts: - next = current.join(part) - assert next is not None, (current, part) - current = next - res.append(current) - return res - make_colitems = staticmethod(make_colitems) - - def getpkgdir(path): - path = py.path.local(path) - pkgpath = path.pypkgpath() - if pkgpath is None: - pkgpath = path - return pkgpath - getpkgdir = staticmethod(getpkgdir) - - def init_reporter(self, reporter, sshhosts, reporter_class, arg=""): - """ This initialises so called `reporter` class, which will - handle all event presenting to user. Does not get called - if main received custom reporter - """ - startserverflag = self.config.option.startserver - restflag = self.config.option.restreport - - if startserverflag and reporter is None: - from py.__.test.rsession.web import start_server, exported_methods - if self.config.option.runbrowser: - from socket import INADDR_ANY - port = INADDR_ANY # pick a random port when starting browser - else: - port = 8000 # stick to a fixed port otherwise - - reporter = exported_methods.report - httpd = start_server(server_address = ('', port)) - port = httpd.server_port - if self.config.option.runbrowser: - import webbrowser, thread - # webbrowser.open() may block until the browser finishes or not - url = "http://localhost:%d" % (port,) - thread.start_new_thread(webbrowser.open, (url,)) - elif reporter is None: - if restflag: - from py.__.test.rsession.rest import RestReporter - reporter_class = RestReporter - if arg: - reporter_instance = reporter_class(self.config, sshhosts, self.getpkgdir(arg)) - else: - reporter_instance = reporter_class(self.config, sshhosts) - reporter = reporter_instance.report - else: - startserverflag = False - - return reporter, startserverflag - - def reporterror(reporter, data): - excinfo, item = data - if excinfo is None: - reporter(report.ItemStart(item)) - elif excinfo.type is py.test.Item.Skipped: - reporter(report.SkippedTryiter(excinfo, item)) - else: - reporter(report.FailedTryiter(excinfo, item)) - reporterror = staticmethod(reporterror) - - def kill_server(self, startserverflag): - """ Kill web server - """ - if startserverflag: - from py.__.test.rsession.web import kill_server - kill_server() - - def wrap_reporter(self, reporter): - """ We wrap reporter around, which makes it possible to us to track - number of failures - """ - self.was_failure = False - def new_reporter(event): - if isinstance(event, report.ReceivedItemOutcome) and \ - not event.outcome.passed and \ - not event.outcome.skipped: - self.was_failure = True - return reporter(event) - checkfun = lambda : self.config.option.exitfirst and \ - self.was_failure - # for tests - self.checkfun = checkfun - return new_reporter, checkfun - -def parse_directories(sshhosts): - """ Parse sshadresses of hosts to have distinct hostname/hostdir - """ - directories = {} - for host in sshhosts: - m = re.match("^(.*?):(.*)$", host.hostname) - if m: - host.hostname = m.group(1) - host.relpath = m.group(2) + "-" + host.hostname - else: - host.relpath = "pytestcache-%s" % host.hostname - -class RSession(AbstractSession): - """ Remote version of session - """ - def main(self, reporter=None): - """ main loop for running tests. """ - args = self.config.args - - sshhosts, remotepython, rsync_roots = self.read_distributed_config() - reporter, startserverflag = self.init_reporter(reporter, - sshhosts, RemoteReporter) - reporter, checkfun = self.wrap_reporter(reporter) - - reporter(report.TestStarted(sshhosts)) - - pkgdir = self.getpkgdir(args[0]) - done_dict = {} - hostopts = HostOptions(rsync_roots=rsync_roots, - remote_python=remotepython, - optimise_localhost=self.optimise_localhost) - hostmanager = HostManager(sshhosts, self.config, pkgdir, hostopts) - try: - nodes = hostmanager.init_hosts(reporter, done_dict) - reporter(report.RsyncFinished()) - try: - self.dispatch_tests(nodes, args, pkgdir, reporter, checkfun, done_dict) - except (KeyboardInterrupt, SystemExit): - print >>sys.stderr, "C-c pressed waiting for gateways to teardown..." - channels = [node.channel for node in nodes] - hostmanager.kill_channels(channels) - hostmanager.teardown_gateways(reporter, channels) - print >>sys.stderr, "... Done" - raise - - channels = [node.channel for node in nodes] - hostmanager.teardown_hosts(reporter, channels, nodes, - exitfirst=self.config.option.exitfirst) - reporter(report.Nodes(nodes)) - retval = reporter(report.TestFinished()) - self.kill_server(startserverflag) - return retval - except (KeyboardInterrupt, SystemExit): - reporter(report.InterruptedExecution()) - self.kill_server(startserverflag) - raise - except: - reporter(report.CrashedExecution()) - self.kill_server(startserverflag) - raise - - def read_distributed_config(self): - """ Read from conftest file the configuration of distributed testing - """ - try: - 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.getvalue("disthosts")] - parse_directories(sshhosts) - remotepython = self.config.getvalue("dist_remotepython") - return sshhosts, remotepython, rsync_roots - - def dispatch_tests(self, nodes, args, pkgdir, reporter, checkfun, done_dict): - colitems = self.make_colitems(args, baseon=pkgdir.dirpath()) - keyword = self.config.option.keyword - itemgenerator = itemgen(colitems, reporter, keyword, self.reporterror) - - all_tests = dispatch_loop(nodes, itemgenerator, checkfun) - #if all_tests: - # todo = {} - # for key, value in all_tests.items(): - # if key not in done_dict: - # todo[key] = True - # rg = randomgen(todo, done_dict) - # dispatch_loop(nodes, rg, lambda:False, max_tasks_per_node=1) - - -class LSession(AbstractSession): - """ Local version of session - """ - def main(self, reporter=None, runner=None): - # check out if used options makes any sense - args = self.config.args - - sshhosts = [HostInfo('localhost')] # this is just an info to reporter - - if not self.config.option.nomagic: - py.magic.invoke(assertion=1) - - reporter, startserverflag = self.init_reporter(reporter, - sshhosts, LocalReporter, args[0]) - reporter, checkfun = self.wrap_reporter(reporter) - - reporter(report.TestStarted(sshhosts)) - pkgdir = self.getpkgdir(args[0]) - colitems = self.make_colitems(args, baseon=pkgdir.dirpath()) - reporter(report.RsyncFinished()) - - if runner is None: - runner = self.init_runner(pkgdir) - - keyword = self.config.option.keyword - - itemgenerator = itemgen(colitems, reporter, keyword, self.reporterror) - local_loop(self, reporter, itemgenerator, checkfun, self.config, runner=runner) - - retval = reporter(report.TestFinished()) - self.kill_server(startserverflag) - - if not self.config.option.nomagic: - py.magic.revoke(assertion=1) - - self.write_docs(pkgdir) - return retval - - def write_docs(self, pkgdir): - if self.config.option.apigen: - from py.__.apigen.tracer.docstorage import DocStorageAccessor - apigen = py.path.local(self.config.option.apigen).pyimport() - print >>sys.stderr, 'building documentation' - capture = py.io.OutErrCapture() - try: - try: - apigen.build(pkgdir, DocStorageAccessor(self.docstorage)) - except (ValueError, AttributeError): - #import traceback - #exc, e, tb = sys.exc_info() - #print '%s - %s' % (exc, e) - #print ''.join(traceback.format_tb(tb)) - #del tb - #print '-' * 79 - raise NotImplementedError("Provided script does not seem " - "to contain build function") - finally: - capture.reset() - - def init_runner(self, pkgdir): - if self.config.option.apigen: - from py.__.apigen.tracer.tracer import Tracer, DocStorage - module = py - try: - apigen = py.path.local(self.config.option.apigen).pyimport() - items = apigen.get_documentable_items(pkgdir) - if isinstance(items, dict): - self.docstorage = DocStorage().from_dict(items) - else: - self.docstorage = DocStorage().from_pkg(items) - except ImportError: - raise ImportError("Provided script cannot be imported") - except (ValueError, AttributeError): - raise NotImplementedError("Provided script does not seem " - "to contain get_documentable_items") - self.tracer = Tracer(self.docstorage) - return apigen_runner - else: - if (self.config.getvalue('dist_boxing') or self.config.option.boxing)\ - and not self.config.option.nocapture: - return box_runner - return plain_runner - diff --git a/py/test/rsession/rsync.py b/py/test/rsession/rsync.py deleted file mode 100644 index bfa873e5c..000000000 --- a/py/test/rsession/rsync.py +++ /dev/null @@ -1,137 +0,0 @@ -import py, os, stat, md5 -from Queue import Queue - - -class RSync(object): - - def __init__(self, callback=None, **options): - for name in options: - assert name in ('delete') - self.options = options - self.callback = callback - self.channels = {} - self.receivequeue = Queue() - self.links = [] - - def filter(self, path): - return True - - def add_target(self, gateway, destdir, finishedcallback=None): - def itemcallback(req): - self.receivequeue.put((channel, req)) - channel = gateway.remote_exec(REMOTE_SOURCE) - channel.setcallback(itemcallback, endmarker = None) - channel.send((str(destdir), self.options)) - self.channels[channel] = finishedcallback - - def send(self, sourcedir): - self.sourcedir = str(sourcedir) - # normalize a trailing '/' away - self.sourcedir = os.path.dirname(os.path.join(self.sourcedir, 'x')) - # send directory structure and file timestamps/sizes - self._send_directory_structure(self.sourcedir) - - # paths and to_send are only used for doing - # progress-related callbacks - self.paths = {} - self.to_send = {} - - # send modified file to clients - while self.channels: - channel, req = self.receivequeue.get() - if req is None: - # end-of-channel - if channel in self.channels: - # too early! we must have got an error - channel.waitclose() - # or else we raise one - raise IOError('connection unexpectedly closed: %s ' % ( - channel.gateway,)) - else: - command, data = req - if command == "links": - for link in self.links: - channel.send(link) - # completion marker, this host is done - channel.send(42) - elif command == "done": - finishedcallback = self.channels.pop(channel) - if finishedcallback: - finishedcallback() - elif command == "ack": - if self.callback: - self.callback("ack", self.paths[data], channel) - elif command == "list_done": - # sum up all to send - if self.callback: - s = sum([self.paths[i] for i in self.to_send[channel]]) - self.callback("list", s, channel) - elif command == "send": - modified_rel_path, checksum = data - modifiedpath = os.path.join(self.sourcedir, *modified_rel_path) - f = open(modifiedpath, 'rb') - data = f.read() - - # provide info to progress callback function - modified_rel_path = "/".join(modified_rel_path) - self.paths[modified_rel_path] = len(data) - if channel not in self.to_send: - self.to_send[channel] = [] - self.to_send[channel].append(modified_rel_path) - - f.close() - if checksum is not None and checksum == md5.md5(data).digest(): - data = None # not really modified - else: - # ! there is a reason for the interning: - # sharing multiple copies of the file's data - data = intern(data) - print '%s <= %s' % ( - channel.gateway._getremoteaddress(), - modified_rel_path) - channel.send(data) - del data - else: - assert "Unknown command %s" % command - - def _broadcast(self, msg): - for channel in self.channels: - channel.send(msg) - - def _send_link(self, basename, linkpoint): - self.links.append(("link", basename, linkpoint)) - - def _send_directory_structure(self, path): - st = os.lstat(path) - if stat.S_ISREG(st.st_mode): - # regular file: send a timestamp/size pair - self._broadcast((st.st_mtime, st.st_size)) - elif stat.S_ISDIR(st.st_mode): - # dir: send a list of entries - names = [] - subpaths = [] - for name in os.listdir(path): - p = os.path.join(path, name) - if self.filter(p): - names.append(name) - subpaths.append(p) - self._broadcast(names) - for p in subpaths: - self._send_directory_structure(p) - elif stat.S_ISLNK(st.st_mode): - linkpoint = os.readlink(path) - basename = path[len(self.sourcedir) + 1:] - if not linkpoint.startswith(os.sep): - # relative link, just send it - self._send_link(basename, linkpoint) - elif linkpoint.startswith(self.sourcedir): - self._send_link(basename, linkpoint[len(self.sourcedir) + 1:]) - else: - self._send_link(basename, linkpoint) - self._broadcast(None) - else: - raise ValueError, "cannot sync %r" % (path,) - -REMOTE_SOURCE = py.path.local(__file__).dirpath().\ - join('rsync_remote.py').open().read() + "\nf()" - diff --git a/py/test/rsession/slave.py b/py/test/rsession/slave.py index aa8f1d19c..8fec1ca35 100644 --- a/py/test/rsession/slave.py +++ b/py/test/rsession/slave.py @@ -5,28 +5,65 @@ Node code for slaves. import py from py.__.test.rsession.executor import RunExecutor, BoxExecutor, AsyncExecutor from py.__.test.rsession.outcome import Outcome +import thread +import os -class Info: - pid = None +class PidInfo(object): + """ Pure container class to store information of actually running + pid + """ + def __init__(self): + self.pid = 0 + self.lock = thread.allocate_lock() + + def set_pid(self, pid): + self.lock.acquire() + try: + self.pid = pid + finally: + self.lock.release() + + def kill(self): + self.lock.acquire() + try: + if self.pid: + os.kill(self.pid, 15) + self.pid = 0 + finally: + self.lock.release() + + def waitandclear(self, pid, num): + """ This is an obscure hack to keep locking properly, adhere to posix semantics + and try to clean it as much as possible, not clean at all + """ + self.lock.acquire() + try: + retval = os.waitpid(self.pid, 0) + self.pid = 0 + return retval + finally: + self.lock.release() class SlaveNode(object): - def __init__(self, rootcollector, executor=AsyncExecutor): + def __init__(self, rootcollector, config, pidinfo, executor=AsyncExecutor): self.rootcollector = rootcollector + self.config = config self.executor = executor + self.pidinfo = pidinfo def execute(self, itemspec): item = self.rootcollector.getitembynames(itemspec) #if isinstance(item, py.test.Function): # ex = Executor(item.obj, setup=item.setup) #else: - ex = self.executor(item) + ex = self.executor(item, config=self.config) if self.executor is AsyncExecutor: cont, pid = ex.execute() + self.pidinfo.set_pid(pid) else: # for tests only return ex.execute() - Info.pid = pid - return cont() + return cont(self.pidinfo.waitandclear) def run(self, itemspec): #outcome = self.execute(itemspec) @@ -35,9 +72,9 @@ class SlaveNode(object): if self.executor.wraps: return outcome else: - return outcome.make_repr() + return outcome.make_repr(self.config.option.tbstyle) -def slave_main(receive, send, path, info = None): +def slave_main(receive, send, path, config, pidinfo): import os assert os.path.exists(path) path = os.path.abspath(path) @@ -47,7 +84,7 @@ def slave_main(receive, send, path, info = None): if node is not None: return node col = py.test.collect.Directory(str(py.path.local(path).join(item[0]))) - node = nodes[item[0]] = SlaveNode(col) + node = nodes[item[0]] = SlaveNode(col, config, pidinfo) return node while 1: nextitem = receive() @@ -62,8 +99,7 @@ def slave_main(receive, send, path, info = None): excinfo = py.code.ExceptionInfo() send(Outcome(excinfo=excinfo, is_critical=True).make_repr()) else: - from py.__.test.rsession.rsession import remote_options - if not res[0] and not res[3] and remote_options.exitfirst: + if not res[0] and not res[3] and config.option.exitfirst: # we're finished, but need to eat what we can send(res) break @@ -71,43 +107,42 @@ def slave_main(receive, send, path, info = None): while nextitem is not None: nextitem = receive() - + def setup(): - def callback_gen(queue): - from py.__.test.rsession.slave import Info + def callback_gen(channel, queue, info): def callback(item): if item == 42: # magic call-cleanup # XXX should kill a pid here - if Info.pid: - os.kill(Info.pid, 15) + info.kill() + channel.close() sys.exit(0) queue.put(item) return callback import os, sys - from Queue import Queue pkgdir = channel.receive() # path is ready - options = channel.receive() # options stuff, should be dictionary + config_repr = channel.receive() basedir = os.path.dirname(pkgdir) pkgname = os.path.basename(pkgdir) # setup defaults... sys.path.insert(0, basedir) import py - options['we_are_remote'] = True - from py.__.test.rsession.rsession import RemoteOptions - from py.__.test.rsession.slave import Info - Info.pid = 0 - from py.__.test.rsession import rsession - rsession.remote_options = RemoteOptions(options) - # XXX the following assumes that py lib is there, a bit - # much of an assumtion - if not rsession.remote_options.nomagic: + config = py.test.config + if config._initialized: + config = config._reparse([basedir]) + config.merge_repr(config_repr) + else: + config.initdirect(basedir, config_repr) + #config.conftest.lget('adddefaultoptions')() + if not config.option.nomagic: py.magic.invoke(assertion=1) mod = __import__(pkgname) assert py.path.local(mod.__file__).dirpath() == py.path.local(pkgdir) - from py.__.test.rsession.slave import slave_main - queue = Queue() - channel.setcallback(callback_gen(queue)) - slave_main(queue.get, channel.send, basedir) - if not rsession.remote_options.nomagic: + from py.__.test.rsession.slave import slave_main, PidInfo + queue = py.std.Queue.Queue() + pidinfo = PidInfo() + channel.setcallback(callback_gen(channel, queue, pidinfo)) + slave_main(queue.get, channel.send, basedir, config, pidinfo) + if not config.option.nomagic: py.magic.revoke(assertion=1) + channel.close() diff --git a/py/test/rsession/testing/test_boxing.py b/py/test/rsession/testing/test_boxing.py index 37c2207bd..c3eecd1c7 100644 --- a/py/test/rsession/testing/test_boxing.py +++ b/py/test/rsession/testing/test_boxing.py @@ -9,17 +9,16 @@ if sys.platform == 'win32': from py.__.test.rsession.box import Box from py.__.test.rsession.testing import example2 -from py.__.test.rsession.conftest import option def setup_module(mod): - from py.__.test.rsession.rsession import remote_options - remote_options['nice_level'] = 0 + mod.rootdir = py.path.local(py.__file__).dirpath().dirpath() + mod.config = py.test.config._reparse([mod.rootdir]) def test_basic_boxing(): # XXX: because we do not have option transfer ## if not hasattr(option, 'nocapture') or not option.nocapture: ## py.test.skip("Interacts with pylib i/o skipping which is bad actually") - b = Box(example2.boxf1) + b = Box(example2.boxf1, config=config) b.run() assert b.stdoutrepr == "some out\n" assert b.stderrrepr == "some err\n" @@ -28,7 +27,7 @@ def test_basic_boxing(): assert b.retval == 1 def test_boxing_on_fds(): - b = Box(example2.boxf2) + b = Box(example2.boxf2, config=config) b.run() assert b.stdoutrepr == "someout" assert b.stderrrepr == "someerr" @@ -37,13 +36,13 @@ def test_boxing_on_fds(): assert b.retval == 2 def test_boxing_signal(): - b = Box(example2.boxseg) + b = Box(example2.boxseg, config=config) b.run() assert b.signal == 11 assert b.retval is None def test_boxing_huge_data(): - b = Box(example2.boxhuge) + b = Box(example2.boxhuge, config=config) b.run() assert b.stdoutrepr assert b.exitstat == 0 @@ -53,7 +52,7 @@ def test_boxing_huge_data(): def test_box_seq(): # we run many boxes with huge data, just one after another for i in xrange(100): - b = Box(example2.boxhuge) + b = Box(example2.boxhuge, config=config) b.run() assert b.stdoutrepr assert b.exitstat == 0 @@ -62,13 +61,13 @@ def test_box_seq(): def test_box_in_a_box(): def boxfun(): - b = Box(example2.boxf2) + b = Box(example2.boxf2, config=config) b.run() print b.stdoutrepr print >>sys.stderr, b.stderrrepr return b.retval - b = Box(boxfun) + b = Box(boxfun, config=config) b.run() assert b.stdoutrepr == "someout\n" assert b.stderrrepr == "someerr\n" @@ -77,8 +76,6 @@ def test_box_in_a_box(): assert b.retval == 2 def test_box_killer(): - if option.skip_kill_test: - py.test.skip('skipping kill test') class A: pass info = A() @@ -87,7 +84,7 @@ def test_box_killer(): def box_fun(): time.sleep(10) # we don't want to last forever here - b = Box(box_fun) + b = Box(box_fun, config=config) par, pid = b.run(continuation=True) os.kill(pid, 15) par(pid) diff --git a/py/test/rsession/testing/test_config.py b/py/test/rsession/testing/test_config.py deleted file mode 100644 index 0ae714bf1..000000000 --- a/py/test/rsession/testing/test_config.py +++ /dev/null @@ -1,24 +0,0 @@ - -""" test session config options -""" - -import py -from py.__.test.rsession.rsession import session_options, SessionOptions,\ - remote_options - -def test_session_opts(): - tmpdir = py.test.ensuretemp("sessionopts") - tmpdir.ensure("conftest.py").write("""class SessionOptions: - max_tasks_per_node = 5 - nice_level = 10 - """) - tmp2 = py.test.ensuretemp("xxx") - args = [str(tmpdir)] - 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 = py.test.config._reparse([str(tmp2)]) - session_options.bind_config(config) - assert session_options.max_tasks_per_node == \ - SessionOptions.defaults['max_tasks_per_node'] diff --git a/py/test/rsession/testing/test_executor.py b/py/test/rsession/testing/test_executor.py index 9ee9e9796..713a37673 100644 --- a/py/test/rsession/testing/test_executor.py +++ b/py/test/rsession/testing/test_executor.py @@ -10,8 +10,7 @@ from py.__.test.rsession.testing.test_slave import funcprint_spec, \ def setup_module(mod): mod.rootdir = py.path.local(py.__file__).dirpath().dirpath() - from py.__.test.rsession.rsession import remote_options - remote_options['nice_level'] = 0 + mod.config = py.test.config._reparse([mod.rootdir]) def XXXtest_executor_passing_function(): ex = Executor(example1.f1) @@ -61,32 +60,32 @@ class ItemTestSkipping(py.test.Item): py.test.skip("hello") def test_run_executor(): - ex = RunExecutor(ItemTestPassing("pass")) + ex = RunExecutor(ItemTestPassing("pass"), config=config) outcome = ex.execute() assert outcome.passed - ex = RunExecutor(ItemTestFailing("fail")) + ex = RunExecutor(ItemTestFailing("fail"), config=config) outcome = ex.execute() assert not outcome.passed - ex = RunExecutor(ItemTestSkipping("skip")) + ex = RunExecutor(ItemTestSkipping("skip"), config=config) outcome = ex.execute() assert outcome.skipped assert not outcome.passed assert not outcome.excinfo def test_box_executor(): - ex = BoxExecutor(ItemTestPassing("pass")) + ex = BoxExecutor(ItemTestPassing("pass"), config=config) outcome_repr = ex.execute() outcome = ReprOutcome(outcome_repr) assert outcome.passed - ex = BoxExecutor(ItemTestFailing("fail")) + ex = BoxExecutor(ItemTestFailing("fail"), config=config) outcome_repr = ex.execute() outcome = ReprOutcome(outcome_repr) assert not outcome.passed - ex = BoxExecutor(ItemTestSkipping("skip")) + ex = BoxExecutor(ItemTestSkipping("skip"), config=config) outcome_repr = ex.execute() outcome = ReprOutcome(outcome_repr) assert outcome.skipped @@ -96,7 +95,7 @@ def test_box_executor(): def test_box_executor_stdout(): rootcol = py.test.collect.Directory(rootdir) item = rootcol.getitembynames(funcprint_spec) - ex = BoxExecutor(item) + ex = BoxExecutor(item, config=config) outcome_repr = ex.execute() outcome = ReprOutcome(outcome_repr) assert outcome.passed @@ -105,7 +104,7 @@ def test_box_executor_stdout(): def test_box_executor_stdout_error(): rootcol = py.test.collect.Directory(rootdir) item = rootcol.getitembynames(funcprintfail_spec) - ex = BoxExecutor(item) + ex = BoxExecutor(item, config=config) outcome_repr = ex.execute() outcome = ReprOutcome(outcome_repr) assert not outcome.passed @@ -114,7 +113,7 @@ def test_box_executor_stdout_error(): def test_cont_executor(): rootcol = py.test.collect.Directory(rootdir) item = rootcol.getitembynames(funcprintfail_spec) - ex = AsyncExecutor(item) + ex = AsyncExecutor(item, config=config) cont, pid = ex.execute() assert pid outcome_repr = cont() diff --git a/py/test/rsession/testing/test_lsession.py b/py/test/rsession/testing/test_lsession.py index 285c40e96..db12b8305 100644 --- a/py/test/rsession/testing/test_lsession.py +++ b/py/test/rsession/testing/test_lsession.py @@ -5,7 +5,7 @@ import py from py.__.test.rsession.rsession import LSession from py.__.test.rsession import report -from py.__.test.rsession.local import box_runner, plain_runner +from py.__.test.rsession.local import box_runner, plain_runner, apigen_runner def setup_module(mod): mod.tmp = py.test.ensuretemp("lsession_module") @@ -82,22 +82,26 @@ class TestLSession(object): l = [] def some_fun(*args): l.append(args) - - pdb.post_mortem = some_fun - args = [str(tmpdir.join(subdir)), '--pdb'] - config = py.test.config._reparse(args) - lsession = LSession(config) - allevents = [] + try: - lsession.main(reporter=allevents.append, runner=plain_runner) - except SystemExit: - pass - else: - py.test.fail("Didn't raise system exit") - failure_events = [event for event in allevents if isinstance(event, - report.ImmediateFailure)] - assert len(failure_events) == 1 - assert len(l) == 1 + post_mortem = pdb.post_mortem + pdb.post_mortem = some_fun + args = [str(tmpdir.join(subdir)), '--pdb'] + config = py.test.config._reparse(args) + lsession = LSession(config) + allevents = [] + try: + lsession.main(reporter=allevents.append, runner=plain_runner) + except SystemExit: + pass + else: + py.test.fail("Didn't raise system exit") + failure_events = [event for event in allevents if isinstance(event, + report.ImmediateFailure)] + assert len(failure_events) == 1 + assert len(l) == 1 + finally: + pdb.post_mortem = post_mortem def test_minus_x(self): if not hasattr(py.std.os, 'fork'): @@ -262,3 +266,31 @@ class TestLSession(object): assert testevents[0].outcome.passed assert testevents[0].outcome.stderr == "" assert testevents[0].outcome.stdout == "1\n2\n3\n" + + def test_runner_selection(self): + tmpdir = py.test.ensuretemp("lsession_runner_selection") + tmpdir.ensure("apigen.py").write(py.code.Source(""" + def get_documentable_items(*args): + return {} + """)) + opt_mapping = { + '': plain_runner, + '--box': box_runner, + '--apigen=%s/apigen.py' % str(tmpdir): apigen_runner, + } + pkgdir = tmpdir.dirpath() + for opt in opt_mapping.keys(): + if opt: + all = opt + " " + str(tmpdir) + else: + all = str(tmpdir) + config = py.test.config._reparse(all.split(" ")) + lsession = LSession(config) + assert lsession.init_runner(pkgdir) is opt_mapping[opt] + #tmpdir.dirpath().ensure("conftest.py").write(py.code.Source(""" + #dist_boxing=True + #""")) + #config = py.test.config._reparse([str(tmpdir)]) + #lsession = LSession(config) + #assert lsession.init_runner(pkgdir) is box_runner + # XXX check why it fails diff --git a/py/test/rsession/testing/test_master.py b/py/test/rsession/testing/test_master.py index 9c32d39f0..2febae6f0 100644 --- a/py/test/rsession/testing/test_master.py +++ b/py/test/rsession/testing/test_master.py @@ -11,17 +11,14 @@ if sys.platform == 'win32': from py.__.test.rsession.master import dispatch_loop, setup_slave, MasterNode, randomgen from py.__.test.rsession.outcome import ReprOutcome, Outcome -from py.__.test.rsession.testing.test_slave import funcpass_spec, funcfail_spec +from py.__.test.rsession.testing.test_slave import funcpass_spec, funcfail_spec, funchang_spec from py.__.test.rsession import report -from py.__.test.rsession.rsession import session_options, remote_options from py.__.test.rsession.hostmanage import HostInfo def setup_module(mod): # bind an empty config config = py.test.config._reparse([]) - config.option.max_tasks_per_node = 10 - session_options.bind_config(config) - #assert not remote_options.exitfirst + config._overwrite('dist_taskspernode', 10) mod.pkgdir = py.path.local(py.__file__).dirpath() class DummyGateway(object): @@ -92,11 +89,12 @@ def test_dispatch_loop(): def test_slave_setup(): gw = py.execnet.PopenGateway() - channel = setup_slave(gw, pkgdir, remote_options.d) + config = py.test.config._reparse([]) + channel = setup_slave(gw, pkgdir, config) channel.send(funcpass_spec) output = ReprOutcome(channel.receive()) assert output.passed - channel.send(None) + channel.send(42) channel.waitclose(10) gw.exit() @@ -114,7 +112,8 @@ def test_slave_running(): gw = py.execnet.PopenGateway() gw.host = HostInfo("localhost") gw.host.gw = gw - channel = setup_slave(gw, pkgdir, remote_options.d) + config = py.test.config._reparse([]) + channel = setup_slave(gw, pkgdir, config) mn = MasterNode(channel, simple_report, {}) return mn @@ -127,6 +126,34 @@ def test_slave_running(): shouldstop = lambda : False dispatch_loop(master_nodes, itemgenerator, shouldstop) +def test_slave_running_interrupted(): + #def simple_report(event): + # if not isinstance(event, report.ReceivedItemOutcome): + # return + # item = event.item + # if item.code.name == 'funcpass': + # assert event.outcome.passed + # else: + # assert not event.outcome.passed + reports = [] + + def open_gw(): + gw = py.execnet.PopenGateway() + gw.host = HostInfo("localhost") + gw.host.gw = gw + config = py.test.config._reparse([]) + channel = setup_slave(gw, pkgdir, config) + mn = MasterNode(channel, reports.append, {}) + return mn, gw, channel + + mn, gw, channel = open_gw() + rootcol = py.test.collect.Directory(pkgdir.dirpath()) + funchang_item = rootcol.getitembynames(funchang_spec) + mn.send(funchang_item) + mn.send(StopIteration) + # XXX: We have to wait here a bit to make sure that it really did happen + channel.waitclose(2) + def test_randomgen(): d = {} gen = randomgen({1:True, 2:True, 3:True}, d) diff --git a/py/test/rsession/testing/test_outcome.py b/py/test/rsession/testing/test_outcome.py index 5f1a92401..bc79df42c 100644 --- a/py/test/rsession/testing/test_outcome.py +++ b/py/test/rsession/testing/test_outcome.py @@ -28,7 +28,7 @@ def test_exception_info_repr(): except: outcome = Outcome(excinfo=py.code.ExceptionInfo()) - repr = outcome.make_excinfo_repr() + repr = outcome.make_excinfo_repr("long") assert marshal.dumps(repr) excinfo = ExcInfoRepr(repr) diff --git a/py/test/rsession/testing/test_reporter.py b/py/test/rsession/testing/test_reporter.py index f82ec9038..5a9212bbc 100644 --- a/py/test/rsession/testing/test_reporter.py +++ b/py/test/rsession/testing/test_reporter.py @@ -166,11 +166,12 @@ class AbstractTestReporter(object): r.report(report.HostReady(hosts[2])) out, err = cap.reset() assert not err - expected = """================= Test started, hosts: host1, host2, host3 ================== - host1: READY (still 2 to go) + expected1 = "Test started, hosts: host1, host2, host3" + expected2 = """host1: READY (still 2 to go) host2: READY (still 1 to go) host3: READY""" - assert out.find(expected) != -1 + assert out.find(expected1) != -1 + assert out.find(expected2) != -1 class TestLocalReporter(AbstractTestReporter): reporter = LocalReporter @@ -181,8 +182,9 @@ class TestLocalReporter(AbstractTestReporter): def test_module(self): #py.test.skip("XXX rewrite test to not rely on exact formatting") - assert self._test_module().endswith("test_slave.py[9] FsF."),\ - self._test_module() + output = self._test_module() + assert output.find("test_slave") != -1 + assert output.endswith("FsF."), output def test_full_module(self): #py.test.skip("XXX rewrite test to not rely on exact formatting") @@ -202,20 +204,20 @@ class TestRemoteReporter(AbstractTestReporter): def test_report_received_item_outcome(self): #py.test.skip("XXX rewrite test to not rely on exact formatting") val = self.report_received_item_outcome() - expected = """ localhost: FAILED py test rsession testing test_slave.py funcpass - localhost: SKIPPED py test rsession testing test_slave.py funcpass - localhost: FAILED py test rsession testing test_slave.py funcpass - localhost: PASSED py test rsession testing test_slave.py funcpass + expected = """ localhost: FAILED py.test.rsession.testing.test_slave.py funcpass + localhost: SKIPPED py.test.rsession.testing.test_slave.py funcpass + localhost: FAILED py.test.rsession.testing.test_slave.py funcpass + localhost: PASSED py.test.rsession.testing.test_slave.py funcpass """ assert val.find(expected) != -1 def test_module(self): val = self._test_module() print val - expected = """ localhost: FAILED py test rsession testing test_slave.py funcpass - localhost: SKIPPED py test rsession testing test_slave.py funcpass - localhost: FAILED py test rsession testing test_slave.py funcpass - localhost: PASSED py test rsession testing test_slave.py funcpass + expected = """ localhost: FAILED py.test.rsession.testing.test_slave.py funcpass + localhost: SKIPPED py.test.rsession.testing.test_slave.py funcpass + localhost: FAILED py.test.rsession.testing.test_slave.py funcpass + localhost: PASSED py.test.rsession.testing.test_slave.py funcpass """ assert val.find(expected) != -1 diff --git a/py/test/rsession/testing/test_rest.py b/py/test/rsession/testing/test_rest.py index 3621ce127..f24561913 100644 --- a/py/test/rsession/testing/test_rest.py +++ b/py/test/rsession/testing/test_rest.py @@ -10,6 +10,8 @@ from py.__.test.rsession.rest import RestReporter, NoLinkWriter from py.__.rest.rst import * from py.__.test.rsession.hostmanage import HostInfo +py.test.skip("This tests are not really testing, needs rewrite") + class RestTestReporter(RestReporter): def __init__(self, *args, **kwargs): if args: diff --git a/py/test/rsession/testing/test_rsession.py b/py/test/rsession/testing/test_rsession.py index 701ab0a52..416a4c14d 100644 --- a/py/test/rsession/testing/test_rsession.py +++ b/py/test/rsession/testing/test_rsession.py @@ -5,12 +5,12 @@ import py from py.__.test.rsession import report from py.__.test.rsession.rsession import RSession, parse_directories,\ - session_options, remote_options, parse_directories -from py.__.test.rsession.hostmanage import init_hosts, teardown_hosts,\ + parse_directories +from py.__.test.rsession.hostmanage import HostOptions, HostManager,\ HostInfo from py.__.test.rsession.testing.test_slave import funcfail_spec,\ funcpass_spec, funcskip_spec, funcprint_spec, funcprintfail_spec, \ - funcoptioncustom_spec, funcoption_spec + funcoptioncustom_spec def setup_module(mod): mod.pkgdir = py.path.local(py.__file__).dirpath() @@ -18,7 +18,8 @@ def setup_module(mod): def test_setup_non_existing_hosts(): setup_events = [] hosts = [HostInfo("alskdjalsdkjasldkajlsd")] - cmd = "init_hosts(setup_events.append, hosts, pkgdir)" + hm = HostManager(hosts, None, pkgdir) + cmd = "hm.init_hosts(setup_events.append)" py.test.raises((py.process.cmdexec.Error, IOError, EOFError), cmd) #assert setup_events @@ -105,7 +106,7 @@ class TestRSessionRemote: tmpdir = py.test.ensuretemp("example_distribution") tmpdir.ensure(subdir, "conftest.py").write(py.code.Source(""" disthosts = [%r] - distrsync_roots = ["%s"] + distrsync_roots = ["%s", "py"] """ % ('localhost', subdir))) tmpdir.ensure(subdir, "__init__.py") tmpdir.ensure(subdir, "test_one.py").write(py.code.Source(""" @@ -119,7 +120,11 @@ class TestRSessionRemote: pass def test_5(): assert __file__ != '%s' - """ % str(tmpdir.join(subdir)))) + def test_6(): + import py + assert py.__file__ != '%s' + """ % (str(tmpdir.join(subdir)), py.__file__))) + tmpdir.join("py").mksymlinkto(py.path.local(py.__file__).dirpath()) args = [str(tmpdir.join(subdir))] config = py.test.config._reparse(args) rsession = RSession(config, optimise_localhost=False) @@ -131,21 +136,21 @@ class TestRSessionRemote: passevents = [i for i in testevents if i.outcome.passed] failevents = [i for i in testevents if i.outcome.excinfo] skippedevents = [i for i in testevents if i.outcome.skipped] - assert len(testevents) == 5 - assert len(passevents) == 2 + assert len(testevents) == 6 + assert len(passevents) == 3 assert len(failevents) == 3 tb = failevents[0].outcome.excinfo.traceback - assert tb[0].path.find("test_one") != -1 + assert str(tb[0].path).find("test_one") != -1 assert tb[0].source.find("test_2") != -1 assert failevents[0].outcome.excinfo.typename == 'AssertionError' tb = failevents[1].outcome.excinfo.traceback - assert tb[0].path.find("test_one") != -1 + assert str(tb[0].path).find("test_one") != -1 assert tb[0].source.find("test_3") != -1 assert failevents[1].outcome.excinfo.typename == 'ValueError' assert failevents[1].outcome.excinfo.value == '23' tb = failevents[2].outcome.excinfo.traceback assert failevents[2].outcome.excinfo.typename == 'TypeError' - assert tb[0].path.find("executor") != -1 + assert str(tb[0].path).find("executor") != -1 assert tb[0].source.find("execute") != -1 def test_setup_teardown_ssh(self): @@ -155,10 +160,10 @@ class TestRSessionRemote: teardown_events = [] 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) - teardown_hosts(teardown_events.append, + opts = HostOptions(optimise_localhost=False, rsync_roots=['py']) + hm = HostManager(hosts, config, pkgdir, opts) + nodes = hm.init_hosts(setup_events.append) + hm.teardown_hosts(teardown_events.append, [node.channel for node in nodes], nodes) count_rsyn_calls = [i for i in setup_events @@ -182,9 +187,9 @@ class TestRSessionRemote: allevents = [] 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) + opts = HostOptions(optimise_localhost=False, rsync_roots=['py']) + hm = HostManager(hosts, config, pkgdir, opts) + nodes = hm.init_hosts(allevents.append) from py.__.test.rsession.testing.test_executor \ import ItemTestPassing, ItemTestFailing, ItemTestSkipping @@ -202,7 +207,7 @@ class TestRSessionRemote: node.send(itemskip) node.send(itemprint) - teardown_hosts(allevents.append, [node.channel for node in nodes], nodes) + hm.teardown_hosts(allevents.append, [node.channel for node in nodes], nodes) events = [i for i in allevents if isinstance(i, report.ReceivedItemOutcome)] @@ -224,31 +229,33 @@ class TestRSessionRemote: hosts = [HostInfo('localhost')] parse_directories(hosts) config = py.test.config._reparse([]) - session_options.bind_config(config) - d = remote_options.d.copy() - d['custom'] = 'custom' - nodes = init_hosts(allevents.append, hosts, pkgdir, - rsync_roots=["py"], remote_options=d, - optimise_localhost=False) - - rootcol = py.test.collect.Directory(pkgdir.dirpath()) - itempass = rootcol.getitembynames(funcoption_spec) - itempassaswell = rootcol.getitembynames(funcoptioncustom_spec) - - for node in nodes: - node.send(itempass) - node.send(itempassaswell) - - teardown_hosts(allevents.append, [node.channel for node in nodes], nodes) - events = [i for i in allevents - if isinstance(i, report.ReceivedItemOutcome)] - passed = [i for i in events - if i.outcome.passed] - skipped = [i for i in events - if i.outcome.skipped] - assert len(passed) == 2 * len(nodes) - assert len(skipped) == 0 - assert len(events) == len(passed) + config._overwrite('custom', 'custom') + # we need to overwrite default list to serialize + from py.__.test.rsession.master import defaultconftestnames + defaultconftestnames.append("custom") + try: + opts = HostOptions(optimise_localhost=False, rsync_roots=['py']) + hm = HostManager(hosts, config, pkgdir, opts) + nodes = hm.init_hosts(allevents.append) + + rootcol = py.test.collect.Directory(pkgdir.dirpath()) + itempass = rootcol.getitembynames(funcoptioncustom_spec) + + for node in nodes: + node.send(itempass) + + hm.teardown_hosts(allevents.append, [node.channel for node in nodes], nodes) + events = [i for i in allevents + if isinstance(i, report.ReceivedItemOutcome)] + passed = [i for i in events + if i.outcome.passed] + skipped = [i for i in events + if i.outcome.skipped] + assert len(passed) == 1 * len(nodes) + assert len(skipped) == 0 + assert len(events) == len(passed) + finally: + defaultconftestnames.remove("custom") def test_nice_level(self): """ Tests if nice level behaviour is ok @@ -258,14 +265,16 @@ class TestRSessionRemote: parse_directories(hosts) tmpdir = py.test.ensuretemp("nice") tmpdir.ensure("__init__.py") - tmpdir.ensure("conftest.py").write("""disthosts = ['localhost']""") + tmpdir.ensure("conftest.py").write(py.code.Source(""" + disthosts = ['localhost'] + dist_nicelevel = 10 + """)) tmpdir.ensure("test_one.py").write("""def test_nice(): import os assert os.nice(0) == 10 """) config = py.test.config._reparse([tmpdir]) - config.option.nice_level = 10 rsession = RSession(config) allevents = [] rsession.main(reporter=allevents.append) @@ -298,7 +307,10 @@ class TestInithosts(object): hostnames = ['h1:/tmp', 'h1:/tmp', 'h1:/other', 'h2', 'h2:home'] hosts = [HostInfo(i) for i in hostnames] parse_directories(hosts) - init_hosts(testevents.append, hosts, pkgdir, do_sync=False) + config = py.test.config._reparse([]) + opts = HostOptions(do_sync=False, create_gateways=False) + hm = HostManager(hosts, config, pkgdir, opts) + nodes = hm.init_hosts(testevents.append) events = [i for i in testevents if isinstance(i, report.HostRSyncing)] assert len(events) == 4 assert events[0].host.hostname == 'h1' diff --git a/py/test/rsession/testing/test_rsession.py.merge.tmp b/py/test/rsession/testing/test_rsession.py.merge.tmp deleted file mode 100644 index 416a4c14d..000000000 --- a/py/test/rsession/testing/test_rsession.py.merge.tmp +++ /dev/null @@ -1,324 +0,0 @@ - -""" Tests various aspects of rsession, like ssh hosts setup/teardown -""" - -import py -from py.__.test.rsession import report -from py.__.test.rsession.rsession import RSession, parse_directories,\ - parse_directories -from py.__.test.rsession.hostmanage import HostOptions, HostManager,\ - HostInfo -from py.__.test.rsession.testing.test_slave import funcfail_spec,\ - funcpass_spec, funcskip_spec, funcprint_spec, funcprintfail_spec, \ - funcoptioncustom_spec - -def setup_module(mod): - mod.pkgdir = py.path.local(py.__file__).dirpath() - -def test_setup_non_existing_hosts(): - setup_events = [] - hosts = [HostInfo("alskdjalsdkjasldkajlsd")] - hm = HostManager(hosts, None, pkgdir) - cmd = "hm.init_hosts(setup_events.append)" - py.test.raises((py.process.cmdexec.Error, IOError, EOFError), cmd) - #assert setup_events - -def test_getpkdir(): - one = pkgdir.join("initpkg.py") - two = pkgdir.join("path", "__init__.py") - p1 = RSession.getpkgdir(one) - p2 = RSession.getpkgdir(two) - assert p1 == p2 - assert p1 == pkgdir - -def test_getpkdir_no_inits(): - tmp = py.test.ensuretemp("getpkdir1") - fn = tmp.ensure("hello.py") - assert RSession.getpkgdir(fn) == fn - -def test_make_colitems(): - one = pkgdir.join("initpkg.py") - two = pkgdir.join("path", "__init__.py") - - cols = RSession.make_colitems([one, two], baseon=pkgdir) - assert len(cols) == 2 - col_one, col_two = cols - assert col_one.listnames() == ["py", "initpkg.py"] - assert col_two.listnames() == ["py", "path", "__init__.py"] - - cols = RSession.make_colitems([one, two], baseon=pkgdir.dirpath()) - assert len(cols) == 2 - col_one, col_two = cols - assert col_one.listnames() == [pkgdir.dirpath().basename, - "py", "initpkg.py"] - assert col_two.listnames() == [pkgdir.dirpath().basename, - "py", "path", "__init__.py"] - -def test_example_tryiter(): - events = [] - tmpdir = py.test.ensuretemp("tryitertest") - tmpdir.ensure("a", "__init__.py") - tmpdir.ensure("conftest.py").write(py.code.Source(""" - import py - py.test.skip("Reason") - """)) - tmpdir.ensure("a", "test_empty.py").write(py.code.Source(""" - def test_empty(): - pass - """)) - rootcol = py.test.collect.Directory(tmpdir) - data = list(rootcol.tryiter(reporterror=events.append)) - assert len(events) == 2 - assert str(events[1][0].value) == "Reason" - -class TestRSessionRemote: - def test_example_distribution_minus_x(self): - tmpdir = py.test.ensuretemp("example_distribution_minus_x") - tmpdir.ensure("sub", "conftest.py").write(py.code.Source(""" - disthosts = [%r] - """ % ('localhost',))) - tmpdir.ensure("sub", "__init__.py") - tmpdir.ensure("sub", "test_one.py").write(py.code.Source(""" - def test_1(): - pass - def test_x(): - import py - py.test.skip("aaa") - def test_2(): - assert 0 - def test_3(): - raise ValueError(23) - def test_4(someargs): - pass - """)) - args = [str(tmpdir.join("sub")), "-x"] - config = py.test.config._reparse(args) - rsession = RSession(config) - allevents = [] - rsession.main(reporter=allevents.append) - testevents = [x for x in allevents - if isinstance(x, report.ReceivedItemOutcome)] - assert len(testevents) == 3 - assert rsession.checkfun() - - def test_example_distribution(self): - subdir = "sub_example_dist" - tmpdir = py.test.ensuretemp("example_distribution") - tmpdir.ensure(subdir, "conftest.py").write(py.code.Source(""" - disthosts = [%r] - distrsync_roots = ["%s", "py"] - """ % ('localhost', subdir))) - tmpdir.ensure(subdir, "__init__.py") - tmpdir.ensure(subdir, "test_one.py").write(py.code.Source(""" - def test_1(): - pass - def test_2(): - assert 0 - def test_3(): - raise ValueError(23) - def test_4(someargs): - pass - def test_5(): - assert __file__ != '%s' - def test_6(): - import py - assert py.__file__ != '%s' - """ % (str(tmpdir.join(subdir)), py.__file__))) - tmpdir.join("py").mksymlinkto(py.path.local(py.__file__).dirpath()) - args = [str(tmpdir.join(subdir))] - config = py.test.config._reparse(args) - rsession = RSession(config, optimise_localhost=False) - allevents = [] - rsession.main(reporter=allevents.append) - testevents = [x for x in allevents - if isinstance(x, report.ReceivedItemOutcome)] - assert len(testevents) - passevents = [i for i in testevents if i.outcome.passed] - failevents = [i for i in testevents if i.outcome.excinfo] - skippedevents = [i for i in testevents if i.outcome.skipped] - assert len(testevents) == 6 - assert len(passevents) == 3 - assert len(failevents) == 3 - tb = failevents[0].outcome.excinfo.traceback - assert str(tb[0].path).find("test_one") != -1 - assert tb[0].source.find("test_2") != -1 - assert failevents[0].outcome.excinfo.typename == 'AssertionError' - tb = failevents[1].outcome.excinfo.traceback - assert str(tb[0].path).find("test_one") != -1 - assert tb[0].source.find("test_3") != -1 - assert failevents[1].outcome.excinfo.typename == 'ValueError' - assert failevents[1].outcome.excinfo.value == '23' - tb = failevents[2].outcome.excinfo.traceback - assert failevents[2].outcome.excinfo.typename == 'TypeError' - assert str(tb[0].path).find("executor") != -1 - assert tb[0].source.find("execute") != -1 - - def test_setup_teardown_ssh(self): - hosts = [HostInfo('localhost')] - parse_directories(hosts) - setup_events = [] - teardown_events = [] - - config = py.test.config._reparse([]) - opts = HostOptions(optimise_localhost=False, rsync_roots=['py']) - hm = HostManager(hosts, config, pkgdir, opts) - nodes = hm.init_hosts(setup_events.append) - hm.teardown_hosts(teardown_events.append, - [node.channel for node in nodes], nodes) - - count_rsyn_calls = [i for i in setup_events - if isinstance(i, report.HostRSyncing)] - assert len(count_rsyn_calls) == len([i for i in hosts]) - count_ready_calls = [i for i in setup_events - if isinstance(i, report.HostReady)] - assert len(count_ready_calls) == len([i for i in hosts]) - - # same for teardown events - teardown_wait_starts = [i for i in teardown_events - if isinstance(i, report.CallStart)] - teardown_wait_ends = [i for i in teardown_events - if isinstance(i, report.CallFinish)] - assert len(teardown_wait_starts) == len(hosts) - assert len(teardown_wait_ends) == len(hosts) - - def test_setup_teardown_run_ssh(self): - hosts = [HostInfo('localhost')] - parse_directories(hosts) - allevents = [] - - config = py.test.config._reparse([]) - opts = HostOptions(optimise_localhost=False, rsync_roots=['py']) - hm = HostManager(hosts, config, pkgdir, opts) - nodes = hm.init_hosts(allevents.append) - - from py.__.test.rsession.testing.test_executor \ - import ItemTestPassing, ItemTestFailing, ItemTestSkipping - - rootcol = py.test.collect.Directory(pkgdir.dirpath()) - itempass = rootcol.getitembynames(funcpass_spec) - itemfail = rootcol.getitembynames(funcfail_spec) - itemskip = rootcol.getitembynames(funcskip_spec) - itemprint = rootcol.getitembynames(funcprint_spec) - - # actually run some tests - for node in nodes: - node.send(itempass) - node.send(itemfail) - node.send(itemskip) - node.send(itemprint) - - hm.teardown_hosts(allevents.append, [node.channel for node in nodes], nodes) - - events = [i for i in allevents - if isinstance(i, report.ReceivedItemOutcome)] - passed = [i for i in events - if i.outcome.passed] - skipped = [i for i in events - if i.outcome.skipped] - assert len(passed) == 2 * len(nodes) - 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.find('samfing') != -1] - assert len(passed_stdout) == len(nodes), passed - - def test_config_pass(self): - """ Tests options object passing master -> server - """ - allevents = [] - hosts = [HostInfo('localhost')] - parse_directories(hosts) - config = py.test.config._reparse([]) - config._overwrite('custom', 'custom') - # we need to overwrite default list to serialize - from py.__.test.rsession.master import defaultconftestnames - defaultconftestnames.append("custom") - try: - opts = HostOptions(optimise_localhost=False, rsync_roots=['py']) - hm = HostManager(hosts, config, pkgdir, opts) - nodes = hm.init_hosts(allevents.append) - - rootcol = py.test.collect.Directory(pkgdir.dirpath()) - itempass = rootcol.getitembynames(funcoptioncustom_spec) - - for node in nodes: - node.send(itempass) - - hm.teardown_hosts(allevents.append, [node.channel for node in nodes], nodes) - events = [i for i in allevents - if isinstance(i, report.ReceivedItemOutcome)] - passed = [i for i in events - if i.outcome.passed] - skipped = [i for i in events - if i.outcome.skipped] - assert len(passed) == 1 * len(nodes) - assert len(skipped) == 0 - assert len(events) == len(passed) - finally: - defaultconftestnames.remove("custom") - - def test_nice_level(self): - """ Tests if nice level behaviour is ok - """ - allevents = [] - hosts = [HostInfo('localhost')] - parse_directories(hosts) - tmpdir = py.test.ensuretemp("nice") - tmpdir.ensure("__init__.py") - tmpdir.ensure("conftest.py").write(py.code.Source(""" - disthosts = ['localhost'] - dist_nicelevel = 10 - """)) - tmpdir.ensure("test_one.py").write("""def test_nice(): - import os - assert os.nice(0) == 10 - """) - - config = py.test.config._reparse([tmpdir]) - rsession = RSession(config) - allevents = [] - 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] - assert len(passevents) == 1 - -class XxxTestDirectories(object): - # need complete rewrite, and unsure if it makes sense at all - def test_simple_parse(self): - sshhosts = [HostInfo(i) for i in ['h1', 'h2', 'h3']] - parse_directories(sshhosts) - - def test_sophisticated_parse(self): - sshhosts = ['a@h1:/tmp', 'h2:tmp', 'h3'] - dirs = parse_directories(sshhosts) - assert py.builtin.sorted( - dirs.values()) == ['/tmp', 'pytestcache', 'tmp'] - - def test_parse_multiple_hosts(self): - hosts = ['h1', 'h1', 'h1:/tmp'] - dirs = parse_directories(hosts) - assert dirs == {(0, 'h1'): 'pytestcache', (1, 'h1'): 'pytestcache', - (2, 'h1'):'/tmp'} - -class TestInithosts(object): - def test_inithosts(self): - testevents = [] - hostnames = ['h1:/tmp', 'h1:/tmp', 'h1:/other', 'h2', 'h2:home'] - hosts = [HostInfo(i) for i in hostnames] - parse_directories(hosts) - config = py.test.config._reparse([]) - opts = HostOptions(do_sync=False, create_gateways=False) - hm = HostManager(hosts, config, pkgdir, opts) - nodes = hm.init_hosts(testevents.append) - events = [i for i in testevents if isinstance(i, report.HostRSyncing)] - assert len(events) == 4 - assert events[0].host.hostname == 'h1' - assert events[0].host.relpath == '/tmp-h1' - assert events[1].host.hostname == 'h1' - assert events[1].host.relpath == '/other-h1' - assert events[2].host.hostname == 'h2' - assert events[2].host.relpath == 'pytestcache-h2' - assert events[3].host.hostname == 'h2' - assert events[3].host.relpath == 'home-h2' - diff --git a/py/test/rsession/testing/test_slave.py b/py/test/rsession/testing/test_slave.py index 88b539e6d..c44470754 100644 --- a/py/test/rsession/testing/test_slave.py +++ b/py/test/rsession/testing/test_slave.py @@ -1,6 +1,6 @@ """ Testing the slave side node code (in a local way). """ -from py.__.test.rsession.slave import SlaveNode, slave_main +from py.__.test.rsession.slave import SlaveNode, slave_main, setup, PidInfo from py.__.test.rsession.outcome import ReprOutcome import py, sys @@ -11,10 +11,7 @@ if sys.platform == 'win32': py.test.skip("rsession is unsupported on Windows.") def setup_module(module): - from py.__.test.rsession.rsession import session_options module.rootdir = py.path.local(py.__file__).dirpath().dirpath() - config = py.test.config._reparse([]) - session_options.bind_config(config) # ---------------------------------------------------------------------- # inlined testing functions used below @@ -34,13 +31,8 @@ def funcprintfail(): print "samfing elz" asddsa -def funcoption(): - from py.__.test.rsession.rsession import remote_options - assert remote_options.we_are_remote - def funcoptioncustom(): - from py.__.test.rsession.rsession import remote_options - assert remote_options.custom == "custom" + assert py.test.config.getvalue("custom") def funchang(): import time @@ -52,7 +44,6 @@ funcfail_spec = (BASE + "funcfail").split("/") funcskip_spec = (BASE + "funcskip").split("/") funcprint_spec = (BASE + "funcprint").split("/") funcprintfail_spec = (BASE + "funcprintfail").split("/") -funcoption_spec = (BASE + "funcoption").split("/") funcoptioncustom_spec = (BASE + "funcoptioncustom").split("/") funchang_spec = (BASE + "funchang").split("/") mod_spec = BASE[:-1].split("/") @@ -63,7 +54,9 @@ from py.__.test.rsession.executor import RunExecutor def gettestnode(): rootcol = py.test.collect.Directory(rootdir) - node = SlaveNode(rootcol, executor=RunExecutor) + config = py.test.config._reparse([rootdir]) + pidinfo = PidInfo() + node = SlaveNode(rootcol, config, pidinfo, executor=RunExecutor) return node def test_slave_run_passing(): @@ -116,7 +109,9 @@ def test_slave_main_simple(): funcpass_spec, funcfail_spec ] - slave_main(q.pop, res.append, str(rootdir)) + config = py.test.config._reparse([]) + pidinfo = PidInfo() + slave_main(q.pop, res.append, str(rootdir), config, pidinfo) assert len(res) == 2 res_repr = [ReprOutcome(r) for r in res] assert not res_repr[0].passed and res_repr[1].passed @@ -126,8 +121,8 @@ def test_slave_run_different_stuff(): node.run("py doc log.txt".split()) def test_slave_setup_fails_on_import_error(): - from py.__.test.rsession.slave import setup tmp = py.test.ensuretemp("slavesetup") + config = py.test.config._reparse([tmp]) class C: def __init__(self): self.count = 0 @@ -136,12 +131,15 @@ def test_slave_setup_fails_on_import_error(): if self.count == 0: retval = str(tmp) elif self.count == 1: - from py.__.test.rsession.rsession import remote_options - retval = remote_options.d + retval = config.make_repr(conftestnames=['dist_nicelevel']) else: raise NotImplementedError("more data") self.count += 1 return retval + + def close(self): + pass + try: exec py.code.Source(setup, "setup()").compile() in { 'channel': C()} @@ -153,16 +151,14 @@ def test_slave_setup_fails_on_import_error(): def test_slave_setup_exit(): tmp = py.test.ensuretemp("slaveexit") tmp.ensure("__init__.py") - from py.__.test.rsession.slave import setup - from Queue import Queue - q = Queue() + q = py.std.Queue.Queue() + config = py.test.config._reparse([tmp]) class C: res = [] def __init__(self): - from py.__.test.rsession.rsession import remote_options self.q = [str(tmp), - remote_options.d, + config.make_repr(conftestnames=['dist_nicelevel']), funchang_spec, 42, funcpass_spec] @@ -178,6 +174,9 @@ def test_slave_setup_exit(): callback(self.q.pop()) f() #thread.start_new_thread(f, ()) + + def close(self): + pass send = res.append try: @@ -188,8 +187,8 @@ def test_slave_setup_exit(): py.test.fail("Did not exit") def test_slave_setup_fails_on_missing_pkg(): - from py.__.test.rsession.slave import setup tmp = py.test.ensuretemp("slavesetup2") + config = py.test.config._reparse([tmp]) x = tmp.ensure("sometestpackage", "__init__.py") class C: def __init__(self): @@ -199,8 +198,7 @@ def test_slave_setup_fails_on_missing_pkg(): if self.count == 0: retval = str(x.dirpath()) elif self.count == 1: - from py.__.test.rsession.rsession import remote_options - retval = remote_options.d + retval = config.make_repr(conftestnames=['dist_nicelevel']) else: raise NotImplementedError("more data") self.count += 1 @@ -223,3 +221,19 @@ def test_slave_setup_fails_on_missing_pkg(): else: py.test.fail("missing exception") + +def test_pidinfo(): + if not hasattr(os, 'fork') or not hasattr(os, 'waitpid'): + py.test.skip("Platform does not support fork") + pidinfo = PidInfo() + pid = os.fork() + if pid: + pidinfo.set_pid(pid) + pidinfo.waitandclear(pid, 0) + else: + import time, sys + time.sleep(.3) + os._exit(0) + # check if this really exits + py.test.raises(OSError, "os.waitpid(pid, 0)") + diff --git a/py/test/rsession/testing/test_web.py b/py/test/rsession/testing/test_web.py index 55fc65b73..2e757dca2 100644 --- a/py/test/rsession/testing/test_web.py +++ b/py/test/rsession/testing/test_web.py @@ -14,9 +14,7 @@ except ImportError: def setup_module(mod): config = py.test.config._reparse([]) - from py.__.test.rsession.rsession import session_options - session_options.bind_config(config) - session_options.import_pypy = True + config._overwrite('_dist_import_pypy', True) from py.__.test.rsession.web import TestHandler as _TestHandler from py.__.test.rsession.web import MultiQueue mod._TestHandler = _TestHandler diff --git a/py/test/rsession/testing/test_webjs.py b/py/test/rsession/testing/test_webjs.py index f5209a04e..71210c67a 100644 --- a/py/test/rsession/testing/test_webjs.py +++ b/py/test/rsession/testing/test_webjs.py @@ -23,9 +23,7 @@ def setup_module(mod): dom.window = dom.Window(html) dom.document = dom.window.document config = py.test.config._reparse([]) - from py.__.test.rsession.rsession import session_options - session_options.bind_config(config) - session_options.import_pypy = True + config._overwrite('_dist_import_pypy', True) from py.__.test.rsession import webjs from py.__.test.rsession.web import exported_methods mod.webjs = webjs diff --git a/py/test/rsession/testing/test_webjs.py.merge.tmp b/py/test/rsession/testing/test_webjs.py.merge.tmp deleted file mode 100644 index 71210c67a..000000000 --- a/py/test/rsession/testing/test_webjs.py.merge.tmp +++ /dev/null @@ -1,138 +0,0 @@ -import py - -try: - import pypy - from pypy.translator.js.modules import dom - from pypy.translator.js.tester import schedule_callbacks - from py.__.test.rsession.rsession import session_options - dom.Window # check whether dom was properly imported or is just a - # leftover in sys.modules -except (ImportError, AttributeError): - py.test.skip('PyPy not found') - -from py.__.test.rsession import webjs -from py.__.test.rsession.web import exported_methods -here = py.magic.autopath().dirpath() - -def setup_module(mod): - # load HTML into window object - html = here.join('../webdata/index.html').read() - mod.html = html - from pypy.translator.js.modules import dom - mod.dom = dom - dom.window = dom.Window(html) - dom.document = dom.window.document - config = py.test.config._reparse([]) - config._overwrite('_dist_import_pypy', True) - from py.__.test.rsession import webjs - from py.__.test.rsession.web import exported_methods - mod.webjs = webjs - mod.exported_methods = exported_methods - -def setup_function(f): - dom.window = dom.Window(html) - dom.document = dom.window.document - -def test_html_loaded(): - body = dom.window.document.getElementsByTagName('body')[0] - assert len(body.childNodes) > 0 - assert str(body.childNodes[1].nodeName) == 'A' - -def test_set_msgbox(): - msgbox = dom.window.document.getElementById('messagebox') - assert len(msgbox.childNodes) == 0 - webjs.set_msgbox('foo', 'bar') - assert len(msgbox.childNodes) == 1 - assert msgbox.childNodes[0].nodeName == 'PRE' - assert msgbox.childNodes[0].childNodes[0].nodeValue == 'foo\nbar' - -def test_show_info(): - info = dom.window.document.getElementById('info') - info.style.visibility = 'hidden' - info.innerHTML = '' - webjs.show_info('foobar') - content = info.innerHTML - assert content == 'foobar' - bgcolor = info.style.backgroundColor - assert bgcolor == 'beige' - -def test_hide_info(): - info = dom.window.document.getElementById('info') - info.style.visibility = 'visible' - webjs.hide_info() - assert info.style.visibility == 'hidden' - -def test_process(): - main_t = dom.window.document.getElementById('main_table') - assert len(main_t.getElementsByTagName('tr')) == 0 - assert not webjs.process({}) - - msg = {'type': 'ItemStart', - 'itemtype': 'Module', - 'itemname': 'foo.py', - 'fullitemname': 'modules/foo.py', - 'length': 10, - } - assert webjs.process(msg) - trs = main_t.getElementsByTagName('tr') - assert len(trs) == 1 - tr = trs[0] - assert len(tr.childNodes) == 2 - assert tr.childNodes[0].nodeName == 'TD' - assert tr.childNodes[0].innerHTML == 'foo.py[0/10]' - assert tr.childNodes[1].nodeName == 'TD' - assert tr.childNodes[1].childNodes[0].nodeName == 'TABLE' - assert len(tr.childNodes[1].getElementsByTagName('tr')) == 0 - -def test_process_two(): - main_t = dom.window.document.getElementById('main_table') - msg = {'type': 'ItemStart', - 'itemtype': 'Module', - 'itemname': 'foo.py', - 'fullitemname': 'modules/foo.py', - 'length': 10, - } - webjs.process(msg) - msg = {'type': 'ReceivedItemOutcome', - 'fullmodulename': 'modules/foo.py', - 'passed' : 'True', - 'fullitemname' : 'modules/foo.py/test_item', - 'hostkey': None, - } - webjs.process(msg) - trs = main_t.getElementsByTagName('tr') - tds = trs[0].getElementsByTagName('td') - # two cells in the row, one in the table inside one of the cells - assert len(tds) == 3 - html = tds[0].innerHTML - assert html == 'foo.py[1/10]' - assert tds[2].innerHTML == '.' - -def test_signal(): - main_t = dom.window.document.getElementById('main_table') - msg = {'type': 'ItemStart', - 'itemtype': 'Module', - 'itemname': 'foo.py', - 'fullitemname': 'modules/foo.py', - 'length': 10, - } - webjs.process(msg) - msg = {'type': 'ReceivedItemOutcome', - 'fullmodulename': 'modules/foo.py', - 'passed' : 'False', - 'fullitemname' : 'modules/foo.py/test_item', - 'hostkey': None, - 'signal': '10', - 'skipped': 'False', - } - exported_methods.fail_reasons['modules/foo.py/test_item'] = 'Received signal 10' - exported_methods.stdout['modules/foo.py/test_item'] = '' - exported_methods.stderr['modules/foo.py/test_item'] = '' - webjs.process(msg) - schedule_callbacks(exported_methods) - # ouch - assert dom.document.getElementById('modules/foo.py').childNodes[0].\ - childNodes[0].childNodes[0].childNodes[0].nodeValue == 'F' - -# XXX: Write down test for full run - diff --git a/py/test/rsession/web.py b/py/test/rsession/web.py index dd37fdff6..95764fa7b 100644 --- a/py/test/rsession/web.py +++ b/py/test/rsession/web.py @@ -14,18 +14,18 @@ import sys import socket import py -from py.__.test.rsession.rsession import RSession, session_options +from py.__.test.rsession.rsession import RSession from py.__.test.rsession import report from py.__.test import collect from py.__.test.rsession.webdata import json DATADIR = py.path.local(__file__).dirpath("webdata") FUNCTION_LIST = ["main", "show_skip", "show_traceback", "show_info", "hide_info", - "show_host", "hide_host", "hide_messagebox"] + "show_host", "hide_host", "hide_messagebox", "opt_scroll"] try: try: - if not session_options.import_pypy: + if not py.test.config.getvalue('_dist_import_pypy'): raise ImportError except AttributeError: pass @@ -416,10 +416,10 @@ def start_server(server_address = ('', 8000), handler=TestHandler, start_new=Tru if start_new: thread.start_new_thread(httpd.serve_forever, ()) - print "Server started, listening on %s" % (server_address,) + print "Server started, listening on port %d" % (httpd.server_port,) return httpd else: - print "Server started, listening on %s" % (server_address,) + print "Server started, listening on port %d" % (httpd.server_port,) httpd.serve_forever() def kill_server(): diff --git a/py/test/rsession/web.py.merge.tmp b/py/test/rsession/web.py.merge.tmp deleted file mode 100644 index 95764fa7b..000000000 --- a/py/test/rsession/web.py.merge.tmp +++ /dev/null @@ -1,430 +0,0 @@ - -""" web server for py.test -""" - -from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler - -import thread, threading -import re -import time -import random -import Queue -import os -import sys -import socket - -import py -from py.__.test.rsession.rsession import RSession -from py.__.test.rsession import report -from py.__.test import collect -from py.__.test.rsession.webdata import json - -DATADIR = py.path.local(__file__).dirpath("webdata") -FUNCTION_LIST = ["main", "show_skip", "show_traceback", "show_info", "hide_info", - "show_host", "hide_host", "hide_messagebox", "opt_scroll"] - -try: - try: - if not py.test.config.getvalue('_dist_import_pypy'): - raise ImportError - except AttributeError: - pass - from pypy.rpython.ootypesystem.bltregistry import MethodDesc, BasicExternal,\ - described - from pypy.translator.js.main import rpython2javascript - from pypy.translator.js import commproxy - from pypy.rpython.extfunc import _callable - - commproxy.USE_MOCHIKIT = False - IMPORTED_PYPY = True -except (ImportError, NameError): - class BasicExternal(object): - pass - - def described(*args, **kwargs): - def decorator(func): - return func - return decorator - - def _callable(*args, **kwargs): - pass - - IMPORTED_PYPY = False - -def add_item(event): - """ A little helper - """ - item = event.item - itemtype = item.__class__.__name__ - itemname = item.name - fullitemname = "/".join(item.listnames()) - d = {'fullitemname': fullitemname, 'itemtype': itemtype, - 'itemname': itemname} - #if itemtype == 'Module': - try: - d['length'] = str(len(list(event.item.tryiter()))) - except: - d['length'] = "?" - return d - -class MultiQueue(object): - """ a tailor-made queue (internally using Queue) for py.test.rsession.web - - API-wise the main difference is that the get() method gets a sessid - argument, which is used to determine what data to feed to the client - - when a data queue for a sessid doesn't yet exist, it is created, and - filled with data that has already been fed to the other clients - """ - def __init__(self): - self._cache = [] - self._session_queues = {} - self._lock = py.std.thread.allocate_lock() - - def put(self, item): - self._lock.acquire() - try: - self._cache.append(item) - for key, q in self._session_queues.items(): - q.put(item) - finally: - self._lock.release() - - def _del(self, sessid): - self._lock.acquire() - try: - del self._session_queues[sessid] - finally: - self._lock.release() - - def get(self, sessid): - self._lock.acquire() - try: - if not sessid in self._session_queues: - self._create_session_queue(sessid) - finally: - self._lock.release() - return self._session_queues[sessid].get(sessid) - - def empty(self): - self._lock.acquire() - try: - if not self._session_queues: - return not len(self._cache) - for q in self._session_queues.values(): - if not q.empty(): - return False - finally: - self._lock.release() - return True - - def empty_queue(self, sessid): - return self._session_queues[sessid].empty() - - def _create_session_queue(self, sessid): - self._session_queues[sessid] = q = Queue.Queue() - for item in self._cache: - q.put(item) - -class ExportedMethods(BasicExternal): - _render_xmlhttp = True - def __init__(self): - self.pending_events = MultiQueue() - self.start_event = threading.Event() - self.end_event = threading.Event() - self.skip_reasons = {} - self.fail_reasons = {} - self.stdout = {} - self.stderr = {} - self.all = 0 - - def findmodule(self, item): - # find the most outwards parent which is module - current = item - while current: - if isinstance(current, collect.Module): - break - current = current.parent - - if current is not None: - return str(current.name), str("/".join(current.listnames())) - else: - return str(item.parent.name), str("/".join(item.parent.listnames())) - - def show_hosts(self): - self.start_event.wait() - to_send = {} - for host in self.hosts: - to_send[host.hostid] = host.hostname - return to_send - show_hosts = described(retval={str:str}, args=[('callback', - _callable([{str:str}]))])(show_hosts) - - def show_skip(self, item_name="aa"): - return {'item_name': item_name, - 'reason': self.skip_reasons[item_name]} - show_skip = described(retval={str:str}, args=[('item_name',str),('callback', - _callable([{str:str}]))])(show_skip) - - def show_fail(self, item_name="aa"): - return {'item_name':item_name, - 'traceback':str(self.fail_reasons[item_name]), - 'stdout':self.stdout[item_name], - 'stderr':self.stderr[item_name]} - show_fail = described(retval={str:str}, args=[('item_name',str),('callback', - _callable([{str:str}]))])(show_fail) - - _sessids = None - _sesslock = py.std.thread.allocate_lock() - def show_sessid(self): - if not self._sessids: - self._sessids = [] - self._sesslock.acquire() - try: - while 1: - chars = list(py.std.string.lowercase) - py.std.random.shuffle(chars) - sessid = ''.join(chars[:8]) - if sessid not in self._sessids: - self._sessids.append(sessid) - break - finally: - self._sesslock.release() - return sessid - show_sessid = described(retval=str, args=[('callback', - _callable([str]))])(show_sessid) - - def failed(self, **kwargs): - if not 'sessid' in kwargs: - return - sessid = kwargs['sessid'] - to_del = -1 - for num, i in enumerate(self._sessids): - if i == sessid: - to_del = num - if to_del != -1: - del self._sessids[to_del] - self.pending_events._del(kwargs['sessid']) - - def show_all_statuses(self, sessid=-1): - retlist = [self.show_status_change(sessid)] - while not self.pending_events.empty_queue(sessid): - retlist.append(self.show_status_change(sessid)) - retval = retlist - return retval - show_all_statuses = described(retval=[{str:str}],args= - [('sessid',str), ('callback',_callable([[{str:str}]]))])(show_all_statuses) - - def show_status_change(self, sessid): - event = self.pending_events.get(sessid) - if event is None: - self.end_event.set() - return {} - # some dispatcher here - if isinstance(event, report.ReceivedItemOutcome): - args = {} - outcome = event.outcome - for key, val in outcome.__dict__.iteritems(): - args[key] = str(val) - args.update(add_item(event)) - mod_name, mod_fullname = self.findmodule(event.item) - args['modulename'] = str(mod_name) - args['fullmodulename'] = str(mod_fullname) - fullitemname = args['fullitemname'] - if outcome.skipped: - self.skip_reasons[fullitemname] = outcome.skipped - elif outcome.excinfo: - self.fail_reasons[fullitemname] = self.repr_failure_tblong( - event.item, outcome.excinfo, outcome.excinfo.traceback) - self.stdout[fullitemname] = outcome.stdout - self.stderr[fullitemname] = outcome.stderr - elif outcome.signal: - self.fail_reasons[fullitemname] = "Received signal %d" % outcome.signal - self.stdout[fullitemname] = outcome.stdout - self.stderr[fullitemname] = outcome.stderr - if event.channel: - args['hostkey'] = event.channel.gateway.host.hostid - else: - args['hostkey'] = '' - elif isinstance(event, report.ItemStart): - args = add_item(event) - elif isinstance(event, report.TestFinished): - args = {} - args['run'] = str(self.all) - args['fails'] = str(len(self.fail_reasons)) - args['skips'] = str(len(self.skip_reasons)) - elif isinstance(event, report.SendItem): - args = add_item(event) - args['hostkey'] = event.channel.gateway.host.hostid - elif isinstance(event, report.HostReady): - self.ready_hosts[event.host] = True - args = {'hostname' : event.host.hostname, 'hostkey' : event.host.hostid} - elif isinstance(event, report.FailedTryiter): - args = add_item(event) - elif isinstance(event, report.SkippedTryiter): - args = add_item(event) - args['reason'] = str(event.excinfo.value) - else: - args = {} - args['event'] = str(event) - args['type'] = event.__class__.__name__ - return args - - def repr_failure_tblong(self, item, excinfo, traceback): - lines = [] - for index, entry in py.builtin.enumerate(traceback): - lines.append('----------') - lines.append("%s: %s" % (entry.path, entry.lineno)) - lines += self.repr_source(entry.relline, entry.source) - lines.append("%s: %s" % (excinfo.typename, excinfo.value)) - return "\n".join(lines) - - def repr_source(self, relline, source): - lines = [] - for num, line in enumerate(source.split("\n")): - if num == relline: - lines.append(">>>>" + line) - else: - lines.append(" " + line) - return lines - - def report_ReceivedItemOutcome(self, event): - self.all += 1 - self.pending_events.put(event) - - def report_ItemStart(self, event): - if isinstance(event.item, py.test.collect.Module): - self.pending_events.put(event) - - def report_unknown(self, event): - # XXX: right now, we just pass it for showing - self.pending_events.put(event) - - def report_TestStarted(self, event): - # XXX: It overrides out self.hosts - self.hosts = {} - self.ready_hosts = {} - for host in event.hosts: - self.hosts[host] = host - self.ready_hosts[host] = False - self.start_event.set() - self.pending_events.put(event) - - def report(self, what): - repfun = getattr(self, "report_" + what.__class__.__name__, - self.report_unknown) - try: - repfun(what) - except (KeyboardInterrupt, SystemExit): - raise - except: - print "Internal reporting problem" - excinfo = py.code.ExceptionInfo() - for i in excinfo.traceback: - print str(i)[2:-1] - print excinfo - -## try: -## self.wait_flag.acquire() -## self.pending_events.insert(0, event) -## self.wait_flag.notify() -## finally: -## self.wait_flag.release() - -exported_methods = ExportedMethods() - -class TestHandler(BaseHTTPRequestHandler): - exported_methods = exported_methods - - def do_GET(self): - path = self.path - if path.endswith("/"): - path = path[:-1] - if path.startswith("/"): - path = path[1:] - m = re.match('^(.*)\?(.*)$', path) - if m: - path = m.group(1) - getargs = m.group(2) - else: - getargs = "" - name_path = path.replace(".", "_") - method_to_call = getattr(self, "run_" + name_path, None) - if method_to_call is None: - exec_meth = getattr(self.exported_methods, name_path, None) - if exec_meth is None: - self.send_error(404, "File %s not found" % path) - else: - try: - self.serve_data('text/json', - json.write(exec_meth(**self.parse_args(getargs)))) - except socket.error: - # client happily disconnected - exported_methods.failed(**self.parse_args(getargs)) - else: - method_to_call() - - def parse_args(self, getargs): - # parse get argument list - if getargs == "": - return {} - - unquote = py.std.urllib.unquote - args = {} - arg_pairs = getargs.split("&") - for arg in arg_pairs: - key, value = arg.split("=") - args[unquote(key)] = unquote(value) - return args - - def log_message(self, format, *args): - # XXX just discard it - pass - - do_POST = do_GET - - def run_(self): - self.run_index() - - def run_index(self): - data = py.path.local(DATADIR).join("index.html").open().read() - self.serve_data("text/html", data) - - def run_jssource(self): - js_name = py.path.local(__file__).dirpath("webdata").join("source.js") - web_name = py.path.local(__file__).dirpath().join("webjs.py") - if IMPORTED_PYPY and web_name.mtime() > js_name.mtime(): - from py.__.test.rsession import webjs - - javascript_source = rpython2javascript(webjs, - FUNCTION_LIST, use_pdb=False) - open(str(js_name), "w").write(javascript_source) - self.serve_data("text/javascript", javascript_source) - else: - js_source = open(str(js_name), "r").read() - self.serve_data("text/javascript", js_source) - - def serve_data(self, content_type, data): - self.send_response(200) - self.send_header("Content-type", content_type) - self.send_header("Content-length", len(data)) - self.end_headers() - self.wfile.write(data) - -def start_server(server_address = ('', 8000), handler=TestHandler, start_new=True): - httpd = HTTPServer(server_address, handler) - - if start_new: - thread.start_new_thread(httpd.serve_forever, ()) - print "Server started, listening on port %d" % (httpd.server_port,) - return httpd - else: - print "Server started, listening on port %d" % (httpd.server_port,) - httpd.serve_forever() - -def kill_server(): - exported_methods.pending_events.put(None) - while not exported_methods.pending_events.empty(): - time.sleep(.1) - exported_methods.end_event.wait() - diff --git a/py/test/rsession/webdata/index.html b/py/test/rsession/webdata/index.html index ef94c8a41..b8ecad48c 100644 --- a/py/test/rsession/webdata/index.html +++ b/py/test/rsession/webdata/index.html @@ -97,6 +97,12 @@ End of Traceback + + Options + + + Scroll with tests arriving + diff --git a/py/test/rsession/webdata/source.js b/py/test/rsession/webdata/source.js index b20d30801..902bade7b 100644 --- a/py/test/rsession/webdata/source.js +++ b/py/test/rsession/webdata/source.js @@ -354,7 +354,7 @@ ExportedMethods.prototype.show_fail = function ( item_name,callback ) { x.send(null); } function some_strange_function_which_will_never_be_called () { - var v0,v1,v2,v3,v4,v5,v6,v7,v8,v9,v10,v11,v12; + var v0,v1,v2,v3,v4,v5,v6,v7,v8,v9,v10,v11,v12,v13; var block = 0; for(;;){ switch(block){ @@ -371,6 +371,7 @@ function some_strange_function_which_will_never_be_called () { show_host ( v9 ); hide_host ( ); hide_messagebox ( ); + opt_scroll ( ); block = 1; break; case 1: @@ -379,25 +380,105 @@ function some_strange_function_which_will_never_be_called () { } } -function show_info (data_0) { - var v39,v40,v41,v42,v43,data_1,info_0,v44,v45,v46,info_1,v47,v48,v49,v50,v51,v52,data_2,info_2,v53,v54,v55,v56; +function hide_host () { + var v100,v101,v102,elem_5,v103,v104,v105,v106,v107,v108,v109,elem_6,v110,v111,v112,v113; var block = 0; for(;;){ switch(block){ case 0: - v40 = __consts_0.Document; - v41 = v40.getElementById(__consts_0.const_str__2); - v42 = v41.style; - v42.visibility = __consts_0.const_str__3; - data_1 = data_0; - info_0 = v41; + v101 = __consts_0.Document; + v102 = v101.getElementById(__consts_0.const_str__2); + elem_5 = v102; block = 1; break; case 1: - v44 = info_0.childNodes; - v45 = ll_len__List_ExternalType_ ( v44 ); - v46 = !!v45; - if (v46 == true) + v103 = elem_5.childNodes; + v104 = ll_len__List_ExternalType_ ( v103 ); + v105 = !!v104; + if (v105 == true) + { + elem_6 = elem_5; + block = 4; + break; + } + else{ + v106 = elem_5; + block = 2; + break; + } + case 2: + v107 = v106.style; + v107.visibility = __consts_0.const_str__3; + __consts_0.py____test_rsession_webjs_Globals.ohost = __consts_0.const_str__5; + block = 3; + break; + case 3: + return ( v100 ); + case 4: + v110 = elem_6; + v111 = elem_6.childNodes; + v112 = ll_getitem_nonneg__dum_nocheckConst_List_ExternalT ( undefined,v111,0 ); + v110.removeChild(v112); + elem_5 = elem_6; + block = 1; + break; + } + } +} + +function py____test_rsession_webjs_Globals () { + this.odata_empty = false; + this.osessid = __consts_0.const_str__5; + this.ohost = __consts_0.const_str__5; + this.orsync_dots = 0; + this.ofinished = false; + this.ohost_dict = __consts_0.const_tuple; + this.opending = __consts_0.const_list; + this.orsync_done = false; + this.ohost_pending = __consts_0.const_tuple__8; +} + +py____test_rsession_webjs_Globals.prototype.toString = function (){ + return ( '' ); +} + +inherits(py____test_rsession_webjs_Globals,Object); +function ll_len__List_ExternalType_ (l_0) { + var v128,v129,v130; + var block = 0; + for(;;){ + switch(block){ + case 0: + v129 = l_0; + v130 = v129.length; + v128 = v130; + block = 1; + break; + case 1: + return ( v128 ); + } + } +} + +function show_info (data_0) { + var v46,v47,v48,v49,v50,data_1,info_0,v51,v52,v53,info_1,v54,v55,v56,v57,v58,v59,data_2,info_2,v60,v61,v62,v63; + var block = 0; + for(;;){ + switch(block){ + case 0: + v47 = __consts_0.Document; + v48 = v47.getElementById(__consts_0.const_str__9); + v49 = v48.style; + v49.visibility = __consts_0.const_str__10; + data_1 = data_0; + info_0 = v48; + block = 1; + break; + case 1: + v51 = info_0.childNodes; + v52 = ll_len__List_ExternalType_ ( v51 ); + v53 = !!v52; + if (v53 == true) { data_2 = data_1; info_2 = info_0; @@ -406,25 +487,25 @@ function show_info (data_0) { } else{ info_1 = info_0; - v47 = data_1; + v54 = data_1; block = 2; break; } case 2: - v48 = create_text_elem ( v47 ); - v49 = info_1; - v49.appendChild(v48); - v51 = info_1.style; - v51.backgroundColor = __consts_0.const_str__4; + v55 = create_text_elem ( v54 ); + v56 = info_1; + v56.appendChild(v55); + v58 = info_1.style; + v58.backgroundColor = __consts_0.const_str__11; block = 3; break; case 3: - return ( v39 ); + return ( v46 ); case 4: - v53 = info_2; - v54 = info_2.childNodes; - v55 = ll_getitem_nonneg__dum_nocheckConst_List_ExternalT ( undefined,v54,0 ); - v53.removeChild(v55); + v60 = info_2; + v61 = info_2.childNodes; + v62 = ll_getitem_nonneg__dum_nocheckConst_List_ExternalT ( undefined,v61,0 ); + v60.removeChild(v62); data_1 = data_2; info_0 = info_2; block = 1; @@ -433,121 +514,199 @@ function show_info (data_0) { } } -function ll_len__List_ExternalType_ (l_0) { - var v116,v117,v118; +function show_host (host_name_0) { + var v69,v70,v71,v72,v73,host_name_1,elem_0,v74,v75,v76,v77,host_name_2,tbody_0,elem_1,v78,v79,last_exc_value_0,host_name_3,tbody_1,elem_2,item_0,v80,v81,v82,v83,v84,v85,v86,v87,v88,v89,host_name_4,tbody_2,elem_3,v90,v91,v92,v93,v94,v95,host_name_5,elem_4,v96,v97,v98,v99; var block = 0; for(;;){ switch(block){ case 0: - v117 = l_0; - v118 = v117.length; - v116 = v118; + v70 = __consts_0.Document; + v71 = v70.getElementById(__consts_0.const_str__2); + v72 = v71.childNodes; + v73 = ll_list_is_true__List_ExternalType_ ( v72 ); + if (v73 == true) + { + host_name_5 = host_name_0; + elem_4 = v71; + block = 6; + break; + } + else{ + host_name_1 = host_name_0; + elem_0 = v71; + block = 1; + break; + } + case 1: + v74 = create_elem ( __consts_0.const_str__12 ); + v75 = __consts_0.py____test_rsession_webjs_Globals.ohost_pending; + v76 = ll_dict_getitem__Dict_String__List_String___String ( v75,host_name_1 ); + v77 = ll_listiter__Record_index__Signed__iterable_List_S ( undefined,v76 ); + host_name_2 = host_name_1; + tbody_0 = v74; + elem_1 = elem_0; + v78 = v77; + block = 2; + break; + case 2: + try { + v79 = ll_listnext__Record_index__Signed__iterable_0 ( v78 ); + host_name_3 = host_name_2; + tbody_1 = tbody_0; + elem_2 = elem_1; + item_0 = v79; + v80 = v78; + block = 3; + break; + } + catch (exc){ + if (isinstanceof(exc, exceptions_StopIteration)) + { + host_name_4 = host_name_2; + tbody_2 = tbody_0; + elem_3 = elem_1; + block = 4; + break; + } + throw(exc); + } + case 3: + v81 = create_elem ( __consts_0.const_str__13 ); + v82 = create_elem ( __consts_0.const_str__14 ); + v83 = v82; + v84 = create_text_elem ( item_0 ); + v83.appendChild(v84); + v86 = v81; + v86.appendChild(v82); + v88 = tbody_1; + v88.appendChild(v81); + host_name_2 = host_name_3; + tbody_0 = tbody_1; + elem_1 = elem_2; + v78 = v80; + block = 2; + break; + case 4: + v90 = elem_3; + v90.appendChild(tbody_2); + v92 = elem_3.style; + v92.visibility = __consts_0.const_str__10; + __consts_0.py____test_rsession_webjs_Globals.ohost = host_name_4; + setTimeout ( 'reshow_host()',100 ); + block = 5; + break; + case 5: + return ( v69 ); + case 6: + v96 = elem_4; + v97 = elem_4.childNodes; + v98 = ll_getitem_nonneg__dum_nocheckConst_List_ExternalT ( undefined,v97,0 ); + v96.removeChild(v98); + host_name_1 = host_name_5; + elem_0 = elem_4; block = 1; break; - case 1: - return ( v116 ); } } } -function main () { - var v13,v14,v15,v16,v17; +function ll_getitem_nonneg__dum_nocheckConst_List_ExternalT (func_0,l_1,index_0) { + var v131,v132,v133,l_2,index_1,v134,v135,v136,v137,index_2,v138,v139,v140; var block = 0; for(;;){ switch(block){ case 0: - v14 = __consts_0.ExportedMethods; - v15 = v14.show_hosts(host_init); - v16 = __consts_0.ExportedMethods; - v17 = v16.show_sessid(sessid_comeback); + v132 = (index_0>=0); + undefined; + l_2 = l_1; + index_1 = index_0; block = 1; break; case 1: - return ( v13 ); + v134 = l_2; + v135 = v134.length; + v136 = (index_1=v172); + v174 = v173; + if (v174 == true) + { + block = 3; + break; + } + else{ + iter_1 = iter_0; + index_3 = v170; + l_4 = v169; + block = 1; + break; + } + case 1: + v175 = (index_3+1); + iter_1.index = v175; + v177 = l_4; + v178 = v177[index_3]; + v168 = v178; + block = 2; + break; + case 2: + return ( v168 ); + case 3: + v179 = __consts_0.exceptions_StopIteration; + v180 = v179.meta; + v181 = v179; + etype_1 = v180; + evalue_1 = v181; + block = 4; + break; + case 4: + throw(evalue_1); + } + } +} + +function hide_info () { + var v64,v65,v66,v67,v68; + var block = 0; + for(;;){ + switch(block){ + case 0: + v65 = __consts_0.Document; + v66 = v65.getElementById(__consts_0.const_str__9); + v67 = v66.style; + v67.visibility = __consts_0.const_str__3; + block = 1; + break; + case 1: + return ( v64 ); + } + } +} + +function hide_messagebox () { + var v114,v115,v116,mbox_0,v117,v118,mbox_1,v119,v120,v121,v122; + var block = 0; + for(;;){ + switch(block){ + case 0: + v115 = __consts_0.Document; + v116 = v115.getElementById(__consts_0.const_str__17); + mbox_0 = v116; + block = 1; + break; + case 1: + v117 = mbox_0.childNodes; + v118 = ll_list_is_true__List_ExternalType_ ( v117 ); + if (v118 == true) + { + mbox_1 = mbox_0; + block = 3; + break; + } + else{ + block = 2; + break; + } + case 2: + return ( v114 ); + case 3: + v119 = mbox_1; + v120 = mbox_1.childNodes; + v121 = ll_getitem_nonneg__dum_nocheckConst_List_ExternalT ( undefined,v120,0 ); + v119.removeChild(v121); + mbox_0 = mbox_1; + block = 1; + break; + } + } +} + +function exceptions_Exception () { +} + +exceptions_Exception.prototype.toString = function (){ + return ( '' ); +} + +inherits(exceptions_Exception,Object); +function exceptions_StopIteration () { +} + +exceptions_StopIteration.prototype.toString = function (){ + return ( '' ); +} + +inherits(exceptions_StopIteration,exceptions_Exception); +function create_elem (s_0) { + var v151,v152,v153; + var block = 0; + for(;;){ + switch(block){ + case 0: + v152 = __consts_0.Document; + v153 = v152.createElement(s_0); + v151 = v153; + block = 1; + break; + case 1: + return ( v151 ); + } + } +} + +function py____test_rsession_webjs_Options () { + this.oscroll = false; +} + +py____test_rsession_webjs_Options.prototype.toString = function (){ + return ( '' ); +} + +inherits(py____test_rsession_webjs_Options,Object); +function ll_dict_getitem__Dict_String__String__String (d_1,key_2) { + var v188,v189,v190,v191,v192,v193,v194,etype_2,evalue_2,key_3,v195,v196,v197; + var block = 0; + for(;;){ + switch(block){ + case 0: + v189 = d_1; + v190 = (v189[key_2]!=undefined); + v191 = v190; + if (v191 == true) + { + key_3 = key_2; + v195 = d_1; + block = 3; + break; + } + else{ + block = 1; + break; + } + case 1: + v192 = __consts_0.exceptions_KeyError; + v193 = v192.meta; + v194 = v192; + etype_2 = v193; + evalue_2 = v194; + block = 2; + break; + case 2: + throw(evalue_2); + case 3: + v196 = v195; + v197 = v196[key_3]; + v188 = v197; + block = 4; + break; + case 4: + return ( v188 ); + } + } +} + +function show_traceback (item_name_1) { + var v28,v29,v30,v31,v32,v33,v34,v35,v36,v37,v38,v39,v40,v41,v42,v43,v44,v45; + var block = 0; + for(;;){ + switch(block){ + case 0: + v29 = ll_dict_getitem__Dict_String__Record_item2__Str_St ( __consts_0.const_tuple__23,item_name_1 ); + v30 = v29.item0; + v31 = v29.item1; + v32 = v29.item2; + v33 = new StringBuilder(); + v33.ll_append(__consts_0.const_str__24); + v35 = ll_str__StringR_StringConst_String ( undefined,v30 ); + v33.ll_append(v35); + v33.ll_append(__consts_0.const_str__25); + v38 = ll_str__StringR_StringConst_String ( undefined,v31 ); + v33.ll_append(v38); + v33.ll_append(__consts_0.const_str__26); + v41 = ll_str__StringR_StringConst_String ( undefined,v32 ); + v33.ll_append(v41); + v33.ll_append(__consts_0.const_str__19); + v44 = v33.ll_build(); + set_msgbox ( item_name_1,v44 ); + block = 1; + break; + case 1: + return ( v28 ); + } + } +} + +function ll_dict_getitem__Dict_String__List_String___String (d_0,key_0) { + var v154,v155,v156,v157,v158,v159,v160,etype_0,evalue_0,key_1,v161,v162,v163; + var block = 0; + for(;;){ + switch(block){ + case 0: + v155 = d_0; + v156 = (v155[key_0]!=undefined); + v157 = v156; + if (v157 == true) + { + key_1 = key_0; + v161 = d_0; + block = 3; + break; + } + else{ + block = 1; + break; + } + case 1: + v158 = __consts_0.exceptions_KeyError; + v159 = v158.meta; + v160 = v158; + etype_0 = v159; + evalue_0 = v160; + block = 2; + break; + case 2: + throw(evalue_0); + case 3: + v162 = v161; + v163 = v162[key_1]; + v154 = v163; + block = 4; + break; + case 4: + return ( v154 ); + } + } +} + +function main () { + var v14,v15,v16,v17,v18,v19,v20,v21,v22,v23,v24; + var block = 0; + for(;;){ + switch(block){ + case 0: + __consts_0.py____test_rsession_webjs_Globals.ofinished = false; + v16 = __consts_0.ExportedMethods; + v17 = v16.show_hosts(host_init); + v18 = __consts_0.ExportedMethods; + v19 = v18.show_sessid(sessid_comeback); + __consts_0.Document.onkeypress = key_pressed; + v21 = __consts_0.Document; + v22 = v21.getElementById(__consts_0.const_str__28); + v23 = v22; + v23.setAttribute(__consts_0.const_str__29,__consts_0.const_str__30); + block = 1; + break; + case 1: + return ( v14 ); + } + } +} + +function ll_listiter__Record_index__Signed__iterable_List_S (ITER_0,lst_0) { + var v164,v165,v166,v167; + var block = 0; + for(;;){ + switch(block){ + case 0: + v165 = new Object(); + v165.iterable = lst_0; + v165.index = 0; + v164 = v165; + block = 1; + break; + case 1: + return ( v164 ); + } + } +} + +function create_text_elem (txt_0) { + var v141,v142,v143; + var block = 0; + for(;;){ + switch(block){ + case 0: + v142 = __consts_0.Document; + v143 = v142.createTextNode(txt_0); + v141 = v143; + block = 1; + break; + case 1: + return ( v141 ); + } + } +} + +function reshow_host () { + var v182,v183,v184,v185,v186,v187; + var block = 0; + for(;;){ + switch(block){ + case 0: + v183 = __consts_0.py____test_rsession_webjs_Globals.ohost; + v184 = ll_streq__String_String ( v183,__consts_0.const_str__5 ); + v185 = v184; + if (v185 == true) + { + block = 2; + break; + } + else{ + block = 1; + break; + } + case 1: + v186 = __consts_0.py____test_rsession_webjs_Globals.ohost; + show_host ( v186 ); + block = 2; + break; + case 2: + return ( v182 ); + } + } +} + +function host_init (host_dict_0) { + var v234,v235,v236,v237,v238,v239,host_dict_1,tbody_3,v240,v241,last_exc_value_1,host_dict_2,tbody_4,host_0,v242,v243,v244,v245,v246,v247,v248,v249,v250,v251,v252,v253,v254,v255,v256,v257,v258,v259,v260,v261,v262,v263,v264,v265,v266,v267,v268,host_dict_3,v269,v270,v271,v272,v273,v274,v275,v276,last_exc_value_2,key_6,v277,v278,v279,v280,v281; + var block = 0; + for(;;){ + switch(block){ + case 0: + v235 = __consts_0.Document; + v236 = v235.getElementById(__consts_0.const_str__31); + v237 = host_dict_0; + v238 = ll_dict_kvi__Dict_String__String__List_String_LlT_ ( v237,undefined,undefined ); + v239 = ll_listiter__Record_index__Signed__iterable_List_S ( undefined,v238 ); host_dict_1 = host_dict_0; - tbody_3 = v134; - v138 = v137; + tbody_3 = v236; + v240 = v239; block = 1; break; case 1: try { - v139 = ll_listnext__Record_index__Signed__iterable_0 ( v138 ); + v241 = ll_listnext__Record_index__Signed__iterable_0 ( v240 ); host_dict_2 = host_dict_1; tbody_4 = tbody_3; - host_0 = v139; - v140 = v138; + host_0 = v241; + v242 = v240; block = 2; break; } @@ -627,52 +1167,52 @@ function host_init (host_dict_0) { throw(exc); } case 2: - v141 = create_elem ( __consts_0.const_str__16 ); - v142 = tbody_4; - v142.appendChild(v141); - v144 = create_elem ( __consts_0.const_str__17 ); - v145 = v144.style; - v145.background = __consts_0.const_str__18; - v147 = ll_dict_getitem__Dict_String__String__String ( host_dict_2,host_0 ); - v148 = create_text_elem ( v147 ); - v149 = v144; - v149.appendChild(v148); - v144.id = host_0; - v152 = v141; - v152.appendChild(v144); - v154 = v144; - v155 = new StringBuilder(); - v155.ll_append(__consts_0.const_str__19); - v157 = ll_str__StringR_StringConst_String ( undefined,host_0 ); - v155.ll_append(v157); - v155.ll_append(__consts_0.const_str__20); - v160 = v155.ll_build(); - v154.setAttribute(__consts_0.const_str__21,v160); - v162 = v144; - v162.setAttribute(__consts_0.const_str__22,__consts_0.const_str__23); + v243 = create_elem ( __consts_0.const_str__13 ); + v244 = tbody_4; + v244.appendChild(v243); + v246 = create_elem ( __consts_0.const_str__14 ); + v247 = v246.style; + v247.background = __consts_0.const_str__32; + v249 = ll_dict_getitem__Dict_String__String__String ( host_dict_2,host_0 ); + v250 = create_text_elem ( v249 ); + v251 = v246; + v251.appendChild(v250); + v246.id = host_0; + v254 = v243; + v254.appendChild(v246); + v256 = v246; + v257 = new StringBuilder(); + v257.ll_append(__consts_0.const_str__33); + v259 = ll_str__StringR_StringConst_String ( undefined,host_0 ); + v257.ll_append(v259); + v257.ll_append(__consts_0.const_str__34); + v262 = v257.ll_build(); + v256.setAttribute(__consts_0.const_str__35,v262); + v264 = v246; + v264.setAttribute(__consts_0.const_str__36,__consts_0.const_str__37); __consts_0.py____test_rsession_webjs_Globals.orsync_dots = 0; __consts_0.py____test_rsession_webjs_Globals.orsync_done = false; setTimeout ( 'update_rsync()',1000 ); host_dict_1 = host_dict_2; tbody_3 = tbody_4; - v138 = v140; + v240 = v242; block = 1; break; case 3: __consts_0.py____test_rsession_webjs_Globals.ohost_dict = host_dict_3; - v168 = ll_newdict__Dict_String__List_String__LlT ( undefined ); - __consts_0.py____test_rsession_webjs_Globals.ohost_pending = v168; - v170 = host_dict_3; - v171 = ll_dict_kvi__Dict_String__String__List_String_LlT_ ( v170,undefined,undefined ); - v172 = ll_listiter__Record_index__Signed__iterable_List_S ( undefined,v171 ); - v173 = v172; + v270 = ll_newdict__Dict_String__List_String__LlT ( undefined ); + __consts_0.py____test_rsession_webjs_Globals.ohost_pending = v270; + v272 = host_dict_3; + v273 = ll_dict_kvi__Dict_String__String__List_String_LlT_ ( v272,undefined,undefined ); + v274 = ll_listiter__Record_index__Signed__iterable_List_S ( undefined,v273 ); + v275 = v274; block = 4; break; case 4: try { - v174 = ll_listnext__Record_index__Signed__iterable_0 ( v173 ); - key_0 = v174; - v175 = v173; + v276 = ll_listnext__Record_index__Signed__iterable_0 ( v275 ); + key_6 = v276; + v277 = v275; block = 5; break; } @@ -685,174 +1225,53 @@ function host_init (host_dict_0) { throw(exc); } case 5: - v176 = new Array(); - v176.length = 0; - v178 = __consts_0.py____test_rsession_webjs_Globals.ohost_pending; - v178[key_0]=v176; - v173 = v175; + v278 = new Array(); + v278.length = 0; + v280 = __consts_0.py____test_rsession_webjs_Globals.ohost_pending; + v280[key_6]=v278; + v275 = v277; block = 4; break; case 6: - return ( v132 ); + return ( v234 ); } } } function get_elem (el_0) { - var v241,v242,v243; + var v217,v218,v219; var block = 0; for(;;){ switch(block){ case 0: - v242 = __consts_0.Document; - v243 = v242.getElementById(el_0); - v241 = v243; + v218 = __consts_0.Document; + v219 = v218.getElementById(el_0); + v217 = v219; block = 1; break; case 1: - return ( v241 ); + return ( v217 ); } } } -function hide_messagebox () { - var v107,v108,v109,mbox_0,v110,v111,mbox_1,v112,v113,v114,v115; +function ll_strconcat__String_String (obj_0,arg0_0) { + var v220,v221,v222; var block = 0; for(;;){ switch(block){ case 0: - v108 = __consts_0.Document; - v109 = v108.getElementById(__consts_0.const_str__12); - mbox_0 = v109; + v221 = obj_0; + v222 = (v221+arg0_0); + v220 = v222; block = 1; break; case 1: - v110 = mbox_0.childNodes; - v111 = ll_list_is_true__List_ExternalType_ ( v110 ); - if (v111 == true) - { - mbox_1 = mbox_0; - block = 3; - break; - } - else{ - block = 2; - break; - } - case 2: - return ( v107 ); - case 3: - v112 = mbox_1; - v113 = mbox_1.childNodes; - v114 = ll_getitem_nonneg__dum_nocheckConst_List_ExternalT ( undefined,v113,0 ); - v112.removeChild(v114); - mbox_0 = mbox_1; - block = 1; - break; + return ( v220 ); } } } -function py____test_rsession_webjs_Globals () { - this.odata_empty = false; - this.osessid = __consts_0.const_str__24; - this.ohost = __consts_0.const_str__24; - this.orsync_dots = 0; - this.ohost_dict = __consts_0.const_tuple__25; - this.opending = __consts_0.const_list; - this.orsync_done = false; - this.ohost_pending = __consts_0.const_tuple__27; -} - -py____test_rsession_webjs_Globals.prototype.toString = function (){ - return ( '' ); -} - -inherits(py____test_rsession_webjs_Globals,Object); -function create_elem (s_1) { - var v244,v245,v246; - var block = 0; - for(;;){ - switch(block){ - case 0: - v245 = __consts_0.Document; - v246 = v245.createElement(s_1); - v244 = v246; - block = 1; - break; - case 1: - return ( v244 ); - } - } -} - -function ll_dict_getitem__Dict_String__Record_item2__Str_St (d_0,key_1) { - var v184,v185,v186,v187,v188,v189,v190,etype_0,evalue_0,key_2,v191,v192,v193; - var block = 0; - for(;;){ - switch(block){ - case 0: - v185 = d_0; - v186 = (v185[key_1]!=undefined); - v187 = v186; - if (v187 == true) - { - key_2 = key_1; - v191 = d_0; - block = 3; - break; - } - else{ - block = 1; - break; - } - case 1: - v188 = __consts_0.exceptions_KeyError; - v189 = v188.meta; - v190 = v188; - etype_0 = v189; - evalue_0 = v190; - block = 2; - break; - case 2: - throw(evalue_0); - case 3: - v192 = v191; - v193 = v192[key_2]; - v184 = v193; - block = 4; - break; - case 4: - return ( v184 ); - } - } -} - -function create_text_elem (txt_0) { - var v119,v120,v121; - var block = 0; - for(;;){ - switch(block){ - case 0: - v120 = __consts_0.Document; - v121 = v120.createTextNode(txt_0); - v119 = v121; - block = 1; - break; - case 1: - return ( v119 ); - } - } -} - -function exceptions_Exception () { -} - -exceptions_Exception.prototype.toString = function (){ - return ( '' ); -} - -inherits(exceptions_Exception,Object); function exceptions_StandardError () { } @@ -869,277 +1288,19 @@ exceptions_LookupError.prototype.toString = function (){ } inherits(exceptions_LookupError,exceptions_StandardError); -function hide_info () { - var v57,v58,v59,v60,v61; +function ll_dict_getitem__Dict_String__Record_item2__Str_St (d_2,key_4) { + var v223,v224,v225,v226,v227,v228,v229,etype_3,evalue_3,key_5,v230,v231,v232; var block = 0; for(;;){ switch(block){ case 0: - v58 = __consts_0.Document; - v59 = v58.getElementById(__consts_0.const_str__2); - v60 = v59.style; - v60.visibility = __consts_0.const_str__29; - block = 1; - break; - case 1: - return ( v57 ); - } - } -} - -function show_skip (item_name_0) { - var v18,v19,v20; - var block = 0; - for(;;){ - switch(block){ - case 0: - v19 = ll_dict_getitem__Dict_String__String__String ( __consts_0.const_tuple__30,item_name_0 ); - set_msgbox ( item_name_0,v19 ); - block = 1; - break; - case 1: - return ( v18 ); - } - } -} - -function show_host (host_name_0) { - var v62,v63,v64,v65,v66,host_name_1,elem_0,v67,v68,v69,v70,host_name_2,tbody_0,elem_1,v71,v72,last_exc_value_0,host_name_3,tbody_1,elem_2,item_0,v73,v74,v75,v76,v77,v78,v79,v80,v81,v82,host_name_4,tbody_2,elem_3,v83,v84,v85,v86,v87,v88,host_name_5,elem_4,v89,v90,v91,v92; - var block = 0; - for(;;){ - switch(block){ - case 0: - v63 = __consts_0.Document; - v64 = v63.getElementById(__consts_0.const_str__31); - v65 = v64.childNodes; - v66 = ll_list_is_true__List_ExternalType_ ( v65 ); - if (v66 == true) + v224 = d_2; + v225 = (v224[key_4]!=undefined); + v226 = v225; + if (v226 == true) { - host_name_5 = host_name_0; - elem_4 = v64; - block = 6; - break; - } - else{ - host_name_1 = host_name_0; - elem_0 = v64; - block = 1; - break; - } - case 1: - v67 = create_elem ( __consts_0.const_str__32 ); - v68 = __consts_0.py____test_rsession_webjs_Globals.ohost_pending; - v69 = ll_dict_getitem__Dict_String__List_String___String ( v68,host_name_1 ); - v70 = ll_listiter__Record_index__Signed__iterable_List_S ( undefined,v69 ); - host_name_2 = host_name_1; - tbody_0 = v67; - elem_1 = elem_0; - v71 = v70; - block = 2; - break; - case 2: - try { - v72 = ll_listnext__Record_index__Signed__iterable_0 ( v71 ); - host_name_3 = host_name_2; - tbody_1 = tbody_0; - elem_2 = elem_1; - item_0 = v72; - v73 = v71; - block = 3; - break; - } - catch (exc){ - if (isinstanceof(exc, exceptions_StopIteration)) - { - host_name_4 = host_name_2; - tbody_2 = tbody_0; - elem_3 = elem_1; - block = 4; - break; - } - throw(exc); - } - case 3: - v74 = create_elem ( __consts_0.const_str__16 ); - v75 = create_elem ( __consts_0.const_str__17 ); - v76 = v75; - v77 = create_text_elem ( item_0 ); - v76.appendChild(v77); - v79 = v74; - v79.appendChild(v75); - v81 = tbody_1; - v81.appendChild(v74); - host_name_2 = host_name_3; - tbody_0 = tbody_1; - elem_1 = elem_2; - v71 = v73; - block = 2; - break; - case 4: - v83 = elem_3; - v83.appendChild(tbody_2); - v85 = elem_3.style; - v85.visibility = __consts_0.const_str__3; - __consts_0.py____test_rsession_webjs_Globals.ohost = host_name_4; - setTimeout ( 'reshow_host()',100 ); - block = 5; - break; - case 5: - return ( v62 ); - case 6: - v89 = elem_4; - v90 = elem_4.childNodes; - v91 = ll_getitem_nonneg__dum_nocheckConst_List_ExternalT ( undefined,v90,0 ); - v89.removeChild(v91); - host_name_1 = host_name_5; - elem_0 = elem_4; - block = 1; - break; - } - } -} - -function update_rsync () { - var v293,v294,v295,v296,v297,v298,v299,elem_7,v300,v301,v302,v303,v304,v305,v306,v307,v308,elem_8,v309,v310,v311,v312,v313,v314,v315,v316,v317,v318,v319,text_0,elem_9,v320,v321,v322,v323,v324; - var block = 0; - for(;;){ - switch(block){ - case 0: - v294 = __consts_0.Document; - v295 = v294.getElementById(__consts_0.const_str__33); - v296 = __consts_0.py____test_rsession_webjs_Globals.orsync_done; - v297 = v296; - v298 = (v297==1); - v299 = v298; - if (v299 == true) - { - v321 = v295; - block = 5; - break; - } - else{ - elem_7 = v295; - block = 1; - break; - } - case 1: - v300 = __consts_0.py____test_rsession_webjs_Globals.orsync_dots; - v301 = ll_char_mul__Char_Signed ( '.',v300 ); - v302 = ll_strconcat__String_String ( __consts_0.const_str__34,v301 ); - v303 = __consts_0.py____test_rsession_webjs_Globals.orsync_dots; - v304 = (v303+1); - __consts_0.py____test_rsession_webjs_Globals.orsync_dots = v304; - v306 = __consts_0.py____test_rsession_webjs_Globals.orsync_dots; - v307 = (v306>5); - v308 = v307; - if (v308 == true) - { - text_0 = v302; - elem_9 = elem_7; - block = 4; - break; - } - else{ - elem_8 = elem_7; - v309 = v302; - block = 2; - break; - } - case 2: - v310 = new StringBuilder(); - v310.ll_append(__consts_0.const_str__35); - v312 = ll_str__StringR_StringConst_String ( undefined,v309 ); - v310.ll_append(v312); - v310.ll_append(__consts_0.const_str__36); - v315 = v310.ll_build(); - v316 = elem_8.childNodes; - v317 = ll_getitem_nonneg__dum_nocheckConst_List_ExternalT ( undefined,v316,0 ); - v317.nodeValue = v315; - setTimeout ( 'update_rsync()',1000 ); - block = 3; - break; - case 3: - return ( v293 ); - case 4: - __consts_0.py____test_rsession_webjs_Globals.orsync_dots = 0; - elem_8 = elem_9; - v309 = text_0; - block = 2; - break; - case 5: - v322 = v321.childNodes; - v323 = ll_getitem_nonneg__dum_nocheckConst_List_ExternalT ( undefined,v322,0 ); - v323.nodeValue = __consts_0.const_str__33; - block = 3; - break; - } - } -} - -function ll_getitem_nonneg__dum_nocheckConst_List_ExternalT (func_0,l_1,index_0) { - var v122,v123,v124,l_2,index_1,v125,v126,v127,v128,index_2,v129,v130,v131; - var block = 0; - for(;;){ - switch(block){ - case 0: - v123 = (index_0>=0); - undefined; - l_2 = l_1; - index_1 = index_0; - block = 1; - break; - case 1: - v125 = l_2; - v126 = v125.length; - v127 = (index_15); + v344 = v343; + if (v344 == true) + { + text_0 = v338; + elem_9 = elem_7; + block = 5; + break; + } + else{ + elem_8 = elem_7; + v345 = v338; + block = 3; + break; + } + case 3: + v346 = new StringBuilder(); + v346.ll_append(__consts_0.const_str__40); + v348 = ll_str__StringR_StringConst_String ( undefined,v345 ); + v346.ll_append(v348); + v346.ll_append(__consts_0.const_str__41); + v351 = v346.ll_build(); + v352 = elem_8.childNodes; + v353 = ll_getitem_nonneg__dum_nocheckConst_List_ExternalT ( undefined,v352,0 ); + v353.nodeValue = v351; + setTimeout ( 'update_rsync()',1000 ); + block = 4; + break; + case 4: + return ( v327 ); + case 5: + __consts_0.py____test_rsession_webjs_Globals.orsync_dots = 0; + elem_8 = elem_9; + v345 = text_0; + block = 3; + break; + case 6: + v358 = v357.childNodes; + v359 = ll_getitem_nonneg__dum_nocheckConst_List_ExternalT ( undefined,v358,0 ); + v359.nodeValue = __consts_0.const_str__38; + block = 4; + break; + } + } +} + +function key_pressed (key_7) { + var v286,v287,v288,v289,v290,v291,v292,v293,v294,v295,v296,v297,v298,v299,v300,v301; + var block = 0; + for(;;){ + switch(block){ + case 0: + v287 = key_7.charCode; + v288 = (v287==115); + v289 = v288; + if (v289 == true) + { + block = 2; + break; + } + else{ + block = 1; + break; + } + case 1: + return ( v286 ); + case 2: + v290 = __consts_0.Document; + v291 = v290.getElementById(__consts_0.const_str__28); + v292 = __consts_0.py____test_rsession_webjs_Options.oscroll; + v293 = v292; + if (v293 == true) + { + v298 = v291; + block = 4; + break; + } + else{ + v294 = v291; + block = 3; + break; + } + case 3: + v295 = v294; + v295.setAttribute(__consts_0.const_str__29,__consts_0.const_str__42); + __consts_0.py____test_rsession_webjs_Options.oscroll = true; block = 1; break; + case 4: + v299 = v298; + v299.removeAttribute(__consts_0.const_str__29); + __consts_0.py____test_rsession_webjs_Options.oscroll = false; + block = 1; + break; + } + } +} + +function ll_newdict__Dict_String__List_String__LlT (DICT_0) { + var v361,v362; + var block = 0; + for(;;){ + switch(block){ + case 0: + v362 = new Object(); + v361 = v362; + block = 1; + break; + case 1: + return ( v361 ); } } } function comeback (msglist_0) { - var v214,v215,v216,v217,msglist_1,v218,v219,v220,v221,msglist_2,v222,v223,last_exc_value_3,msglist_3,v224,v225,v226,v227,msglist_4,v228,v229,v230,v231,v232,v233,last_exc_value_4,v234,v235,v236,v237,v238,v239,v240; + var v363,v364,v365,v366,msglist_1,v367,v368,v369,v370,msglist_2,v371,v372,last_exc_value_3,msglist_3,v373,v374,v375,v376,msglist_4,v377,v378,v379,v380,v381,v382,last_exc_value_4,v383,v384,v385,v386,v387,v388,v389; var block = 0; for(;;){ switch(block){ case 0: - v215 = ll_len__List_Dict_String__String__ ( msglist_0 ); - v216 = (v215==0); - v217 = v216; - if (v217 == true) + v364 = ll_len__List_Dict_String__String__ ( msglist_0 ); + v365 = (v364==0); + v366 = v365; + if (v366 == true) { block = 4; break; @@ -1406,20 +1642,20 @@ function comeback (msglist_0) { break; } case 1: - v218 = __consts_0.py____test_rsession_webjs_Globals.opending; - v219 = 0; - v220 = ll_listslice_startonly__List_Dict_String__String__ ( undefined,v218,v219 ); - v221 = ll_listiter__Record_index__Signed__iterable_List_D ( undefined,v220 ); + v367 = __consts_0.py____test_rsession_webjs_Globals.opending; + v368 = 0; + v369 = ll_listslice_startonly__List_Dict_String__String__ ( undefined,v367,v368 ); + v370 = ll_listiter__Record_index__Signed__iterable_List_D ( undefined,v369 ); msglist_2 = msglist_1; - v222 = v221; + v371 = v370; block = 2; break; case 2: try { - v223 = ll_listnext__Record_index__Signed__iterable ( v222 ); + v372 = ll_listnext__Record_index__Signed__iterable ( v371 ); msglist_3 = msglist_2; - v224 = v222; - v225 = v223; + v373 = v371; + v374 = v372; block = 3; break; } @@ -1433,12 +1669,12 @@ function comeback (msglist_0) { throw(exc); } case 3: - v226 = process ( v225 ); - v227 = v226; - if (v227 == true) + v375 = process ( v374 ); + v376 = v375; + if (v376 == true) { msglist_2 = msglist_3; - v222 = v224; + v371 = v373; block = 2; break; } @@ -1447,20 +1683,20 @@ function comeback (msglist_0) { break; } case 4: - return ( v214 ); + return ( v363 ); case 5: - v228 = new Array(); - v228.length = 0; - __consts_0.py____test_rsession_webjs_Globals.opending = v228; - v231 = ll_listiter__Record_index__Signed__iterable_List_D ( undefined,msglist_4 ); - v232 = v231; + v377 = new Array(); + v377.length = 0; + __consts_0.py____test_rsession_webjs_Globals.opending = v377; + v380 = ll_listiter__Record_index__Signed__iterable_List_D ( undefined,msglist_4 ); + v381 = v380; block = 6; break; case 6: try { - v233 = ll_listnext__Record_index__Signed__iterable ( v232 ); - v234 = v232; - v235 = v233; + v382 = ll_listnext__Record_index__Signed__iterable ( v381 ); + v383 = v381; + v384 = v382; block = 7; break; } @@ -1473,11 +1709,11 @@ function comeback (msglist_0) { throw(exc); } case 7: - v236 = process ( v235 ); - v237 = v236; - if (v237 == true) + v385 = process ( v384 ); + v386 = v385; + if (v386 == true) { - v232 = v234; + v381 = v383; block = 6; break; } @@ -1486,559 +1722,34 @@ function comeback (msglist_0) { break; } case 8: - v238 = __consts_0.ExportedMethods; - v239 = __consts_0.py____test_rsession_webjs_Globals.osessid; - v240 = v238.show_all_statuses(v239,comeback); + v387 = __consts_0.ExportedMethods; + v388 = __consts_0.py____test_rsession_webjs_Globals.osessid; + v389 = v387.show_all_statuses(v388,comeback); block = 4; break; } } } -function ll_listnext__Record_index__Signed__iterable_0 (iter_0) { - var v269,v270,v271,v272,v273,v274,v275,iter_1,index_3,l_3,v276,v277,v278,v279,v280,v281,v282,etype_1,evalue_1; - var block = 0; - for(;;){ - switch(block){ - case 0: - v270 = iter_0.iterable; - v271 = iter_0.index; - v272 = v270; - v273 = v272.length; - v274 = (v271>=v273); - v275 = v274; - if (v275 == true) - { - block = 3; - break; - } - else{ - iter_1 = iter_0; - index_3 = v271; - l_3 = v270; - block = 1; - break; - } - case 1: - v276 = (index_3+1); - iter_1.index = v276; - v278 = l_3; - v279 = v278[index_3]; - v269 = v279; - block = 2; - break; - case 2: - return ( v269 ); - case 3: - v280 = __consts_0.exceptions_StopIteration; - v281 = v280.meta; - v282 = v280; - etype_1 = v281; - evalue_1 = v282; - block = 4; - break; - case 4: - throw(evalue_1); - } - } -} - -function ll_listnext__Record_index__Signed__iterable (iter_2) { - var v391,v392,v393,v394,v395,v396,v397,iter_3,index_4,l_8,v398,v399,v400,v401,v402,v403,v404,etype_4,evalue_4; - var block = 0; - for(;;){ - switch(block){ - case 0: - v392 = iter_2.iterable; - v393 = iter_2.index; - v394 = v392; - v395 = v394.length; - v396 = (v393>=v395); - v397 = v396; - if (v397 == true) - { - block = 3; - break; - } - else{ - iter_3 = iter_2; - index_4 = v393; - l_8 = v392; - block = 1; - break; - } - case 1: - v398 = (index_4+1); - iter_3.index = v398; - v400 = l_8; - v401 = v400[index_4]; - v391 = v401; - block = 2; - break; - case 2: - return ( v391 ); - case 3: - v402 = __consts_0.exceptions_StopIteration; - v403 = v402.meta; - v404 = v402; - etype_4 = v403; - evalue_4 = v404; - block = 4; - break; - case 4: - throw(evalue_4); - } - } -} - -function process (msg_0) { - var v405,v406,v407,v408,msg_1,v409,v410,v411,v412,v413,v414,v415,msg_2,v416,v417,v418,msg_3,v419,v420,v421,msg_4,v422,v423,v424,msg_5,v425,v426,v427,msg_6,v428,v429,v430,msg_7,v431,v432,v433,v434,v435,v436,v437,v438,v439,v440,v441,v442,v443,msg_8,v444,v445,v446,msg_9,v447,v448,v449,msg_10,module_part_0,v450,v451,v452,v453,v454,v455,v456,v457,v458,v459,v460,v461,v462,v463,v464,v465,v466,v467,v468,msg_11,v469,v470,v471,msg_12,v472,v473,v474,module_part_1,v475,v476,v477,v478,v479,v480,v481,v482,v483,msg_13,v484,v485,v486,v487,v488,v489,v490,v491,v492,v493,v494,v495,v496,v497,v498,v499,v500,v501,v502,v503,v504,v505,v506,v507,v508,v509,v510,v511,v512,v513,v514,v515,v516,v517,v518,v519,v520,v521,v522,msg_14,v523,v524,v525,msg_15,v526,v527,v528,v529,v530,v531,msg_16,v532,v533,v534,v535,v536,v537,v538,v539,v540,v541,v542,v543,v544,v545,v546,v547,v548,v549,v550,msg_17,v551,v552,v553,v554,v555,v556,v557,v558,v559,v560,v561,v562,v563,v564,v565,v566,v567,v568,v569,v570,v571,v572,v573,v574,v575,v576,v577,v578,v579,v580,v581,v582,main_t_0,v583,v584,v585,v586; - var block = 0; - for(;;){ - switch(block){ - case 0: - v406 = get_dict_len ( msg_0 ); - v407 = (v406==0); - v408 = v407; - if (v408 == true) - { - v405 = false; - block = 10; - break; - } - else{ - msg_1 = msg_0; - block = 1; - break; - } - case 1: - v409 = __consts_0.Document; - v410 = v409.getElementById(__consts_0.const_str__38); - v411 = __consts_0.Document; - v412 = v411.getElementById(__consts_0.const_str__39); - v413 = ll_dict_getitem__Dict_String__String__String ( msg_1,__consts_0.const_str__40 ); - v414 = ll_streq__String_String ( v413,__consts_0.const_str__41 ); - v415 = v414; - if (v415 == true) - { - main_t_0 = v412; - v583 = msg_1; - block = 25; - break; - } - else{ - msg_2 = msg_1; - block = 2; - break; - } - case 2: - v416 = ll_dict_getitem__Dict_String__String__String ( msg_2,__consts_0.const_str__40 ); - v417 = ll_streq__String_String ( v416,__consts_0.const_str__42 ); - v418 = v417; - if (v418 == true) - { - msg_17 = msg_2; - block = 24; - break; - } - else{ - msg_3 = msg_2; - block = 3; - break; - } - case 3: - v419 = ll_dict_getitem__Dict_String__String__String ( msg_3,__consts_0.const_str__40 ); - v420 = ll_streq__String_String ( v419,__consts_0.const_str__43 ); - v421 = v420; - if (v421 == true) - { - msg_16 = msg_3; - block = 23; - break; - } - else{ - msg_4 = msg_3; - block = 4; - break; - } - case 4: - v422 = ll_dict_getitem__Dict_String__String__String ( msg_4,__consts_0.const_str__40 ); - v423 = ll_streq__String_String ( v422,__consts_0.const_str__44 ); - v424 = v423; - if (v424 == true) - { - msg_14 = msg_4; - block = 20; - break; - } - else{ - msg_5 = msg_4; - block = 5; - break; - } - case 5: - v425 = ll_dict_getitem__Dict_String__String__String ( msg_5,__consts_0.const_str__40 ); - v426 = ll_streq__String_String ( v425,__consts_0.const_str__45 ); - v427 = v426; - if (v427 == true) - { - msg_13 = msg_5; - block = 19; - break; - } - else{ - msg_6 = msg_5; - block = 6; - break; - } - case 6: - v428 = ll_dict_getitem__Dict_String__String__String ( msg_6,__consts_0.const_str__40 ); - v429 = ll_streq__String_String ( v428,__consts_0.const_str__46 ); - v430 = v429; - if (v430 == true) - { - msg_11 = msg_6; - block = 16; - break; - } - else{ - msg_7 = msg_6; - block = 7; - break; - } - case 7: - v431 = ll_dict_getitem__Dict_String__String__String ( msg_7,__consts_0.const_str__40 ); - v432 = ll_streq__String_String ( v431,__consts_0.const_str__47 ); - v433 = v432; - if (v433 == true) - { - msg_8 = msg_7; - block = 13; - break; - } - else{ - v434 = msg_7; - block = 8; - break; - } - case 8: - v435 = ll_dict_getitem__Dict_String__String__String ( v434,__consts_0.const_str__40 ); - v436 = ll_streq__String_String ( v435,__consts_0.const_str__48 ); - v437 = v436; - if (v437 == true) - { - block = 12; - break; - } - else{ - block = 9; - break; - } - case 9: - v438 = __consts_0.py____test_rsession_webjs_Globals.odata_empty; - v439 = v438; - if (v439 == true) - { - block = 11; - break; - } - else{ - v405 = true; - block = 10; - break; - } - case 10: - return ( v405 ); - case 11: - v440 = __consts_0.Document; - v441 = v440.getElementById(__consts_0.const_str__12); - scroll_down_if_needed ( v441 ); - v405 = true; - block = 10; - break; - case 12: - __consts_0.py____test_rsession_webjs_Globals.orsync_done = true; - block = 9; - break; - case 13: - v444 = ll_dict_getitem__Dict_String__String__String ( msg_8,__consts_0.const_str__49 ); - v445 = get_elem ( v444 ); - v446 = !!v445; - if (v446 == true) - { - msg_10 = msg_8; - module_part_0 = v445; - block = 15; - break; - } - else{ - msg_9 = msg_8; - block = 14; - break; - } - case 14: - v447 = __consts_0.py____test_rsession_webjs_Globals.opending; - v448 = v447; - ll_append__List_Dict_String__String___Dict_String_ ( v448,msg_9 ); - v405 = true; - block = 10; - break; - case 15: - v450 = create_elem ( __consts_0.const_str__16 ); - v451 = create_elem ( __consts_0.const_str__17 ); - v452 = ll_dict_getitem__Dict_String__String__String ( msg_10,__consts_0.const_str__50 ); - v453 = new Object(); - v453.item0 = v452; - v455 = v453.item0; - v456 = new StringBuilder(); - v456.ll_append(__consts_0.const_str__51); - v458 = ll_str__StringR_StringConst_String ( undefined,v455 ); - v456.ll_append(v458); - v456.ll_append(__consts_0.const_str__52); - v461 = v456.ll_build(); - v462 = create_text_elem ( v461 ); - v463 = v451; - v463.appendChild(v462); - v465 = v450; - v465.appendChild(v451); - v467 = module_part_0; - v467.appendChild(v450); - block = 9; - break; - case 16: - v469 = ll_dict_getitem__Dict_String__String__String ( msg_11,__consts_0.const_str__49 ); - v470 = get_elem ( v469 ); - v471 = !!v470; - if (v471 == true) - { - module_part_1 = v470; - block = 18; - break; - } - else{ - msg_12 = msg_11; - block = 17; - break; - } - case 17: - v472 = __consts_0.py____test_rsession_webjs_Globals.opending; - v473 = v472; - ll_append__List_Dict_String__String___Dict_String_ ( v473,msg_12 ); - v405 = true; - block = 10; - break; - case 18: - v475 = create_elem ( __consts_0.const_str__16 ); - v476 = create_elem ( __consts_0.const_str__17 ); - v477 = create_text_elem ( __consts_0.const_str__53 ); - v478 = v476; - v478.appendChild(v477); - v480 = v475; - v480.appendChild(v476); - v482 = module_part_1; - v482.appendChild(v475); - block = 9; - break; - case 19: - v484 = ll_dict_getitem__Dict_String__String__String ( msg_13,__consts_0.const_str__54 ); - v485 = ll_dict_getitem__Dict_String__String__String ( msg_13,__consts_0.const_str__55 ); - v486 = ll_dict_getitem__Dict_String__String__String ( msg_13,__consts_0.const_str__56 ); - v487 = new Object(); - v487.item0 = v484; - v487.item1 = v485; - v487.item2 = v486; - v491 = v487.item0; - v492 = v487.item1; - v493 = v487.item2; - v494 = new StringBuilder(); - v494.ll_append(__consts_0.const_str__57); - v496 = ll_str__StringR_StringConst_String ( undefined,v491 ); - v494.ll_append(v496); - v494.ll_append(__consts_0.const_str__58); - v499 = ll_str__StringR_StringConst_String ( undefined,v492 ); - v494.ll_append(v499); - v494.ll_append(__consts_0.const_str__59); - v502 = ll_str__StringR_StringConst_String ( undefined,v493 ); - v494.ll_append(v502); - v494.ll_append(__consts_0.const_str__60); - v505 = v494.ll_build(); - v506 = new StringBuilder(); - v506.ll_append(__consts_0.const_str__61); - v508 = ll_str__StringR_StringConst_String ( undefined,v505 ); - v506.ll_append(v508); - v510 = v506.ll_build(); - __consts_0.Document.title = v510; - v512 = new StringBuilder(); - v512.ll_append(__consts_0.const_str__35); - v514 = ll_str__StringR_StringConst_String ( undefined,v505 ); - v512.ll_append(v514); - v512.ll_append(__consts_0.const_str__36); - v517 = v512.ll_build(); - v518 = __consts_0.Document; - v519 = v518.getElementById(__consts_0.const_str__33); - v520 = v519.childNodes; - v521 = ll_getitem_nonneg__dum_nocheckConst_List_ExternalT ( undefined,v520,0 ); - v521.nodeValue = v517; - block = 9; - break; - case 20: - v523 = ll_dict_getitem__Dict_String__String__String ( msg_14,__consts_0.const_str__62 ); - v524 = get_elem ( v523 ); - v525 = !!v524; - if (v525 == true) - { - v529 = msg_14; - v530 = v524; - block = 22; - break; - } - else{ - msg_15 = msg_14; - block = 21; - break; - } - case 21: - v526 = __consts_0.py____test_rsession_webjs_Globals.opending; - v527 = v526; - ll_append__List_Dict_String__String___Dict_String_ ( v527,msg_15 ); - v405 = true; - block = 10; - break; - case 22: - add_received_item_outcome ( v529,v530 ); - block = 9; - break; - case 23: - v532 = __consts_0.Document; - v533 = ll_dict_getitem__Dict_String__String__String ( msg_16,__consts_0.const_str__63 ); - v534 = v532.getElementById(v533); - v535 = v534.style; - v535.background = __consts_0.const_str__64; - v537 = __consts_0.py____test_rsession_webjs_Globals.ohost_dict; - v538 = ll_dict_getitem__Dict_String__String__String ( msg_16,__consts_0.const_str__63 ); - v539 = ll_dict_getitem__Dict_String__String__String ( v537,v538 ); - v540 = new Object(); - v540.item0 = v539; - v542 = v540.item0; - v543 = new StringBuilder(); - v544 = ll_str__StringR_StringConst_String ( undefined,v542 ); - v543.ll_append(v544); - v543.ll_append(__consts_0.const_str__65); - v547 = v543.ll_build(); - v548 = v534.childNodes; - v549 = ll_getitem_nonneg__dum_nocheckConst_List_ExternalT ( undefined,v548,0 ); - v549.nodeValue = v547; - block = 9; - break; - case 24: - v551 = __consts_0.Document; - v552 = ll_dict_getitem__Dict_String__String__String ( msg_17,__consts_0.const_str__63 ); - v553 = v551.getElementById(v552); - v554 = __consts_0.py____test_rsession_webjs_Globals.ohost_pending; - v555 = ll_dict_getitem__Dict_String__String__String ( msg_17,__consts_0.const_str__63 ); - v556 = ll_dict_getitem__Dict_String__List_String___String ( v554,v555 ); - v557 = v556; - v558 = ll_dict_getitem__Dict_String__String__String ( msg_17,__consts_0.const_str__49 ); - ll_prepend__List_String__String ( v557,v558 ); - v560 = __consts_0.py____test_rsession_webjs_Globals.ohost_pending; - v561 = ll_dict_getitem__Dict_String__String__String ( msg_17,__consts_0.const_str__63 ); - v562 = ll_dict_getitem__Dict_String__List_String___String ( v560,v561 ); - v563 = ll_len__List_String_ ( v562 ); - v564 = __consts_0.py____test_rsession_webjs_Globals.ohost_dict; - v565 = ll_dict_getitem__Dict_String__String__String ( msg_17,__consts_0.const_str__63 ); - v566 = ll_dict_getitem__Dict_String__String__String ( v564,v565 ); - v567 = new Object(); - v567.item0 = v566; - v567.item1 = v563; - v570 = v567.item0; - v571 = v567.item1; - v572 = new StringBuilder(); - v573 = ll_str__StringR_StringConst_String ( undefined,v570 ); - v572.ll_append(v573); - v572.ll_append(__consts_0.const_str__66); - v576 = ll_int_str__IntegerR_SignedConst_Signed ( undefined,v571 ); - v572.ll_append(v576); - v572.ll_append(__consts_0.const_str__36); - v579 = v572.ll_build(); - v580 = v553.childNodes; - v581 = ll_getitem_nonneg__dum_nocheckConst_List_ExternalT ( undefined,v580,0 ); - v581.nodeValue = v579; - block = 9; - break; - case 25: - v584 = make_module_box ( v583 ); - v585 = main_t_0; - v585.appendChild(v584); - block = 9; - break; - } - } -} - -function ll_int_str__IntegerR_SignedConst_Signed (repr_0,i_6) { - var v782,v783; - var block = 0; - for(;;){ - switch(block){ - case 0: - v783 = ll_int2dec__Signed ( i_6 ); - v782 = v783; - block = 1; - break; - case 1: - return ( v782 ); - } - } -} - -function reshow_host () { - var v344,v345,v346,v347,v348,v349; - var block = 0; - for(;;){ - switch(block){ - case 0: - v345 = __consts_0.py____test_rsession_webjs_Globals.ohost; - v346 = ll_streq__String_String ( v345,__consts_0.const_str__24 ); - v347 = v346; - if (v347 == true) - { - block = 2; - break; - } - else{ - block = 1; - break; - } - case 1: - v348 = __consts_0.py____test_rsession_webjs_Globals.ohost; - show_host ( v348 ); - block = 2; - break; - case 2: - return ( v344 ); - } - } -} - function ll_char_mul__Char_Signed (ch_0,times_0) { - var v350,v351,v352,v353,ch_1,times_1,i_2,buf_0,v354,v355,v356,v357,v358,ch_2,times_2,i_3,buf_1,v359,v360,v361; + var v394,v395,v396,v397,ch_1,times_1,i_2,buf_0,v398,v399,v400,v401,v402,ch_2,times_2,i_3,buf_1,v403,v404,v405; var block = 0; for(;;){ switch(block){ case 0: - v351 = new StringBuilder(); - v352 = v351; - v352.ll_allocate(times_0); + v395 = new StringBuilder(); + v396 = v395; + v396.ll_allocate(times_0); ch_1 = ch_0; times_1 = times_0; i_2 = 0; - buf_0 = v351; + buf_0 = v395; block = 1; break; case 1: - v354 = (i_20); - v770 = v769; - if (v770 == true) - { - l_12 = l_11; - newitem_4 = newitem_2; - dst_1 = dst_0; - block = 4; - break; - } - else{ - newitem_3 = newitem_2; - v771 = l_11; - block = 2; - break; - } - case 2: - v772 = v771; - v772[0]=newitem_3; - block = 3; - break; - case 3: - return ( v763 ); - case 4: - v774 = (dst_1-1); - v775 = l_12; - v776 = l_12; - v777 = v776[v774]; - v775[dst_1]=v777; - l_11 = l_12; - newitem_2 = newitem_4; - dst_0 = v774; - block = 1; - break; - } - } -} - function ll_listslice_startonly__List_Dict_String__String__ (RESLIST_0,l1_0,start_0) { - var v369,v370,v371,v372,v373,v374,v375,v376,v377,v378,l1_1,i_4,j_0,l_6,len1_0,v379,v380,l1_2,i_5,j_1,l_7,len1_1,v381,v382,v383,v384,v385,v386; + var v409,v410,v411,v412,v413,v414,v415,v416,v417,v418,l1_1,i_4,j_0,l_6,len1_0,v419,v420,l1_2,i_5,j_1,l_7,len1_1,v421,v422,v423,v424,v425,v426; var block = 0; for(;;){ switch(block){ case 0: - v370 = l1_0; - v371 = v370.length; - v372 = (start_0>=0); + v410 = l1_0; + v411 = v410.length; + v412 = (start_0>=0); undefined; - v374 = (start_0<=v371); + v414 = (start_0<=v411); undefined; - v376 = (v371-start_0); + v416 = (v411-start_0); undefined; - v378 = ll_newlist__List_Dict_String__String__LlT_Signed ( undefined,v376 ); + v418 = ll_newlist__List_Dict_String__String__LlT_Signed ( undefined,v416 ); l1_1 = l1_0; i_4 = start_0; j_0 = 0; - l_6 = v378; - len1_0 = v371; + l_6 = v418; + len1_0 = v411; block = 1; break; case 1: - v379 = (i_4' ); -} - -inherits(exceptions_StopIteration,exceptions_Exception); -function scroll_down_if_needed (mbox_2) { - var v597,v598,v599,v600,v601,v602,v603,v604,v605,v606; - var block = 0; - for(;;){ - switch(block){ - case 0: - v598 = __consts_0.Window.scrollMaxY; - v599 = __consts_0.Window.scrollY; - v600 = (v598-v599); - v601 = (v600<50); - v602 = v601; - if (v602 == true) + v446 = get_dict_len ( msg_0 ); + v447 = (v446==0); + v448 = v447; + if (v448 == true) { - v603 = mbox_2; - block = 2; + v445 = false; + block = 12; break; } else{ + msg_1 = msg_0; block = 1; break; } case 1: - return ( v597 ); + v449 = __consts_0.Document; + v450 = v449.getElementById(__consts_0.const_str__43); + v451 = __consts_0.Document; + v452 = v451.getElementById(__consts_0.const_str__44); + v453 = ll_dict_getitem__Dict_String__String__String ( msg_1,__consts_0.const_str__45 ); + v454 = ll_streq__String_String ( v453,__consts_0.const_str__46 ); + v455 = v454; + if (v455 == true) + { + main_t_0 = v452; + v632 = msg_1; + block = 29; + break; + } + else{ + msg_2 = msg_1; + block = 2; + break; + } case 2: - v604 = v603.parentNode; - v605 = v604; - v605.scrollIntoView(); + v456 = ll_dict_getitem__Dict_String__String__String ( msg_2,__consts_0.const_str__45 ); + v457 = ll_streq__String_String ( v456,__consts_0.const_str__47 ); + v458 = v457; + if (v458 == true) + { + msg_19 = msg_2; + block = 28; + break; + } + else{ + msg_3 = msg_2; + block = 3; + break; + } + case 3: + v459 = ll_dict_getitem__Dict_String__String__String ( msg_3,__consts_0.const_str__45 ); + v460 = ll_streq__String_String ( v459,__consts_0.const_str__48 ); + v461 = v460; + if (v461 == true) + { + msg_18 = msg_3; + block = 27; + break; + } + else{ + msg_4 = msg_3; + block = 4; + break; + } + case 4: + v462 = ll_dict_getitem__Dict_String__String__String ( msg_4,__consts_0.const_str__45 ); + v463 = ll_streq__String_String ( v462,__consts_0.const_str__49 ); + v464 = v463; + if (v464 == true) + { + msg_16 = msg_4; + block = 24; + break; + } + else{ + msg_5 = msg_4; + block = 5; + break; + } + case 5: + v465 = ll_dict_getitem__Dict_String__String__String ( msg_5,__consts_0.const_str__45 ); + v466 = ll_streq__String_String ( v465,__consts_0.const_str__50 ); + v467 = v466; + if (v467 == true) + { + msg_15 = msg_5; + block = 23; + break; + } + else{ + msg_6 = msg_5; + block = 6; + break; + } + case 6: + v468 = ll_dict_getitem__Dict_String__String__String ( msg_6,__consts_0.const_str__45 ); + v469 = ll_streq__String_String ( v468,__consts_0.const_str__51 ); + v470 = v469; + if (v470 == true) + { + msg_13 = msg_6; + block = 20; + break; + } + else{ + msg_7 = msg_6; + block = 7; + break; + } + case 7: + v471 = ll_dict_getitem__Dict_String__String__String ( msg_7,__consts_0.const_str__45 ); + v472 = ll_streq__String_String ( v471,__consts_0.const_str__52 ); + v473 = v472; + if (v473 == true) + { + msg_10 = msg_7; + block = 17; + break; + } + else{ + msg_8 = msg_7; + block = 8; + break; + } + case 8: + v474 = ll_dict_getitem__Dict_String__String__String ( msg_8,__consts_0.const_str__45 ); + v475 = ll_streq__String_String ( v474,__consts_0.const_str__53 ); + v476 = v475; + if (v476 == true) + { + block = 16; + break; + } + else{ + msg_9 = msg_8; + block = 9; + break; + } + case 9: + v477 = ll_dict_getitem__Dict_String__String__String ( msg_9,__consts_0.const_str__45 ); + v478 = ll_streq__String_String ( v477,__consts_0.const_str__54 ); + v479 = v478; + if (v479 == true) + { + block = 15; + break; + } + else{ + v480 = msg_9; + block = 10; + break; + } + case 10: + v481 = ll_dict_getitem__Dict_String__String__String ( v480,__consts_0.const_str__45 ); + v482 = ll_streq__String_String ( v481,__consts_0.const_str__55 ); + v483 = v482; + if (v483 == true) + { + block = 14; + break; + } + else{ + block = 11; + break; + } + case 11: + v484 = __consts_0.py____test_rsession_webjs_Globals.odata_empty; + v485 = v484; + if (v485 == true) + { + block = 13; + break; + } + else{ + v445 = true; + block = 12; + break; + } + case 12: + return ( v445 ); + case 13: + v486 = __consts_0.Document; + v487 = v486.getElementById(__consts_0.const_str__17); + scroll_down_if_needed ( v487 ); + v445 = true; + block = 12; + break; + case 14: + show_crash ( ); + block = 11; + break; + case 15: + show_interrupt ( ); + block = 11; + break; + case 16: + __consts_0.py____test_rsession_webjs_Globals.orsync_done = true; + block = 11; + break; + case 17: + v492 = ll_dict_getitem__Dict_String__String__String ( msg_10,__consts_0.const_str__56 ); + v493 = get_elem ( v492 ); + v494 = !!v493; + if (v494 == true) + { + msg_12 = msg_10; + module_part_0 = v493; + block = 19; + break; + } + else{ + msg_11 = msg_10; + block = 18; + break; + } + case 18: + v495 = __consts_0.py____test_rsession_webjs_Globals.opending; + v496 = v495; + ll_append__List_Dict_String__String___Dict_String_ ( v496,msg_11 ); + v445 = true; + block = 12; + break; + case 19: + v498 = create_elem ( __consts_0.const_str__13 ); + v499 = create_elem ( __consts_0.const_str__14 ); + v500 = ll_dict_getitem__Dict_String__String__String ( msg_12,__consts_0.const_str__57 ); + v501 = new Object(); + v501.item0 = v500; + v503 = v501.item0; + v504 = new StringBuilder(); + v504.ll_append(__consts_0.const_str__58); + v506 = ll_str__StringR_StringConst_String ( undefined,v503 ); + v504.ll_append(v506); + v504.ll_append(__consts_0.const_str__59); + v509 = v504.ll_build(); + v510 = create_text_elem ( v509 ); + v511 = v499; + v511.appendChild(v510); + v513 = v498; + v513.appendChild(v499); + v515 = module_part_0; + v515.appendChild(v498); + block = 11; + break; + case 20: + v517 = ll_dict_getitem__Dict_String__String__String ( msg_13,__consts_0.const_str__56 ); + v518 = get_elem ( v517 ); + v519 = !!v518; + if (v519 == true) + { + module_part_1 = v518; + block = 22; + break; + } + else{ + msg_14 = msg_13; + block = 21; + break; + } + case 21: + v520 = __consts_0.py____test_rsession_webjs_Globals.opending; + v521 = v520; + ll_append__List_Dict_String__String___Dict_String_ ( v521,msg_14 ); + v445 = true; + block = 12; + break; + case 22: + v523 = create_elem ( __consts_0.const_str__13 ); + v524 = create_elem ( __consts_0.const_str__14 ); + v525 = create_text_elem ( __consts_0.const_str__60 ); + v526 = v524; + v526.appendChild(v525); + v528 = v523; + v528.appendChild(v524); + v530 = module_part_1; + v530.appendChild(v523); + block = 11; + break; + case 23: + v532 = ll_dict_getitem__Dict_String__String__String ( msg_15,__consts_0.const_str__61 ); + v533 = ll_dict_getitem__Dict_String__String__String ( msg_15,__consts_0.const_str__62 ); + v534 = ll_dict_getitem__Dict_String__String__String ( msg_15,__consts_0.const_str__63 ); + v535 = new Object(); + v535.item0 = v532; + v535.item1 = v533; + v535.item2 = v534; + v539 = v535.item0; + v540 = v535.item1; + v541 = v535.item2; + v542 = new StringBuilder(); + v542.ll_append(__consts_0.const_str__64); + v544 = ll_str__StringR_StringConst_String ( undefined,v539 ); + v542.ll_append(v544); + v542.ll_append(__consts_0.const_str__65); + v547 = ll_str__StringR_StringConst_String ( undefined,v540 ); + v542.ll_append(v547); + v542.ll_append(__consts_0.const_str__66); + v550 = ll_str__StringR_StringConst_String ( undefined,v541 ); + v542.ll_append(v550); + v542.ll_append(__consts_0.const_str__67); + v553 = v542.ll_build(); + __consts_0.py____test_rsession_webjs_Globals.ofinished = true; + v555 = new StringBuilder(); + v555.ll_append(__consts_0.const_str__68); + v557 = ll_str__StringR_StringConst_String ( undefined,v553 ); + v555.ll_append(v557); + v559 = v555.ll_build(); + __consts_0.Document.title = v559; + v561 = new StringBuilder(); + v561.ll_append(__consts_0.const_str__40); + v563 = ll_str__StringR_StringConst_String ( undefined,v553 ); + v561.ll_append(v563); + v561.ll_append(__consts_0.const_str__41); + v566 = v561.ll_build(); + v567 = __consts_0.Document; + v568 = v567.getElementById(__consts_0.const_str__38); + v569 = v568.childNodes; + v570 = ll_getitem_nonneg__dum_nocheckConst_List_ExternalT ( undefined,v569,0 ); + v570.nodeValue = v566; + block = 11; + break; + case 24: + v572 = ll_dict_getitem__Dict_String__String__String ( msg_16,__consts_0.const_str__69 ); + v573 = get_elem ( v572 ); + v574 = !!v573; + if (v574 == true) + { + v578 = msg_16; + v579 = v573; + block = 26; + break; + } + else{ + msg_17 = msg_16; + block = 25; + break; + } + case 25: + v575 = __consts_0.py____test_rsession_webjs_Globals.opending; + v576 = v575; + ll_append__List_Dict_String__String___Dict_String_ ( v576,msg_17 ); + v445 = true; + block = 12; + break; + case 26: + add_received_item_outcome ( v578,v579 ); + block = 11; + break; + case 27: + v581 = __consts_0.Document; + v582 = ll_dict_getitem__Dict_String__String__String ( msg_18,__consts_0.const_str__70 ); + v583 = v581.getElementById(v582); + v584 = v583.style; + v584.background = __consts_0.const_str__71; + v586 = __consts_0.py____test_rsession_webjs_Globals.ohost_dict; + v587 = ll_dict_getitem__Dict_String__String__String ( msg_18,__consts_0.const_str__70 ); + v588 = ll_dict_getitem__Dict_String__String__String ( v586,v587 ); + v589 = new Object(); + v589.item0 = v588; + v591 = v589.item0; + v592 = new StringBuilder(); + v593 = ll_str__StringR_StringConst_String ( undefined,v591 ); + v592.ll_append(v593); + v592.ll_append(__consts_0.const_str__72); + v596 = v592.ll_build(); + v597 = v583.childNodes; + v598 = ll_getitem_nonneg__dum_nocheckConst_List_ExternalT ( undefined,v597,0 ); + v598.nodeValue = v596; + block = 11; + break; + case 28: + v600 = __consts_0.Document; + v601 = ll_dict_getitem__Dict_String__String__String ( msg_19,__consts_0.const_str__70 ); + v602 = v600.getElementById(v601); + v603 = __consts_0.py____test_rsession_webjs_Globals.ohost_pending; + v604 = ll_dict_getitem__Dict_String__String__String ( msg_19,__consts_0.const_str__70 ); + v605 = ll_dict_getitem__Dict_String__List_String___String ( v603,v604 ); + v606 = v605; + v607 = ll_dict_getitem__Dict_String__String__String ( msg_19,__consts_0.const_str__56 ); + ll_prepend__List_String__String ( v606,v607 ); + v609 = __consts_0.py____test_rsession_webjs_Globals.ohost_pending; + v610 = ll_dict_getitem__Dict_String__String__String ( msg_19,__consts_0.const_str__70 ); + v611 = ll_dict_getitem__Dict_String__List_String___String ( v609,v610 ); + v612 = ll_len__List_String_ ( v611 ); + v613 = __consts_0.py____test_rsession_webjs_Globals.ohost_dict; + v614 = ll_dict_getitem__Dict_String__String__String ( msg_19,__consts_0.const_str__70 ); + v615 = ll_dict_getitem__Dict_String__String__String ( v613,v614 ); + v616 = new Object(); + v616.item0 = v615; + v616.item1 = v612; + v619 = v616.item0; + v620 = v616.item1; + v621 = new StringBuilder(); + v622 = ll_str__StringR_StringConst_String ( undefined,v619 ); + v621.ll_append(v622); + v621.ll_append(__consts_0.const_str__73); + v625 = ll_int_str__IntegerR_SignedConst_Signed ( undefined,v620 ); + v621.ll_append(v625); + v621.ll_append(__consts_0.const_str__41); + v628 = v621.ll_build(); + v629 = v602.childNodes; + v630 = ll_getitem_nonneg__dum_nocheckConst_List_ExternalT ( undefined,v629,0 ); + v630.nodeValue = v628; + block = 11; + break; + case 29: + v633 = make_module_box ( v632 ); + v634 = main_t_0; + v634.appendChild(v633); + block = 11; + break; + } + } +} + +function ll_prepend__List_String__String (l_10,newitem_1) { + var v817,v818,v819,v820,v821,v822,l_11,newitem_2,dst_0,v823,v824,newitem_3,v825,v826,v827,l_12,newitem_4,dst_1,v828,v829,v830,v831,v832; + var block = 0; + for(;;){ + switch(block){ + case 0: + v818 = l_10; + v819 = v818.length; + v820 = l_10; + v821 = (v819+1); + v820.length = v821; + l_11 = l_10; + newitem_2 = newitem_1; + dst_0 = v819; block = 1; break; + case 1: + v823 = (dst_0>0); + v824 = v823; + if (v824 == true) + { + l_12 = l_11; + newitem_4 = newitem_2; + dst_1 = dst_0; + block = 4; + break; + } + else{ + newitem_3 = newitem_2; + v825 = l_11; + block = 2; + break; + } + case 2: + v826 = v825; + v826[0]=newitem_3; + block = 3; + break; + case 3: + return ( v817 ); + case 4: + v828 = (dst_1-1); + v829 = l_12; + v830 = l_12; + v831 = v830[v828]; + v829[dst_1]=v831; + l_11 = l_12; + newitem_2 = newitem_4; + dst_0 = v828; + block = 1; + break; + } + } +} + +function ll_int_str__IntegerR_SignedConst_Signed (repr_0,i_6) { + var v836,v837; + var block = 0; + for(;;){ + switch(block){ + case 0: + v837 = ll_int2dec__Signed ( i_6 ); + v836 = v837; + block = 1; + break; + case 1: + return ( v836 ); + } + } +} + +function ll_newlist__List_String_LlT_Signed (LIST_1,length_0) { + var v390,v391,v392,v393; + var block = 0; + for(;;){ + switch(block){ + case 0: + v391 = new Array(); + v392 = v391; + v392.length = length_0; + v390 = v391; + block = 1; + break; + case 1: + return ( v390 ); } } } function ll_listiter__Record_index__Signed__iterable_List_D (ITER_1,lst_1) { - var v387,v388,v389,v390; + var v427,v428,v429,v430; var block = 0; for(;;){ switch(block){ case 0: - v388 = new Object(); - v388.iterable = lst_1; - v388.index = 0; - v387 = v388; + v428 = new Object(); + v428.iterable = lst_1; + v428.index = 0; + v427 = v428; block = 1; break; case 1: - return ( v387 ); + return ( v427 ); + } + } +} + +function ll_len__List_Dict_String__String__ (l_5) { + var v406,v407,v408; + var block = 0; + for(;;){ + switch(block){ + case 0: + v407 = l_5; + v408 = v407.length; + v406 = v408; + block = 1; + break; + case 1: + return ( v406 ); + } + } +} + +function ll_int2dec__Signed (i_7) { + var v898,v899; + var block = 0; + for(;;){ + switch(block){ + case 0: + v899 = i_7.toString(); + v898 = v899; + block = 1; + break; + case 1: + return ( v898 ); + } + } +} + +function ll_len__List_String_ (l_13) { + var v833,v834,v835; + var block = 0; + for(;;){ + switch(block){ + case 0: + v834 = l_13; + v835 = v834.length; + v833 = v835; + block = 1; + break; + case 1: + return ( v833 ); + } + } +} + +function ll_newlist__List_Dict_String__String__LlT_Signed (self_1,length_1) { + var v636,v637; + var block = 0; + for(;;){ + switch(block){ + case 0: + v637 = ll_newlist__List_Dict_String__String__LlT_Signed_0 ( undefined,length_1 ); + v636 = v637; + block = 1; + break; + case 1: + return ( v636 ); + } + } +} + +function ll_listnext__Record_index__Signed__iterable (iter_2) { + var v431,v432,v433,v434,v435,v436,v437,iter_3,index_4,l_8,v438,v439,v440,v441,v442,v443,v444,etype_4,evalue_4; + var block = 0; + for(;;){ + switch(block){ + case 0: + v432 = iter_2.iterable; + v433 = iter_2.index; + v434 = v432; + v435 = v434.length; + v436 = (v433>=v435); + v437 = v436; + if (v437 == true) + { + block = 3; + break; + } + else{ + iter_3 = iter_2; + index_4 = v433; + l_8 = v432; + block = 1; + break; + } + case 1: + v438 = (index_4+1); + iter_3.index = v438; + v440 = l_8; + v441 = v440[index_4]; + v431 = v441; + block = 2; + break; + case 2: + return ( v431 ); + case 3: + v442 = __consts_0.exceptions_StopIteration; + v443 = v442.meta; + v444 = v442; + etype_4 = v443; + evalue_4 = v444; + block = 4; + break; + case 4: + throw(evalue_4); + } + } +} + +function show_crash () { + var v645,v646,v647,v648,v649,v650,v651,v652; + var block = 0; + for(;;){ + switch(block){ + case 0: + __consts_0.py____test_rsession_webjs_Globals.ofinished = true; + __consts_0.Document.title = __consts_0.const_str__74; + v648 = __consts_0.Document; + v649 = v648.getElementById(__consts_0.const_str__38); + v650 = v649.childNodes; + v651 = ll_getitem_nonneg__dum_nocheckConst_List_ExternalT ( undefined,v650,0 ); + v651.nodeValue = __consts_0.const_str__75; + block = 1; + break; + case 1: + return ( v645 ); + } + } +} + +function ll_newlist__List_Dict_String__String__LlT_Signed_0 (LIST_2,length_2) { + var v900,v901,v902,v903; + var block = 0; + for(;;){ + switch(block){ + case 0: + v901 = new Array(); + v902 = v901; + v902.length = length_2; + v900 = v901; + block = 1; + break; + case 1: + return ( v900 ); + } + } +} + +function scroll_down_if_needed (mbox_2) { + var v638,v639,v640,v641,v642,v643,v644; + var block = 0; + for(;;){ + switch(block){ + case 0: + v639 = __consts_0.py____test_rsession_webjs_Options.oscroll; + v640 = v639; + if (v640 == true) + { + v641 = mbox_2; + block = 2; + break; + } + else{ + block = 1; + break; + } + case 1: + return ( v638 ); + case 2: + v642 = v641.parentNode; + v643 = v642; + v643.scrollIntoView(); + block = 1; + break; } } } function ll_append__List_Dict_String__String___Dict_String_ (l_9,newitem_0) { - var v607,v608,v609,v610,v611,v612,v613,v614; + var v661,v662,v663,v664,v665,v666,v667,v668; var block = 0; for(;;){ switch(block){ case 0: - v608 = l_9; - v609 = v608.length; - v610 = l_9; - v611 = (v609+1); - v610.length = v611; - v613 = l_9; - v613[v609]=newitem_0; + v662 = l_9; + v663 = v662.length; + v664 = l_9; + v665 = (v663+1); + v664.length = v665; + v667 = l_9; + v667[v663]=newitem_0; block = 1; break; case 1: - return ( v607 ); + return ( v661 ); } } } -function add_received_item_outcome (msg_18,module_part_2) { - var v615,v616,v617,v618,msg_19,module_part_3,v619,v620,v621,v622,v623,v624,v625,v626,v627,v628,v629,v630,v631,v632,v633,v634,v635,v636,v637,msg_20,module_part_4,item_name_6,td_0,v638,v639,v640,v641,msg_21,module_part_5,item_name_7,td_1,v642,v643,v644,v645,v646,v647,v648,v649,v650,v651,v652,v653,v654,v655,v656,v657,v658,v659,v660,v661,msg_22,module_part_6,td_2,v662,v663,v664,v665,v666,module_part_7,td_3,v667,v668,v669,v670,v671,v672,v673,v674,v675,v676,v677,v678,v679,v680,v681,v682,v683,v684,v685,v686,v687,v688,v689,v690,v691,v692,v693,v694,v695,v696,v697,v698,v699,v700,v701,msg_23,module_part_8,td_4,v702,v703,v704,msg_24,module_part_9,item_name_8,td_5,v705,v706,v707,v708,msg_25,module_part_10,item_name_9,td_6,v709,v710,v711,v712,v713,v714,v715,v716,v717,v718,v719,v720,v721,v722,v723,v724,v725,v726,v727,v728,msg_26,module_part_11,td_7,v729,v730,v731,msg_27,module_part_12,v732,v733,v734,v735,v736,v737,v738,v739,v740,v741,v742,v743,v744,v745,v746,v747,v748,v749,v750,v751,v752,v753,v754,v755,v756,v757,v758,v759,v760,v761,v762; +function make_module_box (msg_30) { + var v838,v839,v840,v841,v842,v843,v844,v845,v846,v847,v848,v849,v850,v851,v852,v853,v854,v855,v856,v857,v858,v859,v860,v861,v862,v863,v864,v865,v866,v867,v868,v869,v870,v871,v872,v873,v874,v875,v876,v877,v878,v879,v880,v881,v882,v883,v884,v885,v886,v887,v888,v889,v890,v891,v892,v893,v894,v895,v896,v897; var block = 0; for(;;){ switch(block){ case 0: - v616 = ll_dict_getitem__Dict_String__String__String ( msg_18,__consts_0.const_str__63 ); - v617 = ll_strlen__String ( v616 ); - v618 = !!v617; - if (v618 == true) + v839 = create_elem ( __consts_0.const_str__13 ); + v840 = create_elem ( __consts_0.const_str__14 ); + v841 = v839; + v841.appendChild(v840); + v843 = v840; + v844 = ll_dict_getitem__Dict_String__String__String ( msg_30,__consts_0.const_str__76 ); + v845 = ll_dict_getitem__Dict_String__String__String ( msg_30,__consts_0.const_str__77 ); + v846 = new Object(); + v846.item0 = v844; + v846.item1 = v845; + v849 = v846.item0; + v850 = v846.item1; + v851 = new StringBuilder(); + v852 = ll_str__StringR_StringConst_String ( undefined,v849 ); + v851.ll_append(v852); + v851.ll_append(__consts_0.const_str__78); + v855 = ll_str__StringR_StringConst_String ( undefined,v850 ); + v851.ll_append(v855); + v851.ll_append(__consts_0.const_str__41); + v858 = v851.ll_build(); + v859 = create_text_elem ( v858 ); + v843.appendChild(v859); + v861 = ll_dict_getitem__Dict_String__String__String ( msg_30,__consts_0.const_str__77 ); + v862 = ll_int__String_Signed ( v861,10 ); + v863 = ll_dict_getitem__Dict_String__String__String ( msg_30,__consts_0.const_str__56 ); + __consts_0.const_tuple__79[v863]=v862; + v865 = ll_dict_getitem__Dict_String__String__String ( msg_30,__consts_0.const_str__76 ); + v866 = ll_dict_getitem__Dict_String__String__String ( msg_30,__consts_0.const_str__56 ); + __consts_0.const_tuple__80[v866]=v865; + v868 = ll_dict_getitem__Dict_String__String__String ( msg_30,__consts_0.const_str__56 ); + v869 = ll_strconcat__String_String ( __consts_0.const_str__81,v868 ); + v840.id = v869; + v871 = v840; + v872 = ll_dict_getitem__Dict_String__String__String ( msg_30,__consts_0.const_str__56 ); + v873 = new Object(); + v873.item0 = v872; + v875 = v873.item0; + v876 = new StringBuilder(); + v876.ll_append(__consts_0.const_str__82); + v878 = ll_str__StringR_StringConst_String ( undefined,v875 ); + v876.ll_append(v878); + v876.ll_append(__consts_0.const_str__34); + v881 = v876.ll_build(); + v871.setAttribute(__consts_0.const_str__35,v881); + v883 = v840; + v883.setAttribute(__consts_0.const_str__36,__consts_0.const_str__83); + v885 = create_elem ( __consts_0.const_str__14 ); + v886 = v839; + v886.appendChild(v885); + v888 = create_elem ( __consts_0.const_str__84 ); + v889 = v885; + v889.appendChild(v888); + v891 = create_elem ( __consts_0.const_str__12 ); + v892 = ll_dict_getitem__Dict_String__String__String ( msg_30,__consts_0.const_str__56 ); + v891.id = v892; + v894 = v888; + v894.appendChild(v891); + v896 = ll_dict_getitem__Dict_String__String__String ( msg_30,__consts_0.const_str__56 ); + __consts_0.const_tuple__85[v896]=0; + v838 = v839; + block = 1; + break; + case 1: + return ( v838 ); + } + } +} + +function show_interrupt () { + var v653,v654,v655,v656,v657,v658,v659,v660; + var block = 0; + for(;;){ + switch(block){ + case 0: + __consts_0.py____test_rsession_webjs_Globals.ofinished = true; + __consts_0.Document.title = __consts_0.const_str__86; + v656 = __consts_0.Document; + v657 = v656.getElementById(__consts_0.const_str__38); + v658 = v657.childNodes; + v659 = ll_getitem_nonneg__dum_nocheckConst_List_ExternalT ( undefined,v658,0 ); + v659.nodeValue = __consts_0.const_str__87; + block = 1; + break; + case 1: + return ( v653 ); + } + } +} + +function add_received_item_outcome (msg_20,module_part_2) { + var v669,v670,v671,v672,msg_21,module_part_3,v673,v674,v675,v676,v677,v678,v679,v680,v681,v682,v683,v684,v685,v686,v687,v688,v689,v690,v691,msg_22,module_part_4,item_name_6,td_0,v692,v693,v694,v695,msg_23,module_part_5,item_name_7,td_1,v696,v697,v698,v699,v700,v701,v702,v703,v704,v705,v706,v707,v708,v709,v710,v711,v712,v713,v714,v715,msg_24,module_part_6,td_2,v716,v717,v718,v719,v720,module_part_7,td_3,v721,v722,v723,v724,v725,v726,v727,v728,v729,v730,v731,v732,v733,v734,v735,v736,v737,v738,v739,v740,v741,v742,v743,v744,v745,v746,v747,v748,v749,v750,v751,v752,v753,v754,v755,msg_25,module_part_8,td_4,v756,v757,v758,msg_26,module_part_9,item_name_8,td_5,v759,v760,v761,v762,msg_27,module_part_10,item_name_9,td_6,v763,v764,v765,v766,v767,v768,v769,v770,v771,v772,v773,v774,v775,v776,v777,v778,v779,v780,v781,v782,msg_28,module_part_11,td_7,v783,v784,v785,msg_29,module_part_12,v786,v787,v788,v789,v790,v791,v792,v793,v794,v795,v796,v797,v798,v799,v800,v801,v802,v803,v804,v805,v806,v807,v808,v809,v810,v811,v812,v813,v814,v815,v816; + var block = 0; + for(;;){ + switch(block){ + case 0: + v670 = ll_dict_getitem__Dict_String__String__String ( msg_20,__consts_0.const_str__70 ); + v671 = ll_strlen__String ( v670 ); + v672 = !!v671; + if (v672 == true) { - msg_27 = msg_18; + msg_29 = msg_20; module_part_12 = module_part_2; block = 11; break; } else{ - msg_19 = msg_18; + msg_21 = msg_20; module_part_3 = module_part_2; block = 1; break; } case 1: - v619 = create_elem ( __consts_0.const_str__17 ); - v620 = v619; - v621 = ll_dict_getitem__Dict_String__String__String ( msg_19,__consts_0.const_str__49 ); - v622 = new Object(); - v622.item0 = v621; - v624 = v622.item0; - v625 = new StringBuilder(); - v625.ll_append(__consts_0.const_str__73); - v627 = ll_str__StringR_StringConst_String ( undefined,v624 ); - v625.ll_append(v627); - v625.ll_append(__consts_0.const_str__20); - v630 = v625.ll_build(); - v620.setAttribute(__consts_0.const_str__21,v630); - v632 = v619; - v632.setAttribute(__consts_0.const_str__22,__consts_0.const_str__74); - v634 = ll_dict_getitem__Dict_String__String__String ( msg_19,__consts_0.const_str__49 ); - v635 = ll_dict_getitem__Dict_String__String__String ( msg_19,__consts_0.const_str__78 ); - v636 = ll_streq__String_String ( v635,__consts_0.const_str__79 ); - v637 = v636; - if (v637 == true) + v673 = create_elem ( __consts_0.const_str__14 ); + v674 = v673; + v675 = ll_dict_getitem__Dict_String__String__String ( msg_21,__consts_0.const_str__56 ); + v676 = new Object(); + v676.item0 = v675; + v678 = v676.item0; + v679 = new StringBuilder(); + v679.ll_append(__consts_0.const_str__82); + v681 = ll_str__StringR_StringConst_String ( undefined,v678 ); + v679.ll_append(v681); + v679.ll_append(__consts_0.const_str__34); + v684 = v679.ll_build(); + v674.setAttribute(__consts_0.const_str__35,v684); + v686 = v673; + v686.setAttribute(__consts_0.const_str__36,__consts_0.const_str__83); + v688 = ll_dict_getitem__Dict_String__String__String ( msg_21,__consts_0.const_str__56 ); + v689 = ll_dict_getitem__Dict_String__String__String ( msg_21,__consts_0.const_str__88 ); + v690 = ll_streq__String_String ( v689,__consts_0.const_str__30 ); + v691 = v690; + if (v691 == true) { - msg_26 = msg_19; + msg_28 = msg_21; module_part_11 = module_part_3; - td_7 = v619; + td_7 = v673; block = 10; break; } else{ - msg_20 = msg_19; + msg_22 = msg_21; module_part_4 = module_part_3; - item_name_6 = v634; - td_0 = v619; + item_name_6 = v688; + td_0 = v673; block = 2; break; } case 2: - v638 = ll_dict_getitem__Dict_String__String__String ( msg_20,__consts_0.const_str__80 ); - v639 = ll_streq__String_String ( v638,__consts_0.const_str__81 ); - v640 = !v639; - v641 = v640; - if (v641 == true) + v692 = ll_dict_getitem__Dict_String__String__String ( msg_22,__consts_0.const_str__89 ); + v693 = ll_streq__String_String ( v692,__consts_0.const_str__90 ); + v694 = !v693; + v695 = v694; + if (v695 == true) { - msg_24 = msg_20; + msg_26 = msg_22; module_part_9 = module_part_4; item_name_8 = item_name_6; td_5 = td_0; @@ -2484,7 +2745,7 @@ function add_received_item_outcome (msg_18,module_part_2) { break; } else{ - msg_21 = msg_20; + msg_23 = msg_22; module_part_5 = module_part_4; item_name_7 = item_name_6; td_1 = td_0; @@ -2492,40 +2753,40 @@ function add_received_item_outcome (msg_18,module_part_2) { break; } case 3: - v642 = create_elem ( __consts_0.const_str__82 ); - v643 = v642; - v644 = ll_dict_getitem__Dict_String__String__String ( msg_21,__consts_0.const_str__49 ); - v645 = new Object(); - v645.item0 = v644; - v647 = v645.item0; - v648 = new StringBuilder(); - v648.ll_append(__consts_0.const_str__83); - v650 = ll_str__StringR_StringConst_String ( undefined,v647 ); - v648.ll_append(v650); - v648.ll_append(__consts_0.const_str__20); - v653 = v648.ll_build(); - v643.setAttribute(__consts_0.const_str__84,v653); - v655 = create_text_elem ( __consts_0.const_str__85 ); - v656 = v642; - v656.appendChild(v655); - v658 = td_1; - v658.appendChild(v642); - v660 = __consts_0.ExportedMethods; - v661 = v660.show_fail(item_name_7,fail_come_back); - msg_22 = msg_21; + v696 = create_elem ( __consts_0.const_str__91 ); + v697 = v696; + v698 = ll_dict_getitem__Dict_String__String__String ( msg_23,__consts_0.const_str__56 ); + v699 = new Object(); + v699.item0 = v698; + v701 = v699.item0; + v702 = new StringBuilder(); + v702.ll_append(__consts_0.const_str__92); + v704 = ll_str__StringR_StringConst_String ( undefined,v701 ); + v702.ll_append(v704); + v702.ll_append(__consts_0.const_str__34); + v707 = v702.ll_build(); + v697.setAttribute(__consts_0.const_str__93,v707); + v709 = create_text_elem ( __consts_0.const_str__94 ); + v710 = v696; + v710.appendChild(v709); + v712 = td_1; + v712.appendChild(v696); + v714 = __consts_0.ExportedMethods; + v715 = v714.show_fail(item_name_7,fail_come_back); + msg_24 = msg_23; module_part_6 = module_part_5; td_2 = td_1; block = 4; break; case 4: - v662 = ll_dict_getitem__Dict_String__String__String ( msg_22,__consts_0.const_str__62 ); - v663 = ll_dict_getitem__Dict_String__Signed__String ( __consts_0.const_tuple__76,v662 ); - v664 = (v663%50); - v665 = (v664==0); - v666 = v665; - if (v666 == true) + v716 = ll_dict_getitem__Dict_String__String__String ( msg_24,__consts_0.const_str__69 ); + v717 = ll_dict_getitem__Dict_String__Signed__String ( __consts_0.const_tuple__85,v716 ); + v718 = (v717%50); + v719 = (v718==0); + v720 = v719; + if (v720 == true) { - msg_23 = msg_22; + msg_25 = msg_24; module_part_8 = module_part_6; td_4 = td_2; block = 7; @@ -2534,66 +2795,66 @@ function add_received_item_outcome (msg_18,module_part_2) { else{ module_part_7 = module_part_6; td_3 = td_2; - v667 = msg_22; + v721 = msg_24; block = 5; break; } case 5: - v668 = ll_dict_getitem__Dict_String__String__String ( v667,__consts_0.const_str__62 ); - v669 = ll_dict_getitem__Dict_String__Signed__String ( __consts_0.const_tuple__76,v668 ); - v670 = (v669+1); - __consts_0.const_tuple__76[v668]=v670; - v672 = ll_strconcat__String_String ( __consts_0.const_str__72,v668 ); - v673 = get_elem ( v672 ); - v674 = ll_dict_getitem__Dict_String__String__String ( __consts_0.const_tuple__71,v668 ); - v675 = ll_dict_getitem__Dict_String__Signed__String ( __consts_0.const_tuple__76,v668 ); - v676 = ll_dict_getitem__Dict_String__Signed__String ( __consts_0.const_tuple__70,v668 ); - v677 = new Object(); - v677.item0 = v674; - v677.item1 = v675; - v677.item2 = v676; - v681 = v677.item0; - v682 = v677.item1; - v683 = v677.item2; - v684 = new StringBuilder(); - v685 = ll_str__StringR_StringConst_String ( undefined,v681 ); - v684.ll_append(v685); - v684.ll_append(__consts_0.const_str__66); - v688 = v682.toString(); - v684.ll_append(v688); - v684.ll_append(__consts_0.const_str__86); - v691 = v683.toString(); - v684.ll_append(v691); - v684.ll_append(__consts_0.const_str__36); - v694 = v684.ll_build(); - v695 = v673.childNodes; - v696 = ll_getitem_nonneg__dum_nocheckConst_List_ExternalT ( undefined,v695,0 ); - v696.nodeValue = v694; - v698 = module_part_7.childNodes; - v699 = ll_getitem__dum_nocheckConst_List_ExternalType__Si ( undefined,v698,-1 ); - v700 = v699; - v700.appendChild(td_3); + v722 = ll_dict_getitem__Dict_String__String__String ( v721,__consts_0.const_str__69 ); + v723 = ll_dict_getitem__Dict_String__Signed__String ( __consts_0.const_tuple__85,v722 ); + v724 = (v723+1); + __consts_0.const_tuple__85[v722]=v724; + v726 = ll_strconcat__String_String ( __consts_0.const_str__81,v722 ); + v727 = get_elem ( v726 ); + v728 = ll_dict_getitem__Dict_String__String__String ( __consts_0.const_tuple__80,v722 ); + v729 = ll_dict_getitem__Dict_String__Signed__String ( __consts_0.const_tuple__85,v722 ); + v730 = ll_dict_getitem__Dict_String__Signed__String ( __consts_0.const_tuple__79,v722 ); + v731 = new Object(); + v731.item0 = v728; + v731.item1 = v729; + v731.item2 = v730; + v735 = v731.item0; + v736 = v731.item1; + v737 = v731.item2; + v738 = new StringBuilder(); + v739 = ll_str__StringR_StringConst_String ( undefined,v735 ); + v738.ll_append(v739); + v738.ll_append(__consts_0.const_str__73); + v742 = v736.toString(); + v738.ll_append(v742); + v738.ll_append(__consts_0.const_str__95); + v745 = v737.toString(); + v738.ll_append(v745); + v738.ll_append(__consts_0.const_str__41); + v748 = v738.ll_build(); + v749 = v727.childNodes; + v750 = ll_getitem_nonneg__dum_nocheckConst_List_ExternalT ( undefined,v749,0 ); + v750.nodeValue = v748; + v752 = module_part_7.childNodes; + v753 = ll_getitem__dum_nocheckConst_List_ExternalType__Si ( undefined,v752,-1 ); + v754 = v753; + v754.appendChild(td_3); block = 6; break; case 6: - return ( v615 ); + return ( v669 ); case 7: - v702 = create_elem ( __consts_0.const_str__16 ); - v703 = module_part_8; - v703.appendChild(v702); + v756 = create_elem ( __consts_0.const_str__13 ); + v757 = module_part_8; + v757.appendChild(v756); module_part_7 = module_part_8; td_3 = td_4; - v667 = msg_23; + v721 = msg_25; block = 5; break; case 8: - v705 = ll_dict_getitem__Dict_String__String__String ( msg_24,__consts_0.const_str__80 ); - v706 = ll_streq__String_String ( v705,__consts_0.const_str__87 ); - v707 = !v706; - v708 = v707; - if (v708 == true) + v759 = ll_dict_getitem__Dict_String__String__String ( msg_26,__consts_0.const_str__89 ); + v760 = ll_streq__String_String ( v759,__consts_0.const_str__96 ); + v761 = !v760; + v762 = v761; + if (v762 == true) { - msg_25 = msg_24; + msg_27 = msg_26; module_part_10 = module_part_9; item_name_9 = item_name_8; td_6 = td_5; @@ -2601,7 +2862,7 @@ function add_received_item_outcome (msg_18,module_part_2) { break; } else{ - msg_21 = msg_24; + msg_23 = msg_26; module_part_5 = module_part_9; item_name_7 = item_name_8; td_1 = td_5; @@ -2609,73 +2870,73 @@ function add_received_item_outcome (msg_18,module_part_2) { break; } case 9: - v709 = __consts_0.ExportedMethods; - v710 = v709.show_skip(item_name_9,skip_come_back); - v711 = create_elem ( __consts_0.const_str__82 ); - v712 = v711; - v713 = ll_dict_getitem__Dict_String__String__String ( msg_25,__consts_0.const_str__49 ); - v714 = new Object(); - v714.item0 = v713; - v716 = v714.item0; - v717 = new StringBuilder(); - v717.ll_append(__consts_0.const_str__88); - v719 = ll_str__StringR_StringConst_String ( undefined,v716 ); - v717.ll_append(v719); - v717.ll_append(__consts_0.const_str__20); - v722 = v717.ll_build(); - v712.setAttribute(__consts_0.const_str__84,v722); - v724 = create_text_elem ( __consts_0.const_str__89 ); - v725 = v711; - v725.appendChild(v724); - v727 = td_6; - v727.appendChild(v711); - msg_22 = msg_25; + v763 = __consts_0.ExportedMethods; + v764 = v763.show_skip(item_name_9,skip_come_back); + v765 = create_elem ( __consts_0.const_str__91 ); + v766 = v765; + v767 = ll_dict_getitem__Dict_String__String__String ( msg_27,__consts_0.const_str__56 ); + v768 = new Object(); + v768.item0 = v767; + v770 = v768.item0; + v771 = new StringBuilder(); + v771.ll_append(__consts_0.const_str__97); + v773 = ll_str__StringR_StringConst_String ( undefined,v770 ); + v771.ll_append(v773); + v771.ll_append(__consts_0.const_str__34); + v776 = v771.ll_build(); + v766.setAttribute(__consts_0.const_str__93,v776); + v778 = create_text_elem ( __consts_0.const_str__98 ); + v779 = v765; + v779.appendChild(v778); + v781 = td_6; + v781.appendChild(v765); + msg_24 = msg_27; module_part_6 = module_part_10; td_2 = td_6; block = 4; break; case 10: - v729 = create_text_elem ( __consts_0.const_str__90 ); - v730 = td_7; - v730.appendChild(v729); - msg_22 = msg_26; + v783 = create_text_elem ( __consts_0.const_str__99 ); + v784 = td_7; + v784.appendChild(v783); + msg_24 = msg_28; module_part_6 = module_part_11; td_2 = td_7; block = 4; break; case 11: - v732 = __consts_0.Document; - v733 = ll_dict_getitem__Dict_String__String__String ( msg_27,__consts_0.const_str__63 ); - v734 = v732.getElementById(v733); - v735 = __consts_0.py____test_rsession_webjs_Globals.ohost_pending; - v736 = ll_dict_getitem__Dict_String__String__String ( msg_27,__consts_0.const_str__63 ); - v737 = ll_dict_getitem__Dict_String__List_String___String ( v735,v736 ); - v738 = v737; - v739 = ll_pop_default__dum_nocheckConst_List_String_ ( undefined,v738 ); - v740 = __consts_0.py____test_rsession_webjs_Globals.ohost_pending; - v741 = ll_dict_getitem__Dict_String__String__String ( msg_27,__consts_0.const_str__63 ); - v742 = ll_dict_getitem__Dict_String__List_String___String ( v740,v741 ); - v743 = ll_len__List_String_ ( v742 ); - v744 = __consts_0.py____test_rsession_webjs_Globals.ohost_dict; - v745 = ll_dict_getitem__Dict_String__String__String ( msg_27,__consts_0.const_str__63 ); - v746 = ll_dict_getitem__Dict_String__String__String ( v744,v745 ); - v747 = new Object(); - v747.item0 = v746; - v747.item1 = v743; - v750 = v747.item0; - v751 = v747.item1; - v752 = new StringBuilder(); - v753 = ll_str__StringR_StringConst_String ( undefined,v750 ); - v752.ll_append(v753); - v752.ll_append(__consts_0.const_str__66); - v756 = ll_int_str__IntegerR_SignedConst_Signed ( undefined,v751 ); - v752.ll_append(v756); - v752.ll_append(__consts_0.const_str__36); - v759 = v752.ll_build(); - v760 = v734.childNodes; - v761 = ll_getitem_nonneg__dum_nocheckConst_List_ExternalT ( undefined,v760,0 ); - v761.nodeValue = v759; - msg_19 = msg_27; + v786 = __consts_0.Document; + v787 = ll_dict_getitem__Dict_String__String__String ( msg_29,__consts_0.const_str__70 ); + v788 = v786.getElementById(v787); + v789 = __consts_0.py____test_rsession_webjs_Globals.ohost_pending; + v790 = ll_dict_getitem__Dict_String__String__String ( msg_29,__consts_0.const_str__70 ); + v791 = ll_dict_getitem__Dict_String__List_String___String ( v789,v790 ); + v792 = v791; + v793 = ll_pop_default__dum_nocheckConst_List_String_ ( undefined,v792 ); + v794 = __consts_0.py____test_rsession_webjs_Globals.ohost_pending; + v795 = ll_dict_getitem__Dict_String__String__String ( msg_29,__consts_0.const_str__70 ); + v796 = ll_dict_getitem__Dict_String__List_String___String ( v794,v795 ); + v797 = ll_len__List_String_ ( v796 ); + v798 = __consts_0.py____test_rsession_webjs_Globals.ohost_dict; + v799 = ll_dict_getitem__Dict_String__String__String ( msg_29,__consts_0.const_str__70 ); + v800 = ll_dict_getitem__Dict_String__String__String ( v798,v799 ); + v801 = new Object(); + v801.item0 = v800; + v801.item1 = v797; + v804 = v801.item0; + v805 = v801.item1; + v806 = new StringBuilder(); + v807 = ll_str__StringR_StringConst_String ( undefined,v804 ); + v806.ll_append(v807); + v806.ll_append(__consts_0.const_str__73); + v810 = ll_int_str__IntegerR_SignedConst_Signed ( undefined,v805 ); + v806.ll_append(v810); + v806.ll_append(__consts_0.const_str__41); + v813 = v806.ll_build(); + v814 = v788.childNodes; + v815 = ll_getitem_nonneg__dum_nocheckConst_List_ExternalT ( undefined,v814,0 ); + v815.nodeValue = v813; + msg_21 = msg_29; module_part_3 = module_part_12; block = 1; break; @@ -2683,140 +2944,68 @@ function add_received_item_outcome (msg_18,module_part_2) { } } -function ll_streq__String_String (s1_0,s2_0) { - var v587,v588,v589,v590,s2_1,v591,v592,v593,v594,v595,v596; +function ll_getitem__dum_nocheckConst_List_ExternalType__Si (func_2,l_14,index_5) { + var v1015,v1016,v1017,v1018,v1019,l_15,index_6,length_3,v1020,v1021,v1022,v1023,index_7,v1024,v1025,v1026,l_16,length_4,v1027,v1028; var block = 0; for(;;){ switch(block){ case 0: - v588 = !!s1_0; - v589 = !v588; - v590 = v589; - if (v590 == true) + v1016 = l_14; + v1017 = v1016.length; + v1018 = (index_5<0); + v1019 = v1018; + if (v1019 == true) { - v594 = s2_0; - block = 3; + l_16 = l_14; + length_4 = v1017; + v1027 = index_5; + block = 4; break; } else{ - s2_1 = s2_0; - v591 = s1_0; + l_15 = l_14; + index_6 = index_5; + length_3 = v1017; block = 1; break; } case 1: - v592 = v591; - v593 = (v592==s2_1); - v587 = v593; - block = 2; - break; - case 2: - return ( v587 ); - case 3: - v595 = !!v594; - v596 = !v595; - v587 = v596; - block = 2; - break; - } - } -} - -function ll_newlist__List_Dict_String__String__LlT_Signed (self_1,length_1) { - var v846,v847; - var block = 0; - for(;;){ - switch(block){ - case 0: - v847 = ll_newlist__List_Dict_String__String__LlT_Signed_0 ( undefined,length_1 ); - v846 = v847; - block = 1; - break; - case 1: - return ( v846 ); - } - } -} - -function skip_come_back (msg_30) { - var v973,v974,v975,v976; - var block = 0; - for(;;){ - switch(block){ - case 0: - v974 = ll_dict_getitem__Dict_String__String__String ( msg_30,__consts_0.const_str__50 ); - v975 = ll_dict_getitem__Dict_String__String__String ( msg_30,__consts_0.const_str__91 ); - __consts_0.const_tuple__30[v975]=v974; - block = 1; - break; - case 1: - return ( v973 ); - } - } -} - -function ll_pop_default__dum_nocheckConst_List_String_ (func_3,l_17) { - var v977,v978,v979,l_18,length_4,v980,v981,v982,v983,v984,v985,res_0,newlength_0,v986,v987,v988; - var block = 0; - for(;;){ - switch(block){ - case 0: - v978 = l_17; - v979 = v978.length; - l_18 = l_17; - length_4 = v979; - block = 1; - break; - case 1: - v980 = (length_4>0); + v1020 = (index_6>=0); undefined; - v982 = (length_4-1); - v983 = l_18; - v984 = v983[v982]; - ll_null_item__List_String_ ( l_18 ); - res_0 = v984; - newlength_0 = v982; - v986 = l_18; + v1022 = (index_6=base_15); - v909 = v908; - if (v909 == true) + v964 = (digit_0>=base_15); + v965 = v964; + if (v965 == true) { s_11 = s_20; val_1 = val_11; @@ -3206,24 +3395,24 @@ function ll_int__String_Signed (s_2,base_0) { digit_1 = digit_0; sign_12 = sign_11; strlen_15 = strlen_14; - v910 = val_11; + v966 = val_11; block = 26; break; } case 26: - v911 = (v910*base_16); - v912 = (v911+digit_1); - v913 = (i_22+1); + v967 = (v966*base_16); + v968 = (v967+digit_1); + v969 = (i_22+1); s_10 = s_21; base_8 = base_16; - val_0 = v912; - i_12 = v913; + val_0 = v968; + i_12 = v969; sign_0 = sign_12; strlen_4 = strlen_15; block = 11; break; case 27: - v914 = (c_4<=90); + v970 = (c_4<=90); s_23 = s_22; base_18 = base_17; c_5 = c_4; @@ -3231,12 +3420,12 @@ function ll_int__String_Signed (s_2,base_0) { i_24 = i_23; sign_14 = sign_13; strlen_17 = strlen_16; - v915 = v914; + v971 = v970; block = 28; break; case 28: - v916 = v915; - if (v916 == true) + v972 = v971; + if (v972 == true) { s_24 = s_23; base_19 = base_18; @@ -3244,7 +3433,7 @@ function ll_int__String_Signed (s_2,base_0) { i_25 = i_24; sign_15 = sign_14; strlen_18 = strlen_17; - v917 = c_5; + v973 = c_5; block = 29; break; } @@ -3260,19 +3449,19 @@ function ll_int__String_Signed (s_2,base_0) { break; } case 29: - v918 = (v917-65); - v919 = (v918+10); + v974 = (v973-65); + v975 = (v974+10); s_20 = s_24; base_15 = base_19; val_11 = val_14; i_21 = i_25; - digit_0 = v919; + digit_0 = v975; sign_11 = sign_15; strlen_14 = strlen_18; block = 25; break; case 30: - v920 = (c_6<=122); + v976 = (c_6<=122); s_26 = s_25; base_21 = base_20; c_7 = c_6; @@ -3280,12 +3469,12 @@ function ll_int__String_Signed (s_2,base_0) { i_27 = i_26; sign_17 = sign_16; strlen_20 = strlen_19; - v921 = v920; + v977 = v976; block = 31; break; case 31: - v922 = v921; - if (v922 == true) + v978 = v977; + if (v978 == true) { s_27 = s_26; base_22 = base_21; @@ -3293,7 +3482,7 @@ function ll_int__String_Signed (s_2,base_0) { i_28 = i_27; sign_18 = sign_17; strlen_21 = strlen_20; - v923 = c_7; + v979 = c_7; block = 32; break; } @@ -3309,48 +3498,48 @@ function ll_int__String_Signed (s_2,base_0) { break; } case 32: - v924 = (v923-97); - v925 = (v924+10); + v980 = (v979-97); + v981 = (v980+10); s_20 = s_27; base_15 = base_22; val_11 = val_17; i_21 = i_28; - digit_0 = v925; + digit_0 = v981; sign_11 = sign_18; strlen_14 = strlen_21; block = 25; break; case 33: - v927 = (v926+1); + v983 = (v982+1); s_10 = s_28; base_8 = base_23; val_0 = 0; - i_12 = v927; + i_12 = v983; sign_0 = 1; strlen_4 = strlen_22; block = 11; break; case 34: - v929 = (v928+1); + v985 = (v984+1); s_10 = s_29; base_8 = base_24; val_0 = 0; - i_12 = v929; + i_12 = v985; sign_0 = -1; strlen_4 = strlen_23; block = 11; break; case 35: - v930 = s_30; - v931 = v930[i_29]; - v932 = (v931==' '); - v933 = v932; - if (v933 == true) + v986 = s_30; + v987 = v986[i_29]; + v988 = (v987==' '); + v989 = v988; + if (v989 == true) { s_31 = s_30; base_26 = base_25; strlen_25 = strlen_24; - v934 = i_29; + v990 = i_29; block = 36; break; } @@ -3363,10 +3552,10 @@ function ll_int__String_Signed (s_2,base_0) { break; } case 36: - v935 = (v934+1); + v991 = (v990+1); s_6 = s_31; base_4 = base_26; - i_8 = v935; + i_8 = v991; strlen_0 = strlen_25; block = 6; break; @@ -3374,57 +3563,112 @@ function ll_int__String_Signed (s_2,base_0) { } } -function fail_come_back (msg_29) { - var v939,v940,v941,v942,v943,v944,v945,v946,v947,v948; +function ll_strlen__String (obj_1) { + var v992,v993,v994; var block = 0; for(;;){ switch(block){ case 0: - v940 = ll_dict_getitem__Dict_String__String__String ( msg_29,__consts_0.const_str__93 ); - v941 = ll_dict_getitem__Dict_String__String__String ( msg_29,__consts_0.const_str__94 ); - v942 = ll_dict_getitem__Dict_String__String__String ( msg_29,__consts_0.const_str__95 ); - v943 = new Object(); - v943.item0 = v940; - v943.item1 = v941; - v943.item2 = v942; - v947 = ll_dict_getitem__Dict_String__String__String ( msg_29,__consts_0.const_str__91 ); - __consts_0.const_tuple[v947]=v943; + v993 = obj_1; + v994 = v993.length; + v992 = v994; block = 1; break; case 1: - return ( v939 ); + return ( v992 ); } } } -function ll_null_item__List_String_ (lst_2) { - var v993,v994; +function ll_pop_default__dum_nocheckConst_List_String_ (func_3,l_17) { + var v1033,v1034,v1035,l_18,length_5,v1036,v1037,v1038,v1039,v1040,v1041,res_0,newlength_0,v1042,v1043,v1044; var block = 0; for(;;){ switch(block){ case 0: + v1034 = l_17; + v1035 = v1034.length; + l_18 = l_17; + length_5 = v1035; + block = 1; + break; + case 1: + v1036 = (length_5>0); undefined; - block = 1; + v1038 = (length_5-1); + v1039 = l_18; + v1040 = v1039[v1038]; + ll_null_item__List_String_ ( l_18 ); + res_0 = v1040; + newlength_0 = v1038; + v1042 = l_18; + block = 2; break; - case 1: - return ( v993 ); + case 2: + v1043 = v1042; + v1043.length = newlength_0; + v1033 = res_0; + block = 3; + break; + case 3: + return ( v1033 ); } } } -function ll_dict_getitem__Dict_String__Signed__String (d_4,key_7) { - var v949,v950,v951,v952,v953,v954,v955,etype_6,evalue_6,key_8,v956,v957,v958; +function fail_come_back (msg_31) { + var v995,v996,v997,v998,v999,v1000,v1001,v1002,v1003,v1004; var block = 0; for(;;){ switch(block){ case 0: - v950 = d_4; - v951 = (v950[key_7]!=undefined); - v952 = v951; - if (v952 == true) + v996 = ll_dict_getitem__Dict_String__String__String ( msg_31,__consts_0.const_str__101 ); + v997 = ll_dict_getitem__Dict_String__String__String ( msg_31,__consts_0.const_str__102 ); + v998 = ll_dict_getitem__Dict_String__String__String ( msg_31,__consts_0.const_str__103 ); + v999 = new Object(); + v999.item0 = v996; + v999.item1 = v997; + v999.item2 = v998; + v1003 = ll_dict_getitem__Dict_String__String__String ( msg_31,__consts_0.const_str__104 ); + __consts_0.const_tuple__23[v1003]=v999; + block = 1; + break; + case 1: + return ( v995 ); + } + } +} + +function skip_come_back (msg_32) { + var v1029,v1030,v1031,v1032; + var block = 0; + for(;;){ + switch(block){ + case 0: + v1030 = ll_dict_getitem__Dict_String__String__String ( msg_32,__consts_0.const_str__57 ); + v1031 = ll_dict_getitem__Dict_String__String__String ( msg_32,__consts_0.const_str__104 ); + __consts_0.const_tuple__15[v1031]=v1030; + block = 1; + break; + case 1: + return ( v1029 ); + } + } +} + +function ll_dict_getitem__Dict_String__Signed__String (d_4,key_8) { + var v1005,v1006,v1007,v1008,v1009,v1010,v1011,etype_6,evalue_6,key_9,v1012,v1013,v1014; + var block = 0; + for(;;){ + switch(block){ + case 0: + v1006 = d_4; + v1007 = (v1006[key_8]!=undefined); + v1008 = v1007; + if (v1008 == true) { - key_8 = key_7; - v956 = d_4; + key_9 = key_8; + v1012 = d_4; block = 3; break; } @@ -3433,94 +3677,23 @@ function ll_dict_getitem__Dict_String__Signed__String (d_4,key_7) { break; } case 1: - v953 = __consts_0.exceptions_KeyError; - v954 = v953.meta; - v955 = v953; - etype_6 = v954; - evalue_6 = v955; + v1009 = __consts_0.exceptions_KeyError; + v1010 = v1009.meta; + v1011 = v1009; + etype_6 = v1010; + evalue_6 = v1011; block = 2; break; case 2: throw(evalue_6); case 3: - v957 = v956; - v958 = v957[key_8]; - v949 = v958; + v1013 = v1012; + v1014 = v1013[key_9]; + v1005 = v1014; block = 4; break; case 4: - return ( v949 ); - } - } -} - -function ll_getitem__dum_nocheckConst_List_ExternalType__Si (func_2,l_14,index_5) { - var v959,v960,v961,v962,v963,l_15,index_6,length_2,v964,v965,v966,v967,index_7,v968,v969,v970,l_16,length_3,v971,v972; - var block = 0; - for(;;){ - switch(block){ - case 0: - v960 = l_14; - v961 = v960.length; - v962 = (index_5<0); - v963 = v962; - if (v963 == true) - { - l_16 = l_14; - length_3 = v961; - v971 = index_5; - block = 4; - break; - } - else{ - l_15 = l_14; - index_6 = index_5; - length_2 = v961; - block = 1; - break; - } - case 1: - v964 = (index_6>=0); - undefined; - v966 = (index_6' ); } -function exceptions_Exception_meta () { -} - -exceptions_Exception_meta.prototype.toString = function (){ - return ( '' ); -} - -inherits(exceptions_Exception_meta,Object_meta); -function exceptions_StopIteration_meta () { -} - -exceptions_StopIteration_meta.prototype.toString = function (){ - return ( '' ); -} - -inherits(exceptions_StopIteration_meta,exceptions_Exception_meta); -function exceptions_StandardError_meta () { -} - -exceptions_StandardError_meta.prototype.toString = function (){ - return ( '' ); -} - -inherits(exceptions_StandardError_meta,exceptions_Exception_meta); -function exceptions_LookupError_meta () { -} - -exceptions_LookupError_meta.prototype.toString = function (){ - return ( '' ); -} - -inherits(exceptions_LookupError_meta,exceptions_StandardError_meta); -function exceptions_ValueError_meta () { -} - -exceptions_ValueError_meta.prototype.toString = function (){ - return ( '' ); -} - -inherits(exceptions_ValueError_meta,exceptions_StandardError_meta); -function exceptions_KeyError_meta () { -} - -exceptions_KeyError_meta.prototype.toString = function (){ - return ( '' ); -} - -inherits(exceptions_KeyError_meta,exceptions_LookupError_meta); function py____test_rsession_webjs_Globals_meta () { } @@ -3597,125 +3737,196 @@ py____test_rsession_webjs_Globals_meta.prototype.toString = function (){ } inherits(py____test_rsession_webjs_Globals_meta,Object_meta); +function exceptions_Exception_meta () { +} + +exceptions_Exception_meta.prototype.toString = function (){ + return ( '' ); +} + +inherits(exceptions_Exception_meta,Object_meta); +function exceptions_StandardError_meta () { +} + +exceptions_StandardError_meta.prototype.toString = function (){ + return ( '' ); +} + +inherits(exceptions_StandardError_meta,exceptions_Exception_meta); +function exceptions_ValueError_meta () { +} + +exceptions_ValueError_meta.prototype.toString = function (){ + return ( '' ); +} + +inherits(exceptions_ValueError_meta,exceptions_StandardError_meta); +function exceptions_LookupError_meta () { +} + +exceptions_LookupError_meta.prototype.toString = function (){ + return ( '' ); +} + +inherits(exceptions_LookupError_meta,exceptions_StandardError_meta); +function exceptions_KeyError_meta () { +} + +exceptions_KeyError_meta.prototype.toString = function (){ + return ( '' ); +} + +inherits(exceptions_KeyError_meta,exceptions_LookupError_meta); +function exceptions_StopIteration_meta () { +} + +exceptions_StopIteration_meta.prototype.toString = function (){ + return ( '' ); +} + +inherits(exceptions_StopIteration_meta,exceptions_Exception_meta); +function py____test_rsession_webjs_Options_meta () { +} + +py____test_rsession_webjs_Options_meta.prototype.toString = function (){ + return ( '' ); +} + +inherits(py____test_rsession_webjs_Options_meta,Object_meta); __consts_0 = {}; -__consts_0.const_str__59 = ' failures, '; -__consts_0.const_str__19 = "show_host('"; -__consts_0.const_str__72 = '_txt_'; -__consts_0.exceptions_ValueError__97 = exceptions_ValueError; -__consts_0.exceptions_ValueError_meta = new exceptions_ValueError_meta(); -__consts_0.exceptions_ValueError = new exceptions_ValueError(); -__consts_0.const_str__82 = 'a'; -__consts_0.const_str__36 = ']'; -__consts_0.const_str__44 = 'ReceivedItemOutcome'; -__consts_0.const_str__73 = "show_info('"; -__consts_0.const_str__51 = '- skipped ('; -__consts_0.const_str__23 = 'hide_host()'; -__consts_0.const_str__74 = 'hide_info()'; -__consts_0.const_str__14 = '#message'; +__consts_0.const_str__66 = ' failures, '; +__consts_0.const_str__33 = "show_host('"; +__consts_0.const_str__81 = '_txt_'; +__consts_0.const_str__91 = 'a'; +__consts_0.const_str__41 = ']'; +__consts_0.const_list__114 = []; +__consts_0.const_str__49 = 'ReceivedItemOutcome'; +__consts_0.const_str__82 = "show_info('"; +__consts_0.const_str__58 = '- skipped ('; +__consts_0.const_tuple = undefined; +__consts_0.const_str__37 = 'hide_host()'; +__consts_0.const_str__83 = 'hide_info()'; +__consts_0.const_str__20 = '#message'; __consts_0.ExportedMethods = new ExportedMethods(); -__consts_0.const_str__32 = 'tbody'; -__consts_0.const_tuple = {}; -__consts_0.const_str__52 = ')'; -__consts_0.const_str__39 = 'main_table'; -__consts_0.exceptions_KeyError__101 = exceptions_KeyError; -__consts_0.const_str__20 = "')"; -__consts_0.const_str__48 = 'RsyncFinished'; -__consts_0.Window = window; -__consts_0.const_str__58 = ' run, '; -__consts_0.const_str__94 = 'stdout'; -__consts_0.const_str = 'aa'; -__consts_0.const_tuple__70 = {}; -__consts_0.const_str__43 = 'HostReady'; -__consts_0.const_str__57 = 'FINISHED '; -__consts_0.const_str__34 = 'Rsyncing'; -__consts_0.const_str__2 = 'info'; -__consts_0.const_tuple__25 = undefined; -__consts_0.const_str__29 = 'hidden'; +__consts_0.const_str__12 = 'tbody'; +__consts_0.const_tuple__79 = {}; +__consts_0.exceptions_KeyError__108 = exceptions_KeyError; __consts_0.exceptions_KeyError_meta = new exceptions_KeyError_meta(); -__consts_0.const_str__85 = 'F'; -__consts_0.const_str__22 = 'onmouseout'; -__consts_0.const_str__40 = 'type'; -__consts_0.const_str__78 = 'passed'; -__consts_0.const_str__90 = '.'; -__consts_0.const_str__46 = 'FailedTryiter'; -__consts_0.py____test_rsession_webjs_Globals__104 = py____test_rsession_webjs_Globals; -__consts_0.py____test_rsession_webjs_Globals_meta = new py____test_rsession_webjs_Globals_meta(); -__consts_0.const_tuple__27 = undefined; -__consts_0.const_list__103 = []; -__consts_0.const_str__24 = ''; -__consts_0.py____test_rsession_webjs_Globals = new py____test_rsession_webjs_Globals(); -__consts_0.const_str__18 = '#ff0000'; -__consts_0.const_str__12 = 'messagebox'; -__consts_0.const_str__49 = 'fullitemname'; -__consts_0.const_str__75 = 'table'; -__consts_0.const_str__61 = 'Py.test '; -__consts_0.const_str__56 = 'skips'; -__consts_0.exceptions_StopIteration__99 = exceptions_StopIteration; +__consts_0.const_str__59 = ')'; +__consts_0.const_str__44 = 'main_table'; +__consts_0.const_str__87 = 'Tests [interrupted]'; +__consts_0.const_str__34 = "')"; +__consts_0.const_str__53 = 'RsyncFinished'; +__consts_0.const_str__65 = ' run, '; +__consts_0.exceptions_KeyError = new exceptions_KeyError(); +__consts_0.const_str__102 = 'stdout'; +__consts_0.const_str = 'aa'; +__consts_0.const_str__67 = ' skipped'; +__consts_0.const_str__74 = 'Py.test [crashed]'; +__consts_0.const_str__48 = 'HostReady'; +__consts_0.const_str__64 = 'FINISHED '; +__consts_0.const_str__39 = 'Rsyncing'; +__consts_0.const_str__9 = 'info'; +__consts_0.const_str__14 = 'td'; +__consts_0.const_str__42 = 'true'; +__consts_0.exceptions_ValueError__106 = exceptions_ValueError; +__consts_0.exceptions_StopIteration__110 = exceptions_StopIteration; __consts_0.exceptions_StopIteration_meta = new exceptions_StopIteration_meta(); __consts_0.exceptions_StopIteration = new exceptions_StopIteration(); -__consts_0.const_str__10 = '\n'; -__consts_0.const_str__13 = 'pre'; -__consts_0.const_str__8 = '\n======== Stdout: ========\n'; -__consts_0.const_str__64 = '#00ff00'; -__consts_0.const_str__4 = 'beige'; -__consts_0.const_str__68 = 'length'; -__consts_0.const_tuple__30 = {}; -__consts_0.const_str__93 = 'traceback'; -__consts_0.const_str__38 = 'testmain'; -__consts_0.const_str__88 = "javascript:show_skip('"; -__consts_0.const_str__66 = '['; -__consts_0.const_str__50 = 'reason'; -__consts_0.const_str__83 = "javascript:show_traceback('"; -__consts_0.const_str__33 = 'Tests'; -__consts_0.const_str__89 = 's'; -__consts_0.const_str__54 = 'run'; -__consts_0.const_str__47 = 'SkippedTryiter'; -__consts_0.const_str__81 = 'None'; -__consts_0.const_str__79 = 'True'; -__consts_0.const_str__86 = '/'; -__consts_0.const_str__63 = 'hostkey'; -__consts_0.const_str__55 = 'fails'; -__consts_0.const_str__41 = 'ItemStart'; -__consts_0.const_str__67 = 'itemname'; -__consts_0.const_str__45 = 'TestFinished'; -__consts_0.const_str__31 = 'jobs'; -__consts_0.const_str__9 = '\n========== Stderr: ==========\n'; -__consts_0.const_str__60 = ' skipped'; -__consts_0.const_str__95 = 'stderr'; -__consts_0.const_str__84 = 'href'; -__consts_0.const_tuple__71 = {}; -__consts_0.const_str__3 = 'visible'; -__consts_0.const_str__87 = 'False'; -__consts_0.const_str__21 = 'onmouseover'; -__consts_0.const_str__53 = '- FAILED TO LOAD MODULE'; -__consts_0.const_str__69 = '[0/'; +__consts_0.const_tuple__85 = {}; +__consts_0.const_str__94 = 'F'; +__consts_0.const_str__36 = 'onmouseout'; +__consts_0.const_str__45 = 'type'; +__consts_0.const_str__88 = 'passed'; +__consts_0.const_str__99 = '.'; +__consts_0.const_str__51 = 'FailedTryiter'; +__consts_0.py____test_rsession_webjs_Options__112 = py____test_rsession_webjs_Options; +__consts_0.py____test_rsession_webjs_Options_meta = new py____test_rsession_webjs_Options_meta(); +__consts_0.const_str__32 = '#ff0000'; +__consts_0.const_str__29 = 'checked'; +__consts_0.const_str__17 = 'messagebox'; +__consts_0.const_str__56 = 'fullitemname'; +__consts_0.const_str__84 = 'table'; +__consts_0.const_str__68 = 'Py.test '; +__consts_0.const_str__63 = 'skips'; +__consts_0.const_str__55 = 'CrashedExecution'; +__consts_0.const_str__19 = '\n'; +__consts_0.py____test_rsession_webjs_Options = new py____test_rsession_webjs_Options(); +__consts_0.const_str__18 = 'pre'; +__consts_0.const_str__86 = 'Py.test [interrupted]'; +__consts_0.const_str__25 = '\n======== Stdout: ========\n'; +__consts_0.const_str__71 = '#00ff00'; +__consts_0.const_tuple__8 = undefined; +__consts_0.const_str__11 = 'beige'; +__consts_0.const_str__77 = 'length'; +__consts_0.const_tuple__80 = {}; +__consts_0.const_str__101 = 'traceback'; +__consts_0.const_str__43 = 'testmain'; +__consts_0.const_str__97 = "javascript:show_skip('"; +__consts_0.const_str__73 = '['; +__consts_0.const_str__75 = 'Tests [crashed]'; +__consts_0.const_str__57 = 'reason'; +__consts_0.const_str__92 = "javascript:show_traceback('"; +__consts_0.const_str__38 = 'Tests'; +__consts_0.const_tuple__23 = {}; +__consts_0.const_str__98 = 's'; +__consts_0.const_str__61 = 'run'; +__consts_0.const_str__52 = 'SkippedTryiter'; +__consts_0.const_str__90 = 'None'; +__consts_0.const_str__30 = 'True'; +__consts_0.const_str__95 = '/'; +__consts_0.const_str__70 = 'hostkey'; +__consts_0.const_str__62 = 'fails'; +__consts_0.const_str__46 = 'ItemStart'; +__consts_0.const_str__76 = 'itemname'; +__consts_0.const_str__50 = 'TestFinished'; +__consts_0.const_str__2 = 'jobs'; +__consts_0.const_str__26 = '\n========== Stderr: ==========\n'; +__consts_0.const_tuple__15 = {}; +__consts_0.const_str__103 = 'stderr'; +__consts_0.const_str__93 = 'href'; +__consts_0.exceptions_ValueError_meta = new exceptions_ValueError_meta(); +__consts_0.const_str__10 = 'visible'; +__consts_0.const_str__96 = 'False'; +__consts_0.const_str__35 = 'onmouseover'; +__consts_0.const_str__60 = '- FAILED TO LOAD MODULE'; +__consts_0.const_str__78 = '[0/'; __consts_0.const_list = undefined; -__consts_0.const_str__42 = 'SendItem'; -__consts_0.const_str__62 = 'fullmodulename'; -__consts_0.const_str__80 = 'skipped'; -__consts_0.const_str__15 = 'hostsbody'; -__consts_0.const_str__65 = '[0]'; -__consts_0.const_str__17 = 'td'; -__consts_0.const_str__7 = '====== Traceback: =========\n'; -__consts_0.const_str__16 = 'tr'; -__consts_0.const_str__91 = 'item_name'; -__consts_0.const_str__35 = 'Tests ['; +__consts_0.const_str__47 = 'SendItem'; +__consts_0.const_str__69 = 'fullmodulename'; +__consts_0.const_str__89 = 'skipped'; +__consts_0.const_str__31 = 'hostsbody'; +__consts_0.const_str__72 = '[0]'; +__consts_0.const_str__3 = 'hidden'; +__consts_0.const_str__24 = '====== Traceback: =========\n'; +__consts_0.const_str__13 = 'tr'; +__consts_0.const_str__104 = 'item_name'; +__consts_0.const_str__40 = 'Tests ['; +__consts_0.py____test_rsession_webjs_Globals__115 = py____test_rsession_webjs_Globals; __consts_0.Document = document; -__consts_0.exceptions_KeyError = new exceptions_KeyError(); -__consts_0.const_tuple__76 = {}; -__consts_0.exceptions_ValueError_meta.class_ = __consts_0.exceptions_ValueError__97; -__consts_0.exceptions_ValueError.meta = __consts_0.exceptions_ValueError_meta; -__consts_0.exceptions_KeyError_meta.class_ = __consts_0.exceptions_KeyError__101; -__consts_0.py____test_rsession_webjs_Globals_meta.class_ = __consts_0.py____test_rsession_webjs_Globals__104; -__consts_0.py____test_rsession_webjs_Globals.odata_empty = true; -__consts_0.py____test_rsession_webjs_Globals.osessid = __consts_0.const_str__24; -__consts_0.py____test_rsession_webjs_Globals.ohost = __consts_0.const_str__24; -__consts_0.py____test_rsession_webjs_Globals.orsync_dots = 0; -__consts_0.py____test_rsession_webjs_Globals.ohost_dict = __consts_0.const_tuple__25; -__consts_0.py____test_rsession_webjs_Globals.meta = __consts_0.py____test_rsession_webjs_Globals_meta; -__consts_0.py____test_rsession_webjs_Globals.opending = __consts_0.const_list__103; -__consts_0.py____test_rsession_webjs_Globals.orsync_done = false; -__consts_0.py____test_rsession_webjs_Globals.ohost_pending = __consts_0.const_tuple__27; -__consts_0.exceptions_StopIteration_meta.class_ = __consts_0.exceptions_StopIteration__99; -__consts_0.exceptions_StopIteration.meta = __consts_0.exceptions_StopIteration_meta; +__consts_0.exceptions_ValueError = new exceptions_ValueError(); +__consts_0.py____test_rsession_webjs_Globals_meta = new py____test_rsession_webjs_Globals_meta(); +__consts_0.const_str__5 = ''; +__consts_0.py____test_rsession_webjs_Globals = new py____test_rsession_webjs_Globals(); +__consts_0.const_str__54 = 'InterruptedExecution'; +__consts_0.const_str__28 = 'opt_scroll'; +__consts_0.exceptions_KeyError_meta.class_ = __consts_0.exceptions_KeyError__108; __consts_0.exceptions_KeyError.meta = __consts_0.exceptions_KeyError_meta; +__consts_0.exceptions_StopIteration_meta.class_ = __consts_0.exceptions_StopIteration__110; +__consts_0.exceptions_StopIteration.meta = __consts_0.exceptions_StopIteration_meta; +__consts_0.py____test_rsession_webjs_Options_meta.class_ = __consts_0.py____test_rsession_webjs_Options__112; +__consts_0.py____test_rsession_webjs_Options.meta = __consts_0.py____test_rsession_webjs_Options_meta; +__consts_0.py____test_rsession_webjs_Options.oscroll = true; +__consts_0.exceptions_ValueError_meta.class_ = __consts_0.exceptions_ValueError__106; +__consts_0.exceptions_ValueError.meta = __consts_0.exceptions_ValueError_meta; +__consts_0.py____test_rsession_webjs_Globals_meta.class_ = __consts_0.py____test_rsession_webjs_Globals__115; +__consts_0.py____test_rsession_webjs_Globals.odata_empty = true; +__consts_0.py____test_rsession_webjs_Globals.osessid = __consts_0.const_str__5; +__consts_0.py____test_rsession_webjs_Globals.ohost = __consts_0.const_str__5; +__consts_0.py____test_rsession_webjs_Globals.orsync_dots = 0; +__consts_0.py____test_rsession_webjs_Globals.ofinished = false; +__consts_0.py____test_rsession_webjs_Globals.ohost_dict = __consts_0.const_tuple; +__consts_0.py____test_rsession_webjs_Globals.meta = __consts_0.py____test_rsession_webjs_Globals_meta; +__consts_0.py____test_rsession_webjs_Globals.opending = __consts_0.const_list__114; +__consts_0.py____test_rsession_webjs_Globals.orsync_done = false; +__consts_0.py____test_rsession_webjs_Globals.ohost_pending = __consts_0.const_tuple__8; diff --git a/py/test/rsession/webjs.py b/py/test/rsession/webjs.py index 1239b871f..9841a0651 100644 --- a/py/test/rsession/webjs.py +++ b/py/test/rsession/webjs.py @@ -36,6 +36,14 @@ class Globals(object): glob = Globals() +class Options(object): + """ Store global options + """ + def __init__(self): + self.scroll = True + +opts = Options() + def comeback(msglist): if len(msglist) == 0: return @@ -62,11 +70,29 @@ def hide_info(): info = dom.document.getElementById("info") info.style.visibility = "hidden" +def show_interrupt(): + glob.finished = True + dom.document.title = "Py.test [interrupted]" + dom.document.getElementById("Tests").childNodes[0].nodeValue = "Tests [interrupted]" + +def show_crash(): + glob.finished = True + dom.document.title = "Py.test [crashed]" + dom.document.getElementById("Tests").childNodes[0].nodeValue = "Tests [crashed]" + SCROLL_LINES = 50 +def opt_scroll(): + if opts.scroll: + opts.scroll = False + else: + opts.scroll = True + def scroll_down_if_needed(mbox): - if dom.window.scrollMaxY - dom.window.scrollY < SCROLL_LINES: - mbox.parentNode.scrollIntoView() + if not opts.scroll: + return + #if dom.window.scrollMaxY - dom.window.scrollY < SCROLL_LINES: + mbox.parentNode.scrollIntoView() def hide_messagebox(): mbox = dom.document.getElementById("messagebox") @@ -175,6 +201,7 @@ def process(msg): add_received_item_outcome(msg, module_part) elif msg['type'] == 'TestFinished': text = "FINISHED %s run, %s failures, %s skipped" % (msg['run'], msg['fails'], msg['skips']) + glob.finished = True dom.document.title = "Py.test %s" % text dom.document.getElementById("Tests").childNodes[0].nodeValue = \ "Tests [%s]" % text @@ -202,6 +229,10 @@ def process(msg): module_part.appendChild(tr) elif msg['type'] == 'RsyncFinished': glob.rsync_done = True + elif msg['type'] == 'InterruptedExecution': + show_interrupt() + elif msg['type'] == 'CrashedExecution': + show_crash() if glob.data_empty: mbox = dom.document.getElementById('messagebox') scroll_down_if_needed(mbox) @@ -262,6 +293,8 @@ def hide_host(): glob.host = "" def update_rsync(): + if glob.finished: + return elem = dom.document.getElementById("Tests") if glob.rsync_done is True: elem.childNodes[0].nodeValue = "Tests" @@ -294,11 +327,23 @@ def host_init(host_dict): for key in host_dict.keys(): glob.host_pending[key] = [] +def key_pressed(key): + if key.charCode == ord('s'): + scroll_box = dom.document.getElementById("opt_scroll") + if opts.scroll: + scroll_box.removeAttribute("checked") + opts.scroll = False + else: + scroll_box.setAttribute("checked", "true") + opts.scroll = True + def sessid_comeback(id): glob.sessid = id exported_methods.show_all_statuses(id, comeback) def main(): + glob.finished = False exported_methods.show_hosts(host_init) exported_methods.show_sessid(sessid_comeback) - + dom.document.onkeypress = key_pressed + dom.document.getElementById("opt_scroll").setAttribute("checked", "True") diff --git a/py/test/session.py b/py/test/session.py index 6bfea128d..e0e19627f 100644 --- a/py/test/session.py +++ b/py/test/session.py @@ -38,12 +38,11 @@ class Session(object): def main(self): """ main loop for running tests. """ - colitems = self._map2colitems(self.config.remaining) + colitems = self.config.getcolitems() try: self.header(colitems) try: for colitem in colitems: - colitem.option = self.config.option self.runtraced(colitem) except KeyboardInterrupt: raise @@ -53,9 +52,6 @@ class Session(object): self.footer(colitems) except Exit, ex: pass - # return [(fspath as string, [names as string])] - return [(str(item.listchain()[0].fspath), item.listnames()) - for item, outcome in self.getitemoutcomepairs(py.test.Item.Failed)] def runtraced(self, colitem): if self.shouldclose(): @@ -91,7 +87,7 @@ class Session(object): if self.config.option.collectonly and isinstance(colitem, py.test.Item): return if isinstance(colitem, py.test.Item): - self.skipbykeyword(colitem) + colitem.skipbykeyword(self.config.option.keyword) res = colitem.run() if res is None: return py.test.Item.Passed() @@ -110,39 +106,6 @@ class Session(object): finish() return res - def skipbykeyword(self, colitem): - keyword = self.config.option.keyword - if not keyword: - return - chain = colitem.listchain() - for key in filter(None, keyword.split()): - eor = key[:1] == '-' - if eor: - key = key[1:] - if not (eor ^ self._matchonekeyword(key, chain)): - py.test.skip("test not selected by keyword %r" %(keyword,)) - - def _matchonekeyword(self, key, chain): - for subitem in chain: - if subitem.haskeyword(key): - return True - return False - - - def _map2colitems(items): - # first convert all path objects into collectors - from py.__.test.collect import getfscollector - colitems = [] - for item in items: - if isinstance(item, (list, tuple)): - colitems.extend(Session._map2colitems(item)) - elif not isinstance(item, py.test.collect.Collector): - colitems.append(getfscollector(item)) - else: - colitems.append(item) - return colitems - _map2colitems = staticmethod(_map2colitems) - class Exit(Exception): """ for immediate program exits without tracebacks and reporter/summary. """ def __init__(self, msg="unknown reason", item=None): diff --git a/py/test/terminal/out.py b/py/test/terminal/out.py index 473e2b0fb..9fa620389 100644 --- a/py/test/terminal/out.py +++ b/py/test/terminal/out.py @@ -10,8 +10,9 @@ class Out(object): def __init__(self, file): self.file = py.io.dupfile(file) - def sep(self, sepchar, title=None): - fullwidth = self.fullwidth + def sep(self, sepchar, title=None, fullwidth=None): + if not fullwidth: + fullwidth = self.fullwidth # the goal is to have the line be as long as possible # under the condition that len(line) <= fullwidth if title is not None: @@ -37,15 +38,10 @@ class TerminalOut(Out): tty = True def __init__(self, file): super(TerminalOut, self).__init__(file) - try: - import termios,fcntl,struct - call = fcntl.ioctl(0,termios.TIOCGWINSZ,"\000"*8) - height,width = struct.unpack( "hhhh", call ) [:2] - self.fullwidth = width - except (SystemExit, KeyboardInterrupt), e: - raise - except: - pass + + def sep(self, sepchar, title=None): + super(TerminalOut, self).sep(sepchar, title, + terminal_helper.get_terminal_width()) def write(self, s): self.file.write(str(s)) @@ -84,8 +80,10 @@ def getout(file): # if file is None: file = py.std.sys.stdout - elif hasattr(file, 'send'): # likely a channel like thing + elif hasattr(file, 'send'): file = WriteFile(file.send) + elif callable(file): + file = WriteFile(file) if hasattr(file, 'isatty') and file.isatty(): return TerminalOut(file) else: diff --git a/py/test/terminal/remote.py b/py/test/terminal/remote.py index 40eca2e5b..41e2c0118 100644 --- a/py/test/terminal/remote.py +++ b/py/test/terminal/remote.py @@ -29,46 +29,6 @@ def checkpyfilechange(rootdir, statcache={}): changed = True return changed -class FailingCollector(py.test.collect.Collector): - def __init__(self, faileditems): - self._faileditems = faileditems - - def __iter__(self): - for x in self._faileditems: - yield x - -def waitfinish(channel): - try: - while 1: - try: - channel.waitclose(0.1) - except (IOError, py.error.Error): - continue - else: - return channel.receive() - finally: - #print "closing down channel and gateway" - channel.gateway.exit() - -def failure_slave(channel): - """ we run this on the other side. """ - args, failures = channel.receive() - config = py.test.config._reparse(args) - # making this session definitely non-remote - config.option.executable = py.std.sys.executable - config.option.looponfailing = False - config.option._remote = False - config.option._fromremote = True - if failures: - cols = getfailureitems(failures) - else: - cols = args - #print "processing", cols - session = config.getsessionclass()(config) - session.shouldclose = channel.isclosed - failures = session.main() - channel.send(failures) - def getfailureitems(failures): l = [] for rootpath, names in failures: @@ -91,61 +51,77 @@ def getfailureitems(failures): l.append(current) return l -def failure_master(executable, out, args, failures): - gw = py.execnet.PopenGateway(executable) - channel = gw.remote_exec(""" - from py.__.test.terminal.remote import failure_slave - failure_slave(channel) - """, stdout=out, stderr=out) - channel.send((args, failures)) - return waitfinish(channel) +class RemoteTerminalSession(object): + def __init__(self, config, file=None): + self.config = config + self._setexecutable() + if file is None: + file = py.std.sys.stdout + self._file = file + self.out = getout(file) -def generalize(p1, p2): - general = p1 - for x, y in zip(p1.parts(), p2.parts()): - if x != y: - break - general = x - return general + def _setexecutable(self): + name = self.config.option.executable + if name is None: + executable = py.std.sys.executable + else: + executable = py.path.local.sysfind(name) + assert executable is not None, executable + self.executable = executable -def getrootdir(args): - tops = [] - for arg in args: - p = py.path.local(arg) - tops.append(p.pypkgpath() or p) - p = reduce(generalize, tops) - if p.check(file=1): - p = p.dirpath() - return p + def main(self): + rootdir = self.config.topdir + wasfailing = False + failures = [] + while 1: + if self.config.option.looponfailing and (failures or not wasfailing): + while not checkpyfilechange(rootdir): + py.std.time.sleep(0.4) + wasfailing = len(failures) + failures = self.run_remote_session(failures) + if not self.config.option.looponfailing: + break + print "#" * 60 + print "# looponfailing: mode: %d failures args" % len(failures) + for root, names in failures: + name = "/".join(names) # XXX + print "Failure at: %r" % (name,) + print "# watching py files below %s" % rootdir + print "# ", "^" * len(str(rootdir)) + return failures -def main(config, file, args): - """ testing process and output happens at a remote place. """ - assert file - if hasattr(file, 'write'): - def out(data): - file.write(data) - file.flush() - else: - out = file - failures = [] - args = list(args) - rootdir = getrootdir(config.remaining) - #print "rootdir", rootdir - wasfailing = False - while 1: - if config.option.looponfailing and (failures or not wasfailing): - while not checkpyfilechange(rootdir): - py.std.time.sleep(0.4) - wasfailing = len(failures) - failures = failure_master(config.option.executable, out, args, failures) - if not config.option.looponfailing: - break - print "#" * 60 - print "# looponfailing: mode: %d failures remaining" % len(failures) - for root, names in failures: - name = "/".join(names) # XXX - print "Failure at: %r" % (name,) - print "# watching py files below %s" % rootdir - print "# ", "^" * len(str(rootdir)) - return failures + def run_remote_session(self, failures): + print "* opening PopenGateway: ", self.executable + gw = py.execnet.PopenGateway(self.executable) + channel = gw.remote_exec(""" + from py.__.test.terminal.remote import slaverun_TerminalSession + slaverun_TerminalSession(channel) + """, stdout=self.out, stderr=self.out) + print "MASTER: triggered slave terminal session ->" + repr = self.config.make_repr(conftestnames=[]) + channel.send((str(self.config.topdir), repr, failures)) + print "MASTER: send start info" + try: + return channel.receive() + except channel.RemoteError, e: + print e + return [] +def slaverun_TerminalSession(channel): + """ we run this on the other side. """ + print "SLAVE: starting" + topdir, repr, failures = channel.receive() + print "SLAVE: received configuration" + config = py.test.config + config.initdirect(topdir, repr, failures) + config.option.looponfailing = False + config.option.usepdb = False + config.option.executable = None + + session = config.initsession() + session.shouldclose = channel.isclosed + print "SLAVE: starting session.main()" + session.main() + failures = session.getitemoutcomepairs(py.test.Item.Failed) + failures = [config.get_collector_trail(item) for item,_ in failures] + channel.send(failures) diff --git a/py/test/terminal/terminal.py b/py/test/terminal/terminal.py index 118ff3c11..c422b40d6 100644 --- a/py/test/terminal/terminal.py +++ b/py/test/terminal/terminal.py @@ -4,6 +4,7 @@ from time import time as now Item = py.test.Item from py.__.test.terminal.out import getout import py.__.code.safe_repr +from py.__.test.representation import Presenter def getrelpath(source, dest): base = source.common(dest) @@ -25,15 +26,8 @@ class TerminalSession(Session): file = py.std.sys.stdout self._file = file self.out = getout(file) - self._started = {} self._opencollectors = [] - - 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() + self.presenter = Presenter(self.out, config) # --------------------- # PROGRESS information @@ -128,10 +122,10 @@ class TerminalSession(Session): for name in 'looponfailing', 'exitfirst', 'nomagic': if getattr(option, name): modes.append(name) - if option._fromremote: - modes.insert(0, 'child process') - else: - modes.insert(0, 'inprocess') + #if self._isremoteoption._fromremote: + # modes.insert(0, 'child process') + #else: + # modes.insert(0, 'inprocess') mode = "/".join(modes) self.out.line("testing-mode: %s" % mode) self.out.line("executable: %s (%s)" % @@ -146,7 +140,7 @@ class TerminalSession(Session): self.out.line("test target: %s" %(x.fspath,)) conftestmodules = self.config.conftest.getconftestmodules(None) - for i,x in py.builtin.enumerate(conftestmodules): + 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): @@ -279,173 +273,8 @@ class TerminalSession(Session): if not traceback: self.out.line("empty traceback from item %r" % (item,)) return - handler = getattr(self, 'repr_failure_tb%s' % self.config.option.tbstyle) - handler(item, excinfo, traceback) - - def repr_failure_tblong(self, item, excinfo, traceback): - if not self.config.option.nomagic and excinfo.errisinstance(RuntimeError): - recursionindex = traceback.recursionindex() - else: - recursionindex = None - last = traceback[-1] - first = traceback[0] - for index, entry in py.builtin.enumerate(traceback): - if entry == first: - if item: - self.repr_failure_info(item, entry) - self.out.line() - else: - self.out.line("") - source = self.getentrysource(entry) - firstsourceline = entry.getfirstlinesource() - marker_location = entry.lineno - firstsourceline - if entry == last: - self.repr_source(source, 'E', marker_location) - self.repr_failure_explanation(excinfo, source) - else: - self.repr_source(source, '>', marker_location) - self.out.line("") - self.out.line("[%s:%d]" %(entry.frame.code.path, entry.lineno+1)) - self.repr_locals(entry) - - # trailing info - if entry == last: - #if item: - # self.repr_failure_info(item, entry) - self.repr_out_err(item) - self.out.sep("_") - else: - self.out.sep("_ ") - if index == recursionindex: - self.out.line("Recursion detected (same locals & position)") - self.out.sep("!") - break - - def repr_failure_tbshort(self, item, excinfo, traceback): - # print a Python-style short traceback - if not self.config.option.nomagic and excinfo.errisinstance(RuntimeError): - recursionindex = traceback.recursionindex() - else: - recursionindex = None - last = traceback[-1] - first = traceback[0] - self.out.line() - for index, entry in py.builtin.enumerate(traceback): - code = entry.frame.code - self.out.line(' File "%s", line %d, in %s' % ( - code.raw.co_filename, entry.lineno+1, code.raw.co_name)) - try: - fullsource = entry.frame.code.fullsource - except py.error.ENOENT: - source = ["?"] - else: - try: - source = [fullsource[entry.lineno].lstrip()] - except IndexError: - source = [] - if entry == last: - if source: - self.repr_source(source, 'E') - self.repr_failure_explanation(excinfo, source) - else: - if source: - self.repr_source(source, ' ') - self.repr_locals(entry) - - # trailing info - if entry == last: - #if item: - # self.repr_failure_info(item, entry) - self.repr_out_err(item) - self.out.sep("_") - else: - if index == recursionindex: - self.out.line("Recursion detected (same locals & position)") - self.out.sep("!") - break - - # the following is only used by the combination '--pdb --tb=no' - repr_failure_tbno = repr_failure_tbshort - - def repr_failure_info(self, item, entry): - root = item.fspath - modpath = item.getmodpath() - try: - fn, lineno = item.getpathlineno() - except TypeError: - assert isinstance(item.parent, py.test.collect.Generator) - # a generative test yielded a non-callable - fn, lineno = item.parent.getpathlineno() - # hum, the following overloads traceback output - #if fn != entry.frame.code.path or \ - # entry.frame.code.firstlineno != lineno: - # self.out.line("testcode: %s:%d" % (fn, lineno+1)) - if root == fn: - self.out.sep("_", "entrypoint: %s" %(modpath)) - else: - self.out.sep("_", "entrypoint: %s %s" %(root.basename, modpath)) - - def getentrysource(self, entry): - try: - source = entry.getsource() - except py.error.ENOENT: - source = py.code.Source("[failure to get at sourcelines from %r]\n" % entry) - return source.deindent() - - def repr_source(self, source, marker=">", marker_location=-1): - if marker_location < 0: - marker_location += len(source) - if marker_location < 0: - marker_location = 0 - if marker_location >= len(source): - marker_location = len(source) - 1 - for i in range(len(source)): - if i == marker_location: - prefix = marker + " " - else: - prefix = " " - self.out.line(prefix + source[i]) - - def repr_failure_explanation(self, excinfo, source): - try: - s = str(source.getstatement(len(source)-1)) - except KeyboardInterrupt: - raise - except: - s = str(source[-1]) - indent = " " * (4 + (len(s) - len(s.lstrip()))) - # get the real exception information out - lines = excinfo.exconly(tryshort=True).split('\n') - self.out.line('>' + indent[:-1] + lines.pop(0)) - for x in lines: - self.out.line(indent + x) - return - - # XXX reinstate the following with a --magic option? - # the following line gets user-supplied messages (e.g. - # for "assert 0, 'custom message'") - msg = getattr(getattr(excinfo, 'value', ''), 'msg', '') - info = None - if not msg: - special = excinfo.errisinstance((SyntaxError, SystemExit, KeyboardInterrupt)) - if not self.config.option.nomagic and not special: - try: - info = excinfo.traceback[-1].reinterpret() # very detailed info - except KeyboardInterrupt: - raise - except: - if self.config.option.verbose >= 1: - self.out.line("[reinterpretation traceback]") - py.std.traceback.print_exc(file=py.std.sys.stdout) - else: - self.out.line("[reinterpretation failed, increase " - "verbosity to see details]") - # print reinterpreted info if any - if info: - lines = info.split('\n') - self.out.line('>' + indent[:-1] + lines.pop(0)) - for x in lines: - self.out.line(indent + x) + handler = getattr(self.presenter, 'repr_failure_tb%s' % self.config.option.tbstyle) + handler(item, excinfo, traceback, lambda : self.repr_out_err(item)) def repr_out_err(self, colitem): for parent in colitem.listchain(): @@ -453,23 +282,6 @@ class TerminalSession(Session): if obj: self.out.sep("- ", "%s: recorded std%s" % (parent.name, name)) self.out.line(obj) - - def repr_locals(self, entry): - if self.config.option.showlocals: - self.out.sep('- ', 'locals') - for name, value in entry.frame.f_locals.items(): - if name == '__builtins__': - self.out.line("__builtins__ = ") - else: - # This formatting could all be handled by the _repr() function, which is - # only repr.Repr in disguise, so is very configurable. - str_repr = py.__.code.safe_repr._repr(value) - if len(str_repr) < 70 or not isinstance(value, - (list, tuple, dict)): - self.out.line("%-10s = %s" %(name, str_repr)) - else: - self.out.line("%-10s =\\" % (name,)) - py.std.pprint.pprint(value, stream=self.out) def repr_pythonversion(): v = py.std.sys.version_info diff --git a/py/test/testing/test_collect.py b/py/test/testing/test_collect.py index 174cbf6e6..f66ddbd9b 100644 --- a/py/test/testing/test_collect.py +++ b/py/test/testing/test_collect.py @@ -12,18 +12,6 @@ def test_failing_import_execfile(): py.test.raises(ImportError, col.run) py.test.raises(ImportError, col.run) -def XXXtest_finds_root(): - fn = datadir / 'filetest.py' - col = py.test.collect.Module(fn) - root, namelist = col.fromroot() - assert isinstance(root, py.test.collect.Directory) - cur = root - for x in namelist: - cur = cur.join(x) - assert cur.name == col.name - assert cur.parent == col.parent - assert cur.fspath == cur.fspath - def test_collect_listnames_and_back(): col1 = py.test.collect.Directory(datadir.dirpath()) col2 = col1.join(datadir.basename) @@ -203,10 +191,10 @@ def test_custom_python_collection_from_conftest(): assert 23 == 23 """) - from py.__.test.collect import getfscollector for x in (o, checkfile, checkfile.dirpath()): + config = py.test.config._reparse([x]) #print "checking that %s returns custom items" % (x,) - col = getfscollector(x) + col = config._getcollector(x) assert len(list(col.tryiter(py.test.Item))) == 2 #assert items[1].__class__.__name__ == 'MyFunction' @@ -215,7 +203,7 @@ def test_custom_python_collection_from_conftest(): try: config = py.test.config._reparse([]) out = py.std.cStringIO.StringIO() - session = config.getsessionclass()(config, out) + session = config._getsessionclass()(config, out) session.main() l = session.getitemoutcomepairs(py.test.Item.Passed) assert len(l) == 2 @@ -225,7 +213,7 @@ def test_custom_python_collection_from_conftest(): # test that running the file directly works config = py.test.config._reparse([str(checkfile)]) out = py.std.cStringIO.StringIO() - session = config.getsessionclass()(config, out) + session = config._getsessionclass()(config, out) session.main() l = session.getitemoutcomepairs(py.test.Item.Passed) assert len(l) == 2 @@ -250,10 +238,10 @@ def test_custom_NONpython_collection_from_conftest(): """) checkfile = o.ensure('somedir', 'moredir', 'check_something.txt') - from py.__.test.collect import getfscollector for x in (o, checkfile, checkfile.dirpath()): print "checking that %s returns custom items" % (x,) - col = getfscollector(x) + config = py.test.config._reparse([x]) + col = config._getcollector(x) assert len(list(col.tryiter(py.test.Item))) == 1 #assert items[1].__class__.__name__ == 'MyFunction' @@ -262,7 +250,7 @@ def test_custom_NONpython_collection_from_conftest(): try: config = py.test.config._reparse([]) out = py.std.cStringIO.StringIO() - session = config.getsessionclass()(config, out) + session = config._getsessionclass()(config, out) session.main() l = session.getitemoutcomepairs(py.test.Item.Passed) assert len(l) == 1 @@ -272,12 +260,14 @@ def test_custom_NONpython_collection_from_conftest(): # test that running the file directly works config = py.test.config._reparse([str(checkfile)]) out = py.std.cStringIO.StringIO() - session = config.getsessionclass()(config, out) + session = config._getsessionclass()(config, out) session.main() l = session.getitemoutcomepairs(py.test.Item.Passed) assert len(l) == 1 def test_order_of_execution_generator_same_codeline(): + if py.test.config.is_boxed(): + py.test.skip("Does not work with boxing") test_list = [] expected_list = range(6) @@ -295,6 +285,8 @@ def test_order_of_execution_generator_same_codeline(): def test_order_of_execution_generator_different_codeline(): + if py.test.config.is_boxed(): + py.test.skip("Does not work with boxing") test_list = [] expected_list = range(3) diff --git a/py/test/testing/test_config.py b/py/test/testing/test_config.py index 09be0cb0f..e920ed14c 100644 --- a/py/test/testing/test_config.py +++ b/py/test/testing/test_config.py @@ -1,6 +1,8 @@ from __future__ import generators import py +from py.__.test.config import gettopdir + def test_tmpdir(): d1 = py.test.ensuretemp('hello') d2 = py.test.ensuretemp('hello') @@ -72,3 +74,266 @@ def test_siblingconftest_fails_maybe(): print py.process.cmdexec("py.test") finally: old.chdir() + +def test_config_overwrite(): + o = py.test.ensuretemp('testconfigget') + o.ensure("conftest.py").write("x=1") + config = py.test.config._reparse([str(o)]) + assert config.getvalue('x') == 1 + config._overwrite('x', 2) + assert config.getvalue('x') == 2 + config = py.test.config._reparse([str(o)]) + assert config.getvalue('x') == 1 + +def test_gettopdir(): + tmp = py.test.ensuretemp("topdir") + assert gettopdir([tmp]) == tmp + topdir =gettopdir([tmp.join("hello"), tmp.join("world")]) + assert topdir == tmp + +def test_gettopdir_pypkg(): + tmp = py.test.ensuretemp("topdir2") + a = tmp.ensure('a', dir=1) + b = tmp.ensure('a', 'b', '__init__.py') + c = tmp.ensure('a', 'b', 'c.py') + Z = tmp.ensure('Z', dir=1) + assert gettopdir([c]) == a + assert gettopdir([c, Z]) == tmp + + +def test_config_init_direct(): + tmp = py.test.ensuretemp("initdirect") + tmp.ensure("__init__.py") + tmp.ensure("conftest.py").write("x=1 ; y=2") + hello = tmp.ensure("test_hello.py") + config = py.test.config._reparse([hello]) + repr = config.make_repr(conftestnames=['x', 'y']) + config2 = py.test.config._reparse([tmp.dirpath()]) + config2._initialized = False # we have to do that from tests + config2.initdirect(topdir=tmp.dirpath(), repr=repr) + for col1, col2 in zip(config.getcolitems(), config2.getcolitems()): + assert col1.fspath == col2.fspath + py.test.raises(AssertionError, "config2.initdirect(None, None)") + from py.__.test.config import Config + config3 = Config() + config3.initdirect(topdir=tmp.dirpath(), repr=repr, + coltrails=[(tmp.basename, (hello.basename,))]) + assert config3.getvalue('x') == 1 + assert config3.getvalue('y') == 2 + cols = config.getcolitems() + assert len(cols) == 1 + col = cols[0] + assert col.name == 'test_hello.py' + assert col.parent.name == tmp.basename + assert col.parent.parent is None + +def test_config_make_and_merge_repr(): + tmp = py.test.ensuretemp("reprconfig1") + tmp.ensure("__init__.py") + tmp.ensure("conftest.py").write("x=1") + config = py.test.config._reparse([tmp]) + repr = config.make_repr(conftestnames=['x']) + config.option.verbose = 42 + repr2 = config.make_repr(conftestnames=[], optnames=['verbose']) + config = py.test.config._reparse([tmp.dirpath()]) + py.test.raises(KeyError, "config.getvalue('x')") + config.merge_repr(repr) + assert config.getvalue('x') == 1 + config.merge_repr(repr2) + assert config.option.verbose == 42 + +def test_config_marshability(): + tmp = py.test.ensuretemp("configmarshal") + tmp.ensure("__init__.py") + tmp.ensure("conftest.py").write("a = object()") + config = py.test.config._reparse([tmp]) + py.test.raises(ValueError, "config.make_repr(conftestnames=['a'])") + + config.option.hello = lambda x: None + py.test.raises(ValueError, "config.make_repr(conftestnames=[])") + config.make_repr(conftestnames=[], optnames=[]) + +def test_config_rconfig(): + tmp = py.test.ensuretemp("rconfigopt") + tmp.ensure("__init__.py") + tmp.ensure("conftest.py").write(py.code.Source(""" + import py + 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.")) + """)) + config = py.test.config._reparse([tmp, "-g", "11"]) + assert config.option.gdest == 11 + repr = config.make_repr(conftestnames=[]) + config = py.test.config._reparse([tmp.dirpath()]) + py.test.raises(AttributeError, "config.option.gdest") + config.merge_repr(repr) + assert config.option.gdest == 11 + +class TestSessionAndOptions: + def setup_class(cls): + cls.tmproot = py.test.ensuretemp(cls.__name__) + + def setup_method(self, method): + self.tmpdir = self.tmproot.ensure(method.__name__, dir=1) + + def test_sessionname_default(self): + config = py.test.config._reparse([self.tmpdir]) + assert config._getsessionname() == 'TerminalSession' + + def test_sessionname_dist(self): + config = py.test.config._reparse([self.tmpdir, '--dist']) + assert config._getsessionname() == 'RSession' + + def test_implied_lsession(self): + optnames = 'startserver runbrowser apigen=x rest box'.split() + for x in optnames: + config = py.test.config._reparse([self.tmpdir, '--%s' % x]) + assert config._getsessionname() == 'LSession' + + for x in 'startserver runbrowser rest'.split(): + config = py.test.config._reparse([self.tmpdir, '--dist', '--%s' % x]) + assert config._getsessionname() == 'RSession' + + def test_implied_remote_terminal_session(self): + config = py.test.config._reparse([self.tmpdir, '--looponfailing']) + assert config._getsessionname() == 'RemoteTerminalSession' + config = py.test.config._reparse([self.tmpdir, '--exec=x']) + assert config._getsessionname() == 'RemoteTerminalSession' + config = py.test.config._reparse([self.tmpdir, '--dist', '--exec=x']) + assert config._getsessionname() == 'RSession' + + def test_tkintersession(self): + config = py.test.config._reparse([self.tmpdir, '--tkinter']) + assert config._getsessionname() == 'TkinterSession' + config = py.test.config._reparse([self.tmpdir, '--dist']) + + def test_sessionname_lookup_custom(self): + self.tmpdir.join("conftest.py").write(py.code.Source(""" + class MySession: + def __init__(self, config): + self.config = config + """)) + config = py.test.config._reparse(["--session=MySession", self.tmpdir]) + session = config.initsession() + assert session.__class__.__name__ == 'MySession' + + def test_initsession(self): + config = py.test.config._reparse([self.tmpdir]) + session = config.initsession() + assert session.config is config + + def test_boxing_options(self): + # XXX config.is_boxed() is probably not a good idea + tmpdir = self.tmpdir + config = py.test.config._reparse([tmpdir]) + assert not config.option.boxing + assert not config.is_boxed() + + #tmpdir.join("conftest.py").write("dist_boxing=True\n") + #config = py.test.config._reparse([tmpdir]) + #assert config.is_boxed() + + tmpdir.join("conftest.py").write("dist_boxing=False\n") + config = py.test.config._reparse([tmpdir]) + assert not config.is_boxed() + config = py.test.config._reparse([tmpdir, '--box']) + assert config.is_boxed() + + +class TestConfigColitems: + def setup_class(cls): + cls.tmproot = py.test.ensuretemp(cls.__name__) + + def setup_method(self, method): + self.tmpdir = self.tmproot.mkdir(method.__name__) + + def test_getcolitems_onedir(self): + config = py.test.config._reparse([self.tmpdir]) + colitems = config.getcolitems() + assert len(colitems) == 1 + col = colitems[0] + assert isinstance(col, py.test.collect.Directory) + for col in col.listchain(): + assert col.config is config + + def test_getcolitems_twodirs(self): + config = py.test.config._reparse([self.tmpdir, self.tmpdir]) + colitems = config.getcolitems() + assert len(colitems) == 2 + col1, col2 = colitems + assert col1.name == col2.name + assert col1.parent == col2.parent + + def test_getcolitems_curdir_and_subdir(self): + a = self.tmpdir.ensure("a", dir=1) + config = py.test.config._reparse([self.tmpdir, a]) + colitems = config.getcolitems() + assert len(colitems) == 2 + col1, col2 = colitems + assert col1.name == self.tmpdir.basename + assert col2.name == 'a' + for col in colitems: + for subcol in col.listchain(): + assert col.config is config + + def test__getcol_global_file(self): + x = self.tmpdir.ensure("x.py") + config = py.test.config._reparse([x]) + col = config._getcollector(x) + assert isinstance(col, py.test.collect.Module) + assert col.name == 'x.py' + assert col.parent.name == self.tmpdir.basename + assert col.parent.parent is None + for col in col.listchain(): + assert col.config is config + + def test__getcol_global_dir(self): + x = self.tmpdir.ensure("a", dir=1) + config = py.test.config._reparse([x]) + col = config._getcollector(x) + assert isinstance(col, py.test.collect.Directory) + print col.listchain() + assert col.name == 'a' + assert col.parent is None + assert col.config is config + + def test__getcol_pkgfile(self): + x = self.tmpdir.ensure("x.py") + self.tmpdir.ensure("__init__.py") + config = py.test.config._reparse([x]) + col = config._getcollector(x) + assert isinstance(col, py.test.collect.Module) + assert col.name == 'x.py' + assert col.parent.name == x.dirpath().basename + assert col.parent.parent is None + for col in col.listchain(): + assert col.config is config + + def test_get_collector_trail_and_back(self): + a = self.tmpdir.ensure("a", dir=1) + self.tmpdir.ensure("a", "__init__.py") + x = self.tmpdir.ensure("a", "trail.py") + config = py.test.config._reparse([x]) + col = config._getcollector(x) + trail = config.get_collector_trail(col) + assert len(trail) == 2 + assert trail[0] == a.relto(config.topdir) + assert trail[1] == ('trail.py',) + col2 = config._getcollector(trail) + assert col2.listchain() == col.listchain() + + def test_get_collector_trail_topdir_and_beyond(self): + config = py.test.config._reparse([self.tmpdir]) + col = config._getcollector(config.topdir) + trail = config.get_collector_trail(col) + assert len(trail) == 2 + assert trail[0] == '.' + assert trail[1] == () + col2 = config._getcollector(trail) + assert col2.fspath == config.topdir + assert len(col2.listchain()) == 1 + col3 = config._getcollector(config.topdir.dirpath()) + py.test.raises(ValueError, + "config.get_collector_trail(col3)") diff --git a/py/test/testing/test_conftesthandle.py b/py/test/testing/test_conftesthandle.py index 29be6af91..a95cb0591 100644 --- a/py/test/testing/test_conftesthandle.py +++ b/py/test/testing/test_conftesthandle.py @@ -11,6 +11,11 @@ class TestConftestValueAccessGlobal: d.ensure("adir/conftest.py").write("a=1 ; Directory = 3") d.ensure("adir/b/conftest.py").write("b=2 ; a = 1.5") + def test_basic_init(self): + conftest = Conftest() + conftest.setinitial([self.basedir.join("adir")]) + assert conftest.rget("a") == 1 + def test_immediate_initialiation_and_incremental_are_the_same(self): conftest = Conftest() snap0 = len(conftest._path2confmods) @@ -25,40 +30,40 @@ class TestConftestValueAccessGlobal: def test_default_Module_setting_is_visible_always(self): for path in self.basedir.parts(): conftest = Conftest(path) - assert conftest.lget("Module") == py.test.collect.Module + #assert conftest.lget("Module") == py.test.collect.Module assert conftest.rget("Module") == py.test.collect.Module def test_default_has_lower_prio(self): conftest = Conftest(self.basedir.join("adir")) assert conftest.rget('Directory') == 3 - assert conftest.lget('Directory') == py.test.collect.Directory + #assert conftest.lget('Directory') == py.test.collect.Directory def test_value_access_not_existing(self): conftest = Conftest(self.basedir) py.test.raises(KeyError, "conftest.rget('a')") - py.test.raises(KeyError, "conftest.lget('a')") + #py.test.raises(KeyError, "conftest.lget('a')") def test_value_access_by_path(self): conftest = Conftest(self.basedir) assert conftest.rget("a", self.basedir.join('adir')) == 1 - assert conftest.lget("a", self.basedir.join('adir')) == 1 + #assert conftest.lget("a", self.basedir.join('adir')) == 1 assert conftest.rget("a", self.basedir.join('adir', 'b')) == 1.5 - assert conftest.lget("a", self.basedir.join('adir', 'b')) == 1 - assert conftest.lget("b", self.basedir.join('adir', 'b')) == 2 - assert py.test.raises(KeyError, - 'conftest.lget("b", self.basedir.join("a"))' - ) + #assert conftest.lget("a", self.basedir.join('adir', 'b')) == 1 + #assert conftest.lget("b", self.basedir.join('adir', 'b')) == 2 + #assert py.test.raises(KeyError, + # 'conftest.lget("b", self.basedir.join("a"))' + #) def test_value_access_with_init_one_conftest(self): conftest = Conftest(self.basedir.join('adir')) assert conftest.rget("a") == 1 - assert conftest.lget("a") == 1 + #assert conftest.lget("a") == 1 def test_value_access_with_init_two_conftests(self): conftest = Conftest(self.basedir.join("adir", "b")) conftest.rget("a") == 1.5 - conftest.lget("a") == 1 - conftest.lget("b") == 1 + #conftest.lget("a") == 1 + #conftest.lget("b") == 1 class TestConftestValueAccessInPackage(TestConftestValueAccessGlobal): def setup_class(cls): diff --git a/py/test/testing/test_doctest.py b/py/test/testing/test_doctest.py index c73b7fc76..657556c41 100644 --- a/py/test/testing/test_doctest.py +++ b/py/test/testing/test_doctest.py @@ -32,10 +32,10 @@ def test_collect_doctest_files_with_test_prefix(): >>> i-1 4 """)) - from py.__.test.collect import getfscollector for x in (o, checkfile): #print "checking that %s returns custom items" % (x,) - col = getfscollector(x) + config = py.test.config._reparse([x]) + col = config._getcollector(x) items = list(col.tryiter(py.test.Item)) assert len(items) == 1 assert isinstance(items[0], DoctestText) diff --git a/py/test/testing/test_repr.py b/py/test/testing/test_repr.py new file mode 100644 index 000000000..0ce2a1228 --- /dev/null +++ b/py/test/testing/test_repr.py @@ -0,0 +1,64 @@ + +import py +from py.__.test.representation import Presenter +from py.__.test.terminal.out import getout +from StringIO import StringIO +import sys + +def test_repr_source(): + source = py.code.Source(""" + def f(x): + pass + """).strip() + config = py.test.config._reparse([]) + s = StringIO() + out = getout(s) + p = Presenter(out, config) + p.repr_source(source, "|", 0) + lines = s.getvalue().split("\n") + assert len(lines) == 3 + assert lines[0].startswith("|") + assert lines[0].find("def f(x)") != -1 + assert lines[1].find("pass") != -1 + +def test_repr_failure_explanation(): + """ We check here if indentation is right + """ + def f(): + def g(): + 1/0 + try: + g() + except: + e = py.code.ExceptionInfo() + return e + config = py.test.config._reparse([]) + s = StringIO() + out = getout(s) + p = Presenter(out, config) + source = py.code.Source(f) + e = f() + p.repr_failure_explanation(e, source) + assert s.getvalue().startswith("> ") + +def test_repr_local(): + config = py.test.config._reparse(['--showlocals']) + s = StringIO() + out = getout(s) + p = Presenter(out, config) + p.repr_locals(locals()) + for key in locals().keys(): + assert s.getvalue().find(key) != -1 + +def test_repr_traceback_long(): + py.test.skip("unfinished") + config = py.test.config._reparse([]) + s = StringIO() + out = getout(s) + p = Presenter(out, config) + # errr... here we should + # a) prepare an item + # b) prepare excinfo + # c) prepare some traceback info, with few different ideas, + # like recursion detected etc. + # test it... diff --git a/py/test/testing/test_session.py b/py/test/testing/test_session.py index df7dba6af..f423bbecc 100644 --- a/py/test/testing/test_session.py +++ b/py/test/testing/test_session.py @@ -5,52 +5,27 @@ def setup_module(mod): mod.datadir = setupdatadir() mod.tmpdir = py.test.ensuretemp(mod.__name__) -class TestDefaultSession: - def test_simple(self): - config = py.test.config._reparse([datadir/'filetest.py']) - session = config.getsessionclass()(config, py.std.sys.stdout) - 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_default_session_options(): + for opts in ([], ['-l'], ['-s'], ['--tb=no'], ['--tb=short'], + ['--tb=long'], ['--fulltrace'], ['--nomagic'], + ['--traceconfig'], ['-v'], ['-v', '-v']): + yield runfiletest, opts - def test_simple_verbose(self): - config = py.test.config._reparse([datadir/'filetest.py', - '--verbose']) - session = config.getsessionclass()(config, py.std.sys.stdout) - 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 = py.test.config._reparse([datadir/'filetest.py', - '-v', '-v']) - session = config.getsessionclass()(config, py.std.sys.stdout) - 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_session_parsing(self): - from py.__.test.terminal.terminal import TerminalSession - from py.__.test.tkinter.reportsession import ReportSession - config = py.test.config._reparse(['--session=terminal']) - assert issubclass(config.getsessionclass(), TerminalSession) - config = py.test.config._reparse(['--session=tkinter']) - assert issubclass(config.getsessionclass(), ReportSession) - config = py.test.config._reparse(['--tkinter']) - assert issubclass(config.getsessionclass(), ReportSession) +def runfiletest(opts): + config = py.test.config._reparse(opts + [datadir/'filetest.py']) + session = config.initsession() + session.main() + l = session.getitemoutcomepairs(py.test.Item.Failed) + assert len(l) == 2 + l = session.getitemoutcomepairs(py.test.Item.Passed) + assert not l class TestKeywordSelection: def test_select_simple(self): for keyword in ['test_one', 'est_on']: config = py.test.config._reparse([datadir/'filetest.py', '-k', keyword]) - session = config.getsessionclass()(config, py.std.sys.stdout) + session = config._getsessionclass()(config, py.std.sys.stdout) session.main() l = session.getitemoutcomepairs(py.test.Item.Failed) assert len(l) == 1 @@ -79,7 +54,7 @@ class TestKeywordSelection: 'TestClass test_2', 'xxx TestClass test_2',): f = py.std.StringIO.StringIO() config = py.test.config._reparse([o, '-k', keyword]) - session = config.getsessionclass()(config, f) + session = config._getsessionclass()(config, f) session.main() print "keyword", repr(keyword) l = session.getitemoutcomepairs(py.test.Item.Passed) @@ -318,9 +293,8 @@ class TestTerminalSession: assert expected_output in out -from py.__.test.terminal.remote import getrootdir class TestRemote: - def test_rootdir_is_package(self): + def XXXtest_rootdir_is_package(self): d = tmpdir.ensure('rootdirtest1', dir=1) d.ensure('__init__.py') x1 = d.ensure('subdir', '__init__.py') @@ -332,7 +306,7 @@ class TestRemote: assert getrootdir([x3,x2]) == d assert getrootdir([x2,x3]) == d - def test_rootdir_is_not_package(self): + def XXXtest_rootdir_is_not_package(self): one = tmpdir.ensure('rootdirtest1', 'hello') rootdir = getrootdir([one]) assert rootdir == one.dirpath() @@ -348,8 +322,7 @@ class TestRemote: config = py.test.config._reparse( ['--exec=' + py.std.sys.executable, o]) - assert config.option._remote - cls = config.getsessionclass() + cls = config._getsessionclass() out = [] # out = py.std.Queue.Queue() session = cls(config, out.append) session.main() @@ -368,16 +341,16 @@ class TestRemote: """)) print py.std.sys.executable config = py.test.config._reparse(['--looponfailing', str(o)]) - assert config.option._remote - cls = config.getsessionclass() + cls = config._getsessionclass() out = py.std.Queue.Queue() session = cls(config, out.put) pool = py._thread.WorkerPool() reply = pool.dispatch(session.main) while 1: - s = out.get() + s = out.get(timeout=1.0) if s.find('1 failed') != -1: break + print s else: py.test.fail("did not see test_1 failure") # XXX we would like to have a cleaner way to finish diff --git a/py/test/tkinter/backend.py b/py/test/tkinter/backend.py index 2eab3c84e..2f7b92c00 100644 --- a/py/test/tkinter/backend.py +++ b/py/test/tkinter/backend.py @@ -184,6 +184,7 @@ class ReportBackend: self.queue.put(item) def start_tests(self, config = None, args = [], tests = []): + py.test.skip("XXX fix this or remove --tkinter") if self.running: return if config is None: @@ -233,7 +234,7 @@ def remote(channel, tests = [], args = []): if tests: cols = getfailureitems(tests) else: - cols = config.remaining + cols = config.args session = ReportSession(config = config, channel=channel) session.shouldclose = channel.isclosed session.main() diff --git a/py/test/tkinter/reportsession.py b/py/test/tkinter/reportsession.py index 3e1f49cb9..10335edf9 100644 --- a/py/test/tkinter/reportsession.py +++ b/py/test/tkinter/reportsession.py @@ -3,7 +3,7 @@ import py from util import TestReport from py.__.test.session import Session -class ReportSession(Session): +class TkinterSession(Session): def __init__(self, config = None, channel = None): super(ReportSession, self).__init__(config) @@ -44,5 +44,5 @@ class ReportSession(Session): def sendreport(self, report): self.channel.send(report.to_channel()) -TkinterSession = ReportSession +ReportSession = TkinterSession diff --git a/py/test/tkinter/testing/test_backend.py b/py/test/tkinter/testing/test_backend.py index e8d9c6eda..2bc1b53aa 100644 --- a/py/test/tkinter/testing/test_backend.py +++ b/py/test/tkinter/testing/test_backend.py @@ -178,9 +178,9 @@ class TestReportBackend: assert l[0] is None def test_start_tests(self): - config = py.test.config._reparse([]) + config = py.test.config._reparse([datadir/'filetest.py']) self.backend.start_tests(config = config, - args = [str(datadir / 'filetest.py')], + args = config.args, tests = []) while self.backend.running: self.backend.update() diff --git a/py/test/tkinter/testing/test_capture_out_err.py b/py/test/tkinter/testing/test_capture_out_err.py index ca45b7134..9f9a3cda9 100644 --- a/py/test/tkinter/testing/test_capture_out_err.py +++ b/py/test/tkinter/testing/test_capture_out_err.py @@ -8,7 +8,7 @@ def test_capture_out_err(): config = py.test.config._reparse([datadir/'filetest.py']) backend = ReportBackend() backend.start_tests(config = config, - args = config.remaining, + args = config.args, tests = []) while backend.running: backend.update()