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 - [email protected]
+
+- 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
[email protected](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
+
[email protected](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: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to