commit python-py for openSUSE:Factory
Hello community, here is the log from the commit of package python-py for openSUSE:Factory checked in at 2014-07-31 10:04:02 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-py (Old) and /work/SRC/openSUSE:Factory/.python-py.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "python-py" Changes: -------- --- /work/SRC/openSUSE:Factory/python-py/python-py.changes 2014-05-17 06:43:25.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.python-py.new/python-py.changes 2014-07-31 10:04:10.000000000 +0200 @@ -1,0 +2,21 @@ +Wed Jul 30 07:50:37 UTC 2014 - toddrme2178@gmail.com + +- Update to 1.4.22 + - refactor class-level registry on ForkedFunc child start/finish + event to become instance based (i.e. passed into the constructor) +- Update to 1.4.21 + - ForkedFunc now has class-level register_on_start/on_exit() + methods to allow adding information in the boxed process. + Thanks Marc Schlaich. + - ForkedFunc in the child opens in "auto-flush" mode for + stdout/stderr so that when a subprocess dies you can see + its output even if it didn't flush itself. + - refactor traceback generation in light of pytest issue 364 + (shortening tracebacks). you can now set a new traceback style + on a per-entry basis such that a caller can force entries to be + isplayed as short or long entries. + - win32: py.path.local.sysfind(name) will preferrably return files with + extensions so that if "X" and "X.bat" or "X.exe" is on the PATH, + one of the latter two will be returned. + +------------------------------------------------------------------- Old: ---- py-1.4.20.tar.gz New: ---- py-1.4.22.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-py.spec ++++++ --- /var/tmp/diff_new_pack.DLPsck/_old 2014-07-31 10:04:12.000000000 +0200 +++ /var/tmp/diff_new_pack.DLPsck/_new 2014-07-31 10:04:12.000000000 +0200 @@ -17,7 +17,7 @@ Name: python-py -Version: 1.4.20 +Version: 1.4.22 Release: 0 Summary: Library with cross-python path, ini-parsing, io, code, log facilities License: MIT @@ -25,7 +25,6 @@ Url: http://pylib.org Source: http://pypi.python.org/packages/source/p/py/py-%{version}.tar.gz BuildRequires: python-devel -BuildRequires: unzip # Documentation requirements: BuildRequires: python-Sphinx BuildRoot: %{_tmppath}/%{name}-%{version}-build ++++++ py-1.4.20.tar.gz -> py-1.4.22.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/py-1.4.20/AUTHORS new/py-1.4.22/AUTHORS --- old/py-1.4.20/AUTHORS 1970-01-01 01:00:00.000000000 +0100 +++ new/py-1.4.22/AUTHORS 2014-07-17 10:51:42.000000000 +0200 @@ -0,0 +1,24 @@ +Holger Krekel, holger at merlinux eu +Benjamin Peterson, benjamin at python org +Ronny Pfannschmidt, Ronny.Pfannschmidt at gmx de +Guido Wesdorp, johnny at johnnydebris net +Samuele Pedroni, pedronis at openend se +Carl Friedrich Bolz, cfbolz at gmx de +Armin Rigo, arigo at tunes org +Maciek Fijalkowski, fijal at genesilico pl +Brian Dorsey, briandorsey at gmail com +Floris Bruynooghe, flub at devork be +merlinux GmbH, Germany, office at merlinux eu + +Contributors include:: + +Ross Lawley +Ralf Schmitt +Chris Lamb +Harald Armin Massa +Martijn Faassen +Ian Bicking +Jan Balster +Grig Gheorghiu +Bob Ippolito +Christian Tismer diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/py-1.4.20/CHANGELOG new/py-1.4.22/CHANGELOG --- old/py-1.4.20/CHANGELOG 2014-01-29 13:16:52.000000000 +0100 +++ new/py-1.4.22/CHANGELOG 2014-07-17 10:51:42.000000000 +0200 @@ -1,3 +1,29 @@ +1.4.22 +================================================== + +- refactor class-level registry on ForkedFunc child start/finish + event to become instance based (i.e. passed into the constructor) + +1.4.21 +================================================== + +- ForkedFunc now has class-level register_on_start/on_exit() + methods to allow adding information in the boxed process. + Thanks Marc Schlaich. + +- ForkedFunc in the child opens in "auto-flush" mode for + stdout/stderr so that when a subprocess dies you can see + its output even if it didn't flush itself. + +- refactor traceback generation in light of pytest issue 364 + (shortening tracebacks). you can now set a new traceback style + on a per-entry basis such that a caller can force entries to be + isplayed as short or long entries. + +- win32: py.path.local.sysfind(name) will preferrably return files with + extensions so that if "X" and "X.bat" or "X.exe" is on the PATH, + one of the latter two will be returned. + 1.4.20 ================================================== diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/py-1.4.20/MANIFEST.in new/py-1.4.22/MANIFEST.in --- old/py-1.4.20/MANIFEST.in 2014-01-29 13:16:52.000000000 +0100 +++ new/py-1.4.22/MANIFEST.in 2014-07-17 10:51:42.000000000 +0200 @@ -1,4 +1,5 @@ include CHANGELOG +include AUTHORS include README.txt include setup.py include LICENSE diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/py-1.4.20/PKG-INFO new/py-1.4.22/PKG-INFO --- old/py-1.4.20/PKG-INFO 2014-01-29 13:16:53.000000000 +0100 +++ new/py-1.4.22/PKG-INFO 2014-07-17 10:51:42.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: py -Version: 1.4.20 +Version: 1.4.22 Summary: library with cross-python path, ini-parsing, io, code, log facilities Home-page: http://pylib.readthedocs.org/ Author: holger krekel, Ronny Pfannschmidt, Benjamin Peterson and others @@ -13,7 +13,6 @@ * py.apipkg: explicit API control and lazy-importing * py.iniconfig: easy parsing of .ini files * py.code: dynamic code generation and introspection - * py.path: uniform local and svn path objects NOTE: prior to the 1.4 release this distribution used to contain py.test which is now its own package, see http://pytest.org @@ -22,7 +21,7 @@ Bugs and issues: http://bitbucket.org/hpk42/py/issues/ - Authors: Holger Krekel and others, 2004-2013 + Authors: Holger Krekel and others, 2004-2014 Platform: unix diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/py-1.4.20/README.txt new/py-1.4.22/README.txt --- old/py-1.4.20/README.txt 2014-01-29 13:16:52.000000000 +0100 +++ new/py-1.4.22/README.txt 2014-07-17 10:51:42.000000000 +0200 @@ -5,7 +5,6 @@ * py.apipkg: explicit API control and lazy-importing * py.iniconfig: easy parsing of .ini files * py.code: dynamic code generation and introspection -* py.path: uniform local and svn path objects NOTE: prior to the 1.4 release this distribution used to contain py.test which is now its own package, see http://pytest.org @@ -14,5 +13,5 @@ Bugs and issues: http://bitbucket.org/hpk42/py/issues/ -Authors: Holger Krekel and others, 2004-2013 +Authors: Holger Krekel and others, 2004-2014 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/py-1.4.20/py/__init__.py new/py-1.4.22/py/__init__.py --- old/py-1.4.20/py/__init__.py 2014-01-29 13:16:52.000000000 +0100 +++ new/py-1.4.22/py/__init__.py 2014-07-17 10:51:42.000000000 +0200 @@ -8,7 +8,7 @@ (c) Holger Krekel and others, 2004-2013 """ -__version__ = '1.4.20' +__version__ = '1.4.22' from py import _apipkg diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/py-1.4.20/py/_code/code.py new/py-1.4.22/py/_code/code.py --- old/py-1.4.20/py/_code/code.py 2014-01-29 13:16:52.000000000 +0100 +++ new/py-1.4.22/py/_code/code.py 2014-07-17 10:51:42.000000000 +0200 @@ -133,12 +133,17 @@ class TracebackEntry(object): """ a single entry in a traceback """ + _repr_style = None exprinfo = None def __init__(self, rawentry): self._rawentry = rawentry self.lineno = rawentry.tb_lineno - 1 + def set_repr_style(self, mode): + assert mode in ("short", "long") + self._repr_style = mode + @property def frame(self): return py.code.Frame(self._rawentry.tb_frame) @@ -470,17 +475,17 @@ line_index = 0 if line_index < 0: line_index += len(source) - for i in range(len(source)): - if i == line_index: - prefix = self.flow_marker + " " - else: - if short: - continue - prefix = " " - line = prefix + source[i] - lines.append(line) + space_prefix = " " + if short: + lines.append(space_prefix + source.lines[line_index].strip()) + else: + for line in source.lines[:line_index]: + lines.append(space_prefix + line) + lines.append(self.flow_marker + " " + source.lines[line_index]) + for line in source.lines[line_index+1:]: + lines.append(space_prefix + line) if excinfo is not None: - indent = self._getindent(source) + indent = 4 if short else self._getindent(source) lines.extend(self.get_exconly(excinfo, indent=indent, markall=True)) return lines @@ -520,7 +525,6 @@ return ReprLocals(lines) def repr_traceback_entry(self, entry, excinfo=None): - # excinfo is not None if this is the last tb entry source = self._getentrysource(entry) if source is None: source = py.code.Source("???") @@ -530,11 +534,12 @@ line_index = entry.lineno - max(entry.getfirstlinesource(), 0) lines = [] - if self.style in ("short", "long"): - short = self.style == "short" - reprargs = None - if not short: - reprargs = self.repr_args(entry) + style = entry._repr_style + if style is None: + style = self.style + if style in ("short", "long"): + short = style == "short" + reprargs = self.repr_args(entry) if not short else None s = self.get_source(source, line_index, excinfo, short=short) lines.extend(s) if short: @@ -546,10 +551,10 @@ localsrepr = None if not short: localsrepr = self.repr_locals(entry.locals) - return ReprEntry(lines, reprargs, localsrepr, filelocrepr, short) + return ReprEntry(lines, reprargs, localsrepr, filelocrepr, style) if excinfo: lines.extend(self.get_exconly(excinfo, indent=4)) - return ReprEntry(lines, None, None, None, False) + return ReprEntry(lines, None, None, None, style) def _makepath(self, path): if not self.abspath: @@ -628,14 +633,18 @@ self.style = style def toterminal(self, tw): - sepok = False - for entry in self.reprentries: - if self.style == "long": - if sepok: - tw.sep(self.entrysep) + # the entries might have different styles + last_style = None + for i, entry in enumerate(self.reprentries): + if entry.style == "long": tw.line("") - sepok = True entry.toterminal(tw) + if i < len(self.reprentries) - 1: + next_entry = self.reprentries[i+1] + if entry.style == "long" or \ + entry.style == "short" and next_entry.style == "long": + tw.sep(self.entrysep) + if self.extraline: tw.line(self.extraline) @@ -646,6 +655,8 @@ self.extraline = None class ReprEntryNative(TerminalRepr): + style = "native" + def __init__(self, tblines): self.lines = tblines @@ -655,15 +666,15 @@ class ReprEntry(TerminalRepr): localssep = "_ " - def __init__(self, lines, reprfuncargs, reprlocals, filelocrepr, short): + def __init__(self, lines, reprfuncargs, reprlocals, filelocrepr, style): self.lines = lines self.reprfuncargs = reprfuncargs self.reprlocals = reprlocals self.reprfileloc = filelocrepr - self.short = short + self.style = style def toterminal(self, tw): - if self.short: + if self.style == "short": self.reprfileloc.toterminal(tw) for line in self.lines: red = line.startswith("E ") @@ -680,7 +691,8 @@ tw.line("") self.reprlocals.toterminal(tw) if self.reprfileloc: - tw.line("") + if self.lines: + tw.line("") self.reprfileloc.toterminal(tw) def __str__(self): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/py-1.4.20/py/_path/local.py new/py-1.4.22/py/_path/local.py --- old/py-1.4.20/py/_path/local.py 2014-01-29 13:16:52.000000000 +0100 +++ new/py-1.4.22/py/_path/local.py 2014-07-17 10:51:42.000000000 +0200 @@ -700,9 +700,10 @@ for path in paths] else: paths = py.std.os.environ['PATH'].split(':') - tryadd = [''] + tryadd = [] if iswin32: tryadd += os.environ['PATHEXT'].split(os.pathsep) + tryadd.append("") for x in paths: for addext in tryadd: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/py-1.4.20/py/_process/forkedfunc.py new/py-1.4.22/py/_process/forkedfunc.py --- old/py-1.4.20/py/_process/forkedfunc.py 2014-01-29 13:16:52.000000000 +0100 +++ new/py-1.4.22/py/_process/forkedfunc.py 2014-07-17 10:51:42.000000000 +0200 @@ -3,8 +3,6 @@ ForkedFunc provides a way to run a function in a forked process and get at its return value, stdout and stderr output as well as signals and exitstatusus. - - XXX see if tempdir handling is sane """ import py @@ -12,9 +10,26 @@ import sys import marshal -class ForkedFunc(object): + +def get_unbuffered_io(fd, filename): + f = open(str(filename), "w") + if fd != f.fileno(): + os.dup2(f.fileno(), fd) + class AutoFlush: + def write(self, data): + f.write(data) + f.flush() + def __getattr__(self, name): + return getattr(f, name) + return AutoFlush() + + +class ForkedFunc: EXITSTATUS_EXCEPTION = 3 - def __init__(self, fun, args=None, kwargs=None, nice_level=0): + + + def __init__(self, fun, args=None, kwargs=None, nice_level=0, + child_on_start=None, child_on_exit=None): if args is None: args = [] if kwargs is None: @@ -28,35 +43,32 @@ self.STDERR = tempdir.ensure('stderr') pid = os.fork() - if pid: # in parent process + if pid: # in parent process self.pid = pid - else: # in child process - self._child(nice_level) + else: # in child process + self.pid = None + self._child(nice_level, child_on_start, child_on_exit) - def _child(self, nice_level): + def _child(self, nice_level, child_on_start, child_on_exit): # right now we need to call a function, but first we need to # map all IO that might happen - # make sure sys.stdout points to file descriptor one - sys.stdout = stdout = self.STDOUT.open('w') - sys.stdout.flush() - fdstdout = stdout.fileno() - if fdstdout != 1: - os.dup2(fdstdout, 1) - sys.stderr = stderr = self.STDERR.open('w') - fdstderr = stderr.fileno() - if fdstderr != 2: - os.dup2(fdstderr, 2) + sys.stdout = stdout = get_unbuffered_io(1, self.STDOUT) + sys.stderr = stderr = get_unbuffered_io(2, self.STDERR) retvalf = self.RETVAL.open("wb") EXITSTATUS = 0 try: if nice_level: os.nice(nice_level) try: + if child_on_start is not None: + child_on_start() retval = self.fun(*self.args, **self.kwargs) retvalf.write(marshal.dumps(retval)) + if child_on_exit is not None: + child_on_exit() except: excinfo = py.code.ExceptionInfo() - stderr.write(excinfo.exconly()) + stderr.write(str(excinfo._getreprcrash())) EXITSTATUS = self.EXITSTATUS_EXCEPTION finally: stdout.close() @@ -73,8 +85,6 @@ exitstatus = os.WTERMSIG(systemstatus) + 128 else: exitstatus = os.WEXITSTATUS(systemstatus) - #raise ExecutionFailed(status, systemstatus, cmd, - # ''.join(out), ''.join(err)) else: exitstatus = 0 signal = systemstatus & 0x7f @@ -97,7 +107,9 @@ self.tempdir.remove() def __del__(self): - self._removetemp() + if self.pid is not None: # only clean up in main process + self._removetemp() + class Result(object): def __init__(self, exitstatus, signal, retval, stdout, stderr): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/py-1.4.20/py.egg-info/PKG-INFO new/py-1.4.22/py.egg-info/PKG-INFO --- old/py-1.4.20/py.egg-info/PKG-INFO 2014-01-29 13:16:53.000000000 +0100 +++ new/py-1.4.22/py.egg-info/PKG-INFO 2014-07-17 10:51:42.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: py -Version: 1.4.20 +Version: 1.4.22 Summary: library with cross-python path, ini-parsing, io, code, log facilities Home-page: http://pylib.readthedocs.org/ Author: holger krekel, Ronny Pfannschmidt, Benjamin Peterson and others @@ -13,7 +13,6 @@ * py.apipkg: explicit API control and lazy-importing * py.iniconfig: easy parsing of .ini files * py.code: dynamic code generation and introspection - * py.path: uniform local and svn path objects NOTE: prior to the 1.4 release this distribution used to contain py.test which is now its own package, see http://pytest.org @@ -22,7 +21,7 @@ Bugs and issues: http://bitbucket.org/hpk42/py/issues/ - Authors: Holger Krekel and others, 2004-2013 + Authors: Holger Krekel and others, 2004-2014 Platform: unix diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/py-1.4.20/py.egg-info/SOURCES.txt new/py-1.4.22/py.egg-info/SOURCES.txt --- old/py-1.4.20/py.egg-info/SOURCES.txt 2014-01-29 13:16:53.000000000 +0100 +++ new/py-1.4.22/py.egg-info/SOURCES.txt 2014-07-17 10:51:42.000000000 +0200 @@ -1,3 +1,4 @@ +AUTHORS CHANGELOG LICENSE MANIFEST.in @@ -87,6 +88,7 @@ testing/code/test_excinfo.py testing/code/test_source.py testing/io_/__init__.py +testing/io_/test_capture.py testing/io_/test_saferepr.py testing/io_/test_terminalwriter.py testing/log/__init__.py diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/py-1.4.20/setup.py new/py-1.4.22/setup.py --- old/py-1.4.20/setup.py 2014-01-29 13:16:52.000000000 +0100 +++ new/py-1.4.22/setup.py 2014-07-17 10:51:42.000000000 +0200 @@ -7,7 +7,7 @@ name='py', description='library with cross-python path, ini-parsing, io, code, log facilities', long_description = open('README.txt').read(), - version='1.4.20', + version='1.4.22', url='http://pylib.readthedocs.org/', license='MIT license', platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'], diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/py-1.4.20/testing/code/test_excinfo.py new/py-1.4.22/testing/code/test_excinfo.py --- old/py-1.4.20/testing/code/test_excinfo.py 2014-01-29 13:16:52.000000000 +0100 +++ new/py-1.4.22/testing/code/test_excinfo.py 2014-07-17 10:51:42.000000000 +0200 @@ -547,7 +547,7 @@ reprtb = p.repr_traceback_entry(excinfo.traceback[-2]) lines = reprtb.lines basename = py.path.local(mod.__file__).basename - assert lines[0] == '> func1()' + assert lines[0] == ' func1()' assert basename in str(reprtb.reprfileloc.path) assert reprtb.reprfileloc.lineno == 5 @@ -555,8 +555,8 @@ p = FormattedExcinfo(style="short") reprtb = p.repr_traceback_entry(excinfo.traceback[-1], excinfo) lines = reprtb.lines - assert lines[0] == '> raise ValueError("hello")' - assert lines[1] == 'E ValueError: hello' + assert lines[0] == ' raise ValueError("hello")' + assert lines[1] == 'E ValueError: hello' assert basename in str(reprtb.reprfileloc.path) assert reprtb.reprfileloc.lineno == 3 @@ -611,10 +611,10 @@ last_lines = last_reprtb.lines monkeypatch.undo() basename = py.path.local(mod.__file__).basename - assert lines[0] == '> func1()' + assert lines[0] == ' func1()' - assert last_lines[0] == '> raise ValueError("hello")' - assert last_lines[1] == 'E ValueError: hello' + assert last_lines[0] == ' raise ValueError("hello")' + assert last_lines[1] == 'E ValueError: hello' def test_repr_traceback_and_excinfo(self, importasmod): mod = importasmod(""" @@ -819,3 +819,40 @@ # python 2.4 fails to get the source line for the assert if py.std.sys.version_info >= (2, 5): assert s.count('assert 0') == 2 + + def test_traceback_repr_style(self, importasmod): + mod = importasmod(""" + def f(): + g() + def g(): + h() + def h(): + i() + def i(): + raise ValueError() + """) + excinfo = py.test.raises(ValueError, mod.f) + excinfo.traceback = excinfo.traceback.filter() + excinfo.traceback[1].set_repr_style("short") + excinfo.traceback[2].set_repr_style("short") + r = excinfo.getrepr(style="long") + tw = TWMock() + r.toterminal(tw) + for line in tw.lines: print (line) + assert tw.lines[0] == "" + assert tw.lines[1] == " def f():" + assert tw.lines[2] == "> g()" + assert tw.lines[3] == "" + assert tw.lines[4].endswith("mod.py:3: ") + assert tw.lines[5] == ("_ ", None) + assert tw.lines[6].endswith("in g") + assert tw.lines[7] == " h()" + assert tw.lines[8].endswith("in h") + assert tw.lines[9] == " i()" + assert tw.lines[10] == ("_ ", None) + assert tw.lines[11] == "" + assert tw.lines[12] == " def i():" + assert tw.lines[13] == "> raise ValueError()" + assert tw.lines[14] == "E ValueError" + assert tw.lines[15] == "" + assert tw.lines[16].endswith("mod.py:9: ValueError") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/py-1.4.20/testing/io_/test_capture.py new/py-1.4.22/testing/io_/test_capture.py --- old/py-1.4.20/testing/io_/test_capture.py 1970-01-01 01:00:00.000000000 +0100 +++ new/py-1.4.22/testing/io_/test_capture.py 2014-07-17 10:51:42.000000000 +0200 @@ -0,0 +1,501 @@ +from __future__ import with_statement + +import os, sys +import py + +needsdup = py.test.mark.skipif("not hasattr(os, 'dup')") + +from py.builtin import print_ + +if sys.version_info >= (3,0): + def tobytes(obj): + if isinstance(obj, str): + obj = obj.encode('UTF-8') + assert isinstance(obj, bytes) + return obj + def totext(obj): + if isinstance(obj, bytes): + obj = str(obj, 'UTF-8') + assert isinstance(obj, str) + return obj +else: + def tobytes(obj): + if isinstance(obj, unicode): + obj = obj.encode('UTF-8') + assert isinstance(obj, str) + return obj + def totext(obj): + if isinstance(obj, str): + obj = unicode(obj, 'UTF-8') + assert isinstance(obj, unicode) + return obj + +def oswritebytes(fd, obj): + os.write(fd, tobytes(obj)) + +class TestTextIO: + def test_text(self): + f = py.io.TextIO() + f.write("hello") + s = f.getvalue() + assert s == "hello" + f.close() + + def test_unicode_and_str_mixture(self): + f = py.io.TextIO() + if sys.version_info >= (3,0): + f.write("\u00f6") + py.test.raises(TypeError, "f.write(bytes('hello', 'UTF-8'))") + else: + f.write(unicode("\u00f6", 'UTF-8')) + f.write("hello") # bytes + s = f.getvalue() + f.close() + assert isinstance(s, unicode) + +def test_bytes_io(): + f = py.io.BytesIO() + f.write(tobytes("hello")) + py.test.raises(TypeError, "f.write(totext('hello'))") + s = f.getvalue() + assert s == tobytes("hello") + +def test_dontreadfrominput(): + from py._io.capture import DontReadFromInput + f = DontReadFromInput() + assert not f.isatty() + py.test.raises(IOError, f.read) + py.test.raises(IOError, f.readlines) + py.test.raises(IOError, iter, f) + py.test.raises(ValueError, f.fileno) + f.close() # just for completeness + +def pytest_funcarg__tmpfile(request): + testdir = request.getfuncargvalue("testdir") + f = testdir.makepyfile("").open('wb+') + request.addfinalizer(f.close) + return f + +@needsdup +def test_dupfile(tmpfile): + flist = [] + for i in range(5): + nf = py.io.dupfile(tmpfile, encoding="utf-8") + assert nf != tmpfile + assert nf.fileno() != tmpfile.fileno() + assert nf not in flist + print_(i, end="", file=nf) + flist.append(nf) + for i in range(5): + f = flist[i] + f.close() + tmpfile.seek(0) + s = tmpfile.read() + assert "01234" in repr(s) + tmpfile.close() + +def test_dupfile_no_mode(): + """ + dupfile should trap an AttributeError and return f if no mode is supplied. + """ + class SomeFileWrapper(object): + "An object with a fileno method but no mode attribute" + def fileno(self): + return 1 + tmpfile = SomeFileWrapper() + assert py.io.dupfile(tmpfile) is tmpfile + with py.test.raises(AttributeError): + py.io.dupfile(tmpfile, raising=True) + +def lsof_check(func): + pid = os.getpid() + try: + out = py.process.cmdexec("lsof -p %d" % pid) + except py.process.cmdexec.Error: + py.test.skip("could not run 'lsof'") + func() + out2 = py.process.cmdexec("lsof -p %d" % pid) + len1 = len([x for x in out.split("\n") if "REG" in x]) + len2 = len([x for x in out2.split("\n") if "REG" in x]) + assert len2 < len1 + 3, out2 + +class TestFDCapture: + pytestmark = needsdup + + def test_not_now(self, tmpfile): + fd = tmpfile.fileno() + cap = py.io.FDCapture(fd, now=False) + data = tobytes("hello") + os.write(fd, data) + f = cap.done() + s = f.read() + assert not s + cap = py.io.FDCapture(fd, now=False) + cap.start() + os.write(fd, data) + f = cap.done() + s = f.read() + assert s == "hello" + + def test_simple(self, tmpfile): + fd = tmpfile.fileno() + cap = py.io.FDCapture(fd) + data = tobytes("hello") + os.write(fd, data) + f = cap.done() + s = f.read() + assert s == "hello" + f.close() + + def test_simple_many(self, tmpfile): + for i in range(10): + self.test_simple(tmpfile) + + def test_simple_many_check_open_files(self, tmpfile): + lsof_check(lambda: self.test_simple_many(tmpfile)) + + def test_simple_fail_second_start(self, tmpfile): + fd = tmpfile.fileno() + cap = py.io.FDCapture(fd) + f = cap.done() + py.test.raises(ValueError, cap.start) + f.close() + + def test_stderr(self): + cap = py.io.FDCapture(2, patchsys=True) + print_("hello", file=sys.stderr) + f = cap.done() + s = f.read() + assert s == "hello\n" + + def test_stdin(self, tmpfile): + tmpfile.write(tobytes("3")) + tmpfile.seek(0) + cap = py.io.FDCapture(0, tmpfile=tmpfile) + # check with os.read() directly instead of raw_input(), because + # sys.stdin itself may be redirected (as py.test now does by default) + x = os.read(0, 100).strip() + f = cap.done() + assert x == tobytes("3") + + def test_writeorg(self, tmpfile): + data1, data2 = tobytes("foo"), tobytes("bar") + try: + cap = py.io.FDCapture(tmpfile.fileno()) + tmpfile.write(data1) + cap.writeorg(data2) + finally: + tmpfile.close() + f = cap.done() + scap = f.read() + assert scap == totext(data1) + stmp = open(tmpfile.name, 'rb').read() + assert stmp == data2 + + +class TestStdCapture: + def getcapture(self, **kw): + return py.io.StdCapture(**kw) + + def test_capturing_done_simple(self): + cap = self.getcapture() + sys.stdout.write("hello") + sys.stderr.write("world") + outfile, errfile = cap.done() + s = outfile.read() + assert s == "hello" + s = errfile.read() + assert s == "world" + + def test_capturing_reset_simple(self): + cap = self.getcapture() + print("hello world") + sys.stderr.write("hello error\n") + out, err = cap.reset() + assert out == "hello world\n" + assert err == "hello error\n" + + def test_capturing_readouterr(self): + cap = self.getcapture() + try: + print ("hello world") + sys.stderr.write("hello error\n") + out, err = cap.readouterr() + assert out == "hello world\n" + assert err == "hello error\n" + sys.stderr.write("error2") + finally: + out, err = cap.reset() + assert err == "error2" + + def test_capturing_readouterr_unicode(self): + cap = self.getcapture() + print ("hx\xc4\x85\xc4\x87") + out, err = cap.readouterr() + assert out == py.builtin._totext("hx\xc4\x85\xc4\x87\n", "utf8") + + @py.test.mark.skipif('sys.version_info >= (3,)', + reason='text output different for bytes on python3') + def test_capturing_readouterr_decode_error_handling(self): + cap = self.getcapture() + # triggered a internal error in pytest + print('\xa6') + out, err = cap.readouterr() + assert out == py.builtin._totext('\ufffd\n', 'unicode-escape') + + def test_capturing_mixed(self): + cap = self.getcapture(mixed=True) + sys.stdout.write("hello ") + sys.stderr.write("world") + sys.stdout.write(".") + out, err = cap.reset() + assert out.strip() == "hello world." + assert not err + + def test_reset_twice_error(self): + cap = self.getcapture() + print ("hello") + out, err = cap.reset() + py.test.raises(ValueError, cap.reset) + assert out == "hello\n" + assert not err + + def test_capturing_modify_sysouterr_in_between(self): + oldout = sys.stdout + olderr = sys.stderr + cap = self.getcapture() + sys.stdout.write("hello") + sys.stderr.write("world") + sys.stdout = py.io.TextIO() + sys.stderr = py.io.TextIO() + print ("not seen") + sys.stderr.write("not seen\n") + out, err = cap.reset() + assert out == "hello" + assert err == "world" + assert sys.stdout == oldout + assert sys.stderr == olderr + + def test_capturing_error_recursive(self): + cap1 = self.getcapture() + print ("cap1") + cap2 = self.getcapture() + print ("cap2") + out2, err2 = cap2.reset() + out1, err1 = cap1.reset() + assert out1 == "cap1\n" + assert out2 == "cap2\n" + + def test_just_out_capture(self): + cap = self.getcapture(out=True, err=False) + sys.stdout.write("hello") + sys.stderr.write("world") + out, err = cap.reset() + assert out == "hello" + assert not err + + def test_just_err_capture(self): + cap = self.getcapture(out=False, err=True) + sys.stdout.write("hello") + sys.stderr.write("world") + out, err = cap.reset() + assert err == "world" + assert not out + + def test_stdin_restored(self): + old = sys.stdin + cap = self.getcapture(in_=True) + newstdin = sys.stdin + out, err = cap.reset() + assert newstdin != sys.stdin + assert sys.stdin is old + + def test_stdin_nulled_by_default(self): + print ("XXX this test may well hang instead of crashing") + print ("XXX which indicates an error in the underlying capturing") + print ("XXX mechanisms") + cap = self.getcapture() + py.test.raises(IOError, "sys.stdin.read()") + out, err = cap.reset() + + def test_suspend_resume(self): + cap = self.getcapture(out=True, err=False, in_=False) + try: + print ("hello") + sys.stderr.write("error\n") + out, err = cap.suspend() + assert out == "hello\n" + assert not err + print ("in between") + sys.stderr.write("in between\n") + cap.resume() + print ("after") + sys.stderr.write("error_after\n") + finally: + out, err = cap.reset() + assert out == "after\n" + assert not err + +class TestStdCaptureNotNow(TestStdCapture): + def getcapture(self, **kw): + kw['now'] = False + cap = py.io.StdCapture(**kw) + cap.startall() + return cap + +class TestStdCaptureFD(TestStdCapture): + pytestmark = needsdup + + def getcapture(self, **kw): + return py.io.StdCaptureFD(**kw) + + def test_intermingling(self): + cap = self.getcapture() + oswritebytes(1, "1") + sys.stdout.write(str(2)) + sys.stdout.flush() + oswritebytes(1, "3") + oswritebytes(2, "a") + sys.stderr.write("b") + sys.stderr.flush() + oswritebytes(2, "c") + out, err = cap.reset() + assert out == "123" + assert err == "abc" + + def test_callcapture(self): + def func(x, y): + print (x) + py.std.sys.stderr.write(str(y)) + return 42 + + res, out, err = py.io.StdCaptureFD.call(func, 3, y=4) + assert res == 42 + assert out.startswith("3") + assert err.startswith("4") + + def test_many(self, capfd): + def f(): + for i in range(10): + cap = py.io.StdCaptureFD() + cap.reset() + lsof_check(f) + +class TestStdCaptureFDNotNow(TestStdCaptureFD): + pytestmark = needsdup + + def getcapture(self, **kw): + kw['now'] = False + cap = py.io.StdCaptureFD(**kw) + cap.startall() + return cap + +@needsdup +def test_stdcapture_fd_tmpfile(tmpfile): + capfd = py.io.StdCaptureFD(out=tmpfile) + os.write(1, "hello".encode("ascii")) + os.write(2, "world".encode("ascii")) + outf, errf = capfd.done() + assert outf == tmpfile + +class TestStdCaptureFDinvalidFD: + pytestmark = needsdup + def test_stdcapture_fd_invalid_fd(self, testdir): + testdir.makepyfile(""" + import py, os + def test_stdout(): + os.close(1) + cap = py.io.StdCaptureFD(out=True, err=False, in_=False) + cap.done() + def test_stderr(): + os.close(2) + cap = py.io.StdCaptureFD(out=False, err=True, in_=False) + cap.done() + def test_stdin(): + os.close(0) + cap = py.io.StdCaptureFD(out=False, err=False, in_=True) + cap.done() + """) + result = testdir.runpytest("--capture=fd") + assert result.ret == 0 + assert result.parseoutcomes()['passed'] == 3 + +def test_capture_not_started_but_reset(): + capsys = py.io.StdCapture(now=False) + capsys.done() + capsys.done() + capsys.reset() + +@needsdup +def test_capture_no_sys(): + capsys = py.io.StdCapture() + try: + cap = py.io.StdCaptureFD(patchsys=False) + sys.stdout.write("hello") + sys.stderr.write("world") + oswritebytes(1, "1") + oswritebytes(2, "2") + out, err = cap.reset() + assert out == "1" + assert err == "2" + finally: + capsys.reset() + +@needsdup +def test_callcapture_nofd(): + def func(x, y): + oswritebytes(1, "hello") + oswritebytes(2, "hello") + print (x) + sys.stderr.write(str(y)) + return 42 + + capfd = py.io.StdCaptureFD(patchsys=False) + try: + res, out, err = py.io.StdCapture.call(func, 3, y=4) + finally: + capfd.reset() + assert res == 42 + assert out.startswith("3") + assert err.startswith("4") + +@needsdup +@py.test.mark.multi(use=[True, False]) +def test_fdcapture_tmpfile_remains_the_same(tmpfile, use): + if not use: + tmpfile = True + cap = py.io.StdCaptureFD(out=False, err=tmpfile, now=False) + cap.startall() + capfile = cap.err.tmpfile + cap.suspend() + cap.resume() + capfile2 = cap.err.tmpfile + assert capfile2 == capfile + +@py.test.mark.multi(method=['StdCapture', 'StdCaptureFD']) +def test_capturing_and_logging_fundamentals(testdir, method): + if method == "StdCaptureFD" and not hasattr(os, 'dup'): + py.test.skip("need os.dup") + # here we check a fundamental feature + p = testdir.makepyfile(""" + import sys, os + import py, logging + cap = py.io.%s(out=False, in_=False) + + logging.warn("hello1") + outerr = cap.suspend() + print ("suspend, captured %%s" %%(outerr,)) + logging.warn("hello2") + + cap.resume() + logging.warn("hello3") + + outerr = cap.suspend() + print ("suspend2, captured %%s" %% (outerr,)) + """ % (method,)) + result = testdir.runpython(p) + result.stdout.fnmatch_lines([ + "suspend, captured*hello1*", + "suspend2, captured*hello2*WARNING:root:hello3*", + ]) + assert "atexit" not in result.stderr.str() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/py-1.4.20/testing/path/test_local.py new/py-1.4.22/testing/path/test_local.py --- old/py-1.4.20/testing/path/test_local.py 2014-01-29 13:16:52.000000000 +0100 +++ new/py-1.4.22/testing/path/test_local.py 2014-07-17 10:51:42.000000000 +0200 @@ -295,6 +295,14 @@ class TestExecutionOnWindows: pytestmark = win32only + def test_sysfind_bat_exe_before(self, tmpdir, monkeypatch): + monkeypatch.setenv("PATH", str(tmpdir), prepend=os.pathsep) + tmpdir.ensure("hello") + h = tmpdir.ensure("hello.bat") + x = py.path.local.sysfind("hello") + assert x == h + + class TestExecution: pytestmark = skiponwin32 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/py-1.4.20/testing/process/test_forkedfunc.py new/py-1.4.22/testing/process/test_forkedfunc.py --- old/py-1.4.20/testing/process/test_forkedfunc.py 2014-01-29 13:16:52.000000000 +0100 +++ new/py-1.4.22/testing/process/test_forkedfunc.py 2014-07-17 10:51:42.000000000 +0200 @@ -1,7 +1,9 @@ +import pytest import py, sys, os pytestmark = py.test.mark.skipif("not hasattr(os, 'fork')") + def test_waitfinish_removes_tempdir(): ff = py.process.ForkedFunc(boxf1) assert ff.tempdir.check() @@ -50,6 +52,21 @@ assert result.signal == 0 assert result.retval == 2 +def test_forkedfunc_on_fds_output(): + result = py.process.ForkedFunc(boxf3).waitfinish() + assert result.signal == 11 + assert result.out == "s" + + +def test_forkedfunc_on_stdout(): + def boxf3(): + import sys + sys.stdout.write("hello\n") + os.kill(os.getpid(), 11) + result = py.process.ForkedFunc(boxf3).waitfinish() + assert result.signal == 11 + assert result.out == "hello\n" + def test_forkedfunc_signal(): result = py.process.ForkedFunc(boxseg).waitfinish() assert result.retval is None @@ -104,6 +121,26 @@ assert result.signal == 15 +def test_hooks(monkeypatch): + def _boxed(): + return 1 + + def _on_start(): + sys.stdout.write("some out\n") + sys.stdout.flush() + + def _on_exit(): + sys.stderr.write("some err\n") + sys.stderr.flush() + + result = py.process.ForkedFunc(_boxed, child_on_start=_on_start, + child_on_exit=_on_exit).waitfinish() + assert result.out == "some out\n" + assert result.err == "some err\n" + assert result.exitstatus == 0 + assert result.signal == 0 + assert result.retval == 1 + # ====================================================================== # examples @@ -120,6 +157,10 @@ os.write(2, "someerr".encode('ascii')) return 2 +def boxf3(): + os.write(1, "s".encode('ascii')) + os.kill(os.getpid(), 11) + def boxseg(): os.kill(os.getpid(), 11) -- To unsubscribe, e-mail: opensuse-commit+unsubscribe@opensuse.org For additional commands, e-mail: opensuse-commit+help@opensuse.org
participants (1)
-
root@hilbert.suse.de