Bug 1382362 - Update pytest to v3.1.3 and py to v1.4.34, r=davehunt
authorAndrew Halberstadt <ahalberstadt@mozilla.com>
Wed, 19 Jul 2017 16:50:57 -0400
changeset 418748 3e61e9a0fd868a96eeef81c7307ed46a78f3baf0
parent 418747 6c77cacaf82d169e8e7f557f2f14cae275f3410f
child 418749 0d80cfbe62d185c5e8d90e9f73f2349e0ce86a92
push id7566
push usermtabara@mozilla.com
push dateWed, 02 Aug 2017 08:25:16 +0000
treeherdermozilla-beta@86913f512c3c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdavehunt
bugs1382362
milestone56.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1382362 - Update pytest to v3.1.3 and py to v1.4.34, r=davehunt This patch was generated by something similar to: $ cd third_party/python $ hg rm pytest/* py/* $ pip wheel pytest $ unzip pytest.whl $ unzip py.whl $ hg add pytest/* py/* MozReview-Commit-ID: 3LKVrbKfMgK
third_party/python/py/AUTHORS
third_party/python/py/LICENSE
third_party/python/py/MANIFEST.in
third_party/python/py/PKG-INFO
third_party/python/py/README.txt
third_party/python/py/py/__init__.py
third_party/python/py/py/__metainfo.py
third_party/python/py/py/_apipkg.py
third_party/python/py/py/_builtin.py
third_party/python/py/py/_code/__init__.py
third_party/python/py/py/_code/_assertionnew.py
third_party/python/py/py/_code/_assertionold.py
third_party/python/py/py/_code/_py2traceback.py
third_party/python/py/py/_code/assertion.py
third_party/python/py/py/_code/code.py
third_party/python/py/py/_code/source.py
third_party/python/py/py/_error.py
third_party/python/py/py/_iniconfig.py
third_party/python/py/py/_io/__init__.py
third_party/python/py/py/_io/capture.py
third_party/python/py/py/_io/saferepr.py
third_party/python/py/py/_io/terminalwriter.py
third_party/python/py/py/_log/__init__.py
third_party/python/py/py/_log/log.py
third_party/python/py/py/_log/warning.py
third_party/python/py/py/_path/__init__.py
third_party/python/py/py/_path/cacheutil.py
third_party/python/py/py/_path/common.py
third_party/python/py/py/_path/local.py
third_party/python/py/py/_path/svnurl.py
third_party/python/py/py/_path/svnwc.py
third_party/python/py/py/_process/__init__.py
third_party/python/py/py/_process/cmdexec.py
third_party/python/py/py/_process/forkedfunc.py
third_party/python/py/py/_process/killproc.py
third_party/python/py/py/_std.py
third_party/python/py/py/_xmlgen.py
third_party/python/py/py/test.py
third_party/python/py/setup.cfg
third_party/python/py/setup.py
third_party/python/pytest/.coveragerc
third_party/python/pytest/AUTHORS
third_party/python/pytest/LICENSE
third_party/python/pytest/MANIFEST.in
third_party/python/pytest/PKG-INFO
third_party/python/pytest/README.rst
third_party/python/pytest/_pytest/__init__.py
third_party/python/pytest/_pytest/_argcomplete.py
third_party/python/pytest/_pytest/_code/__init__.py
third_party/python/pytest/_pytest/_code/_py2traceback.py
third_party/python/pytest/_pytest/_code/code.py
third_party/python/pytest/_pytest/_code/source.py
third_party/python/pytest/_pytest/_pluggy.py
third_party/python/pytest/_pytest/_version.py
third_party/python/pytest/_pytest/assertion/__init__.py
third_party/python/pytest/_pytest/assertion/reinterpret.py
third_party/python/pytest/_pytest/assertion/rewrite.py
third_party/python/pytest/_pytest/assertion/truncate.py
third_party/python/pytest/_pytest/assertion/util.py
third_party/python/pytest/_pytest/cacheprovider.py
third_party/python/pytest/_pytest/capture.py
third_party/python/pytest/_pytest/compat.py
third_party/python/pytest/_pytest/config.py
third_party/python/pytest/_pytest/debugging.py
third_party/python/pytest/_pytest/deprecated.py
third_party/python/pytest/_pytest/doctest.py
third_party/python/pytest/_pytest/fixtures.py
third_party/python/pytest/_pytest/freeze_support.py
third_party/python/pytest/_pytest/genscript.py
third_party/python/pytest/_pytest/helpconfig.py
third_party/python/pytest/_pytest/hookspec.py
third_party/python/pytest/_pytest/junitxml.py
third_party/python/pytest/_pytest/main.py
third_party/python/pytest/_pytest/mark.py
third_party/python/pytest/_pytest/monkeypatch.py
third_party/python/pytest/_pytest/nose.py
third_party/python/pytest/_pytest/pastebin.py
third_party/python/pytest/_pytest/pdb.py
third_party/python/pytest/_pytest/pytester.py
third_party/python/pytest/_pytest/python.py
third_party/python/pytest/_pytest/recwarn.py
third_party/python/pytest/_pytest/resultlog.py
third_party/python/pytest/_pytest/runner.py
third_party/python/pytest/_pytest/setuponly.py
third_party/python/pytest/_pytest/setupplan.py
third_party/python/pytest/_pytest/skipping.py
third_party/python/pytest/_pytest/standalonetemplate.py
third_party/python/pytest/_pytest/terminal.py
third_party/python/pytest/_pytest/tmpdir.py
third_party/python/pytest/_pytest/unittest.py
third_party/python/pytest/_pytest/vendored_packages/README.md
third_party/python/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/DESCRIPTION.rst
third_party/python/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/METADATA
third_party/python/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/RECORD
third_party/python/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/WHEEL
third_party/python/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/metadata.json
third_party/python/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/pbr.json
third_party/python/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/top_level.txt
third_party/python/pytest/_pytest/vendored_packages/pluggy.py
third_party/python/pytest/_pytest/warnings.py
third_party/python/pytest/pytest.py
third_party/python/pytest/setup.cfg
third_party/python/pytest/setup.py
deleted file mode 100644
--- a/third_party/python/py/AUTHORS
+++ /dev/null
@@ -1,24 +0,0 @@
-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
deleted file mode 100644
--- a/third_party/python/py/LICENSE
+++ /dev/null
@@ -1,19 +0,0 @@
-
-  Permission is hereby granted, free of charge, to any person obtaining a copy
-  of this software and associated documentation files (the "Software"), to deal
-  in the Software without restriction, including without limitation the rights
-  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-  copies of the Software, and to permit persons to whom the Software is
-  furnished to do so, subject to the following conditions:
-     
-  The above copyright notice and this permission notice shall be included in all
-  copies or substantial portions of the Software.
- 
-  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-  SOFTWARE.
-
deleted file mode 100644
--- a/third_party/python/py/MANIFEST.in
+++ /dev/null
@@ -1,9 +0,0 @@
-include CHANGELOG
-include AUTHORS
-include README.txt
-include setup.py
-include LICENSE
-include conftest.py
-include tox.ini
-graft doc
-graft testing
deleted file mode 100644
--- a/third_party/python/py/PKG-INFO
+++ /dev/null
@@ -1,46 +0,0 @@
-Metadata-Version: 1.1
-Name: py
-Version: 1.4.31
-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
-Author-email: pytest-dev@python.org
-License: MIT license
-Description: .. image:: https://drone.io/bitbucket.org/pytest-dev/py/status.png
-           :target: https://drone.io/bitbucket.org/pytest-dev/py/latest
-        .. image:: https://pypip.in/v/py/badge.png
-           :target: https://pypi.python.org/pypi/py
-        
-        The py lib is a Python development support library featuring
-        the following tools and modules:
-        
-        * py.path:  uniform local and svn path objects
-        * py.apipkg:  explicit API control and lazy-importing
-        * py.iniconfig:  easy parsing of .ini files
-        * py.code: dynamic code generation and introspection
-        
-        NOTE: prior to the 1.4 release this distribution used to
-        contain py.test which is now its own package, see http://pytest.org
-        
-        For questions and more information please visit http://pylib.readthedocs.org
-        
-        Bugs and issues: http://bitbucket.org/pytest-dev/py/issues/
-        
-        Authors: Holger Krekel and others, 2004-2015
-        
-Platform: unix
-Platform: linux
-Platform: osx
-Platform: cygwin
-Platform: win32
-Classifier: Development Status :: 6 - Mature
-Classifier: Intended Audience :: Developers
-Classifier: License :: OSI Approved :: MIT License
-Classifier: Operating System :: POSIX
-Classifier: Operating System :: Microsoft :: Windows
-Classifier: Operating System :: MacOS :: MacOS X
-Classifier: Topic :: Software Development :: Testing
-Classifier: Topic :: Software Development :: Libraries
-Classifier: Topic :: Utilities
-Classifier: Programming Language :: Python
-Classifier: Programming Language :: Python :: 3
deleted file mode 100644
--- a/third_party/python/py/README.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-.. image:: https://drone.io/bitbucket.org/pytest-dev/py/status.png
-   :target: https://drone.io/bitbucket.org/pytest-dev/py/latest
-.. image:: https://pypip.in/v/py/badge.png
-   :target: https://pypi.python.org/pypi/py
-
-The py lib is a Python development support library featuring
-the following tools and modules:
-
-* py.path:  uniform local and svn path objects
-* py.apipkg:  explicit API control and lazy-importing
-* py.iniconfig:  easy parsing of .ini files
-* py.code: dynamic code generation and introspection
-
-NOTE: prior to the 1.4 release this distribution used to
-contain py.test which is now its own package, see http://pytest.org
-
-For questions and more information please visit http://pylib.readthedocs.org
-
-Bugs and issues: http://bitbucket.org/pytest-dev/py/issues/
-
-Authors: Holger Krekel and others, 2004-2015
--- a/third_party/python/py/py/__init__.py
+++ b/third_party/python/py/py/__init__.py
@@ -1,150 +1,152 @@
-"""
-py.test and pylib: rapid testing and development utils
-
-this module uses apipkg.py for lazy-loading sub modules
-and classes.  The initpkg-dictionary  below specifies
-name->value mappings where value can be another namespace
-dictionary or an import path.
-
-(c) Holger Krekel and others, 2004-2014
-"""
-__version__ = '1.4.31'
-
-from py import _apipkg
-
-# so that py.error.* instances are picklable
-import sys
-sys.modules['py.error'] = _apipkg.AliasModule("py.error", "py._error", 'error')
-
-_apipkg.initpkg(__name__, attr={'_apipkg': _apipkg}, exportdefs={
-    # access to all standard lib modules
-    'std': '._std:std',
-    # access to all posix errno's as classes
-    'error': '._error:error',
-
-    '_pydir' : '.__metainfo:pydir',
-    'version': 'py:__version__', # backward compatibility
-
-    # pytest-2.0 has a flat namespace, we use alias modules
-    # to keep old references compatible
-    'test' : 'pytest',
-    'test.collect' : 'pytest',
-    'test.cmdline' : 'pytest',
-
-    # hook into the top-level standard library
-    'process' : {
-        '__doc__'        : '._process:__doc__',
-        'cmdexec'        : '._process.cmdexec:cmdexec',
-        'kill'           : '._process.killproc:kill',
-        'ForkedFunc'     : '._process.forkedfunc:ForkedFunc',
-    },
-
-    'apipkg' : {
-        'initpkg'   : '._apipkg:initpkg',
-        'ApiModule' : '._apipkg:ApiModule',
-    },
-
-    'iniconfig' : {
-        'IniConfig'      : '._iniconfig:IniConfig',
-        'ParseError'     : '._iniconfig:ParseError',
-    },
-
-    'path' : {
-        '__doc__'        : '._path:__doc__',
-        'svnwc'          : '._path.svnwc:SvnWCCommandPath',
-        'svnurl'         : '._path.svnurl:SvnCommandPath',
-        'local'          : '._path.local:LocalPath',
-        'SvnAuth'        : '._path.svnwc:SvnAuth',
-    },
-
-    # python inspection/code-generation API
-    'code' : {
-        '__doc__'           : '._code:__doc__',
-        'compile'           : '._code.source:compile_',
-        'Source'            : '._code.source:Source',
-        'Code'              : '._code.code:Code',
-        'Frame'             : '._code.code:Frame',
-        'ExceptionInfo'     : '._code.code:ExceptionInfo',
-        'Traceback'         : '._code.code:Traceback',
-        'getfslineno'       : '._code.source:getfslineno',
-        'getrawcode'        : '._code.code:getrawcode',
-        'patch_builtins'    : '._code.code:patch_builtins',
-        'unpatch_builtins'  : '._code.code:unpatch_builtins',
-        '_AssertionError'   : '._code.assertion:AssertionError',
-        '_reinterpret_old'  : '._code.assertion:reinterpret_old',
-        '_reinterpret'      : '._code.assertion:reinterpret',
-        '_reprcompare'      : '._code.assertion:_reprcompare',
-        '_format_explanation' : '._code.assertion:_format_explanation',
-    },
-
-    # backports and additions of builtins
-    'builtin' : {
-        '__doc__'        : '._builtin:__doc__',
-        'enumerate'      : '._builtin:enumerate',
-        'reversed'       : '._builtin:reversed',
-        'sorted'         : '._builtin:sorted',
-        'any'            : '._builtin:any',
-        'all'            : '._builtin:all',
-        'set'            : '._builtin:set',
-        'frozenset'      : '._builtin:frozenset',
-        'BaseException'  : '._builtin:BaseException',
-        'GeneratorExit'  : '._builtin:GeneratorExit',
-        '_sysex'         : '._builtin:_sysex',
-        'print_'         : '._builtin:print_',
-        '_reraise'       : '._builtin:_reraise',
-        '_tryimport'     : '._builtin:_tryimport',
-        'exec_'          : '._builtin:exec_',
-        '_basestring'    : '._builtin:_basestring',
-        '_totext'        : '._builtin:_totext',
-        '_isbytes'       : '._builtin:_isbytes',
-        '_istext'        : '._builtin:_istext',
-        '_getimself'     : '._builtin:_getimself',
-        '_getfuncdict'   : '._builtin:_getfuncdict',
-        '_getcode'       : '._builtin:_getcode',
-        'builtins'       : '._builtin:builtins',
-        'execfile'       : '._builtin:execfile',
-        'callable'       : '._builtin:callable',
-        'bytes'       : '._builtin:bytes',
-        'text'       : '._builtin:text',
-    },
-
-    # input-output helping
-    'io' : {
-        '__doc__'             : '._io:__doc__',
-        'dupfile'             : '._io.capture:dupfile',
-        'TextIO'              : '._io.capture:TextIO',
-        'BytesIO'             : '._io.capture:BytesIO',
-        'FDCapture'           : '._io.capture:FDCapture',
-        'StdCapture'          : '._io.capture:StdCapture',
-        'StdCaptureFD'        : '._io.capture:StdCaptureFD',
-        'TerminalWriter'      : '._io.terminalwriter:TerminalWriter',
-        'ansi_print'          : '._io.terminalwriter:ansi_print',
-        'get_terminal_width'  : '._io.terminalwriter:get_terminal_width',
-        'saferepr'            : '._io.saferepr:saferepr',
-    },
-
-    # small and mean xml/html generation
-    'xml' : {
-        '__doc__'            : '._xmlgen:__doc__',
-        'html'               : '._xmlgen:html',
-        'Tag'                : '._xmlgen:Tag',
-        'raw'                : '._xmlgen:raw',
-        'Namespace'          : '._xmlgen:Namespace',
-        'escape'             : '._xmlgen:escape',
-    },
-
-    'log' : {
-        # logging API ('producers' and 'consumers' connected via keywords)
-        '__doc__'            : '._log:__doc__',
-        '_apiwarn'           : '._log.warning:_apiwarn',
-        'Producer'           : '._log.log:Producer',
-        'setconsumer'        : '._log.log:setconsumer',
-        '_setstate'          : '._log.log:setstate',
-        '_getstate'          : '._log.log:getstate',
-        'Path'               : '._log.log:Path',
-        'STDOUT'             : '._log.log:STDOUT',
-        'STDERR'             : '._log.log:STDERR',
-        'Syslog'             : '._log.log:Syslog',
-    },
-
-})
+"""
+pylib: rapid testing and development utils
+
+this module uses apipkg.py for lazy-loading sub modules
+and classes.  The initpkg-dictionary  below specifies
+name->value mappings where value can be another namespace
+dictionary or an import path.
+
+(c) Holger Krekel and others, 2004-2014
+"""
+__version__ = '1.4.34'
+
+from py import _apipkg
+
+# so that py.error.* instances are picklable
+import sys
+sys.modules['py.error'] = _apipkg.AliasModule("py.error", "py._error", 'error')
+import py.error  # "Dereference" it now just to be safe (issue110)
+
+
+_apipkg.initpkg(__name__, attr={'_apipkg': _apipkg}, exportdefs={
+    # access to all standard lib modules
+    'std': '._std:std',
+    # access to all posix errno's as classes
+    'error': '._error:error',
+
+    '_pydir' : '.__metainfo:pydir',
+    'version': 'py:__version__', # backward compatibility
+
+    # pytest-2.0 has a flat namespace, we use alias modules
+    # to keep old references compatible
+    'test' : 'pytest',
+    'test.collect' : 'pytest',
+    'test.cmdline' : 'pytest',
+
+    # hook into the top-level standard library
+    'process' : {
+        '__doc__'        : '._process:__doc__',
+        'cmdexec'        : '._process.cmdexec:cmdexec',
+        'kill'           : '._process.killproc:kill',
+        'ForkedFunc'     : '._process.forkedfunc:ForkedFunc',
+    },
+
+    'apipkg' : {
+        'initpkg'   : '._apipkg:initpkg',
+        'ApiModule' : '._apipkg:ApiModule',
+    },
+
+    'iniconfig' : {
+        'IniConfig'      : '._iniconfig:IniConfig',
+        'ParseError'     : '._iniconfig:ParseError',
+    },
+
+    'path' : {
+        '__doc__'        : '._path:__doc__',
+        'svnwc'          : '._path.svnwc:SvnWCCommandPath',
+        'svnurl'         : '._path.svnurl:SvnCommandPath',
+        'local'          : '._path.local:LocalPath',
+        'SvnAuth'        : '._path.svnwc:SvnAuth',
+    },
+
+    # python inspection/code-generation API
+    'code' : {
+        '__doc__'           : '._code:__doc__',
+        'compile'           : '._code.source:compile_',
+        'Source'            : '._code.source:Source',
+        'Code'              : '._code.code:Code',
+        'Frame'             : '._code.code:Frame',
+        'ExceptionInfo'     : '._code.code:ExceptionInfo',
+        'Traceback'         : '._code.code:Traceback',
+        'getfslineno'       : '._code.source:getfslineno',
+        'getrawcode'        : '._code.code:getrawcode',
+        'patch_builtins'    : '._code.code:patch_builtins',
+        'unpatch_builtins'  : '._code.code:unpatch_builtins',
+        '_AssertionError'   : '._code.assertion:AssertionError',
+        '_reinterpret_old'  : '._code.assertion:reinterpret_old',
+        '_reinterpret'      : '._code.assertion:reinterpret',
+        '_reprcompare'      : '._code.assertion:_reprcompare',
+        '_format_explanation' : '._code.assertion:_format_explanation',
+    },
+
+    # backports and additions of builtins
+    'builtin' : {
+        '__doc__'        : '._builtin:__doc__',
+        'enumerate'      : '._builtin:enumerate',
+        'reversed'       : '._builtin:reversed',
+        'sorted'         : '._builtin:sorted',
+        'any'            : '._builtin:any',
+        'all'            : '._builtin:all',
+        'set'            : '._builtin:set',
+        'frozenset'      : '._builtin:frozenset',
+        'BaseException'  : '._builtin:BaseException',
+        'GeneratorExit'  : '._builtin:GeneratorExit',
+        '_sysex'         : '._builtin:_sysex',
+        'print_'         : '._builtin:print_',
+        '_reraise'       : '._builtin:_reraise',
+        '_tryimport'     : '._builtin:_tryimport',
+        'exec_'          : '._builtin:exec_',
+        '_basestring'    : '._builtin:_basestring',
+        '_totext'        : '._builtin:_totext',
+        '_isbytes'       : '._builtin:_isbytes',
+        '_istext'        : '._builtin:_istext',
+        '_getimself'     : '._builtin:_getimself',
+        '_getfuncdict'   : '._builtin:_getfuncdict',
+        '_getcode'       : '._builtin:_getcode',
+        'builtins'       : '._builtin:builtins',
+        'execfile'       : '._builtin:execfile',
+        'callable'       : '._builtin:callable',
+        'bytes'       : '._builtin:bytes',
+        'text'       : '._builtin:text',
+    },
+
+    # input-output helping
+    'io' : {
+        '__doc__'             : '._io:__doc__',
+        'dupfile'             : '._io.capture:dupfile',
+        'TextIO'              : '._io.capture:TextIO',
+        'BytesIO'             : '._io.capture:BytesIO',
+        'FDCapture'           : '._io.capture:FDCapture',
+        'StdCapture'          : '._io.capture:StdCapture',
+        'StdCaptureFD'        : '._io.capture:StdCaptureFD',
+        'TerminalWriter'      : '._io.terminalwriter:TerminalWriter',
+        'ansi_print'          : '._io.terminalwriter:ansi_print',
+        'get_terminal_width'  : '._io.terminalwriter:get_terminal_width',
+        'saferepr'            : '._io.saferepr:saferepr',
+    },
+
+    # small and mean xml/html generation
+    'xml' : {
+        '__doc__'            : '._xmlgen:__doc__',
+        'html'               : '._xmlgen:html',
+        'Tag'                : '._xmlgen:Tag',
+        'raw'                : '._xmlgen:raw',
+        'Namespace'          : '._xmlgen:Namespace',
+        'escape'             : '._xmlgen:escape',
+    },
+
+    'log' : {
+        # logging API ('producers' and 'consumers' connected via keywords)
+        '__doc__'            : '._log:__doc__',
+        '_apiwarn'           : '._log.warning:_apiwarn',
+        'Producer'           : '._log.log:Producer',
+        'setconsumer'        : '._log.log:setconsumer',
+        '_setstate'          : '._log.log:setstate',
+        '_getstate'          : '._log.log:getstate',
+        'Path'               : '._log.log:Path',
+        'STDOUT'             : '._log.log:STDOUT',
+        'STDERR'             : '._log.log:STDERR',
+        'Syslog'             : '._log.log:Syslog',
+    },
+
+})
--- a/third_party/python/py/py/__metainfo.py
+++ b/third_party/python/py/py/__metainfo.py
@@ -1,2 +1,2 @@
-import py
-pydir = py.path.local(py.__file__).dirpath()
+import py
+pydir = py.path.local(py.__file__).dirpath()
--- a/third_party/python/py/py/_apipkg.py
+++ b/third_party/python/py/py/_apipkg.py
@@ -1,181 +1,181 @@
-"""
-apipkg: control the exported namespace of a python package.
-
-see http://pypi.python.org/pypi/apipkg
-
-(c) holger krekel, 2009 - MIT license
-"""
-import os
-import sys
-from types import ModuleType
-
-__version__ = '1.3.dev'
-
-def _py_abspath(path):
-    """
-    special version of abspath
-    that will leave paths from jython jars alone
-    """
-    if path.startswith('__pyclasspath__'):
-
-        return path
-    else:
-        return os.path.abspath(path)
-
-def initpkg(pkgname, exportdefs, attr=dict()):
-    """ initialize given package from the export definitions. """
-    oldmod = sys.modules.get(pkgname)
-    d = {}
-    f = getattr(oldmod, '__file__', None)
-    if f:
-        f = _py_abspath(f)
-    d['__file__'] = f
-    if hasattr(oldmod, '__version__'):
-        d['__version__'] = oldmod.__version__
-    if hasattr(oldmod, '__loader__'):
-        d['__loader__'] = oldmod.__loader__
-    if hasattr(oldmod, '__path__'):
-        d['__path__'] = [_py_abspath(p) for p in oldmod.__path__]
-    if '__doc__' not in exportdefs and getattr(oldmod, '__doc__', None):
-        d['__doc__'] = oldmod.__doc__
-    d.update(attr)
-    if hasattr(oldmod, "__dict__"):
-        oldmod.__dict__.update(d)
-    mod = ApiModule(pkgname, exportdefs, implprefix=pkgname, attr=d)
-    sys.modules[pkgname] = mod
-
-def importobj(modpath, attrname):
-    module = __import__(modpath, None, None, ['__doc__'])
-    if not attrname:
-        return module
-
-    retval = module
-    names = attrname.split(".")
-    for x in names:
-        retval = getattr(retval, x)
-    return retval
-
-class ApiModule(ModuleType):
-    def __docget(self):
-        try:
-            return self.__doc
-        except AttributeError:
-            if '__doc__' in self.__map__:
-                return self.__makeattr('__doc__')
-    def __docset(self, value):
-        self.__doc = value
-    __doc__ = property(__docget, __docset)
-
-    def __init__(self, name, importspec, implprefix=None, attr=None):
-        self.__name__ = name
-        self.__all__ = [x for x in importspec if x != '__onfirstaccess__']
-        self.__map__ = {}
-        self.__implprefix__ = implprefix or name
-        if attr:
-            for name, val in attr.items():
-                # print "setting", self.__name__, name, val
-                setattr(self, name, val)
-        for name, importspec in importspec.items():
-            if isinstance(importspec, dict):
-                subname = '%s.%s' % (self.__name__, name)
-                apimod = ApiModule(subname, importspec, implprefix)
-                sys.modules[subname] = apimod
-                setattr(self, name, apimod)
-            else:
-                parts = importspec.split(':')
-                modpath = parts.pop(0)
-                attrname = parts and parts[0] or ""
-                if modpath[0] == '.':
-                    modpath = implprefix + modpath
-
-                if not attrname:
-                    subname = '%s.%s' % (self.__name__, name)
-                    apimod = AliasModule(subname, modpath)
-                    sys.modules[subname] = apimod
-                    if '.' not in name:
-                        setattr(self, name, apimod)
-                else:
-                    self.__map__[name] = (modpath, attrname)
-
-    def __repr__(self):
-        l = []
-        if hasattr(self, '__version__'):
-            l.append("version=" + repr(self.__version__))
-        if hasattr(self, '__file__'):
-            l.append('from ' + repr(self.__file__))
-        if l:
-            return '<ApiModule %r %s>' % (self.__name__, " ".join(l))
-        return '<ApiModule %r>' % (self.__name__,)
-
-    def __makeattr(self, name):
-        """lazily compute value for name or raise AttributeError if unknown."""
-        # print "makeattr", self.__name__, name
-        target = None
-        if '__onfirstaccess__' in self.__map__:
-            target = self.__map__.pop('__onfirstaccess__')
-            importobj(*target)()
-        try:
-            modpath, attrname = self.__map__[name]
-        except KeyError:
-            if target is not None and name != '__onfirstaccess__':
-                # retry, onfirstaccess might have set attrs
-                return getattr(self, name)
-            raise AttributeError(name)
-        else:
-            result = importobj(modpath, attrname)
-            setattr(self, name, result)
-            try:
-                del self.__map__[name]
-            except KeyError:
-                pass  # in a recursive-import situation a double-del can happen
-            return result
-
-    __getattr__ = __makeattr
-
-    def __dict__(self):
-        # force all the content of the module to be loaded when __dict__ is read
-        dictdescr = ModuleType.__dict__['__dict__']
-        dict = dictdescr.__get__(self)
-        if dict is not None:
-            hasattr(self, 'some')
-            for name in self.__all__:
-                try:
-                    self.__makeattr(name)
-                except AttributeError:
-                    pass
-        return dict
-    __dict__ = property(__dict__)
-
-
-def AliasModule(modname, modpath, attrname=None):
-    mod = []
-
-    def getmod():
-        if not mod:
-            x = importobj(modpath, None)
-            if attrname is not None:
-                x = getattr(x, attrname)
-            mod.append(x)
-        return mod[0]
-
-    class AliasModule(ModuleType):
-
-        def __repr__(self):
-            x = modpath
-            if attrname:
-                x += "." + attrname
-            return '<AliasModule %r for %r>' % (modname, x)
-
-        def __getattribute__(self, name):
-            try:
-                return getattr(getmod(), name)
-            except ImportError:
-                return None
-
-        def __setattr__(self, name, value):
-            setattr(getmod(), name, value)
-
-        def __delattr__(self, name):
-            delattr(getmod(), name)
-
-    return AliasModule(str(modname))
+"""
+apipkg: control the exported namespace of a python package.
+
+see http://pypi.python.org/pypi/apipkg
+
+(c) holger krekel, 2009 - MIT license
+"""
+import os
+import sys
+from types import ModuleType
+
+__version__ = '1.3.dev'
+
+def _py_abspath(path):
+    """
+    special version of abspath
+    that will leave paths from jython jars alone
+    """
+    if path.startswith('__pyclasspath__'):
+
+        return path
+    else:
+        return os.path.abspath(path)
+
+def initpkg(pkgname, exportdefs, attr=dict()):
+    """ initialize given package from the export definitions. """
+    oldmod = sys.modules.get(pkgname)
+    d = {}
+    f = getattr(oldmod, '__file__', None)
+    if f:
+        f = _py_abspath(f)
+    d['__file__'] = f
+    if hasattr(oldmod, '__version__'):
+        d['__version__'] = oldmod.__version__
+    if hasattr(oldmod, '__loader__'):
+        d['__loader__'] = oldmod.__loader__
+    if hasattr(oldmod, '__path__'):
+        d['__path__'] = [_py_abspath(p) for p in oldmod.__path__]
+    if '__doc__' not in exportdefs and getattr(oldmod, '__doc__', None):
+        d['__doc__'] = oldmod.__doc__
+    d.update(attr)
+    if hasattr(oldmod, "__dict__"):
+        oldmod.__dict__.update(d)
+    mod = ApiModule(pkgname, exportdefs, implprefix=pkgname, attr=d)
+    sys.modules[pkgname] = mod
+
+def importobj(modpath, attrname):
+    module = __import__(modpath, None, None, ['__doc__'])
+    if not attrname:
+        return module
+
+    retval = module
+    names = attrname.split(".")
+    for x in names:
+        retval = getattr(retval, x)
+    return retval
+
+class ApiModule(ModuleType):
+    def __docget(self):
+        try:
+            return self.__doc
+        except AttributeError:
+            if '__doc__' in self.__map__:
+                return self.__makeattr('__doc__')
+    def __docset(self, value):
+        self.__doc = value
+    __doc__ = property(__docget, __docset)
+
+    def __init__(self, name, importspec, implprefix=None, attr=None):
+        self.__name__ = name
+        self.__all__ = [x for x in importspec if x != '__onfirstaccess__']
+        self.__map__ = {}
+        self.__implprefix__ = implprefix or name
+        if attr:
+            for name, val in attr.items():
+                # print "setting", self.__name__, name, val
+                setattr(self, name, val)
+        for name, importspec in importspec.items():
+            if isinstance(importspec, dict):
+                subname = '%s.%s' % (self.__name__, name)
+                apimod = ApiModule(subname, importspec, implprefix)
+                sys.modules[subname] = apimod
+                setattr(self, name, apimod)
+            else:
+                parts = importspec.split(':')
+                modpath = parts.pop(0)
+                attrname = parts and parts[0] or ""
+                if modpath[0] == '.':
+                    modpath = implprefix + modpath
+
+                if not attrname:
+                    subname = '%s.%s' % (self.__name__, name)
+                    apimod = AliasModule(subname, modpath)
+                    sys.modules[subname] = apimod
+                    if '.' not in name:
+                        setattr(self, name, apimod)
+                else:
+                    self.__map__[name] = (modpath, attrname)
+
+    def __repr__(self):
+        l = []
+        if hasattr(self, '__version__'):
+            l.append("version=" + repr(self.__version__))
+        if hasattr(self, '__file__'):
+            l.append('from ' + repr(self.__file__))
+        if l:
+            return '<ApiModule %r %s>' % (self.__name__, " ".join(l))
+        return '<ApiModule %r>' % (self.__name__,)
+
+    def __makeattr(self, name):
+        """lazily compute value for name or raise AttributeError if unknown."""
+        # print "makeattr", self.__name__, name
+        target = None
+        if '__onfirstaccess__' in self.__map__:
+            target = self.__map__.pop('__onfirstaccess__')
+            importobj(*target)()
+        try:
+            modpath, attrname = self.__map__[name]
+        except KeyError:
+            if target is not None and name != '__onfirstaccess__':
+                # retry, onfirstaccess might have set attrs
+                return getattr(self, name)
+            raise AttributeError(name)
+        else:
+            result = importobj(modpath, attrname)
+            setattr(self, name, result)
+            try:
+                del self.__map__[name]
+            except KeyError:
+                pass  # in a recursive-import situation a double-del can happen
+            return result
+
+    __getattr__ = __makeattr
+
+    def __dict__(self):
+        # force all the content of the module to be loaded when __dict__ is read
+        dictdescr = ModuleType.__dict__['__dict__']
+        dict = dictdescr.__get__(self)
+        if dict is not None:
+            hasattr(self, 'some')
+            for name in self.__all__:
+                try:
+                    self.__makeattr(name)
+                except AttributeError:
+                    pass
+        return dict
+    __dict__ = property(__dict__)
+
+
+def AliasModule(modname, modpath, attrname=None):
+    mod = []
+
+    def getmod():
+        if not mod:
+            x = importobj(modpath, None)
+            if attrname is not None:
+                x = getattr(x, attrname)
+            mod.append(x)
+        return mod[0]
+
+    class AliasModule(ModuleType):
+
+        def __repr__(self):
+            x = modpath
+            if attrname:
+                x += "." + attrname
+            return '<AliasModule %r for %r>' % (modname, x)
+
+        def __getattribute__(self, name):
+            try:
+                return getattr(getmod(), name)
+            except ImportError:
+                return None
+
+        def __setattr__(self, name, value):
+            setattr(getmod(), name, value)
+
+        def __delattr__(self, name):
+            delattr(getmod(), name)
+
+    return AliasModule(str(modname))
--- a/third_party/python/py/py/_builtin.py
+++ b/third_party/python/py/py/_builtin.py
@@ -1,248 +1,248 @@
-import sys
-
-try:
-    reversed = reversed
-except NameError:
-    def reversed(sequence):
-        """reversed(sequence) -> reverse iterator over values of the sequence
-
-        Return a reverse iterator
-        """
-        if hasattr(sequence, '__reversed__'):
-            return sequence.__reversed__()
-        if not hasattr(sequence, '__getitem__'):
-            raise TypeError("argument to reversed() must be a sequence")
-        return reversed_iterator(sequence)
-
-    class reversed_iterator(object):
-
-        def __init__(self, seq):
-            self.seq = seq
-            self.remaining = len(seq)
-
-        def __iter__(self):
-            return self
-
-        def next(self):
-            i = self.remaining
-            if i > 0:
-                i -= 1
-                item = self.seq[i]
-                self.remaining = i
-                return item
-            raise StopIteration
-
-        def __length_hint__(self):
-            return self.remaining
-
-try:
-    any = any
-except NameError:
-    def any(iterable):
-        for x in iterable:
-            if x:
-                return True
-        return False
-
-try:
-    all = all
-except NameError:
-    def all(iterable):
-        for x in iterable:
-            if not x:
-                return False
-        return True
-
-try:
-    sorted = sorted
-except NameError:
-    builtin_cmp = cmp # need to use cmp as keyword arg
-
-    def sorted(iterable, cmp=None, key=None, reverse=0):
-        use_cmp = None
-        if key is not None:
-            if cmp is None:
-                def use_cmp(x, y):
-                    return builtin_cmp(x[0], y[0])
-            else:
-                def use_cmp(x, y):
-                    return cmp(x[0], y[0])
-            l = [(key(element), element) for element in iterable]
-        else:
-            if cmp is not None:
-                use_cmp = cmp
-            l = list(iterable)
-        if use_cmp is not None:
-            l.sort(use_cmp)
-        else:
-            l.sort()
-        if reverse:
-            l.reverse()
-        if key is not None:
-            return [element for (_, element) in l]
-        return l
-
-try:
-    set, frozenset = set, frozenset
-except NameError:
-    from sets import set, frozenset
-
-# pass through
-enumerate = enumerate
-
-try:
-    BaseException = BaseException
-except NameError:
-    BaseException = Exception
-
-try:
-    GeneratorExit = GeneratorExit
-except NameError:
-    class GeneratorExit(Exception):
-        """ This exception is never raised, it is there to make it possible to
-        write code compatible with CPython 2.5 even in lower CPython
-        versions."""
-        pass
-    GeneratorExit.__module__ = 'exceptions'
-
-_sysex = (KeyboardInterrupt, SystemExit, MemoryError, GeneratorExit)
-
-try:
-    callable = callable
-except NameError:
-    def callable(obj):
-        return hasattr(obj, "__call__")
-
-if sys.version_info >= (3, 0):
-    exec ("print_ = print ; exec_=exec")
-    import builtins
-
-    # some backward compatibility helpers
-    _basestring = str
-    def _totext(obj, encoding=None, errors=None):
-        if isinstance(obj, bytes):
-            if errors is None:
-                obj = obj.decode(encoding)
-            else:
-                obj = obj.decode(encoding, errors)
-        elif not isinstance(obj, str):
-            obj = str(obj)
-        return obj
-
-    def _isbytes(x):
-        return isinstance(x, bytes)
-    def _istext(x):
-        return isinstance(x, str)
-
-    text = str
-    bytes = bytes
-
-
-    def _getimself(function):
-        return getattr(function, '__self__', None)
-
-    def _getfuncdict(function):
-        return getattr(function, "__dict__", None)
-
-    def _getcode(function):
-        return getattr(function, "__code__", None)
-
-    def execfile(fn, globs=None, locs=None):
-        if globs is None:
-            back = sys._getframe(1)
-            globs = back.f_globals
-            locs = back.f_locals
-            del back
-        elif locs is None:
-            locs = globs
-        fp = open(fn, "r")
-        try:
-            source = fp.read()
-        finally:
-            fp.close()
-        co = compile(source, fn, "exec", dont_inherit=True)
-        exec_(co, globs, locs)
-
-else:
-    import __builtin__ as builtins
-    _totext = unicode
-    _basestring = basestring
-    text = unicode
-    bytes = str
-    execfile = execfile
-    callable = callable
-    def _isbytes(x):
-        return isinstance(x, str)
-    def _istext(x):
-        return isinstance(x, unicode)
-
-    def _getimself(function):
-        return getattr(function, 'im_self', None)
-
-    def _getfuncdict(function):
-        return getattr(function, "__dict__", None)
-
-    def _getcode(function):
-        try:
-            return getattr(function, "__code__")
-        except AttributeError:
-            return getattr(function, "func_code", None)
-
-    def print_(*args, **kwargs):
-        """ minimal backport of py3k print statement. """
-        sep = ' '
-        if 'sep' in kwargs:
-            sep = kwargs.pop('sep')
-        end = '\n'
-        if 'end' in kwargs:
-            end = kwargs.pop('end')
-        file = 'file' in kwargs and kwargs.pop('file') or sys.stdout
-        if kwargs:
-            args = ", ".join([str(x) for x in kwargs])
-            raise TypeError("invalid keyword arguments: %s" % args)
-        at_start = True
-        for x in args:
-            if not at_start:
-                file.write(sep)
-            file.write(str(x))
-            at_start = False
-        file.write(end)
-
-    def exec_(obj, globals=None, locals=None):
-        """ minimal backport of py3k exec statement. """
-        __tracebackhide__ = True
-        if globals is None:
-            frame = sys._getframe(1)
-            globals = frame.f_globals
-            if locals is None:
-                locals = frame.f_locals
-        elif locals is None:
-            locals = globals
-        exec2(obj, globals, locals)
-
-if sys.version_info >= (3, 0):
-    def _reraise(cls, val, tb):
-        __tracebackhide__ = True
-        assert hasattr(val, '__traceback__')
-        raise cls.with_traceback(val, tb)
-else:
-    exec ("""
-def _reraise(cls, val, tb):
-    __tracebackhide__ = True
-    raise cls, val, tb
-def exec2(obj, globals, locals):
-    __tracebackhide__ = True
-    exec obj in globals, locals
-""")
-
-def _tryimport(*names):
-    """ return the first successfully imported module. """
-    assert names
-    for name in names:
-        try:
-            __import__(name)
-        except ImportError:
-            excinfo = sys.exc_info()
-        else:
-            return sys.modules[name]
-    _reraise(*excinfo)
+import sys
+
+try:
+    reversed = reversed
+except NameError:
+    def reversed(sequence):
+        """reversed(sequence) -> reverse iterator over values of the sequence
+
+        Return a reverse iterator
+        """
+        if hasattr(sequence, '__reversed__'):
+            return sequence.__reversed__()
+        if not hasattr(sequence, '__getitem__'):
+            raise TypeError("argument to reversed() must be a sequence")
+        return reversed_iterator(sequence)
+
+    class reversed_iterator(object):
+
+        def __init__(self, seq):
+            self.seq = seq
+            self.remaining = len(seq)
+
+        def __iter__(self):
+            return self
+
+        def next(self):
+            i = self.remaining
+            if i > 0:
+                i -= 1
+                item = self.seq[i]
+                self.remaining = i
+                return item
+            raise StopIteration
+
+        def __length_hint__(self):
+            return self.remaining
+
+try:
+    any = any
+except NameError:
+    def any(iterable):
+        for x in iterable:
+            if x:
+                return True
+        return False
+
+try:
+    all = all
+except NameError:
+    def all(iterable):
+        for x in iterable:
+            if not x:
+                return False
+        return True
+
+try:
+    sorted = sorted
+except NameError:
+    builtin_cmp = cmp # need to use cmp as keyword arg
+
+    def sorted(iterable, cmp=None, key=None, reverse=0):
+        use_cmp = None
+        if key is not None:
+            if cmp is None:
+                def use_cmp(x, y):
+                    return builtin_cmp(x[0], y[0])
+            else:
+                def use_cmp(x, y):
+                    return cmp(x[0], y[0])
+            l = [(key(element), element) for element in iterable]
+        else:
+            if cmp is not None:
+                use_cmp = cmp
+            l = list(iterable)
+        if use_cmp is not None:
+            l.sort(use_cmp)
+        else:
+            l.sort()
+        if reverse:
+            l.reverse()
+        if key is not None:
+            return [element for (_, element) in l]
+        return l
+
+try:
+    set, frozenset = set, frozenset
+except NameError:
+    from sets import set, frozenset
+
+# pass through
+enumerate = enumerate
+
+try:
+    BaseException = BaseException
+except NameError:
+    BaseException = Exception
+
+try:
+    GeneratorExit = GeneratorExit
+except NameError:
+    class GeneratorExit(Exception):
+        """ This exception is never raised, it is there to make it possible to
+        write code compatible with CPython 2.5 even in lower CPython
+        versions."""
+        pass
+    GeneratorExit.__module__ = 'exceptions'
+
+_sysex = (KeyboardInterrupt, SystemExit, MemoryError, GeneratorExit)
+
+try:
+    callable = callable
+except NameError:
+    def callable(obj):
+        return hasattr(obj, "__call__")
+
+if sys.version_info >= (3, 0):
+    exec ("print_ = print ; exec_=exec")
+    import builtins
+
+    # some backward compatibility helpers
+    _basestring = str
+    def _totext(obj, encoding=None, errors=None):
+        if isinstance(obj, bytes):
+            if errors is None:
+                obj = obj.decode(encoding)
+            else:
+                obj = obj.decode(encoding, errors)
+        elif not isinstance(obj, str):
+            obj = str(obj)
+        return obj
+
+    def _isbytes(x):
+        return isinstance(x, bytes)
+    def _istext(x):
+        return isinstance(x, str)
+
+    text = str
+    bytes = bytes
+
+
+    def _getimself(function):
+        return getattr(function, '__self__', None)
+
+    def _getfuncdict(function):
+        return getattr(function, "__dict__", None)
+
+    def _getcode(function):
+        return getattr(function, "__code__", None)
+
+    def execfile(fn, globs=None, locs=None):
+        if globs is None:
+            back = sys._getframe(1)
+            globs = back.f_globals
+            locs = back.f_locals
+            del back
+        elif locs is None:
+            locs = globs
+        fp = open(fn, "r")
+        try:
+            source = fp.read()
+        finally:
+            fp.close()
+        co = compile(source, fn, "exec", dont_inherit=True)
+        exec_(co, globs, locs)
+
+else:
+    import __builtin__ as builtins
+    _totext = unicode
+    _basestring = basestring
+    text = unicode
+    bytes = str
+    execfile = execfile
+    callable = callable
+    def _isbytes(x):
+        return isinstance(x, str)
+    def _istext(x):
+        return isinstance(x, unicode)
+
+    def _getimself(function):
+        return getattr(function, 'im_self', None)
+
+    def _getfuncdict(function):
+        return getattr(function, "__dict__", None)
+
+    def _getcode(function):
+        try:
+            return getattr(function, "__code__")
+        except AttributeError:
+            return getattr(function, "func_code", None)
+
+    def print_(*args, **kwargs):
+        """ minimal backport of py3k print statement. """
+        sep = ' '
+        if 'sep' in kwargs:
+            sep = kwargs.pop('sep')
+        end = '\n'
+        if 'end' in kwargs:
+            end = kwargs.pop('end')
+        file = 'file' in kwargs and kwargs.pop('file') or sys.stdout
+        if kwargs:
+            args = ", ".join([str(x) for x in kwargs])
+            raise TypeError("invalid keyword arguments: %s" % args)
+        at_start = True
+        for x in args:
+            if not at_start:
+                file.write(sep)
+            file.write(str(x))
+            at_start = False
+        file.write(end)
+
+    def exec_(obj, globals=None, locals=None):
+        """ minimal backport of py3k exec statement. """
+        __tracebackhide__ = True
+        if globals is None:
+            frame = sys._getframe(1)
+            globals = frame.f_globals
+            if locals is None:
+                locals = frame.f_locals
+        elif locals is None:
+            locals = globals
+        exec2(obj, globals, locals)
+
+if sys.version_info >= (3, 0):
+    def _reraise(cls, val, tb):
+        __tracebackhide__ = True
+        assert hasattr(val, '__traceback__')
+        raise cls.with_traceback(val, tb)
+else:
+    exec ("""
+def _reraise(cls, val, tb):
+    __tracebackhide__ = True
+    raise cls, val, tb
+def exec2(obj, globals, locals):
+    __tracebackhide__ = True
+    exec obj in globals, locals
+""")
+
+def _tryimport(*names):
+    """ return the first successfully imported module. """
+    assert names
+    for name in names:
+        try:
+            __import__(name)
+        except ImportError:
+            excinfo = sys.exc_info()
+        else:
+            return sys.modules[name]
+    _reraise(*excinfo)
--- a/third_party/python/py/py/_code/__init__.py
+++ b/third_party/python/py/py/_code/__init__.py
@@ -1,1 +1,1 @@
-""" python inspection/code generation API """
+""" python inspection/code generation API """
--- a/third_party/python/py/py/_code/_assertionnew.py
+++ b/third_party/python/py/py/_code/_assertionnew.py
@@ -1,339 +1,339 @@
-"""
-Find intermediate evalutation results in assert statements through builtin AST.
-This should replace _assertionold.py eventually.
-"""
-
-import sys
-import ast
-
-import py
-from py._code.assertion import _format_explanation, BuiltinAssertionError
-
-
-if sys.platform.startswith("java") and sys.version_info < (2, 5, 2):
-    # See http://bugs.jython.org/issue1497
-    _exprs = ("BoolOp", "BinOp", "UnaryOp", "Lambda", "IfExp", "Dict",
-              "ListComp", "GeneratorExp", "Yield", "Compare", "Call",
-              "Repr", "Num", "Str", "Attribute", "Subscript", "Name",
-              "List", "Tuple")
-    _stmts = ("FunctionDef", "ClassDef", "Return", "Delete", "Assign",
-              "AugAssign", "Print", "For", "While", "If", "With", "Raise",
-              "TryExcept", "TryFinally", "Assert", "Import", "ImportFrom",
-              "Exec", "Global", "Expr", "Pass", "Break", "Continue")
-    _expr_nodes = set(getattr(ast, name) for name in _exprs)
-    _stmt_nodes = set(getattr(ast, name) for name in _stmts)
-    def _is_ast_expr(node):
-        return node.__class__ in _expr_nodes
-    def _is_ast_stmt(node):
-        return node.__class__ in _stmt_nodes
-else:
-    def _is_ast_expr(node):
-        return isinstance(node, ast.expr)
-    def _is_ast_stmt(node):
-        return isinstance(node, ast.stmt)
-
-
-class Failure(Exception):
-    """Error found while interpreting AST."""
-
-    def __init__(self, explanation=""):
-        self.cause = sys.exc_info()
-        self.explanation = explanation
-
-
-def interpret(source, frame, should_fail=False):
-    mod = ast.parse(source)
-    visitor = DebugInterpreter(frame)
-    try:
-        visitor.visit(mod)
-    except Failure:
-        failure = sys.exc_info()[1]
-        return getfailure(failure)
-    if should_fail:
-        return ("(assertion failed, but when it was re-run for "
-                "printing intermediate values, it did not fail.  Suggestions: "
-                "compute assert expression before the assert or use --no-assert)")
-
-def run(offending_line, frame=None):
-    if frame is None:
-        frame = py.code.Frame(sys._getframe(1))
-    return interpret(offending_line, frame)
-
-def getfailure(failure):
-    explanation = _format_explanation(failure.explanation)
-    value = failure.cause[1]
-    if str(value):
-        lines = explanation.splitlines()
-        if not lines:
-            lines.append("")
-        lines[0] += " << %s" % (value,)
-        explanation = "\n".join(lines)
-    text = "%s: %s" % (failure.cause[0].__name__, explanation)
-    if text.startswith("AssertionError: assert "):
-        text = text[16:]
-    return text
-
-
-operator_map = {
-    ast.BitOr : "|",
-    ast.BitXor : "^",
-    ast.BitAnd : "&",
-    ast.LShift : "<<",
-    ast.RShift : ">>",
-    ast.Add : "+",
-    ast.Sub : "-",
-    ast.Mult : "*",
-    ast.Div : "/",
-    ast.FloorDiv : "//",
-    ast.Mod : "%",
-    ast.Eq : "==",
-    ast.NotEq : "!=",
-    ast.Lt : "<",
-    ast.LtE : "<=",
-    ast.Gt : ">",
-    ast.GtE : ">=",
-    ast.Pow : "**",
-    ast.Is : "is",
-    ast.IsNot : "is not",
-    ast.In : "in",
-    ast.NotIn : "not in"
-}
-
-unary_map = {
-    ast.Not : "not %s",
-    ast.Invert : "~%s",
-    ast.USub : "-%s",
-    ast.UAdd : "+%s"
-}
-
-
-class DebugInterpreter(ast.NodeVisitor):
-    """Interpret AST nodes to gleam useful debugging information. """
-
-    def __init__(self, frame):
-        self.frame = frame
-
-    def generic_visit(self, node):
-        # Fallback when we don't have a special implementation.
-        if _is_ast_expr(node):
-            mod = ast.Expression(node)
-            co = self._compile(mod)
-            try:
-                result = self.frame.eval(co)
-            except Exception:
-                raise Failure()
-            explanation = self.frame.repr(result)
-            return explanation, result
-        elif _is_ast_stmt(node):
-            mod = ast.Module([node])
-            co = self._compile(mod, "exec")
-            try:
-                self.frame.exec_(co)
-            except Exception:
-                raise Failure()
-            return None, None
-        else:
-            raise AssertionError("can't handle %s" %(node,))
-
-    def _compile(self, source, mode="eval"):
-        return compile(source, "<assertion interpretation>", mode)
-
-    def visit_Expr(self, expr):
-        return self.visit(expr.value)
-
-    def visit_Module(self, mod):
-        for stmt in mod.body:
-            self.visit(stmt)
-
-    def visit_Name(self, name):
-        explanation, result = self.generic_visit(name)
-        # See if the name is local.
-        source = "%r in locals() is not globals()" % (name.id,)
-        co = self._compile(source)
-        try:
-            local = self.frame.eval(co)
-        except Exception:
-            # have to assume it isn't
-            local = False
-        if not local:
-            return name.id, result
-        return explanation, result
-
-    def visit_Compare(self, comp):
-        left = comp.left
-        left_explanation, left_result = self.visit(left)
-        for op, next_op in zip(comp.ops, comp.comparators):
-            next_explanation, next_result = self.visit(next_op)
-            op_symbol = operator_map[op.__class__]
-            explanation = "%s %s %s" % (left_explanation, op_symbol,
-                                        next_explanation)
-            source = "__exprinfo_left %s __exprinfo_right" % (op_symbol,)
-            co = self._compile(source)
-            try:
-                result = self.frame.eval(co, __exprinfo_left=left_result,
-                                         __exprinfo_right=next_result)
-            except Exception:
-                raise Failure(explanation)
-            try:
-                if not result:
-                    break
-            except KeyboardInterrupt:
-                raise
-            except:
-                break
-            left_explanation, left_result = next_explanation, next_result
-
-        rcomp = py.code._reprcompare
-        if rcomp:
-            res = rcomp(op_symbol, left_result, next_result)
-            if res:
-                explanation = res
-        return explanation, result
-
-    def visit_BoolOp(self, boolop):
-        is_or = isinstance(boolop.op, ast.Or)
-        explanations = []
-        for operand in boolop.values:
-            explanation, result = self.visit(operand)
-            explanations.append(explanation)
-            if result == is_or:
-                break
-        name = is_or and " or " or " and "
-        explanation = "(" + name.join(explanations) + ")"
-        return explanation, result
-
-    def visit_UnaryOp(self, unary):
-        pattern = unary_map[unary.op.__class__]
-        operand_explanation, operand_result = self.visit(unary.operand)
-        explanation = pattern % (operand_explanation,)
-        co = self._compile(pattern % ("__exprinfo_expr",))
-        try:
-            result = self.frame.eval(co, __exprinfo_expr=operand_result)
-        except Exception:
-            raise Failure(explanation)
-        return explanation, result
-
-    def visit_BinOp(self, binop):
-        left_explanation, left_result = self.visit(binop.left)
-        right_explanation, right_result = self.visit(binop.right)
-        symbol = operator_map[binop.op.__class__]
-        explanation = "(%s %s %s)" % (left_explanation, symbol,
-                                      right_explanation)
-        source = "__exprinfo_left %s __exprinfo_right" % (symbol,)
-        co = self._compile(source)
-        try:
-            result = self.frame.eval(co, __exprinfo_left=left_result,
-                                     __exprinfo_right=right_result)
-        except Exception:
-            raise Failure(explanation)
-        return explanation, result
-
-    def visit_Call(self, call):
-        func_explanation, func = self.visit(call.func)
-        arg_explanations = []
-        ns = {"__exprinfo_func" : func}
-        arguments = []
-        for arg in call.args:
-            arg_explanation, arg_result = self.visit(arg)
-            arg_name = "__exprinfo_%s" % (len(ns),)
-            ns[arg_name] = arg_result
-            arguments.append(arg_name)
-            arg_explanations.append(arg_explanation)
-        for keyword in call.keywords:
-            arg_explanation, arg_result = self.visit(keyword.value)
-            arg_name = "__exprinfo_%s" % (len(ns),)
-            ns[arg_name] = arg_result
-            keyword_source = "%s=%%s" % (keyword.arg)
-            arguments.append(keyword_source % (arg_name,))
-            arg_explanations.append(keyword_source % (arg_explanation,))
-        if call.starargs:
-            arg_explanation, arg_result = self.visit(call.starargs)
-            arg_name = "__exprinfo_star"
-            ns[arg_name] = arg_result
-            arguments.append("*%s" % (arg_name,))
-            arg_explanations.append("*%s" % (arg_explanation,))
-        if call.kwargs:
-            arg_explanation, arg_result = self.visit(call.kwargs)
-            arg_name = "__exprinfo_kwds"
-            ns[arg_name] = arg_result
-            arguments.append("**%s" % (arg_name,))
-            arg_explanations.append("**%s" % (arg_explanation,))
-        args_explained = ", ".join(arg_explanations)
-        explanation = "%s(%s)" % (func_explanation, args_explained)
-        args = ", ".join(arguments)
-        source = "__exprinfo_func(%s)" % (args,)
-        co = self._compile(source)
-        try:
-            result = self.frame.eval(co, **ns)
-        except Exception:
-            raise Failure(explanation)
-        pattern = "%s\n{%s = %s\n}"
-        rep = self.frame.repr(result)
-        explanation = pattern % (rep, rep, explanation)
-        return explanation, result
-
-    def _is_builtin_name(self, name):
-        pattern = "%r not in globals() and %r not in locals()"
-        source = pattern % (name.id, name.id)
-        co = self._compile(source)
-        try:
-            return self.frame.eval(co)
-        except Exception:
-            return False
-
-    def visit_Attribute(self, attr):
-        if not isinstance(attr.ctx, ast.Load):
-            return self.generic_visit(attr)
-        source_explanation, source_result = self.visit(attr.value)
-        explanation = "%s.%s" % (source_explanation, attr.attr)
-        source = "__exprinfo_expr.%s" % (attr.attr,)
-        co = self._compile(source)
-        try:
-            result = self.frame.eval(co, __exprinfo_expr=source_result)
-        except Exception:
-            raise Failure(explanation)
-        explanation = "%s\n{%s = %s.%s\n}" % (self.frame.repr(result),
-                                              self.frame.repr(result),
-                                              source_explanation, attr.attr)
-        # Check if the attr is from an instance.
-        source = "%r in getattr(__exprinfo_expr, '__dict__', {})"
-        source = source % (attr.attr,)
-        co = self._compile(source)
-        try:
-            from_instance = self.frame.eval(co, __exprinfo_expr=source_result)
-        except Exception:
-            from_instance = True
-        if from_instance:
-            rep = self.frame.repr(result)
-            pattern = "%s\n{%s = %s\n}"
-            explanation = pattern % (rep, rep, explanation)
-        return explanation, result
-
-    def visit_Assert(self, assrt):
-        test_explanation, test_result = self.visit(assrt.test)
-        if test_explanation.startswith("False\n{False =") and \
-                test_explanation.endswith("\n"):
-            test_explanation = test_explanation[15:-2]
-        explanation = "assert %s" % (test_explanation,)
-        if not test_result:
-            try:
-                raise BuiltinAssertionError
-            except Exception:
-                raise Failure(explanation)
-        return explanation, test_result
-
-    def visit_Assign(self, assign):
-        value_explanation, value_result = self.visit(assign.value)
-        explanation = "... = %s" % (value_explanation,)
-        name = ast.Name("__exprinfo_expr", ast.Load(),
-                        lineno=assign.value.lineno,
-                        col_offset=assign.value.col_offset)
-        new_assign = ast.Assign(assign.targets, name, lineno=assign.lineno,
-                                col_offset=assign.col_offset)
-        mod = ast.Module([new_assign])
-        co = self._compile(mod, "exec")
-        try:
-            self.frame.exec_(co, __exprinfo_expr=value_result)
-        except Exception:
-            raise Failure(explanation)
-        return explanation, value_result
+"""
+Find intermediate evalutation results in assert statements through builtin AST.
+This should replace _assertionold.py eventually.
+"""
+
+import sys
+import ast
+
+import py
+from py._code.assertion import _format_explanation, BuiltinAssertionError
+
+
+if sys.platform.startswith("java") and sys.version_info < (2, 5, 2):
+    # See http://bugs.jython.org/issue1497
+    _exprs = ("BoolOp", "BinOp", "UnaryOp", "Lambda", "IfExp", "Dict",
+              "ListComp", "GeneratorExp", "Yield", "Compare", "Call",
+              "Repr", "Num", "Str", "Attribute", "Subscript", "Name",
+              "List", "Tuple")
+    _stmts = ("FunctionDef", "ClassDef", "Return", "Delete", "Assign",
+              "AugAssign", "Print", "For", "While", "If", "With", "Raise",
+              "TryExcept", "TryFinally", "Assert", "Import", "ImportFrom",
+              "Exec", "Global", "Expr", "Pass", "Break", "Continue")
+    _expr_nodes = set(getattr(ast, name) for name in _exprs)
+    _stmt_nodes = set(getattr(ast, name) for name in _stmts)
+    def _is_ast_expr(node):
+        return node.__class__ in _expr_nodes
+    def _is_ast_stmt(node):
+        return node.__class__ in _stmt_nodes
+else:
+    def _is_ast_expr(node):
+        return isinstance(node, ast.expr)
+    def _is_ast_stmt(node):
+        return isinstance(node, ast.stmt)
+
+
+class Failure(Exception):
+    """Error found while interpreting AST."""
+
+    def __init__(self, explanation=""):
+        self.cause = sys.exc_info()
+        self.explanation = explanation
+
+
+def interpret(source, frame, should_fail=False):
+    mod = ast.parse(source)
+    visitor = DebugInterpreter(frame)
+    try:
+        visitor.visit(mod)
+    except Failure:
+        failure = sys.exc_info()[1]
+        return getfailure(failure)
+    if should_fail:
+        return ("(assertion failed, but when it was re-run for "
+                "printing intermediate values, it did not fail.  Suggestions: "
+                "compute assert expression before the assert or use --no-assert)")
+
+def run(offending_line, frame=None):
+    if frame is None:
+        frame = py.code.Frame(sys._getframe(1))
+    return interpret(offending_line, frame)
+
+def getfailure(failure):
+    explanation = _format_explanation(failure.explanation)
+    value = failure.cause[1]
+    if str(value):
+        lines = explanation.splitlines()
+        if not lines:
+            lines.append("")
+        lines[0] += " << %s" % (value,)
+        explanation = "\n".join(lines)
+    text = "%s: %s" % (failure.cause[0].__name__, explanation)
+    if text.startswith("AssertionError: assert "):
+        text = text[16:]
+    return text
+
+
+operator_map = {
+    ast.BitOr : "|",
+    ast.BitXor : "^",
+    ast.BitAnd : "&",
+    ast.LShift : "<<",
+    ast.RShift : ">>",
+    ast.Add : "+",
+    ast.Sub : "-",
+    ast.Mult : "*",
+    ast.Div : "/",
+    ast.FloorDiv : "//",
+    ast.Mod : "%",
+    ast.Eq : "==",
+    ast.NotEq : "!=",
+    ast.Lt : "<",
+    ast.LtE : "<=",
+    ast.Gt : ">",
+    ast.GtE : ">=",
+    ast.Pow : "**",
+    ast.Is : "is",
+    ast.IsNot : "is not",
+    ast.In : "in",
+    ast.NotIn : "not in"
+}
+
+unary_map = {
+    ast.Not : "not %s",
+    ast.Invert : "~%s",
+    ast.USub : "-%s",
+    ast.UAdd : "+%s"
+}
+
+
+class DebugInterpreter(ast.NodeVisitor):
+    """Interpret AST nodes to gleam useful debugging information. """
+
+    def __init__(self, frame):
+        self.frame = frame
+
+    def generic_visit(self, node):
+        # Fallback when we don't have a special implementation.
+        if _is_ast_expr(node):
+            mod = ast.Expression(node)
+            co = self._compile(mod)
+            try:
+                result = self.frame.eval(co)
+            except Exception:
+                raise Failure()
+            explanation = self.frame.repr(result)
+            return explanation, result
+        elif _is_ast_stmt(node):
+            mod = ast.Module([node])
+            co = self._compile(mod, "exec")
+            try:
+                self.frame.exec_(co)
+            except Exception:
+                raise Failure()
+            return None, None
+        else:
+            raise AssertionError("can't handle %s" %(node,))
+
+    def _compile(self, source, mode="eval"):
+        return compile(source, "<assertion interpretation>", mode)
+
+    def visit_Expr(self, expr):
+        return self.visit(expr.value)
+
+    def visit_Module(self, mod):
+        for stmt in mod.body:
+            self.visit(stmt)
+
+    def visit_Name(self, name):
+        explanation, result = self.generic_visit(name)
+        # See if the name is local.
+        source = "%r in locals() is not globals()" % (name.id,)
+        co = self._compile(source)
+        try:
+            local = self.frame.eval(co)
+        except Exception:
+            # have to assume it isn't
+            local = False
+        if not local:
+            return name.id, result
+        return explanation, result
+
+    def visit_Compare(self, comp):
+        left = comp.left
+        left_explanation, left_result = self.visit(left)
+        for op, next_op in zip(comp.ops, comp.comparators):
+            next_explanation, next_result = self.visit(next_op)
+            op_symbol = operator_map[op.__class__]
+            explanation = "%s %s %s" % (left_explanation, op_symbol,
+                                        next_explanation)
+            source = "__exprinfo_left %s __exprinfo_right" % (op_symbol,)
+            co = self._compile(source)
+            try:
+                result = self.frame.eval(co, __exprinfo_left=left_result,
+                                         __exprinfo_right=next_result)
+            except Exception:
+                raise Failure(explanation)
+            try:
+                if not result:
+                    break
+            except KeyboardInterrupt:
+                raise
+            except:
+                break
+            left_explanation, left_result = next_explanation, next_result
+
+        rcomp = py.code._reprcompare
+        if rcomp:
+            res = rcomp(op_symbol, left_result, next_result)
+            if res:
+                explanation = res
+        return explanation, result
+
+    def visit_BoolOp(self, boolop):
+        is_or = isinstance(boolop.op, ast.Or)
+        explanations = []
+        for operand in boolop.values:
+            explanation, result = self.visit(operand)
+            explanations.append(explanation)
+            if result == is_or:
+                break
+        name = is_or and " or " or " and "
+        explanation = "(" + name.join(explanations) + ")"
+        return explanation, result
+
+    def visit_UnaryOp(self, unary):
+        pattern = unary_map[unary.op.__class__]
+        operand_explanation, operand_result = self.visit(unary.operand)
+        explanation = pattern % (operand_explanation,)
+        co = self._compile(pattern % ("__exprinfo_expr",))
+        try:
+            result = self.frame.eval(co, __exprinfo_expr=operand_result)
+        except Exception:
+            raise Failure(explanation)
+        return explanation, result
+
+    def visit_BinOp(self, binop):
+        left_explanation, left_result = self.visit(binop.left)
+        right_explanation, right_result = self.visit(binop.right)
+        symbol = operator_map[binop.op.__class__]
+        explanation = "(%s %s %s)" % (left_explanation, symbol,
+                                      right_explanation)
+        source = "__exprinfo_left %s __exprinfo_right" % (symbol,)
+        co = self._compile(source)
+        try:
+            result = self.frame.eval(co, __exprinfo_left=left_result,
+                                     __exprinfo_right=right_result)
+        except Exception:
+            raise Failure(explanation)
+        return explanation, result
+
+    def visit_Call(self, call):
+        func_explanation, func = self.visit(call.func)
+        arg_explanations = []
+        ns = {"__exprinfo_func" : func}
+        arguments = []
+        for arg in call.args:
+            arg_explanation, arg_result = self.visit(arg)
+            arg_name = "__exprinfo_%s" % (len(ns),)
+            ns[arg_name] = arg_result
+            arguments.append(arg_name)
+            arg_explanations.append(arg_explanation)
+        for keyword in call.keywords:
+            arg_explanation, arg_result = self.visit(keyword.value)
+            arg_name = "__exprinfo_%s" % (len(ns),)
+            ns[arg_name] = arg_result
+            keyword_source = "%s=%%s" % (keyword.arg)
+            arguments.append(keyword_source % (arg_name,))
+            arg_explanations.append(keyword_source % (arg_explanation,))
+        if call.starargs:
+            arg_explanation, arg_result = self.visit(call.starargs)
+            arg_name = "__exprinfo_star"
+            ns[arg_name] = arg_result
+            arguments.append("*%s" % (arg_name,))
+            arg_explanations.append("*%s" % (arg_explanation,))
+        if call.kwargs:
+            arg_explanation, arg_result = self.visit(call.kwargs)
+            arg_name = "__exprinfo_kwds"
+            ns[arg_name] = arg_result
+            arguments.append("**%s" % (arg_name,))
+            arg_explanations.append("**%s" % (arg_explanation,))
+        args_explained = ", ".join(arg_explanations)
+        explanation = "%s(%s)" % (func_explanation, args_explained)
+        args = ", ".join(arguments)
+        source = "__exprinfo_func(%s)" % (args,)
+        co = self._compile(source)
+        try:
+            result = self.frame.eval(co, **ns)
+        except Exception:
+            raise Failure(explanation)
+        pattern = "%s\n{%s = %s\n}"
+        rep = self.frame.repr(result)
+        explanation = pattern % (rep, rep, explanation)
+        return explanation, result
+
+    def _is_builtin_name(self, name):
+        pattern = "%r not in globals() and %r not in locals()"
+        source = pattern % (name.id, name.id)
+        co = self._compile(source)
+        try:
+            return self.frame.eval(co)
+        except Exception:
+            return False
+
+    def visit_Attribute(self, attr):
+        if not isinstance(attr.ctx, ast.Load):
+            return self.generic_visit(attr)
+        source_explanation, source_result = self.visit(attr.value)
+        explanation = "%s.%s" % (source_explanation, attr.attr)
+        source = "__exprinfo_expr.%s" % (attr.attr,)
+        co = self._compile(source)
+        try:
+            result = self.frame.eval(co, __exprinfo_expr=source_result)
+        except Exception:
+            raise Failure(explanation)
+        explanation = "%s\n{%s = %s.%s\n}" % (self.frame.repr(result),
+                                              self.frame.repr(result),
+                                              source_explanation, attr.attr)
+        # Check if the attr is from an instance.
+        source = "%r in getattr(__exprinfo_expr, '__dict__', {})"
+        source = source % (attr.attr,)
+        co = self._compile(source)
+        try:
+            from_instance = self.frame.eval(co, __exprinfo_expr=source_result)
+        except Exception:
+            from_instance = True
+        if from_instance:
+            rep = self.frame.repr(result)
+            pattern = "%s\n{%s = %s\n}"
+            explanation = pattern % (rep, rep, explanation)
+        return explanation, result
+
+    def visit_Assert(self, assrt):
+        test_explanation, test_result = self.visit(assrt.test)
+        if test_explanation.startswith("False\n{False =") and \
+                test_explanation.endswith("\n"):
+            test_explanation = test_explanation[15:-2]
+        explanation = "assert %s" % (test_explanation,)
+        if not test_result:
+            try:
+                raise BuiltinAssertionError
+            except Exception:
+                raise Failure(explanation)
+        return explanation, test_result
+
+    def visit_Assign(self, assign):
+        value_explanation, value_result = self.visit(assign.value)
+        explanation = "... = %s" % (value_explanation,)
+        name = ast.Name("__exprinfo_expr", ast.Load(),
+                        lineno=assign.value.lineno,
+                        col_offset=assign.value.col_offset)
+        new_assign = ast.Assign(assign.targets, name, lineno=assign.lineno,
+                                col_offset=assign.col_offset)
+        mod = ast.Module([new_assign])
+        co = self._compile(mod, "exec")
+        try:
+            self.frame.exec_(co, __exprinfo_expr=value_result)
+        except Exception:
+            raise Failure(explanation)
+        return explanation, value_result
--- a/third_party/python/py/py/_code/_assertionold.py
+++ b/third_party/python/py/py/_code/_assertionold.py
@@ -1,555 +1,555 @@
-import py
-import sys, inspect
-from compiler import parse, ast, pycodegen
-from py._code.assertion import BuiltinAssertionError, _format_explanation
-
-passthroughex = py.builtin._sysex
-
-class Failure:
-    def __init__(self, node):
-        self.exc, self.value, self.tb = sys.exc_info()
-        self.node = node
-
-class View(object):
-    """View base class.
-
-    If C is a subclass of View, then C(x) creates a proxy object around
-    the object x.  The actual class of the proxy is not C in general,
-    but a *subclass* of C determined by the rules below.  To avoid confusion
-    we call view class the class of the proxy (a subclass of C, so of View)
-    and object class the class of x.
-
-    Attributes and methods not found in the proxy are automatically read on x.
-    Other operations like setting attributes are performed on the proxy, as
-    determined by its view class.  The object x is available from the proxy
-    as its __obj__ attribute.
-
-    The view class selection is determined by the __view__ tuples and the
-    optional __viewkey__ method.  By default, the selected view class is the
-    most specific subclass of C whose __view__ mentions the class of x.
-    If no such subclass is found, the search proceeds with the parent
-    object classes.  For example, C(True) will first look for a subclass
-    of C with __view__ = (..., bool, ...) and only if it doesn't find any
-    look for one with __view__ = (..., int, ...), and then ..., object,...
-    If everything fails the class C itself is considered to be the default.
-
-    Alternatively, the view class selection can be driven by another aspect
-    of the object x, instead of the class of x, by overriding __viewkey__.
-    See last example at the end of this module.
-    """
-
-    _viewcache = {}
-    __view__ = ()
-
-    def __new__(rootclass, obj, *args, **kwds):
-        self = object.__new__(rootclass)
-        self.__obj__ = obj
-        self.__rootclass__ = rootclass
-        key = self.__viewkey__()
-        try:
-            self.__class__ = self._viewcache[key]
-        except KeyError:
-            self.__class__ = self._selectsubclass(key)
-        return self
-
-    def __getattr__(self, attr):
-        # attributes not found in the normal hierarchy rooted on View
-        # are looked up in the object's real class
-        return getattr(self.__obj__, attr)
-
-    def __viewkey__(self):
-        return self.__obj__.__class__
-
-    def __matchkey__(self, key, subclasses):
-        if inspect.isclass(key):
-            keys = inspect.getmro(key)
-        else:
-            keys = [key]
-        for key in keys:
-            result = [C for C in subclasses if key in C.__view__]
-            if result:
-                return result
-        return []
-
-    def _selectsubclass(self, key):
-        subclasses = list(enumsubclasses(self.__rootclass__))
-        for C in subclasses:
-            if not isinstance(C.__view__, tuple):
-                C.__view__ = (C.__view__,)
-        choices = self.__matchkey__(key, subclasses)
-        if not choices:
-            return self.__rootclass__
-        elif len(choices) == 1:
-            return choices[0]
-        else:
-            # combine the multiple choices
-            return type('?', tuple(choices), {})
-
-    def __repr__(self):
-        return '%s(%r)' % (self.__rootclass__.__name__, self.__obj__)
-
-
-def enumsubclasses(cls):
-    for subcls in cls.__subclasses__():
-        for subsubclass in enumsubclasses(subcls):
-            yield subsubclass
-    yield cls
-
-
-class Interpretable(View):
-    """A parse tree node with a few extra methods."""
-    explanation = None
-
-    def is_builtin(self, frame):
-        return False
-
-    def eval(self, frame):
-        # fall-back for unknown expression nodes
-        try:
-            expr = ast.Expression(self.__obj__)
-            expr.filename = '<eval>'
-            self.__obj__.filename = '<eval>'
-            co = pycodegen.ExpressionCodeGenerator(expr).getCode()
-            result = frame.eval(co)
-        except passthroughex:
-            raise
-        except:
-            raise Failure(self)
-        self.result = result
-        self.explanation = self.explanation or frame.repr(self.result)
-
-    def run(self, frame):
-        # fall-back for unknown statement nodes
-        try:
-            expr = ast.Module(None, ast.Stmt([self.__obj__]))
-            expr.filename = '<run>'
-            co = pycodegen.ModuleCodeGenerator(expr).getCode()
-            frame.exec_(co)
-        except passthroughex:
-            raise
-        except:
-            raise Failure(self)
-
-    def nice_explanation(self):
-        return _format_explanation(self.explanation)
-
-
-class Name(Interpretable):
-    __view__ = ast.Name
-
-    def is_local(self, frame):
-        source = '%r in locals() is not globals()' % self.name
-        try:
-            return frame.is_true(frame.eval(source))
-        except passthroughex:
-            raise
-        except:
-            return False
-
-    def is_global(self, frame):
-        source = '%r in globals()' % self.name
-        try:
-            return frame.is_true(frame.eval(source))
-        except passthroughex:
-            raise
-        except:
-            return False
-
-    def is_builtin(self, frame):
-        source = '%r not in locals() and %r not in globals()' % (
-            self.name, self.name)
-        try:
-            return frame.is_true(frame.eval(source))
-        except passthroughex:
-            raise
-        except:
-            return False
-
-    def eval(self, frame):
-        super(Name, self).eval(frame)
-        if not self.is_local(frame):
-            self.explanation = self.name
-
-class Compare(Interpretable):
-    __view__ = ast.Compare
-
-    def eval(self, frame):
-        expr = Interpretable(self.expr)
-        expr.eval(frame)
-        for operation, expr2 in self.ops:
-            if hasattr(self, 'result'):
-                # shortcutting in chained expressions
-                if not frame.is_true(self.result):
-                    break
-            expr2 = Interpretable(expr2)
-            expr2.eval(frame)
-            self.explanation = "%s %s %s" % (
-                expr.explanation, operation, expr2.explanation)
-            source = "__exprinfo_left %s __exprinfo_right" % operation
-            try:
-                self.result = frame.eval(source,
-                                         __exprinfo_left=expr.result,
-                                         __exprinfo_right=expr2.result)
-            except passthroughex:
-                raise
-            except:
-                raise Failure(self)
-            expr = expr2
-
-class And(Interpretable):
-    __view__ = ast.And
-
-    def eval(self, frame):
-        explanations = []
-        for expr in self.nodes:
-            expr = Interpretable(expr)
-            expr.eval(frame)
-            explanations.append(expr.explanation)
-            self.result = expr.result
-            if not frame.is_true(expr.result):
-                break
-        self.explanation = '(' + ' and '.join(explanations) + ')'
-
-class Or(Interpretable):
-    __view__ = ast.Or
-
-    def eval(self, frame):
-        explanations = []
-        for expr in self.nodes:
-            expr = Interpretable(expr)
-            expr.eval(frame)
-            explanations.append(expr.explanation)
-            self.result = expr.result
-            if frame.is_true(expr.result):
-                break
-        self.explanation = '(' + ' or '.join(explanations) + ')'
-
-
-# == Unary operations ==
-keepalive = []
-for astclass, astpattern in {
-    ast.Not    : 'not __exprinfo_expr',
-    ast.Invert : '(~__exprinfo_expr)',
-    }.items():
-
-    class UnaryArith(Interpretable):
-        __view__ = astclass
-
-        def eval(self, frame, astpattern=astpattern):
-            expr = Interpretable(self.expr)
-            expr.eval(frame)
-            self.explanation = astpattern.replace('__exprinfo_expr',
-                                                  expr.explanation)
-            try:
-                self.result = frame.eval(astpattern,
-                                         __exprinfo_expr=expr.result)
-            except passthroughex:
-                raise
-            except:
-                raise Failure(self)
-
-    keepalive.append(UnaryArith)
-
-# == Binary operations ==
-for astclass, astpattern in {
-    ast.Add    : '(__exprinfo_left + __exprinfo_right)',
-    ast.Sub    : '(__exprinfo_left - __exprinfo_right)',
-    ast.Mul    : '(__exprinfo_left * __exprinfo_right)',
-    ast.Div    : '(__exprinfo_left / __exprinfo_right)',
-    ast.Mod    : '(__exprinfo_left % __exprinfo_right)',
-    ast.Power  : '(__exprinfo_left ** __exprinfo_right)',
-    }.items():
-
-    class BinaryArith(Interpretable):
-        __view__ = astclass
-
-        def eval(self, frame, astpattern=astpattern):
-            left = Interpretable(self.left)
-            left.eval(frame)
-            right = Interpretable(self.right)
-            right.eval(frame)
-            self.explanation = (astpattern
-                                .replace('__exprinfo_left',  left .explanation)
-                                .replace('__exprinfo_right', right.explanation))
-            try:
-                self.result = frame.eval(astpattern,
-                                         __exprinfo_left=left.result,
-                                         __exprinfo_right=right.result)
-            except passthroughex:
-                raise
-            except:
-                raise Failure(self)
-
-    keepalive.append(BinaryArith)
-
-
-class CallFunc(Interpretable):
-    __view__ = ast.CallFunc
-
-    def is_bool(self, frame):
-        source = 'isinstance(__exprinfo_value, bool)'
-        try:
-            return frame.is_true(frame.eval(source,
-                                            __exprinfo_value=self.result))
-        except passthroughex:
-            raise
-        except:
-            return False
-
-    def eval(self, frame):
-        node = Interpretable(self.node)
-        node.eval(frame)
-        explanations = []
-        vars = {'__exprinfo_fn': node.result}
-        source = '__exprinfo_fn('
-        for a in self.args:
-            if isinstance(a, ast.Keyword):
-                keyword = a.name
-                a = a.expr
-            else:
-                keyword = None
-            a = Interpretable(a)
-            a.eval(frame)
-            argname = '__exprinfo_%d' % len(vars)
-            vars[argname] = a.result
-            if keyword is None:
-                source += argname + ','
-                explanations.append(a.explanation)
-            else:
-                source += '%s=%s,' % (keyword, argname)
-                explanations.append('%s=%s' % (keyword, a.explanation))
-        if self.star_args:
-            star_args = Interpretable(self.star_args)
-            star_args.eval(frame)
-            argname = '__exprinfo_star'
-            vars[argname] = star_args.result
-            source += '*' + argname + ','
-            explanations.append('*' + star_args.explanation)
-        if self.dstar_args:
-            dstar_args = Interpretable(self.dstar_args)
-            dstar_args.eval(frame)
-            argname = '__exprinfo_kwds'
-            vars[argname] = dstar_args.result
-            source += '**' + argname + ','
-            explanations.append('**' + dstar_args.explanation)
-        self.explanation = "%s(%s)" % (
-            node.explanation, ', '.join(explanations))
-        if source.endswith(','):
-            source = source[:-1]
-        source += ')'
-        try:
-            self.result = frame.eval(source, **vars)
-        except passthroughex:
-            raise
-        except:
-            raise Failure(self)
-        if not node.is_builtin(frame) or not self.is_bool(frame):
-            r = frame.repr(self.result)
-            self.explanation = '%s\n{%s = %s\n}' % (r, r, self.explanation)
-
-class Getattr(Interpretable):
-    __view__ = ast.Getattr
-
-    def eval(self, frame):
-        expr = Interpretable(self.expr)
-        expr.eval(frame)
-        source = '__exprinfo_expr.%s' % self.attrname
-        try:
-            self.result = frame.eval(source, __exprinfo_expr=expr.result)
-        except passthroughex:
-            raise
-        except:
-            raise Failure(self)
-        self.explanation = '%s.%s' % (expr.explanation, self.attrname)
-        # if the attribute comes from the instance, its value is interesting
-        source = ('hasattr(__exprinfo_expr, "__dict__") and '
-                  '%r in __exprinfo_expr.__dict__' % self.attrname)
-        try:
-            from_instance = frame.is_true(
-                frame.eval(source, __exprinfo_expr=expr.result))
-        except passthroughex:
-            raise
-        except:
-            from_instance = True
-        if from_instance:
-            r = frame.repr(self.result)
-            self.explanation = '%s\n{%s = %s\n}' % (r, r, self.explanation)
-
-# == Re-interpretation of full statements ==
-
-class Assert(Interpretable):
-    __view__ = ast.Assert
-
-    def run(self, frame):
-        test = Interpretable(self.test)
-        test.eval(frame)
-        # simplify 'assert False where False = ...'
-        if (test.explanation.startswith('False\n{False = ') and
-            test.explanation.endswith('\n}')):
-            test.explanation = test.explanation[15:-2]
-        # print the result as  'assert <explanation>'
-        self.result = test.result
-        self.explanation = 'assert ' + test.explanation
-        if not frame.is_true(test.result):
-            try:
-                raise BuiltinAssertionError
-            except passthroughex:
-                raise
-            except:
-                raise Failure(self)
-
-class Assign(Interpretable):
-    __view__ = ast.Assign
-
-    def run(self, frame):
-        expr = Interpretable(self.expr)
-        expr.eval(frame)
-        self.result = expr.result
-        self.explanation = '... = ' + expr.explanation
-        # fall-back-run the rest of the assignment
-        ass = ast.Assign(self.nodes, ast.Name('__exprinfo_expr'))
-        mod = ast.Module(None, ast.Stmt([ass]))
-        mod.filename = '<run>'
-        co = pycodegen.ModuleCodeGenerator(mod).getCode()
-        try:
-            frame.exec_(co, __exprinfo_expr=expr.result)
-        except passthroughex:
-            raise
-        except:
-            raise Failure(self)
-
-class Discard(Interpretable):
-    __view__ = ast.Discard
-
-    def run(self, frame):
-        expr = Interpretable(self.expr)
-        expr.eval(frame)
-        self.result = expr.result
-        self.explanation = expr.explanation
-
-class Stmt(Interpretable):
-    __view__ = ast.Stmt
-
-    def run(self, frame):
-        for stmt in self.nodes:
-            stmt = Interpretable(stmt)
-            stmt.run(frame)
-
-
-def report_failure(e):
-    explanation = e.node.nice_explanation()
-    if explanation:
-        explanation = ", in: " + explanation
-    else:
-        explanation = ""
-    sys.stdout.write("%s: %s%s\n" % (e.exc.__name__, e.value, explanation))
-
-def check(s, frame=None):
-    if frame is None:
-        frame = sys._getframe(1)
-        frame = py.code.Frame(frame)
-    expr = parse(s, 'eval')
-    assert isinstance(expr, ast.Expression)
-    node = Interpretable(expr.node)
-    try:
-        node.eval(frame)
-    except passthroughex:
-        raise
-    except Failure:
-        e = sys.exc_info()[1]
-        report_failure(e)
-    else:
-        if not frame.is_true(node.result):
-            sys.stderr.write("assertion failed: %s\n" % node.nice_explanation())
-
-
-###########################################################
-# API / Entry points
-# #########################################################
-
-def interpret(source, frame, should_fail=False):
-    module = Interpretable(parse(source, 'exec').node)
-    #print "got module", module
-    if isinstance(frame, py.std.types.FrameType):
-        frame = py.code.Frame(frame)
-    try:
-        module.run(frame)
-    except Failure:
-        e = sys.exc_info()[1]
-        return getfailure(e)
-    except passthroughex:
-        raise
-    except:
-        import traceback
-        traceback.print_exc()
-    if should_fail:
-        return ("(assertion failed, but when it was re-run for "
-                "printing intermediate values, it did not fail.  Suggestions: "
-                "compute assert expression before the assert or use --nomagic)")
-    else:
-        return None
-
-def getmsg(excinfo):
-    if isinstance(excinfo, tuple):
-        excinfo = py.code.ExceptionInfo(excinfo)
-    #frame, line = gettbline(tb)
-    #frame = py.code.Frame(frame)
-    #return interpret(line, frame)
-
-    tb = excinfo.traceback[-1]
-    source = str(tb.statement).strip()
-    x = interpret(source, tb.frame, should_fail=True)
-    if not isinstance(x, str):
-        raise TypeError("interpret returned non-string %r" % (x,))
-    return x
-
-def getfailure(e):
-    explanation = e.node.nice_explanation()
-    if str(e.value):
-        lines = explanation.split('\n')
-        lines[0] += "  << %s" % (e.value,)
-        explanation = '\n'.join(lines)
-    text = "%s: %s" % (e.exc.__name__, explanation)
-    if text.startswith('AssertionError: assert '):
-        text = text[16:]
-    return text
-
-def run(s, frame=None):
-    if frame is None:
-        frame = sys._getframe(1)
-        frame = py.code.Frame(frame)
-    module = Interpretable(parse(s, 'exec').node)
-    try:
-        module.run(frame)
-    except Failure:
-        e = sys.exc_info()[1]
-        report_failure(e)
-
-
-if __name__ == '__main__':
-    # example:
-    def f():
-        return 5
-    def g():
-        return 3
-    def h(x):
-        return 'never'
-    check("f() * g() == 5")
-    check("not f()")
-    check("not (f() and g() or 0)")
-    check("f() == g()")
-    i = 4
-    check("i == f()")
-    check("len(f()) == 0")
-    check("isinstance(2+3+4, float)")
-
-    run("x = i")
-    check("x == 5")
-
-    run("assert not f(), 'oops'")
-    run("a, b, c = 1, 2")
-    run("a, b, c = f()")
-
-    check("max([f(),g()]) == 4")
-    check("'hello'[g()] == 'h'")
-    run("'guk%d' % h(f())")
+import py
+import sys, inspect
+from compiler import parse, ast, pycodegen
+from py._code.assertion import BuiltinAssertionError, _format_explanation
+
+passthroughex = py.builtin._sysex
+
+class Failure:
+    def __init__(self, node):
+        self.exc, self.value, self.tb = sys.exc_info()
+        self.node = node
+
+class View(object):
+    """View base class.
+
+    If C is a subclass of View, then C(x) creates a proxy object around
+    the object x.  The actual class of the proxy is not C in general,
+    but a *subclass* of C determined by the rules below.  To avoid confusion
+    we call view class the class of the proxy (a subclass of C, so of View)
+    and object class the class of x.
+
+    Attributes and methods not found in the proxy are automatically read on x.
+    Other operations like setting attributes are performed on the proxy, as
+    determined by its view class.  The object x is available from the proxy
+    as its __obj__ attribute.
+
+    The view class selection is determined by the __view__ tuples and the
+    optional __viewkey__ method.  By default, the selected view class is the
+    most specific subclass of C whose __view__ mentions the class of x.
+    If no such subclass is found, the search proceeds with the parent
+    object classes.  For example, C(True) will first look for a subclass
+    of C with __view__ = (..., bool, ...) and only if it doesn't find any
+    look for one with __view__ = (..., int, ...), and then ..., object,...
+    If everything fails the class C itself is considered to be the default.
+
+    Alternatively, the view class selection can be driven by another aspect
+    of the object x, instead of the class of x, by overriding __viewkey__.
+    See last example at the end of this module.
+    """
+
+    _viewcache = {}
+    __view__ = ()
+
+    def __new__(rootclass, obj, *args, **kwds):
+        self = object.__new__(rootclass)
+        self.__obj__ = obj
+        self.__rootclass__ = rootclass
+        key = self.__viewkey__()
+        try:
+            self.__class__ = self._viewcache[key]
+        except KeyError:
+            self.__class__ = self._selectsubclass(key)
+        return self
+
+    def __getattr__(self, attr):
+        # attributes not found in the normal hierarchy rooted on View
+        # are looked up in the object's real class
+        return getattr(self.__obj__, attr)
+
+    def __viewkey__(self):
+        return self.__obj__.__class__
+
+    def __matchkey__(self, key, subclasses):
+        if inspect.isclass(key):
+            keys = inspect.getmro(key)
+        else:
+            keys = [key]
+        for key in keys:
+            result = [C for C in subclasses if key in C.__view__]
+            if result:
+                return result
+        return []
+
+    def _selectsubclass(self, key):
+        subclasses = list(enumsubclasses(self.__rootclass__))
+        for C in subclasses:
+            if not isinstance(C.__view__, tuple):
+                C.__view__ = (C.__view__,)
+        choices = self.__matchkey__(key, subclasses)
+        if not choices:
+            return self.__rootclass__
+        elif len(choices) == 1:
+            return choices[0]
+        else:
+            # combine the multiple choices
+            return type('?', tuple(choices), {})
+
+    def __repr__(self):
+        return '%s(%r)' % (self.__rootclass__.__name__, self.__obj__)
+
+
+def enumsubclasses(cls):
+    for subcls in cls.__subclasses__():
+        for subsubclass in enumsubclasses(subcls):
+            yield subsubclass
+    yield cls
+
+
+class Interpretable(View):
+    """A parse tree node with a few extra methods."""
+    explanation = None
+
+    def is_builtin(self, frame):
+        return False
+
+    def eval(self, frame):
+        # fall-back for unknown expression nodes
+        try:
+            expr = ast.Expression(self.__obj__)
+            expr.filename = '<eval>'
+            self.__obj__.filename = '<eval>'
+            co = pycodegen.ExpressionCodeGenerator(expr).getCode()
+            result = frame.eval(co)
+        except passthroughex:
+            raise
+        except:
+            raise Failure(self)
+        self.result = result
+        self.explanation = self.explanation or frame.repr(self.result)
+
+    def run(self, frame):
+        # fall-back for unknown statement nodes
+        try:
+            expr = ast.Module(None, ast.Stmt([self.__obj__]))
+            expr.filename = '<run>'
+            co = pycodegen.ModuleCodeGenerator(expr).getCode()
+            frame.exec_(co)
+        except passthroughex:
+            raise
+        except:
+            raise Failure(self)
+
+    def nice_explanation(self):
+        return _format_explanation(self.explanation)
+
+
+class Name(Interpretable):
+    __view__ = ast.Name
+
+    def is_local(self, frame):
+        source = '%r in locals() is not globals()' % self.name
+        try:
+            return frame.is_true(frame.eval(source))
+        except passthroughex:
+            raise
+        except:
+            return False
+
+    def is_global(self, frame):
+        source = '%r in globals()' % self.name
+        try:
+            return frame.is_true(frame.eval(source))
+        except passthroughex:
+            raise
+        except:
+            return False
+
+    def is_builtin(self, frame):
+        source = '%r not in locals() and %r not in globals()' % (
+            self.name, self.name)
+        try:
+            return frame.is_true(frame.eval(source))
+        except passthroughex:
+            raise
+        except:
+            return False
+
+    def eval(self, frame):
+        super(Name, self).eval(frame)
+        if not self.is_local(frame):
+            self.explanation = self.name
+
+class Compare(Interpretable):
+    __view__ = ast.Compare
+
+    def eval(self, frame):
+        expr = Interpretable(self.expr)
+        expr.eval(frame)
+        for operation, expr2 in self.ops:
+            if hasattr(self, 'result'):
+                # shortcutting in chained expressions
+                if not frame.is_true(self.result):
+                    break
+            expr2 = Interpretable(expr2)
+            expr2.eval(frame)
+            self.explanation = "%s %s %s" % (
+                expr.explanation, operation, expr2.explanation)
+            source = "__exprinfo_left %s __exprinfo_right" % operation
+            try:
+                self.result = frame.eval(source,
+                                         __exprinfo_left=expr.result,
+                                         __exprinfo_right=expr2.result)
+            except passthroughex:
+                raise
+            except:
+                raise Failure(self)
+            expr = expr2
+
+class And(Interpretable):
+    __view__ = ast.And
+
+    def eval(self, frame):
+        explanations = []
+        for expr in self.nodes:
+            expr = Interpretable(expr)
+            expr.eval(frame)
+            explanations.append(expr.explanation)
+            self.result = expr.result
+            if not frame.is_true(expr.result):
+                break
+        self.explanation = '(' + ' and '.join(explanations) + ')'
+
+class Or(Interpretable):
+    __view__ = ast.Or
+
+    def eval(self, frame):
+        explanations = []
+        for expr in self.nodes:
+            expr = Interpretable(expr)
+            expr.eval(frame)
+            explanations.append(expr.explanation)
+            self.result = expr.result
+            if frame.is_true(expr.result):
+                break
+        self.explanation = '(' + ' or '.join(explanations) + ')'
+
+
+# == Unary operations ==
+keepalive = []
+for astclass, astpattern in {
+    ast.Not    : 'not __exprinfo_expr',
+    ast.Invert : '(~__exprinfo_expr)',
+    }.items():
+
+    class UnaryArith(Interpretable):
+        __view__ = astclass
+
+        def eval(self, frame, astpattern=astpattern):
+            expr = Interpretable(self.expr)
+            expr.eval(frame)
+            self.explanation = astpattern.replace('__exprinfo_expr',
+                                                  expr.explanation)
+            try:
+                self.result = frame.eval(astpattern,
+                                         __exprinfo_expr=expr.result)
+            except passthroughex:
+                raise
+            except:
+                raise Failure(self)
+
+    keepalive.append(UnaryArith)
+
+# == Binary operations ==
+for astclass, astpattern in {
+    ast.Add    : '(__exprinfo_left + __exprinfo_right)',
+    ast.Sub    : '(__exprinfo_left - __exprinfo_right)',
+    ast.Mul    : '(__exprinfo_left * __exprinfo_right)',
+    ast.Div    : '(__exprinfo_left / __exprinfo_right)',
+    ast.Mod    : '(__exprinfo_left % __exprinfo_right)',
+    ast.Power  : '(__exprinfo_left ** __exprinfo_right)',
+    }.items():
+
+    class BinaryArith(Interpretable):
+        __view__ = astclass
+
+        def eval(self, frame, astpattern=astpattern):
+            left = Interpretable(self.left)
+            left.eval(frame)
+            right = Interpretable(self.right)
+            right.eval(frame)
+            self.explanation = (astpattern
+                                .replace('__exprinfo_left',  left .explanation)
+                                .replace('__exprinfo_right', right.explanation))
+            try:
+                self.result = frame.eval(astpattern,
+                                         __exprinfo_left=left.result,
+                                         __exprinfo_right=right.result)
+            except passthroughex:
+                raise
+            except:
+                raise Failure(self)
+
+    keepalive.append(BinaryArith)
+
+
+class CallFunc(Interpretable):
+    __view__ = ast.CallFunc
+
+    def is_bool(self, frame):
+        source = 'isinstance(__exprinfo_value, bool)'
+        try:
+            return frame.is_true(frame.eval(source,
+                                            __exprinfo_value=self.result))
+        except passthroughex:
+            raise
+        except:
+            return False
+
+    def eval(self, frame):
+        node = Interpretable(self.node)
+        node.eval(frame)
+        explanations = []
+        vars = {'__exprinfo_fn': node.result}
+        source = '__exprinfo_fn('
+        for a in self.args:
+            if isinstance(a, ast.Keyword):
+                keyword = a.name
+                a = a.expr
+            else:
+                keyword = None
+            a = Interpretable(a)
+            a.eval(frame)
+            argname = '__exprinfo_%d' % len(vars)
+            vars[argname] = a.result
+            if keyword is None:
+                source += argname + ','
+                explanations.append(a.explanation)
+            else:
+                source += '%s=%s,' % (keyword, argname)
+                explanations.append('%s=%s' % (keyword, a.explanation))
+        if self.star_args:
+            star_args = Interpretable(self.star_args)
+            star_args.eval(frame)
+            argname = '__exprinfo_star'
+            vars[argname] = star_args.result
+            source += '*' + argname + ','
+            explanations.append('*' + star_args.explanation)
+        if self.dstar_args:
+            dstar_args = Interpretable(self.dstar_args)
+            dstar_args.eval(frame)
+            argname = '__exprinfo_kwds'
+            vars[argname] = dstar_args.result
+            source += '**' + argname + ','
+            explanations.append('**' + dstar_args.explanation)
+        self.explanation = "%s(%s)" % (
+            node.explanation, ', '.join(explanations))
+        if source.endswith(','):
+            source = source[:-1]
+        source += ')'
+        try:
+            self.result = frame.eval(source, **vars)
+        except passthroughex:
+            raise
+        except:
+            raise Failure(self)
+        if not node.is_builtin(frame) or not self.is_bool(frame):
+            r = frame.repr(self.result)
+            self.explanation = '%s\n{%s = %s\n}' % (r, r, self.explanation)
+
+class Getattr(Interpretable):
+    __view__ = ast.Getattr
+
+    def eval(self, frame):
+        expr = Interpretable(self.expr)
+        expr.eval(frame)
+        source = '__exprinfo_expr.%s' % self.attrname
+        try:
+            self.result = frame.eval(source, __exprinfo_expr=expr.result)
+        except passthroughex:
+            raise
+        except:
+            raise Failure(self)
+        self.explanation = '%s.%s' % (expr.explanation, self.attrname)
+        # if the attribute comes from the instance, its value is interesting
+        source = ('hasattr(__exprinfo_expr, "__dict__") and '
+                  '%r in __exprinfo_expr.__dict__' % self.attrname)
+        try:
+            from_instance = frame.is_true(
+                frame.eval(source, __exprinfo_expr=expr.result))
+        except passthroughex:
+            raise
+        except:
+            from_instance = True
+        if from_instance:
+            r = frame.repr(self.result)
+            self.explanation = '%s\n{%s = %s\n}' % (r, r, self.explanation)
+
+# == Re-interpretation of full statements ==
+
+class Assert(Interpretable):
+    __view__ = ast.Assert
+
+    def run(self, frame):
+        test = Interpretable(self.test)
+        test.eval(frame)
+        # simplify 'assert False where False = ...'
+        if (test.explanation.startswith('False\n{False = ') and
+            test.explanation.endswith('\n}')):
+            test.explanation = test.explanation[15:-2]
+        # print the result as  'assert <explanation>'
+        self.result = test.result
+        self.explanation = 'assert ' + test.explanation
+        if not frame.is_true(test.result):
+            try:
+                raise BuiltinAssertionError
+            except passthroughex:
+                raise
+            except:
+                raise Failure(self)
+
+class Assign(Interpretable):
+    __view__ = ast.Assign
+
+    def run(self, frame):
+        expr = Interpretable(self.expr)
+        expr.eval(frame)
+        self.result = expr.result
+        self.explanation = '... = ' + expr.explanation
+        # fall-back-run the rest of the assignment
+        ass = ast.Assign(self.nodes, ast.Name('__exprinfo_expr'))
+        mod = ast.Module(None, ast.Stmt([ass]))
+        mod.filename = '<run>'
+        co = pycodegen.ModuleCodeGenerator(mod).getCode()
+        try:
+            frame.exec_(co, __exprinfo_expr=expr.result)
+        except passthroughex:
+            raise
+        except:
+            raise Failure(self)
+
+class Discard(Interpretable):
+    __view__ = ast.Discard
+
+    def run(self, frame):
+        expr = Interpretable(self.expr)
+        expr.eval(frame)
+        self.result = expr.result
+        self.explanation = expr.explanation
+
+class Stmt(Interpretable):
+    __view__ = ast.Stmt
+
+    def run(self, frame):
+        for stmt in self.nodes:
+            stmt = Interpretable(stmt)
+            stmt.run(frame)
+
+
+def report_failure(e):
+    explanation = e.node.nice_explanation()
+    if explanation:
+        explanation = ", in: " + explanation
+    else:
+        explanation = ""
+    sys.stdout.write("%s: %s%s\n" % (e.exc.__name__, e.value, explanation))
+
+def check(s, frame=None):
+    if frame is None:
+        frame = sys._getframe(1)
+        frame = py.code.Frame(frame)
+    expr = parse(s, 'eval')
+    assert isinstance(expr, ast.Expression)
+    node = Interpretable(expr.node)
+    try:
+        node.eval(frame)
+    except passthroughex:
+        raise
+    except Failure:
+        e = sys.exc_info()[1]
+        report_failure(e)
+    else:
+        if not frame.is_true(node.result):
+            sys.stderr.write("assertion failed: %s\n" % node.nice_explanation())
+
+
+###########################################################
+# API / Entry points
+# #########################################################
+
+def interpret(source, frame, should_fail=False):
+    module = Interpretable(parse(source, 'exec').node)
+    #print "got module", module
+    if isinstance(frame, py.std.types.FrameType):
+        frame = py.code.Frame(frame)
+    try:
+        module.run(frame)
+    except Failure:
+        e = sys.exc_info()[1]
+        return getfailure(e)
+    except passthroughex:
+        raise
+    except:
+        import traceback
+        traceback.print_exc()
+    if should_fail:
+        return ("(assertion failed, but when it was re-run for "
+                "printing intermediate values, it did not fail.  Suggestions: "
+                "compute assert expression before the assert or use --nomagic)")
+    else:
+        return None
+
+def getmsg(excinfo):
+    if isinstance(excinfo, tuple):
+        excinfo = py.code.ExceptionInfo(excinfo)
+    #frame, line = gettbline(tb)
+    #frame = py.code.Frame(frame)
+    #return interpret(line, frame)
+
+    tb = excinfo.traceback[-1]
+    source = str(tb.statement).strip()
+    x = interpret(source, tb.frame, should_fail=True)
+    if not isinstance(x, str):
+        raise TypeError("interpret returned non-string %r" % (x,))
+    return x
+
+def getfailure(e):
+    explanation = e.node.nice_explanation()
+    if str(e.value):
+        lines = explanation.split('\n')
+        lines[0] += "  << %s" % (e.value,)
+        explanation = '\n'.join(lines)
+    text = "%s: %s" % (e.exc.__name__, explanation)
+    if text.startswith('AssertionError: assert '):
+        text = text[16:]
+    return text
+
+def run(s, frame=None):
+    if frame is None:
+        frame = sys._getframe(1)
+        frame = py.code.Frame(frame)
+    module = Interpretable(parse(s, 'exec').node)
+    try:
+        module.run(frame)
+    except Failure:
+        e = sys.exc_info()[1]
+        report_failure(e)
+
+
+if __name__ == '__main__':
+    # example:
+    def f():
+        return 5
+    def g():
+        return 3
+    def h(x):
+        return 'never'
+    check("f() * g() == 5")
+    check("not f()")
+    check("not (f() and g() or 0)")
+    check("f() == g()")
+    i = 4
+    check("i == f()")
+    check("len(f()) == 0")
+    check("isinstance(2+3+4, float)")
+
+    run("x = i")
+    check("x == 5")
+
+    run("assert not f(), 'oops'")
+    run("a, b, c = 1, 2")
+    run("a, b, c = f()")
+
+    check("max([f(),g()]) == 4")
+    check("'hello'[g()] == 'h'")
+    run("'guk%d' % h(f())")
--- a/third_party/python/py/py/_code/_py2traceback.py
+++ b/third_party/python/py/py/_code/_py2traceback.py
@@ -1,79 +1,79 @@
-# copied from python-2.7.3's traceback.py
-# CHANGES:
-# - some_str is replaced, trying to create unicode strings
-#
-import types
-
-def format_exception_only(etype, value):
-    """Format the exception part of a traceback.
-
-    The arguments are the exception type and value such as given by
-    sys.last_type and sys.last_value. The return value is a list of
-    strings, each ending in a newline.
-
-    Normally, the list contains a single string; however, for
-    SyntaxError exceptions, it contains several lines that (when
-    printed) display detailed information about where the syntax
-    error occurred.
-
-    The message indicating which exception occurred is always the last
-    string in the list.
-
-    """
-
-    # An instance should not have a meaningful value parameter, but
-    # sometimes does, particularly for string exceptions, such as
-    # >>> raise string1, string2  # deprecated
-    #
-    # Clear these out first because issubtype(string1, SyntaxError)
-    # would throw another exception and mask the original problem.
-    if (isinstance(etype, BaseException) or
-        isinstance(etype, types.InstanceType) or
-        etype is None or type(etype) is str):
-        return [_format_final_exc_line(etype, value)]
-
-    stype = etype.__name__
-
-    if not issubclass(etype, SyntaxError):
-        return [_format_final_exc_line(stype, value)]
-
-    # It was a syntax error; show exactly where the problem was found.
-    lines = []
-    try:
-        msg, (filename, lineno, offset, badline) = value.args
-    except Exception:
-        pass
-    else:
-        filename = filename or "<string>"
-        lines.append('  File "%s", line %d\n' % (filename, lineno))
-        if badline is not None:
-            lines.append('    %s\n' % badline.strip())
-            if offset is not None:
-                caretspace = badline.rstrip('\n')[:offset].lstrip()
-                # non-space whitespace (likes tabs) must be kept for alignment
-                caretspace = ((c.isspace() and c or ' ') for c in caretspace)
-                # only three spaces to account for offset1 == pos 0
-                lines.append('   %s^\n' % ''.join(caretspace))
-        value = msg
-
-    lines.append(_format_final_exc_line(stype, value))
-    return lines
-
-def _format_final_exc_line(etype, value):
-    """Return a list of a single line -- normal case for format_exception_only"""
-    valuestr = _some_str(value)
-    if value is None or not valuestr:
-        line = "%s\n" % etype
-    else:
-        line = "%s: %s\n" % (etype, valuestr)
-    return line
-
-def _some_str(value):
-    try:
-        return unicode(value)
-    except Exception:
-        try:
-            return str(value)
-        except Exception:
-            pass
-    return '<unprintable %s object>' % type(value).__name__
+# copied from python-2.7.3's traceback.py
+# CHANGES:
+# - some_str is replaced, trying to create unicode strings
+#
+import types
+
+def format_exception_only(etype, value):
+    """Format the exception part of a traceback.
+
+    The arguments are the exception type and value such as given by
+    sys.last_type and sys.last_value. The return value is a list of
+    strings, each ending in a newline.
+
+    Normally, the list contains a single string; however, for
+    SyntaxError exceptions, it contains several lines that (when
+    printed) display detailed information about where the syntax
+    error occurred.
+
+    The message indicating which exception occurred is always the last
+    string in the list.
+
+    """
+
+    # An instance should not have a meaningful value parameter, but
+    # sometimes does, particularly for string exceptions, such as
+    # >>> raise string1, string2  # deprecated
+    #
+    # Clear these out first because issubtype(string1, SyntaxError)
+    # would throw another exception and mask the original problem.
+    if (isinstance(etype, BaseException) or
+        isinstance(etype, types.InstanceType) or
+        etype is None or type(etype) is str):
+        return [_format_final_exc_line(etype, value)]
+
+    stype = etype.__name__
+
+    if not issubclass(etype, SyntaxError):
+        return [_format_final_exc_line(stype, value)]
+
+    # It was a syntax error; show exactly where the problem was found.
+    lines = []
+    try:
+        msg, (filename, lineno, offset, badline) = value.args
+    except Exception:
+        pass
+    else:
+        filename = filename or "<string>"
+        lines.append('  File "%s", line %d\n' % (filename, lineno))
+        if badline is not None:
+            lines.append('    %s\n' % badline.strip())
+            if offset is not None:
+                caretspace = badline.rstrip('\n')[:offset].lstrip()
+                # non-space whitespace (likes tabs) must be kept for alignment
+                caretspace = ((c.isspace() and c or ' ') for c in caretspace)
+                # only three spaces to account for offset1 == pos 0
+                lines.append('   %s^\n' % ''.join(caretspace))
+        value = msg
+
+    lines.append(_format_final_exc_line(stype, value))
+    return lines
+
+def _format_final_exc_line(etype, value):
+    """Return a list of a single line -- normal case for format_exception_only"""
+    valuestr = _some_str(value)
+    if value is None or not valuestr:
+        line = "%s\n" % etype
+    else:
+        line = "%s: %s\n" % (etype, valuestr)
+    return line
+
+def _some_str(value):
+    try:
+        return unicode(value)
+    except Exception:
+        try:
+            return str(value)
+        except Exception:
+            pass
+    return '<unprintable %s object>' % type(value).__name__
--- a/third_party/python/py/py/_code/assertion.py
+++ b/third_party/python/py/py/_code/assertion.py
@@ -1,94 +1,94 @@
-import sys
-import py
-
-BuiltinAssertionError = py.builtin.builtins.AssertionError
-
-_reprcompare = None # if set, will be called by assert reinterp for comparison ops
-
-def _format_explanation(explanation):
-    """This formats an explanation
-
-    Normally all embedded newlines are escaped, however there are
-    three exceptions: \n{, \n} and \n~.  The first two are intended
-    cover nested explanations, see function and attribute explanations
-    for examples (.visit_Call(), visit_Attribute()).  The last one is
-    for when one explanation needs to span multiple lines, e.g. when
-    displaying diffs.
-    """
-    raw_lines = (explanation or '').split('\n')
-    # escape newlines not followed by {, } and ~
-    lines = [raw_lines[0]]
-    for l in raw_lines[1:]:
-        if l.startswith('{') or l.startswith('}') or l.startswith('~'):
-            lines.append(l)
-        else:
-            lines[-1] += '\\n' + l
-
-    result = lines[:1]
-    stack = [0]
-    stackcnt = [0]
-    for line in lines[1:]:
-        if line.startswith('{'):
-            if stackcnt[-1]:
-                s = 'and   '
-            else:
-                s = 'where '
-            stack.append(len(result))
-            stackcnt[-1] += 1
-            stackcnt.append(0)
-            result.append(' +' + '  '*(len(stack)-1) + s + line[1:])
-        elif line.startswith('}'):
-            assert line.startswith('}')
-            stack.pop()
-            stackcnt.pop()
-            result[stack[-1]] += line[1:]
-        else:
-            assert line.startswith('~')
-            result.append('  '*len(stack) + line[1:])
-    assert len(stack) == 1
-    return '\n'.join(result)
-
-
-class AssertionError(BuiltinAssertionError):
-    def __init__(self, *args):
-        BuiltinAssertionError.__init__(self, *args)
-        if args:
-            try:
-                self.msg = str(args[0])
-            except py.builtin._sysex:
-                raise
-            except:
-                self.msg = "<[broken __repr__] %s at %0xd>" %(
-                    args[0].__class__, id(args[0]))
-        else:
-            f = py.code.Frame(sys._getframe(1))
-            try:
-                source = f.code.fullsource
-                if source is not None:
-                    try:
-                        source = source.getstatement(f.lineno, assertion=True)
-                    except IndexError:
-                        source = None
-                    else:
-                        source = str(source.deindent()).strip()
-            except py.error.ENOENT:
-                source = None
-                # this can also occur during reinterpretation, when the
-                # co_filename is set to "<run>".
-            if source:
-                self.msg = reinterpret(source, f, should_fail=True)
-            else:
-                self.msg = "<could not determine information>"
-            if not self.args:
-                self.args = (self.msg,)
-
-if sys.version_info > (3, 0):
-    AssertionError.__module__ = "builtins"
-    reinterpret_old = "old reinterpretation not available for py3"
-else:
-    from py._code._assertionold import interpret as reinterpret_old
-if sys.version_info >= (2, 6) or (sys.platform.startswith("java")):
-    from py._code._assertionnew import interpret as reinterpret
-else:
-    reinterpret = reinterpret_old
-
+import sys
+import py
+
+BuiltinAssertionError = py.builtin.builtins.AssertionError
+
+_reprcompare = None # if set, will be called by assert reinterp for comparison ops
+
+def _format_explanation(explanation):
+    """This formats an explanation
+
+    Normally all embedded newlines are escaped, however there are
+    three exceptions: \n{, \n} and \n~.  The first two are intended
+    cover nested explanations, see function and attribute explanations
+    for examples (.visit_Call(), visit_Attribute()).  The last one is
+    for when one explanation needs to span multiple lines, e.g. when
+    displaying diffs.
+    """
+    raw_lines = (explanation or '').split('\n')
+    # escape newlines not followed by {, } and ~
+    lines = [raw_lines[0]]
+    for l in raw_lines[1:]:
+        if l.startswith('{') or l.startswith('}') or l.startswith('~'):
+            lines.append(l)
+        else:
+            lines[-1] += '\\n' + l
+
+    result = lines[:1]
+    stack = [0]
+    stackcnt = [0]
+    for line in lines[1:]:
+        if line.startswith('{'):
+            if stackcnt[-1]:
+                s = 'and   '
+            else:
+                s = 'where '
+            stack.append(len(result))
+            stackcnt[-1] += 1
+            stackcnt.append(0)
+            result.append(' +' + '  '*(len(stack)-1) + s + line[1:])
+        elif line.startswith('}'):
+            assert line.startswith('}')
+            stack.pop()
+            stackcnt.pop()
+            result[stack[-1]] += line[1:]
+        else:
+            assert line.startswith('~')
+            result.append('  '*len(stack) + line[1:])
+    assert len(stack) == 1
+    return '\n'.join(result)
+
+
+class AssertionError(BuiltinAssertionError):
+    def __init__(self, *args):
+        BuiltinAssertionError.__init__(self, *args)
+        if args:
+            try:
+                self.msg = str(args[0])
+            except py.builtin._sysex:
+                raise
+            except:
+                self.msg = "<[broken __repr__] %s at %0xd>" %(
+                    args[0].__class__, id(args[0]))
+        else:
+            f = py.code.Frame(sys._getframe(1))
+            try:
+                source = f.code.fullsource
+                if source is not None:
+                    try:
+                        source = source.getstatement(f.lineno, assertion=True)
+                    except IndexError:
+                        source = None
+                    else:
+                        source = str(source.deindent()).strip()
+            except py.error.ENOENT:
+                source = None
+                # this can also occur during reinterpretation, when the
+                # co_filename is set to "<run>".
+            if source:
+                self.msg = reinterpret(source, f, should_fail=True)
+            else:
+                self.msg = "<could not determine information>"
+            if not self.args:
+                self.args = (self.msg,)
+
+if sys.version_info > (3, 0):
+    AssertionError.__module__ = "builtins"
+    reinterpret_old = "old reinterpretation not available for py3"
+else:
+    from py._code._assertionold import interpret as reinterpret_old
+if sys.version_info >= (2, 6) or (sys.platform.startswith("java")):
+    from py._code._assertionnew import interpret as reinterpret
+else:
+    reinterpret = reinterpret_old
+
--- a/third_party/python/py/py/_code/code.py
+++ b/third_party/python/py/py/_code/code.py
@@ -1,787 +1,787 @@
-import py
-import sys
-from inspect import CO_VARARGS, CO_VARKEYWORDS
-
-builtin_repr = repr
-
-reprlib = py.builtin._tryimport('repr', 'reprlib')
-
-if sys.version_info[0] >= 3:
-    from traceback import format_exception_only
-else:
-    from py._code._py2traceback import format_exception_only
-
-class Code(object):
-    """ wrapper around Python code objects """
-    def __init__(self, rawcode):
-        if not hasattr(rawcode, "co_filename"):
-            rawcode = py.code.getrawcode(rawcode)
-        try:
-            self.filename = rawcode.co_filename
-            self.firstlineno = rawcode.co_firstlineno - 1
-            self.name = rawcode.co_name
-        except AttributeError:
-            raise TypeError("not a code object: %r" %(rawcode,))
-        self.raw = rawcode
-
-    def __eq__(self, other):
-        return self.raw == other.raw
-
-    def __ne__(self, other):
-        return not self == other
-
-    @property
-    def path(self):
-        """ return a path object pointing to source code (note that it
-        might not point to an actually existing file). """
-        p = py.path.local(self.raw.co_filename)
-        # maybe don't try this checking
-        if not p.check():
-            # XXX maybe try harder like the weird logic
-            # in the standard lib [linecache.updatecache] does?
-            p = self.raw.co_filename
-        return p
-
-    @property
-    def fullsource(self):
-        """ return a py.code.Source object for the full source file of the code
-        """
-        from py._code import source
-        full, _ = source.findsource(self.raw)
-        return full
-
-    def source(self):
-        """ return a py.code.Source object for the code object's source only
-        """
-        # return source only for that part of code
-        return py.code.Source(self.raw)
-
-    def getargs(self, var=False):
-        """ return a tuple with the argument names for the code object
-
-            if 'var' is set True also return the names of the variable and
-            keyword arguments when present
-        """
-        # handfull shortcut for getting args
-        raw = self.raw
-        argcount = raw.co_argcount
-        if var:
-            argcount += raw.co_flags & CO_VARARGS
-            argcount += raw.co_flags & CO_VARKEYWORDS
-        return raw.co_varnames[:argcount]
-
-class Frame(object):
-    """Wrapper around a Python frame holding f_locals and f_globals
-    in which expressions can be evaluated."""
-
-    def __init__(self, frame):
-        self.lineno = frame.f_lineno - 1
-        self.f_globals = frame.f_globals
-        self.f_locals = frame.f_locals
-        self.raw = frame
-        self.code = py.code.Code(frame.f_code)
-
-    @property
-    def statement(self):
-        """ statement this frame is at """
-        if self.code.fullsource is None:
-            return py.code.Source("")
-        return self.code.fullsource.getstatement(self.lineno)
-
-    def eval(self, code, **vars):
-        """ evaluate 'code' in the frame
-
-            'vars' are optional additional local variables
-
-            returns the result of the evaluation
-        """
-        f_locals = self.f_locals.copy()
-        f_locals.update(vars)
-        return eval(code, self.f_globals, f_locals)
-
-    def exec_(self, code, **vars):
-        """ exec 'code' in the frame
-
-            'vars' are optiona; additional local variables
-        """
-        f_locals = self.f_locals.copy()
-        f_locals.update(vars)
-        py.builtin.exec_(code, self.f_globals, f_locals )
-
-    def repr(self, object):
-        """ return a 'safe' (non-recursive, one-line) string repr for 'object'
-        """
-        return py.io.saferepr(object)
-
-    def is_true(self, object):
-        return object
-
-    def getargs(self, var=False):
-        """ return a list of tuples (name, value) for all arguments
-
-            if 'var' is set True also include the variable and keyword
-            arguments when present
-        """
-        retval = []
-        for arg in self.code.getargs(var):
-            try:
-                retval.append((arg, self.f_locals[arg]))
-            except KeyError:
-                pass     # this can occur when using Psyco
-        return retval
-
-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)
-
-    @property
-    def relline(self):
-        return self.lineno - self.frame.code.firstlineno
-
-    def __repr__(self):
-        return "<TracebackEntry %s:%d>" %(self.frame.code.path, self.lineno+1)
-
-    @property
-    def statement(self):
-        """ py.code.Source object for the current statement """
-        source = self.frame.code.fullsource
-        return source.getstatement(self.lineno)
-
-    @property
-    def path(self):
-        """ path to the source code """
-        return self.frame.code.path
-
-    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."""
-        if self.exprinfo is None:
-            source = str(self.statement).strip()
-            x = py.code._reinterpret(source, self.frame, should_fail=True)
-            if not isinstance(x, str):
-                raise TypeError("interpret returned non-string %r" % (x,))
-            self.exprinfo = x
-        return self.exprinfo
-
-    def getfirstlinesource(self):
-        # on Jython this firstlineno can be -1 apparently
-        return max(self.frame.code.firstlineno, 0)
-
-    def getsource(self, astcache=None):
-        """ return failing source code. """
-        # we use the passed in astcache to not reparse asttrees
-        # within exception info printing
-        from py._code.source import getstatementrange_ast
-        source = self.frame.code.fullsource
-        if source is None:
-            return None
-        key = astnode = None
-        if astcache is not None:
-            key = self.frame.code.path
-            if key is not None:
-                astnode = astcache.get(key, None)
-        start = self.getfirstlinesource()
-        try:
-            astnode, _, end = getstatementrange_ast(self.lineno, source,
-                                                    astnode=astnode)
-        except SyntaxError:
-            end = self.lineno + 1
-        else:
-            if key is not None:
-                astcache[key] = astnode
-        return source[start:end]
-
-    source = property(getsource)
-
-    def ishidden(self):
-        """ return True if the current frame has a var __tracebackhide__
-            resolving to True
-
-            mostly for internal use
-        """
-        try:
-            return self.frame.f_locals['__tracebackhide__']
-        except KeyError:
-            try:
-                return self.frame.f_globals['__tracebackhide__']
-            except KeyError:
-                return False
-
-    def __str__(self):
-        try:
-            fn = str(self.path)
-        except py.error.Error:
-            fn = '???'
-        name = self.frame.code.name
-        try:
-            line = str(self.statement).lstrip()
-        except KeyboardInterrupt:
-            raise
-        except:
-            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.
-    """
-    Entry = TracebackEntry
-    def __init__(self, tb):
-        """ initialize from given python traceback object. """
-        if hasattr(tb, 'tb_next'):
-            def f(cur):
-                while cur is not None:
-                    yield self.Entry(cur)
-                    cur = cur.tb_next
-            list.__init__(self, f(tb))
-        else:
-            list.__init__(self, tb)
-
-    def cut(self, path=None, lineno=None, firstlineno=None, excludepath=None):
-        """ return a Traceback instance wrapping part of this Traceback
-
-            by provding any combination of path, lineno and firstlineno, the
-            first frame to start the to-be-returned traceback is determined
-
-            this allows cutting the first part of a Traceback instance e.g.
-            for formatting reasons (removing some uninteresting bits that deal
-            with handling of the exception/traceback)
-        """
-        for x in self:
-            code = x.frame.code
-            codepath = code.path
-            if ((path is None or codepath == path) and
-                (excludepath is None or not hasattr(codepath, 'relto') or
-                 not codepath.relto(excludepath)) and
-                (lineno is None or x.lineno == lineno) and
-                (firstlineno is None or x.frame.code.firstlineno == firstlineno)):
-                return Traceback(x._rawentry)
-        return self
-
-    def __getitem__(self, key):
-        val = super(Traceback, self).__getitem__(key)
-        if isinstance(key, type(slice(0))):
-            val = self.__class__(val)
-        return val
-
-    def filter(self, fn=lambda x: not x.ishidden()):
-        """ return a Traceback instance with certain items removed
-
-            fn is a function that gets a single argument, a TracebackItem
-            instance, and should return True when the item should be added
-            to the Traceback, False when not
-
-            by default this removes all the TracebackItems which are hidden
-            (see ishidden() above)
-        """
-        return Traceback(filter(fn, self))
-
-    def getcrashentry(self):
-        """ return last non-hidden traceback entry that lead
-        to the exception of a traceback.
-        """
-        for i in range(-1, -len(self)-1, -1):
-            entry = self[i]
-            if not entry.ishidden():
-                return entry
-        return self[-1]
-
-    def recursionindex(self):
-        """ return the index of the frame/TracebackItem where recursion
-            originates if appropriate, None if no recursion occurred
-        """
-        cache = {}
-        for i, entry in enumerate(self):
-            # id for the code.raw is needed to work around
-            # the strange metaprogramming in the decorator lib from pypi
-            # which generates code objects that have hash/value equality
-            #XXX needs a test
-            key = entry.frame.code.path, id(entry.frame.code.raw), entry.lineno
-            #print "checking for recursion at", key
-            l = cache.setdefault(key, [])
-            if l:
-                f = entry.frame
-                loc = f.f_locals
-                for otherloc in l:
-                    if f.is_true(f.eval(co_equal,
-                        __recursioncache_locals_1=loc,
-                        __recursioncache_locals_2=otherloc)):
-                        return i
-            l.append(entry.frame.f_locals)
-        return None
-
-co_equal = compile('__recursioncache_locals_1 == __recursioncache_locals_2',
-                   '?', 'eval')
-
-class ExceptionInfo(object):
-    """ wraps sys.exc_info() objects and offers
-        help for navigating the traceback.
-    """
-    _striptext = ''
-    def __init__(self, tup=None, exprinfo=None):
-        if tup is None:
-            tup = sys.exc_info()
-            if exprinfo is None and isinstance(tup[1], AssertionError):
-                exprinfo = getattr(tup[1], 'msg', None)
-                if exprinfo is None:
-                    exprinfo = str(tup[1])
-                if exprinfo and exprinfo.startswith('assert '):
-                    self._striptext = 'AssertionError: '
-        self._excinfo = tup
-        #: the exception class
-        self.type = tup[0]
-        #: the exception instance
-        self.value = tup[1]
-        #: the exception raw traceback
-        self.tb = tup[2]
-        #: the exception type name
-        self.typename = self.type.__name__
-        #: the exception traceback (py.code.Traceback instance)
-        self.traceback = py.code.Traceback(self.tb)
-
-    def __repr__(self):
-        return "<ExceptionInfo %s tblen=%d>" % (self.typename, len(self.traceback))
-
-    def exconly(self, tryshort=False):
-        """ return the exception as a string
-
-            when 'tryshort' resolves to True, and the exception is a
-            py.code._AssertionError, only the actual exception part of
-            the exception representation is returned (so 'AssertionError: ' is
-            removed from the beginning)
-        """
-        lines = format_exception_only(self.type, self.value)
-        text = ''.join(lines)
-        text = text.rstrip()
-        if tryshort:
-            if text.startswith(self._striptext):
-                text = text[len(self._striptext):]
-        return text
-
-    def errisinstance(self, exc):
-        """ return True if the exception is an instance of exc """
-        return isinstance(self.value, exc)
-
-    def _getreprcrash(self):
-        exconly = self.exconly(tryshort=True)
-        entry = self.traceback.getcrashentry()
-        path, lineno = entry.frame.code.raw.co_filename, entry.lineno
-        return ReprFileLocation(path, lineno+1, exconly)
-
-    def getrepr(self, showlocals=False, style="long",
-            abspath=False, tbfilter=True, funcargs=False):
-        """ return str()able representation of this exception info.
-            showlocals: show locals per traceback entry
-            style: long|short|no|native traceback style
-            tbfilter: hide entries (where __tracebackhide__ is true)
-
-            in case of style==native, tbfilter and showlocals is ignored.
-        """
-        if style == 'native':
-            return ReprExceptionInfo(ReprTracebackNative(
-                py.std.traceback.format_exception(
-                    self.type,
-                    self.value,
-                    self.traceback[0]._rawentry,
-                )), self._getreprcrash())
-
-        fmt = FormattedExcinfo(showlocals=showlocals, style=style,
-            abspath=abspath, tbfilter=tbfilter, funcargs=funcargs)
-        return fmt.repr_excinfo(self)
-
-    def __str__(self):
-        entry = self.traceback[-1]
-        loc = ReprFileLocation(entry.path, entry.lineno + 1, self.exconly())
-        return str(loc)
-
-    def __unicode__(self):
-        entry = self.traceback[-1]
-        loc = ReprFileLocation(entry.path, entry.lineno + 1, self.exconly())
-        return unicode(loc)
-
-
-class FormattedExcinfo(object):
-    """ presenting information about failing Functions and Generators. """
-    # for traceback entries
-    flow_marker = ">"
-    fail_marker = "E"
-
-    def __init__(self, showlocals=False, style="long", abspath=True, tbfilter=True, funcargs=False):
-        self.showlocals = showlocals
-        self.style = style
-        self.tbfilter = tbfilter
-        self.funcargs = funcargs
-        self.abspath = abspath
-        self.astcache = {}
-
-    def _getindent(self, source):
-        # figure out indent for given source
-        try:
-            s = str(source.getstatement(len(source)-1))
-        except KeyboardInterrupt:
-            raise
-        except:
-            try:
-                s = str(source[-1])
-            except KeyboardInterrupt:
-                raise
-            except:
-                return 0
-        return 4 + (len(s) - len(s.lstrip()))
-
-    def _getentrysource(self, entry):
-        source = entry.getsource(self.astcache)
-        if source is not None:
-            source = source.deindent()
-        return source
-
-    def _saferepr(self, obj):
-        return py.io.saferepr(obj)
-
-    def repr_args(self, entry):
-        if self.funcargs:
-            args = []
-            for argname, argvalue in entry.frame.getargs(var=True):
-                args.append((argname, self._saferepr(argvalue)))
-            return ReprFuncArgs(args)
-
-    def get_source(self, source, line_index=-1, excinfo=None, short=False):
-        """ return formatted and marked up source lines. """
-        lines = []
-        if source is None or line_index >= len(source.lines):
-            source = py.code.Source("???")
-            line_index = 0
-        if line_index < 0:
-            line_index += len(source)
-        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 = 4 if short else self._getindent(source)
-            lines.extend(self.get_exconly(excinfo, indent=indent, markall=True))
-        return lines
-
-    def get_exconly(self, excinfo, indent=4, markall=False):
-        lines = []
-        indent = " " * indent
-        # get the real exception information out
-        exlines = excinfo.exconly(tryshort=True).split('\n')
-        failindent = self.fail_marker + indent[1:]
-        for line in exlines:
-            lines.append(failindent + line)
-            if not markall:
-                failindent = indent
-        return lines
-
-    def repr_locals(self, locals):
-        if self.showlocals:
-            lines = []
-            keys = [loc for loc in locals if loc[0] != "@"]
-            keys.sort()
-            for name in keys:
-                value = locals[name]
-                if name == '__builtins__':
-                    lines.append("__builtins__ = <builtins>")
-                else:
-                    # This formatting could all be handled by the
-                    # _repr() function, which is only reprlib.Repr in
-                    # disguise, so is very configurable.
-                    str_repr = self._saferepr(value)
-                    #if len(str_repr) < 70 or not isinstance(value,
-                    #                            (list, tuple, dict)):
-                    lines.append("%-10s = %s" %(name, str_repr))
-                    #else:
-                    #    self._line("%-10s =\\" % (name,))
-                    #    # XXX
-                    #    py.std.pprint.pprint(value, stream=self.excinfowriter)
-            return ReprLocals(lines)
-
-    def repr_traceback_entry(self, entry, excinfo=None):
-        source = self._getentrysource(entry)
-        if source is None:
-            source = py.code.Source("???")
-            line_index = 0
-        else:
-            # entry.getfirstlinesource() can be -1, should be 0 on jython
-            line_index = entry.lineno - max(entry.getfirstlinesource(), 0)
-
-        lines = []
-        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:
-                message = "in %s" %(entry.name)
-            else:
-                message = excinfo and excinfo.typename or ""
-            path = self._makepath(entry.path)
-            filelocrepr = ReprFileLocation(path, entry.lineno+1, message)
-            localsrepr = None
-            if not short:
-                localsrepr =  self.repr_locals(entry.locals)
-            return ReprEntry(lines, reprargs, localsrepr, filelocrepr, style)
-        if excinfo:
-            lines.extend(self.get_exconly(excinfo, indent=4))
-        return ReprEntry(lines, None, None, None, style)
-
-    def _makepath(self, path):
-        if not self.abspath:
-            try:
-                np = py.path.local().bestrelpath(path)
-            except OSError:
-                return path
-            if len(np) < len(str(path)):
-                path = np
-        return path
-
-    def repr_traceback(self, excinfo):
-        traceback = excinfo.traceback
-        if self.tbfilter:
-            traceback = traceback.filter()
-        recursionindex = None
-        if excinfo.errisinstance(RuntimeError):
-            if "maximum recursion depth exceeded" in str(excinfo.value):
-                recursionindex = traceback.recursionindex()
-        last = traceback[-1]
-        entries = []
-        extraline = None
-        for index, entry in enumerate(traceback):
-            einfo = (last == entry) and excinfo or None
-            reprentry = self.repr_traceback_entry(entry, einfo)
-            entries.append(reprentry)
-            if index == recursionindex:
-                extraline = "!!! Recursion detected (same locals & position)"
-                break
-        return ReprTraceback(entries, extraline, style=self.style)
-
-    def repr_excinfo(self, excinfo):
-        reprtraceback = self.repr_traceback(excinfo)
-        reprcrash = excinfo._getreprcrash()
-        return ReprExceptionInfo(reprtraceback, reprcrash)
-
-class TerminalRepr:
-    def __str__(self):
-        s = self.__unicode__()
-        if sys.version_info[0] < 3:
-            s = s.encode('utf-8')
-        return s
-
-    def __unicode__(self):
-        # FYI this is called from pytest-xdist's serialization of exception
-        # information.
-        io = py.io.TextIO()
-        tw = py.io.TerminalWriter(file=io)
-        self.toterminal(tw)
-        return io.getvalue().strip()
-
-    def __repr__(self):
-        return "<%s instance at %0x>" %(self.__class__, id(self))
-
-
-class ReprExceptionInfo(TerminalRepr):
-    def __init__(self, reprtraceback, reprcrash):
-        self.reprtraceback = reprtraceback
-        self.reprcrash = reprcrash
-        self.sections = []
-
-    def addsection(self, name, content, sep="-"):
-        self.sections.append((name, content, sep))
-
-    def toterminal(self, tw):
-        self.reprtraceback.toterminal(tw)
-        for name, content, sep in self.sections:
-            tw.sep(sep, name)
-            tw.line(content)
-
-class ReprTraceback(TerminalRepr):
-    entrysep = "_ "
-
-    def __init__(self, reprentries, extraline, style):
-        self.reprentries = reprentries
-        self.extraline = extraline
-        self.style = style
-
-    def toterminal(self, tw):
-        # the entries might have different styles
-        last_style = None
-        for i, entry in enumerate(self.reprentries):
-            if entry.style == "long":
-                tw.line("")
-            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)
-
-class ReprTracebackNative(ReprTraceback):
-    def __init__(self, tblines):
-        self.style = "native"
-        self.reprentries = [ReprEntryNative(tblines)]
-        self.extraline = None
-
-class ReprEntryNative(TerminalRepr):
-    style = "native"
-
-    def __init__(self, tblines):
-        self.lines = tblines
-
-    def toterminal(self, tw):
-        tw.write("".join(self.lines))
-
-class ReprEntry(TerminalRepr):
-    localssep = "_ "
-
-    def __init__(self, lines, reprfuncargs, reprlocals, filelocrepr, style):
-        self.lines = lines
-        self.reprfuncargs = reprfuncargs
-        self.reprlocals = reprlocals
-        self.reprfileloc = filelocrepr
-        self.style = style
-
-    def toterminal(self, tw):
-        if self.style == "short":
-            self.reprfileloc.toterminal(tw)
-            for line in self.lines:
-                red = line.startswith("E   ")
-                tw.line(line, bold=True, red=red)
-            #tw.line("")
-            return
-        if self.reprfuncargs:
-            self.reprfuncargs.toterminal(tw)
-        for line in self.lines:
-            red = line.startswith("E   ")
-            tw.line(line, bold=True, red=red)
-        if self.reprlocals:
-            #tw.sep(self.localssep, "Locals")
-            tw.line("")
-            self.reprlocals.toterminal(tw)
-        if self.reprfileloc:
-            if self.lines:
-                tw.line("")
-            self.reprfileloc.toterminal(tw)
-
-    def __str__(self):
-        return "%s\n%s\n%s" % ("\n".join(self.lines),
-                               self.reprlocals,
-                               self.reprfileloc)
-
-class ReprFileLocation(TerminalRepr):
-    def __init__(self, path, lineno, message):
-        self.path = str(path)
-        self.lineno = lineno
-        self.message = message
-
-    def toterminal(self, tw):
-        # filename and lineno output for each entry,
-        # using an output format that most editors unterstand
-        msg = self.message
-        i = msg.find("\n")
-        if i != -1:
-            msg = msg[:i]
-        tw.line("%s:%s: %s" %(self.path, self.lineno, msg))
-
-class ReprLocals(TerminalRepr):
-    def __init__(self, lines):
-        self.lines = lines
-
-    def toterminal(self, tw):
-        for line in self.lines:
-            tw.line(line)
-
-class ReprFuncArgs(TerminalRepr):
-    def __init__(self, args):
-        self.args = args
-
-    def toterminal(self, tw):
-        if self.args:
-            linesofar = ""
-            for name, value in self.args:
-                ns = "%s = %s" %(name, value)
-                if len(ns) + len(linesofar) + 2 > tw.fullwidth:
-                    if linesofar:
-                        tw.line(linesofar)
-                    linesofar =  ns
-                else:
-                    if linesofar:
-                        linesofar += ", " + ns
-                    else:
-                        linesofar = ns
-            if linesofar:
-                tw.line(linesofar)
-            tw.line("")
-
-
-
-oldbuiltins = {}
-
-def patch_builtins(assertion=True, compile=True):
-    """ put compile and AssertionError builtins to Python's builtins. """
-    if assertion:
-        from py._code import assertion
-        l = oldbuiltins.setdefault('AssertionError', [])
-        l.append(py.builtin.builtins.AssertionError)
-        py.builtin.builtins.AssertionError = assertion.AssertionError
-    if compile:
-        l = oldbuiltins.setdefault('compile', [])
-        l.append(py.builtin.builtins.compile)
-        py.builtin.builtins.compile = py.code.compile
-
-def unpatch_builtins(assertion=True, compile=True):
-    """ remove compile and AssertionError builtins from Python builtins. """
-    if assertion:
-        py.builtin.builtins.AssertionError = oldbuiltins['AssertionError'].pop()
-    if compile:
-        py.builtin.builtins.compile = oldbuiltins['compile'].pop()
-
-def getrawcode(obj, trycall=True):
-    """ return code object for given function. """
-    try:
-        return obj.__code__
-    except AttributeError:
-        obj = getattr(obj, 'im_func', obj)
-        obj = getattr(obj, 'func_code', obj)
-        obj = getattr(obj, 'f_code', obj)
-        obj = getattr(obj, '__code__', obj)
-        if trycall and not hasattr(obj, 'co_firstlineno'):
-            if hasattr(obj, '__call__') and not py.std.inspect.isclass(obj):
-                x = getrawcode(obj.__call__, trycall=False)
-                if hasattr(x, 'co_firstlineno'):
-                    return x
-        return obj
-
+import py
+import sys
+from inspect import CO_VARARGS, CO_VARKEYWORDS
+
+builtin_repr = repr
+
+reprlib = py.builtin._tryimport('repr', 'reprlib')
+
+if sys.version_info[0] >= 3:
+    from traceback import format_exception_only
+else:
+    from py._code._py2traceback import format_exception_only
+
+class Code(object):
+    """ wrapper around Python code objects """
+    def __init__(self, rawcode):
+        if not hasattr(rawcode, "co_filename"):
+            rawcode = py.code.getrawcode(rawcode)
+        try:
+            self.filename = rawcode.co_filename
+            self.firstlineno = rawcode.co_firstlineno - 1
+            self.name = rawcode.co_name
+        except AttributeError:
+            raise TypeError("not a code object: %r" %(rawcode,))
+        self.raw = rawcode
+
+    def __eq__(self, other):
+        return self.raw == other.raw
+
+    def __ne__(self, other):
+        return not self == other
+
+    @property
+    def path(self):
+        """ return a path object pointing to source code (note that it
+        might not point to an actually existing file). """
+        p = py.path.local(self.raw.co_filename)
+        # maybe don't try this checking
+        if not p.check():
+            # XXX maybe try harder like the weird logic
+            # in the standard lib [linecache.updatecache] does?
+            p = self.raw.co_filename
+        return p
+
+    @property
+    def fullsource(self):
+        """ return a py.code.Source object for the full source file of the code
+        """
+        from py._code import source
+        full, _ = source.findsource(self.raw)
+        return full
+
+    def source(self):
+        """ return a py.code.Source object for the code object's source only
+        """
+        # return source only for that part of code
+        return py.code.Source(self.raw)
+
+    def getargs(self, var=False):
+        """ return a tuple with the argument names for the code object
+
+            if 'var' is set True also return the names of the variable and
+            keyword arguments when present
+        """
+        # handfull shortcut for getting args
+        raw = self.raw
+        argcount = raw.co_argcount
+        if var:
+            argcount += raw.co_flags & CO_VARARGS
+            argcount += raw.co_flags & CO_VARKEYWORDS
+        return raw.co_varnames[:argcount]
+
+class Frame(object):
+    """Wrapper around a Python frame holding f_locals and f_globals
+    in which expressions can be evaluated."""
+
+    def __init__(self, frame):
+        self.lineno = frame.f_lineno - 1
+        self.f_globals = frame.f_globals
+        self.f_locals = frame.f_locals
+        self.raw = frame
+        self.code = py.code.Code(frame.f_code)
+
+    @property
+    def statement(self):
+        """ statement this frame is at """
+        if self.code.fullsource is None:
+            return py.code.Source("")
+        return self.code.fullsource.getstatement(self.lineno)
+
+    def eval(self, code, **vars):
+        """ evaluate 'code' in the frame
+
+            'vars' are optional additional local variables
+
+            returns the result of the evaluation
+        """
+        f_locals = self.f_locals.copy()
+        f_locals.update(vars)
+        return eval(code, self.f_globals, f_locals)
+
+    def exec_(self, code, **vars):
+        """ exec 'code' in the frame
+
+            'vars' are optiona; additional local variables
+        """
+        f_locals = self.f_locals.copy()
+        f_locals.update(vars)
+        py.builtin.exec_(code, self.f_globals, f_locals )
+
+    def repr(self, object):
+        """ return a 'safe' (non-recursive, one-line) string repr for 'object'
+        """
+        return py.io.saferepr(object)
+
+    def is_true(self, object):
+        return object
+
+    def getargs(self, var=False):
+        """ return a list of tuples (name, value) for all arguments
+
+            if 'var' is set True also include the variable and keyword
+            arguments when present
+        """
+        retval = []
+        for arg in self.code.getargs(var):
+            try:
+                retval.append((arg, self.f_locals[arg]))
+            except KeyError:
+                pass     # this can occur when using Psyco
+        return retval
+
+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)
+
+    @property
+    def relline(self):
+        return self.lineno - self.frame.code.firstlineno
+
+    def __repr__(self):
+        return "<TracebackEntry %s:%d>" %(self.frame.code.path, self.lineno+1)
+
+    @property
+    def statement(self):
+        """ py.code.Source object for the current statement """
+        source = self.frame.code.fullsource
+        return source.getstatement(self.lineno)
+
+    @property
+    def path(self):
+        """ path to the source code """
+        return self.frame.code.path
+
+    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."""
+        if self.exprinfo is None:
+            source = str(self.statement).strip()
+            x = py.code._reinterpret(source, self.frame, should_fail=True)
+            if not isinstance(x, str):
+                raise TypeError("interpret returned non-string %r" % (x,))
+            self.exprinfo = x
+        return self.exprinfo
+
+    def getfirstlinesource(self):
+        # on Jython this firstlineno can be -1 apparently
+        return max(self.frame.code.firstlineno, 0)
+
+    def getsource(self, astcache=None):
+        """ return failing source code. """
+        # we use the passed in astcache to not reparse asttrees
+        # within exception info printing
+        from py._code.source import getstatementrange_ast
+        source = self.frame.code.fullsource
+        if source is None:
+            return None
+        key = astnode = None
+        if astcache is not None:
+            key = self.frame.code.path
+            if key is not None:
+                astnode = astcache.get(key, None)
+        start = self.getfirstlinesource()
+        try:
+            astnode, _, end = getstatementrange_ast(self.lineno, source,
+                                                    astnode=astnode)
+        except SyntaxError:
+            end = self.lineno + 1
+        else:
+            if key is not None:
+                astcache[key] = astnode
+        return source[start:end]
+
+    source = property(getsource)
+
+    def ishidden(self):
+        """ return True if the current frame has a var __tracebackhide__
+            resolving to True
+
+            mostly for internal use
+        """
+        try:
+            return self.frame.f_locals['__tracebackhide__']
+        except KeyError:
+            try:
+                return self.frame.f_globals['__tracebackhide__']
+            except KeyError:
+                return False
+
+    def __str__(self):
+        try:
+            fn = str(self.path)
+        except py.error.Error:
+            fn = '???'
+        name = self.frame.code.name
+        try:
+            line = str(self.statement).lstrip()
+        except KeyboardInterrupt:
+            raise
+        except:
+            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.
+    """
+    Entry = TracebackEntry
+    def __init__(self, tb):
+        """ initialize from given python traceback object. """
+        if hasattr(tb, 'tb_next'):
+            def f(cur):
+                while cur is not None:
+                    yield self.Entry(cur)
+                    cur = cur.tb_next
+            list.__init__(self, f(tb))
+        else:
+            list.__init__(self, tb)
+
+    def cut(self, path=None, lineno=None, firstlineno=None, excludepath=None):
+        """ return a Traceback instance wrapping part of this Traceback
+
+            by provding any combination of path, lineno and firstlineno, the
+            first frame to start the to-be-returned traceback is determined
+
+            this allows cutting the first part of a Traceback instance e.g.
+            for formatting reasons (removing some uninteresting bits that deal
+            with handling of the exception/traceback)
+        """
+        for x in self:
+            code = x.frame.code
+            codepath = code.path
+            if ((path is None or codepath == path) and
+                (excludepath is None or not hasattr(codepath, 'relto') or
+                 not codepath.relto(excludepath)) and
+                (lineno is None or x.lineno == lineno) and
+                (firstlineno is None or x.frame.code.firstlineno == firstlineno)):
+                return Traceback(x._rawentry)
+        return self
+
+    def __getitem__(self, key):
+        val = super(Traceback, self).__getitem__(key)
+        if isinstance(key, type(slice(0))):
+            val = self.__class__(val)
+        return val
+
+    def filter(self, fn=lambda x: not x.ishidden()):
+        """ return a Traceback instance with certain items removed
+
+            fn is a function that gets a single argument, a TracebackItem
+            instance, and should return True when the item should be added
+            to the Traceback, False when not
+
+            by default this removes all the TracebackItems which are hidden
+            (see ishidden() above)
+        """
+        return Traceback(filter(fn, self))
+
+    def getcrashentry(self):
+        """ return last non-hidden traceback entry that lead
+        to the exception of a traceback.
+        """
+        for i in range(-1, -len(self)-1, -1):
+            entry = self[i]
+            if not entry.ishidden():
+                return entry
+        return self[-1]
+
+    def recursionindex(self):
+        """ return the index of the frame/TracebackItem where recursion
+            originates if appropriate, None if no recursion occurred
+        """
+        cache = {}
+        for i, entry in enumerate(self):
+            # id for the code.raw is needed to work around
+            # the strange metaprogramming in the decorator lib from pypi
+            # which generates code objects that have hash/value equality
+            #XXX needs a test
+            key = entry.frame.code.path, id(entry.frame.code.raw), entry.lineno
+            #print "checking for recursion at", key
+            l = cache.setdefault(key, [])
+            if l:
+                f = entry.frame
+                loc = f.f_locals
+                for otherloc in l:
+                    if f.is_true(f.eval(co_equal,
+                        __recursioncache_locals_1=loc,
+                        __recursioncache_locals_2=otherloc)):
+                        return i
+            l.append(entry.frame.f_locals)
+        return None
+
+co_equal = compile('__recursioncache_locals_1 == __recursioncache_locals_2',
+                   '?', 'eval')
+
+class ExceptionInfo(object):
+    """ wraps sys.exc_info() objects and offers
+        help for navigating the traceback.
+    """
+    _striptext = ''
+    def __init__(self, tup=None, exprinfo=None):
+        if tup is None:
+            tup = sys.exc_info()
+            if exprinfo is None and isinstance(tup[1], AssertionError):
+                exprinfo = getattr(tup[1], 'msg', None)
+                if exprinfo is None:
+                    exprinfo = str(tup[1])
+                if exprinfo and exprinfo.startswith('assert '):
+                    self._striptext = 'AssertionError: '
+        self._excinfo = tup
+        #: the exception class
+        self.type = tup[0]
+        #: the exception instance
+        self.value = tup[1]
+        #: the exception raw traceback
+        self.tb = tup[2]
+        #: the exception type name
+        self.typename = self.type.__name__
+        #: the exception traceback (py.code.Traceback instance)
+        self.traceback = py.code.Traceback(self.tb)
+
+    def __repr__(self):
+        return "<ExceptionInfo %s tblen=%d>" % (self.typename, len(self.traceback))
+
+    def exconly(self, tryshort=False):
+        """ return the exception as a string
+
+            when 'tryshort' resolves to True, and the exception is a
+            py.code._AssertionError, only the actual exception part of
+            the exception representation is returned (so 'AssertionError: ' is
+            removed from the beginning)
+        """
+        lines = format_exception_only(self.type, self.value)
+        text = ''.join(lines)
+        text = text.rstrip()
+        if tryshort:
+            if text.startswith(self._striptext):
+                text = text[len(self._striptext):]
+        return text
+
+    def errisinstance(self, exc):
+        """ return True if the exception is an instance of exc """
+        return isinstance(self.value, exc)
+
+    def _getreprcrash(self):
+        exconly = self.exconly(tryshort=True)
+        entry = self.traceback.getcrashentry()
+        path, lineno = entry.frame.code.raw.co_filename, entry.lineno
+        return ReprFileLocation(path, lineno+1, exconly)
+
+    def getrepr(self, showlocals=False, style="long",
+            abspath=False, tbfilter=True, funcargs=False):
+        """ return str()able representation of this exception info.
+            showlocals: show locals per traceback entry
+            style: long|short|no|native traceback style
+            tbfilter: hide entries (where __tracebackhide__ is true)
+
+            in case of style==native, tbfilter and showlocals is ignored.
+        """
+        if style == 'native':
+            return ReprExceptionInfo(ReprTracebackNative(
+                py.std.traceback.format_exception(
+                    self.type,
+                    self.value,
+                    self.traceback[0]._rawentry,
+                )), self._getreprcrash())
+
+        fmt = FormattedExcinfo(showlocals=showlocals, style=style,
+            abspath=abspath, tbfilter=tbfilter, funcargs=funcargs)
+        return fmt.repr_excinfo(self)
+
+    def __str__(self):
+        entry = self.traceback[-1]
+        loc = ReprFileLocation(entry.path, entry.lineno + 1, self.exconly())
+        return str(loc)
+
+    def __unicode__(self):
+        entry = self.traceback[-1]
+        loc = ReprFileLocation(entry.path, entry.lineno + 1, self.exconly())
+        return loc.__unicode__()
+
+
+class FormattedExcinfo(object):
+    """ presenting information about failing Functions and Generators. """
+    # for traceback entries
+    flow_marker = ">"
+    fail_marker = "E"
+
+    def __init__(self, showlocals=False, style="long", abspath=True, tbfilter=True, funcargs=False):
+        self.showlocals = showlocals
+        self.style = style
+        self.tbfilter = tbfilter
+        self.funcargs = funcargs
+        self.abspath = abspath
+        self.astcache = {}
+
+    def _getindent(self, source):
+        # figure out indent for given source
+        try:
+            s = str(source.getstatement(len(source)-1))
+        except KeyboardInterrupt:
+            raise
+        except:
+            try:
+                s = str(source[-1])
+            except KeyboardInterrupt:
+                raise
+            except:
+                return 0
+        return 4 + (len(s) - len(s.lstrip()))
+
+    def _getentrysource(self, entry):
+        source = entry.getsource(self.astcache)
+        if source is not None:
+            source = source.deindent()
+        return source
+
+    def _saferepr(self, obj):
+        return py.io.saferepr(obj)
+
+    def repr_args(self, entry):
+        if self.funcargs:
+            args = []
+            for argname, argvalue in entry.frame.getargs(var=True):
+                args.append((argname, self._saferepr(argvalue)))
+            return ReprFuncArgs(args)
+
+    def get_source(self, source, line_index=-1, excinfo=None, short=False):
+        """ return formatted and marked up source lines. """
+        lines = []
+        if source is None or line_index >= len(source.lines):
+            source = py.code.Source("???")
+            line_index = 0
+        if line_index < 0:
+            line_index += len(source)
+        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 = 4 if short else self._getindent(source)
+            lines.extend(self.get_exconly(excinfo, indent=indent, markall=True))
+        return lines
+
+    def get_exconly(self, excinfo, indent=4, markall=False):
+        lines = []
+        indent = " " * indent
+        # get the real exception information out
+        exlines = excinfo.exconly(tryshort=True).split('\n')
+        failindent = self.fail_marker + indent[1:]
+        for line in exlines:
+            lines.append(failindent + line)
+            if not markall:
+                failindent = indent
+        return lines
+
+    def repr_locals(self, locals):
+        if self.showlocals:
+            lines = []
+            keys = [loc for loc in locals if loc[0] != "@"]
+            keys.sort()
+            for name in keys:
+                value = locals[name]
+                if name == '__builtins__':
+                    lines.append("__builtins__ = <builtins>")
+                else:
+                    # This formatting could all be handled by the
+                    # _repr() function, which is only reprlib.Repr in
+                    # disguise, so is very configurable.
+                    str_repr = self._saferepr(value)
+                    #if len(str_repr) < 70 or not isinstance(value,
+                    #                            (list, tuple, dict)):
+                    lines.append("%-10s = %s" %(name, str_repr))
+                    #else:
+                    #    self._line("%-10s =\\" % (name,))
+                    #    # XXX
+                    #    py.std.pprint.pprint(value, stream=self.excinfowriter)
+            return ReprLocals(lines)
+
+    def repr_traceback_entry(self, entry, excinfo=None):
+        source = self._getentrysource(entry)
+        if source is None:
+            source = py.code.Source("???")
+            line_index = 0
+        else:
+            # entry.getfirstlinesource() can be -1, should be 0 on jython
+            line_index = entry.lineno - max(entry.getfirstlinesource(), 0)
+
+        lines = []
+        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:
+                message = "in %s" %(entry.name)
+            else:
+                message = excinfo and excinfo.typename or ""
+            path = self._makepath(entry.path)
+            filelocrepr = ReprFileLocation(path, entry.lineno+1, message)
+            localsrepr = None
+            if not short:
+                localsrepr =  self.repr_locals(entry.locals)
+            return ReprEntry(lines, reprargs, localsrepr, filelocrepr, style)
+        if excinfo:
+            lines.extend(self.get_exconly(excinfo, indent=4))
+        return ReprEntry(lines, None, None, None, style)
+
+    def _makepath(self, path):
+        if not self.abspath:
+            try:
+                np = py.path.local().bestrelpath(path)
+            except OSError:
+                return path
+            if len(np) < len(str(path)):
+                path = np
+        return path
+
+    def repr_traceback(self, excinfo):
+        traceback = excinfo.traceback
+        if self.tbfilter:
+            traceback = traceback.filter()
+        recursionindex = None
+        if excinfo.errisinstance(RuntimeError):
+            if "maximum recursion depth exceeded" in str(excinfo.value):
+                recursionindex = traceback.recursionindex()
+        last = traceback[-1]
+        entries = []
+        extraline = None
+        for index, entry in enumerate(traceback):
+            einfo = (last == entry) and excinfo or None
+            reprentry = self.repr_traceback_entry(entry, einfo)
+            entries.append(reprentry)
+            if index == recursionindex:
+                extraline = "!!! Recursion detected (same locals & position)"
+                break
+        return ReprTraceback(entries, extraline, style=self.style)
+
+    def repr_excinfo(self, excinfo):
+        reprtraceback = self.repr_traceback(excinfo)
+        reprcrash = excinfo._getreprcrash()
+        return ReprExceptionInfo(reprtraceback, reprcrash)
+
+class TerminalRepr:
+    def __str__(self):
+        s = self.__unicode__()
+        if sys.version_info[0] < 3:
+            s = s.encode('utf-8')
+        return s
+
+    def __unicode__(self):
+        # FYI this is called from pytest-xdist's serialization of exception
+        # information.
+        io = py.io.TextIO()
+        tw = py.io.TerminalWriter(file=io)
+        self.toterminal(tw)
+        return io.getvalue().strip()
+
+    def __repr__(self):
+        return "<%s instance at %0x>" %(self.__class__, id(self))
+
+
+class ReprExceptionInfo(TerminalRepr):
+    def __init__(self, reprtraceback, reprcrash):
+        self.reprtraceback = reprtraceback
+        self.reprcrash = reprcrash
+        self.sections = []
+
+    def addsection(self, name, content, sep="-"):
+        self.sections.append((name, content, sep))
+
+    def toterminal(self, tw):
+        self.reprtraceback.toterminal(tw)
+        for name, content, sep in self.sections:
+            tw.sep(sep, name)
+            tw.line(content)
+
+class ReprTraceback(TerminalRepr):
+    entrysep = "_ "
+
+    def __init__(self, reprentries, extraline, style):
+        self.reprentries = reprentries
+        self.extraline = extraline
+        self.style = style
+
+    def toterminal(self, tw):
+        # the entries might have different styles
+        last_style = None
+        for i, entry in enumerate(self.reprentries):
+            if entry.style == "long":
+                tw.line("")
+            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)
+
+class ReprTracebackNative(ReprTraceback):
+    def __init__(self, tblines):
+        self.style = "native"
+        self.reprentries = [ReprEntryNative(tblines)]
+        self.extraline = None
+
+class ReprEntryNative(TerminalRepr):
+    style = "native"
+
+    def __init__(self, tblines):
+        self.lines = tblines
+
+    def toterminal(self, tw):
+        tw.write("".join(self.lines))
+
+class ReprEntry(TerminalRepr):
+    localssep = "_ "
+
+    def __init__(self, lines, reprfuncargs, reprlocals, filelocrepr, style):
+        self.lines = lines
+        self.reprfuncargs = reprfuncargs
+        self.reprlocals = reprlocals
+        self.reprfileloc = filelocrepr
+        self.style = style
+
+    def toterminal(self, tw):
+        if self.style == "short":
+            self.reprfileloc.toterminal(tw)
+            for line in self.lines:
+                red = line.startswith("E   ")
+                tw.line(line, bold=True, red=red)
+            #tw.line("")
+            return
+        if self.reprfuncargs:
+            self.reprfuncargs.toterminal(tw)
+        for line in self.lines:
+            red = line.startswith("E   ")
+            tw.line(line, bold=True, red=red)
+        if self.reprlocals:
+            #tw.sep(self.localssep, "Locals")
+            tw.line("")
+            self.reprlocals.toterminal(tw)
+        if self.reprfileloc:
+            if self.lines:
+                tw.line("")
+            self.reprfileloc.toterminal(tw)
+
+    def __str__(self):
+        return "%s\n%s\n%s" % ("\n".join(self.lines),
+                               self.reprlocals,
+                               self.reprfileloc)
+
+class ReprFileLocation(TerminalRepr):
+    def __init__(self, path, lineno, message):
+        self.path = str(path)
+        self.lineno = lineno
+        self.message = message
+
+    def toterminal(self, tw):
+        # filename and lineno output for each entry,
+        # using an output format that most editors unterstand
+        msg = self.message
+        i = msg.find("\n")
+        if i != -1:
+            msg = msg[:i]
+        tw.line("%s:%s: %s" %(self.path, self.lineno, msg))
+
+class ReprLocals(TerminalRepr):
+    def __init__(self, lines):
+        self.lines = lines
+
+    def toterminal(self, tw):
+        for line in self.lines:
+            tw.line(line)
+
+class ReprFuncArgs(TerminalRepr):
+    def __init__(self, args):
+        self.args = args
+
+    def toterminal(self, tw):
+        if self.args:
+            linesofar = ""
+            for name, value in self.args:
+                ns = "%s = %s" %(name, value)
+                if len(ns) + len(linesofar) + 2 > tw.fullwidth:
+                    if linesofar:
+                        tw.line(linesofar)
+                    linesofar =  ns
+                else:
+                    if linesofar:
+                        linesofar += ", " + ns
+                    else:
+                        linesofar = ns
+            if linesofar:
+                tw.line(linesofar)
+            tw.line("")
+
+
+
+oldbuiltins = {}
+
+def patch_builtins(assertion=True, compile=True):
+    """ put compile and AssertionError builtins to Python's builtins. """
+    if assertion:
+        from py._code import assertion
+        l = oldbuiltins.setdefault('AssertionError', [])
+        l.append(py.builtin.builtins.AssertionError)
+        py.builtin.builtins.AssertionError = assertion.AssertionError
+    if compile:
+        l = oldbuiltins.setdefault('compile', [])
+        l.append(py.builtin.builtins.compile)
+        py.builtin.builtins.compile = py.code.compile
+
+def unpatch_builtins(assertion=True, compile=True):
+    """ remove compile and AssertionError builtins from Python builtins. """
+    if assertion:
+        py.builtin.builtins.AssertionError = oldbuiltins['AssertionError'].pop()
+    if compile:
+        py.builtin.builtins.compile = oldbuiltins['compile'].pop()
+
+def getrawcode(obj, trycall=True):
+    """ return code object for given function. """
+    try:
+        return obj.__code__
+    except AttributeError:
+        obj = getattr(obj, 'im_func', obj)
+        obj = getattr(obj, 'func_code', obj)
+        obj = getattr(obj, 'f_code', obj)
+        obj = getattr(obj, '__code__', obj)
+        if trycall and not hasattr(obj, 'co_firstlineno'):
+            if hasattr(obj, '__call__') and not py.std.inspect.isclass(obj):
+                x = getrawcode(obj.__call__, trycall=False)
+                if hasattr(x, 'co_firstlineno'):
+                    return x
+        return obj
+
--- a/third_party/python/py/py/_code/source.py
+++ b/third_party/python/py/py/_code/source.py
@@ -1,419 +1,411 @@
-from __future__ import generators
-
-from bisect import bisect_right
-import sys
-import inspect, tokenize
-import py
-from types import ModuleType
-cpy_compile = compile
-
-try:
-    import _ast
-    from _ast import PyCF_ONLY_AST as _AST_FLAG
-except ImportError:
-    _AST_FLAG = 0
-    _ast = None
-
-
-class Source(object):
-    """ a immutable object holding a source code fragment,
-        possibly deindenting it.
-    """
-    _compilecounter = 0
-    def __init__(self, *parts, **kwargs):
-        self.lines = lines = []
-        de = kwargs.get('deindent', True)
-        rstrip = kwargs.get('rstrip', True)
-        for part in parts:
-            if not part:
-                partlines = []
-            if isinstance(part, Source):
-                partlines = part.lines
-            elif isinstance(part, (tuple, list)):
-                partlines = [x.rstrip("\n") for x in part]
-            elif isinstance(part, py.builtin._basestring):
-                partlines = part.split('\n')
-                if rstrip:
-                    while partlines:
-                        if partlines[-1].strip():
-                            break
-                        partlines.pop()
-            else:
-                partlines = getsource(part, deindent=de).lines
-            if de:
-                partlines = deindent(partlines)
-            lines.extend(partlines)
-
-    def __eq__(self, other):
-        try:
-            return self.lines == other.lines
-        except AttributeError:
-            if isinstance(other, str):
-                return str(self) == other
-            return False
-
-    def __getitem__(self, key):
-        if isinstance(key, int):
-            return self.lines[key]
-        else:
-            if key.step not in (None, 1):
-                raise IndexError("cannot slice a Source with a step")
-            return self.__getslice__(key.start, key.stop)
-
-    def __len__(self):
-        return len(self.lines)
-
-    def __getslice__(self, start, end):
-        newsource = Source()
-        newsource.lines = self.lines[start:end]
-        return newsource
-
-    def strip(self):
-        """ return new source object with trailing
-            and leading blank lines removed.
-        """
-        start, end = 0, len(self)
-        while start < end and not self.lines[start].strip():
-            start += 1
-        while end > start and not self.lines[end-1].strip():
-            end -= 1
-        source = Source()
-        source.lines[:] = self.lines[start:end]
-        return source
-
-    def putaround(self, before='', after='', indent=' ' * 4):
-        """ return a copy of the source object with
-            'before' and 'after' wrapped around it.
-        """
-        before = Source(before)
-        after = Source(after)
-        newsource = Source()
-        lines = [ (indent + line) for line in self.lines]
-        newsource.lines = before.lines + lines +  after.lines
-        return newsource
-
-    def indent(self, indent=' ' * 4):
-        """ return a copy of the source object with
-            all lines indented by the given indent-string.
-        """
-        newsource = Source()
-        newsource.lines = [(indent+line) for line in self.lines]
-        return newsource
-
-    def getstatement(self, lineno, assertion=False):
-        """ return Source statement which contains the
-            given linenumber (counted from 0).
-        """
-        start, end = self.getstatementrange(lineno, assertion)
-        return self[start:end]
-
-    def getstatementrange(self, lineno, assertion=False):
-        """ return (start, end) tuple which spans the minimal
-            statement region which containing the given lineno.
-        """
-        if not (0 <= lineno < len(self)):
-            raise IndexError("lineno out of range")
-        ast, start, end = getstatementrange_ast(lineno, self)
-        return start, end
-
-    def deindent(self, offset=None):
-        """ return a new source object deindented by offset.
-            If offset is None then guess an indentation offset from
-            the first non-blank line.  Subsequent lines which have a
-            lower indentation offset will be copied verbatim as
-            they are assumed to be part of multilines.
-        """
-        # XXX maybe use the tokenizer to properly handle multiline
-        #     strings etc.pp?
-        newsource = Source()
-        newsource.lines[:] = deindent(self.lines, offset)
-        return newsource
-
-    def isparseable(self, deindent=True):
-        """ return True if source is parseable, heuristically
-            deindenting it by default.
-        """
-        try:
-            import parser
-        except ImportError:
-            syntax_checker = lambda x: compile(x, 'asd', 'exec')
-        else:
-            syntax_checker = parser.suite
-
-        if deindent:
-            source = str(self.deindent())
-        else:
-            source = str(self)
-        try:
-            #compile(source+'\n', "x", "exec")
-            syntax_checker(source+'\n')
-        except KeyboardInterrupt:
-            raise
-        except Exception:
-            return False
-        else:
-            return True
-
-    def __str__(self):
-        return "\n".join(self.lines)
-
-    def compile(self, filename=None, mode='exec',
-                flag=generators.compiler_flag,
-                dont_inherit=0, _genframe=None):
-        """ return compiled code object. if filename is None
-            invent an artificial filename which displays
-            the source/line position of the caller frame.
-        """
-        if not filename or py.path.local(filename).check(file=0):
-            if _genframe is None:
-                _genframe = sys._getframe(1) # the caller
-            fn,lineno = _genframe.f_code.co_filename, _genframe.f_lineno
-            base = "<%d-codegen " % self._compilecounter
-            self.__class__._compilecounter += 1
-            if not filename:
-                filename = base + '%s:%d>' % (fn, lineno)
-            else:
-                filename = base + '%r %s:%d>' % (filename, fn, lineno)
-        source = "\n".join(self.lines) + '\n'
-        try:
-            co = cpy_compile(source, filename, mode, flag)
-        except SyntaxError:
-            ex = sys.exc_info()[1]
-            # re-represent syntax errors from parsing python strings
-            msglines = self.lines[:ex.lineno]
-            if ex.offset:
-                msglines.append(" "*ex.offset + '^')
-            msglines.append("(code was compiled probably from here: %s)" % filename)
-            newex = SyntaxError('\n'.join(msglines))
-            newex.offset = ex.offset
-            newex.lineno = ex.lineno
-            newex.text = ex.text
-            raise newex
-        else:
-            if flag & _AST_FLAG:
-                return co
-            lines = [(x + "\n") for x in self.lines]
-            if sys.version_info[0] >= 3:
-                # XXX py3's inspect.getsourcefile() checks for a module
-                # and a pep302 __loader__ ... we don't have a module
-                # at code compile-time so we need to fake it here
-                m = ModuleType("_pycodecompile_pseudo_module")
-                py.std.inspect.modulesbyfile[filename] = None
-                py.std.sys.modules[None] = m
-                m.__loader__ = 1
-            py.std.linecache.cache[filename] = (1, None, lines, filename)
-            return co
-
-#
-# public API shortcut functions
-#
-
-def compile_(source, filename=None, mode='exec', flags=
-            generators.compiler_flag, dont_inherit=0):
-    """ compile the given source to a raw code object,
-        and maintain an internal cache which allows later
-        retrieval of the source code for the code object
-        and any recursively created code objects.
-    """
-    if _ast is not None and isinstance(source, _ast.AST):
-        # XXX should Source support having AST?
-        return cpy_compile(source, filename, mode, flags, dont_inherit)
-    _genframe = sys._getframe(1) # the caller
-    s = Source(source)
-    co = s.compile(filename, mode, flags, _genframe=_genframe)
-    return co
-
-
-def getfslineno(obj):
-    """ Return source location (path, lineno) for the given object.
-    If the source cannot be determined return ("", -1)
-    """
-    try:
-        code = py.code.Code(obj)
-    except TypeError:
-        try:
-            fn = (py.std.inspect.getsourcefile(obj) or
-                  py.std.inspect.getfile(obj))
-        except TypeError:
-            return "", -1
-
-        fspath = fn and py.path.local(fn) or None
-        lineno = -1
-        if fspath:
-            try:
-                _, lineno = findsource(obj)
-            except IOError:
-                pass
-    else:
-        fspath = code.path
-        lineno = code.firstlineno
-    assert isinstance(lineno, int)
-    return fspath, lineno
-
-#
-# helper functions
-#
-
-def findsource(obj):
-    try:
-        sourcelines, lineno = py.std.inspect.findsource(obj)
-    except py.builtin._sysex:
-        raise
-    except:
-        return None, -1
-    source = Source()
-    source.lines = [line.rstrip() for line in sourcelines]
-    return source, lineno
-
-def getsource(obj, **kwargs):
-    obj = py.code.getrawcode(obj)
-    try:
-        strsrc = inspect.getsource(obj)
-    except IndentationError:
-        strsrc = "\"Buggy python version consider upgrading, cannot get source\""
-    assert isinstance(strsrc, str)
-    return Source(strsrc, **kwargs)
-
-def deindent(lines, offset=None):
-    if offset is None:
-        for line in lines:
-            line = line.expandtabs()
-            s = line.lstrip()
-            if s:
-                offset = len(line)-len(s)
-                break
-        else:
-            offset = 0
-    if offset == 0:
-        return list(lines)
-    newlines = []
-    def readline_generator(lines):
-        for line in lines:
-            yield line + '\n'
-        while True:
-            yield ''
-
-    it = readline_generator(lines)
-
-    try:
-        for _, _, (sline, _), (eline, _), _ in tokenize.generate_tokens(lambda: next(it)):
-            if sline > len(lines):
-                break # End of input reached
-            if sline > len(newlines):
-                line = lines[sline - 1].expandtabs()
-                if line.lstrip() and line[:offset].isspace():
-                    line = line[offset:] # Deindent
-                newlines.append(line)
-
-            for i in range(sline, eline):
-                # Don't deindent continuing lines of
-                # multiline tokens (i.e. multiline strings)
-                newlines.append(lines[i])
-    except (IndentationError, tokenize.TokenError):
-        pass
-    # Add any lines we didn't see. E.g. if an exception was raised.
-    newlines.extend(lines[len(newlines):])
-    return newlines
-
-
-def get_statement_startend2(lineno, node):
-    import ast
-    # flatten all statements and except handlers into one lineno-list
-    # AST's line numbers start indexing at 1
-    l = []
-    for x in ast.walk(node):
-        if isinstance(x, _ast.stmt) or isinstance(x, _ast.ExceptHandler):
-            l.append(x.lineno - 1)
-            for name in "finalbody", "orelse":
-                val = getattr(x, name, None)
-                if val:
-                    # treat the finally/orelse part as its own statement
-                    l.append(val[0].lineno - 1 - 1)
-    l.sort()
-    insert_index = bisect_right(l, lineno)
-    start = l[insert_index - 1]
-    if insert_index >= len(l):
-        end = None
-    else:
-        end = l[insert_index]
-    return start, end
-
-
-def getstatementrange_ast(lineno, source, assertion=False, astnode=None):
-    if astnode is None:
-        content = str(source)
-        if sys.version_info < (2,7):
-            content += "\n"
-        try:
-            astnode = compile(content, "source", "exec", 1024)  # 1024 for AST
-        except ValueError:
-            start, end = getstatementrange_old(lineno, source, assertion)
-            return None, start, end
-    start, end = get_statement_startend2(lineno, astnode)
-    # we need to correct the end:
-    # - ast-parsing strips comments
-    # - there might be empty lines
-    # - we might have lesser indented code blocks at the end
-    if end is None:
-        end = len(source.lines)
-
-    if end > start + 1:
-        # make sure we don't span differently indented code blocks
-        # by using the BlockFinder helper used which inspect.getsource() uses itself
-        block_finder = inspect.BlockFinder()
-        # if we start with an indented line, put blockfinder to "started" mode
-        block_finder.started = source.lines[start][0].isspace()
-        it = ((x + "\n") for x in source.lines[start:end])
-        try:
-            for tok in tokenize.generate_tokens(lambda: next(it)):
-                block_finder.tokeneater(*tok)
-        except (inspect.EndOfBlock, IndentationError):
-            end = block_finder.last + start
-        except Exception:
-            pass
-
-    # the end might still point to a comment or empty line, correct it
-    while end:
-        line = source.lines[end - 1].lstrip()
-        if line.startswith("#") or not line:
-            end -= 1
-        else:
-            break
-    return astnode, start, end
-
-
-def getstatementrange_old(lineno, source, assertion=False):
-    """ return (start, end) tuple which spans the minimal
-        statement region which containing the given lineno.
-        raise an IndexError if no such statementrange can be found.
-    """
-    # XXX this logic is only used on python2.4 and below
-    # 1. find the start of the statement
-    from codeop import compile_command
-    for start in range(lineno, -1, -1):
-        if assertion:
-            line = source.lines[start]
-            # the following lines are not fully tested, change with care
-            if 'super' in line and 'self' in line and '__init__' in line:
-                raise IndexError("likely a subclass")
-            if "assert" not in line and "raise" not in line:
-                continue
-        trylines = source.lines[start:lineno+1]
-        # quick hack to prepare parsing an indented line with
-        # compile_command() (which errors on "return" outside defs)
-        trylines.insert(0, 'def xxx():')
-        trysource = '\n '.join(trylines)
-        #              ^ space here
-        try:
-            compile_command(trysource)
-        except (SyntaxError, OverflowError, ValueError):
-            continue
-
-        # 2. find the end of the statement
-        for end in range(lineno+1, len(source)+1):
-            trysource = source[start:end]
-            if trysource.isparseable():
-                return start, end
-    raise SyntaxError("no valid source range around line %d " % (lineno,))
-
-
+from __future__ import generators
+
+from bisect import bisect_right
+import sys
+import inspect, tokenize
+import py
+from types import ModuleType
+cpy_compile = compile
+
+try:
+    import _ast
+    from _ast import PyCF_ONLY_AST as _AST_FLAG
+except ImportError:
+    _AST_FLAG = 0
+    _ast = None
+
+
+class Source(object):
+    """ a immutable object holding a source code fragment,
+        possibly deindenting it.
+    """
+    _compilecounter = 0
+    def __init__(self, *parts, **kwargs):
+        self.lines = lines = []
+        de = kwargs.get('deindent', True)
+        rstrip = kwargs.get('rstrip', True)
+        for part in parts:
+            if not part:
+                partlines = []
+            if isinstance(part, Source):
+                partlines = part.lines
+            elif isinstance(part, (tuple, list)):
+                partlines = [x.rstrip("\n") for x in part]
+            elif isinstance(part, py.builtin._basestring):
+                partlines = part.split('\n')
+                if rstrip:
+                    while partlines:
+                        if partlines[-1].strip():
+                            break
+                        partlines.pop()
+            else:
+                partlines = getsource(part, deindent=de).lines
+            if de:
+                partlines = deindent(partlines)
+            lines.extend(partlines)
+
+    def __eq__(self, other):
+        try:
+            return self.lines == other.lines
+        except AttributeError:
+            if isinstance(other, str):
+                return str(self) == other
+            return False
+
+    def __getitem__(self, key):
+        if isinstance(key, int):
+            return self.lines[key]
+        else:
+            if key.step not in (None, 1):
+                raise IndexError("cannot slice a Source with a step")
+            return self.__getslice__(key.start, key.stop)
+
+    def __len__(self):
+        return len(self.lines)
+
+    def __getslice__(self, start, end):
+        newsource = Source()
+        newsource.lines = self.lines[start:end]
+        return newsource
+
+    def strip(self):
+        """ return new source object with trailing
+            and leading blank lines removed.
+        """
+        start, end = 0, len(self)
+        while start < end and not self.lines[start].strip():
+            start += 1
+        while end > start and not self.lines[end-1].strip():
+            end -= 1
+        source = Source()
+        source.lines[:] = self.lines[start:end]
+        return source
+
+    def putaround(self, before='', after='', indent=' ' * 4):
+        """ return a copy of the source object with
+            'before' and 'after' wrapped around it.
+        """
+        before = Source(before)
+        after = Source(after)
+        newsource = Source()
+        lines = [ (indent + line) for line in self.lines]
+        newsource.lines = before.lines + lines +  after.lines
+        return newsource
+
+    def indent(self, indent=' ' * 4):
+        """ return a copy of the source object with
+            all lines indented by the given indent-string.
+        """
+        newsource = Source()
+        newsource.lines = [(indent+line) for line in self.lines]
+        return newsource
+
+    def getstatement(self, lineno, assertion=False):
+        """ return Source statement which contains the
+            given linenumber (counted from 0).
+        """
+        start, end = self.getstatementrange(lineno, assertion)
+        return self[start:end]
+
+    def getstatementrange(self, lineno, assertion=False):
+        """ return (start, end) tuple which spans the minimal
+            statement region which containing the given lineno.
+        """
+        if not (0 <= lineno < len(self)):
+            raise IndexError("lineno out of range")
+        ast, start, end = getstatementrange_ast(lineno, self)
+        return start, end
+
+    def deindent(self, offset=None):
+        """ return a new source object deindented by offset.
+            If offset is None then guess an indentation offset from
+            the first non-blank line.  Subsequent lines which have a
+            lower indentation offset will be copied verbatim as
+            they are assumed to be part of multilines.
+        """
+        # XXX maybe use the tokenizer to properly handle multiline
+        #     strings etc.pp?
+        newsource = Source()
+        newsource.lines[:] = deindent(self.lines, offset)
+        return newsource
+
+    def isparseable(self, deindent=True):
+        """ return True if source is parseable, heuristically
+            deindenting it by default.
+        """
+        try:
+            import parser
+        except ImportError:
+            syntax_checker = lambda x: compile(x, 'asd', 'exec')
+        else:
+            syntax_checker = parser.suite
+
+        if deindent:
+            source = str(self.deindent())
+        else:
+            source = str(self)
+        try:
+            #compile(source+'\n', "x", "exec")
+            syntax_checker(source+'\n')
+        except KeyboardInterrupt:
+            raise
+        except Exception:
+            return False
+        else:
+            return True
+
+    def __str__(self):
+        return "\n".join(self.lines)
+
+    def compile(self, filename=None, mode='exec',
+                flag=generators.compiler_flag,
+                dont_inherit=0, _genframe=None):
+        """ return compiled code object. if filename is None
+            invent an artificial filename which displays
+            the source/line position of the caller frame.
+        """
+        if not filename or py.path.local(filename).check(file=0):
+            if _genframe is None:
+                _genframe = sys._getframe(1) # the caller
+            fn,lineno = _genframe.f_code.co_filename, _genframe.f_lineno
+            base = "<%d-codegen " % self._compilecounter
+            self.__class__._compilecounter += 1
+            if not filename:
+                filename = base + '%s:%d>' % (fn, lineno)
+            else:
+                filename = base + '%r %s:%d>' % (filename, fn, lineno)
+        source = "\n".join(self.lines) + '\n'
+        try:
+            co = cpy_compile(source, filename, mode, flag)
+        except SyntaxError:
+            ex = sys.exc_info()[1]
+            # re-represent syntax errors from parsing python strings
+            msglines = self.lines[:ex.lineno]
+            if ex.offset:
+                msglines.append(" "*ex.offset + '^')
+            msglines.append("(code was compiled probably from here: %s)" % filename)
+            newex = SyntaxError('\n'.join(msglines))
+            newex.offset = ex.offset
+            newex.lineno = ex.lineno
+            newex.text = ex.text
+            raise newex
+        else:
+            if flag & _AST_FLAG:
+                return co
+            lines = [(x + "\n") for x in self.lines]
+            py.std.linecache.cache[filename] = (1, None, lines, filename)
+            return co
+
+#
+# public API shortcut functions
+#
+
+def compile_(source, filename=None, mode='exec', flags=
+            generators.compiler_flag, dont_inherit=0):
+    """ compile the given source to a raw code object,
+        and maintain an internal cache which allows later
+        retrieval of the source code for the code object
+        and any recursively created code objects.
+    """
+    if _ast is not None and isinstance(source, _ast.AST):
+        # XXX should Source support having AST?
+        return cpy_compile(source, filename, mode, flags, dont_inherit)
+    _genframe = sys._getframe(1) # the caller
+    s = Source(source)
+    co = s.compile(filename, mode, flags, _genframe=_genframe)
+    return co
+
+
+def getfslineno(obj):
+    """ Return source location (path, lineno) for the given object.
+    If the source cannot be determined return ("", -1)
+    """
+    try:
+        code = py.code.Code(obj)
+    except TypeError:
+        try:
+            fn = (py.std.inspect.getsourcefile(obj) or
+                  py.std.inspect.getfile(obj))
+        except TypeError:
+            return "", -1
+
+        fspath = fn and py.path.local(fn) or None
+        lineno = -1
+        if fspath:
+            try:
+                _, lineno = findsource(obj)
+            except IOError:
+                pass
+    else:
+        fspath = code.path
+        lineno = code.firstlineno
+    assert isinstance(lineno, int)
+    return fspath, lineno
+
+#
+# helper functions
+#
+
+def findsource(obj):
+    try:
+        sourcelines, lineno = py.std.inspect.findsource(obj)
+    except py.builtin._sysex:
+        raise
+    except:
+        return None, -1
+    source = Source()
+    source.lines = [line.rstrip() for line in sourcelines]
+    return source, lineno
+
+def getsource(obj, **kwargs):
+    obj = py.code.getrawcode(obj)
+    try:
+        strsrc = inspect.getsource(obj)
+    except IndentationError:
+        strsrc = "\"Buggy python version consider upgrading, cannot get source\""
+    assert isinstance(strsrc, str)
+    return Source(strsrc, **kwargs)
+
+def deindent(lines, offset=None):
+    if offset is None:
+        for line in lines:
+            line = line.expandtabs()
+            s = line.lstrip()
+            if s:
+                offset = len(line)-len(s)
+                break
+        else:
+            offset = 0
+    if offset == 0:
+        return list(lines)
+    newlines = []
+    def readline_generator(lines):
+        for line in lines:
+            yield line + '\n'
+        while True:
+            yield ''
+
+    it = readline_generator(lines)
+
+    try:
+        for _, _, (sline, _), (eline, _), _ in tokenize.generate_tokens(lambda: next(it)):
+            if sline > len(lines):
+                break # End of input reached
+            if sline > len(newlines):
+                line = lines[sline - 1].expandtabs()
+                if line.lstrip() and line[:offset].isspace():
+                    line = line[offset:] # Deindent
+                newlines.append(line)
+
+            for i in range(sline, eline):
+                # Don't deindent continuing lines of
+                # multiline tokens (i.e. multiline strings)
+                newlines.append(lines[i])
+    except (IndentationError, tokenize.TokenError):
+        pass
+    # Add any lines we didn't see. E.g. if an exception was raised.
+    newlines.extend(lines[len(newlines):])
+    return newlines
+
+
+def get_statement_startend2(lineno, node):
+    import ast
+    # flatten all statements and except handlers into one lineno-list
+    # AST's line numbers start indexing at 1
+    l = []
+    for x in ast.walk(node):
+        if isinstance(x, _ast.stmt) or isinstance(x, _ast.ExceptHandler):
+            l.append(x.lineno - 1)
+            for name in "finalbody", "orelse":
+                val = getattr(x, name, None)
+                if val:
+                    # treat the finally/orelse part as its own statement
+                    l.append(val[0].lineno - 1 - 1)
+    l.sort()
+    insert_index = bisect_right(l, lineno)
+    start = l[insert_index - 1]
+    if insert_index >= len(l):
+        end = None
+    else:
+        end = l[insert_index]
+    return start, end
+
+
+def getstatementrange_ast(lineno, source, assertion=False, astnode=None):
+    if astnode is None:
+        content = str(source)
+        if sys.version_info < (2,7):
+            content += "\n"
+        try:
+            astnode = compile(content, "source", "exec", 1024)  # 1024 for AST
+        except ValueError:
+            start, end = getstatementrange_old(lineno, source, assertion)
+            return None, start, end
+    start, end = get_statement_startend2(lineno, astnode)
+    # we need to correct the end:
+    # - ast-parsing strips comments
+    # - there might be empty lines
+    # - we might have lesser indented code blocks at the end
+    if end is None:
+        end = len(source.lines)
+
+    if end > start + 1:
+        # make sure we don't span differently indented code blocks
+        # by using the BlockFinder helper used which inspect.getsource() uses itself
+        block_finder = inspect.BlockFinder()
+        # if we start with an indented line, put blockfinder to "started" mode
+        block_finder.started = source.lines[start][0].isspace()
+        it = ((x + "\n") for x in source.lines[start:end])
+        try:
+            for tok in tokenize.generate_tokens(lambda: next(it)):
+                block_finder.tokeneater(*tok)
+        except (inspect.EndOfBlock, IndentationError):
+            end = block_finder.last + start
+        except Exception:
+            pass
+
+    # the end might still point to a comment or empty line, correct it
+    while end:
+        line = source.lines[end - 1].lstrip()
+        if line.startswith("#") or not line:
+            end -= 1
+        else:
+            break
+    return astnode, start, end
+
+
+def getstatementrange_old(lineno, source, assertion=False):
+    """ return (start, end) tuple which spans the minimal
+        statement region which containing the given lineno.
+        raise an IndexError if no such statementrange can be found.
+    """
+    # XXX this logic is only used on python2.4 and below
+    # 1. find the start of the statement
+    from codeop import compile_command
+    for start in range(lineno, -1, -1):
+        if assertion:
+            line = source.lines[start]
+            # the following lines are not fully tested, change with care
+            if 'super' in line and 'self' in line and '__init__' in line:
+                raise IndexError("likely a subclass")
+            if "assert" not in line and "raise" not in line:
+                continue
+        trylines = source.lines[start:lineno+1]
+        # quick hack to prepare parsing an indented line with
+        # compile_command() (which errors on "return" outside defs)
+        trylines.insert(0, 'def xxx():')
+        trysource = '\n '.join(trylines)
+        #              ^ space here
+        try:
+            compile_command(trysource)
+        except (SyntaxError, OverflowError, ValueError):
+            continue
+
+        # 2. find the end of the statement
+        for end in range(lineno+1, len(source)+1):
+            trysource = source[start:end]
+            if trysource.isparseable():
+                return start, end
+    raise SyntaxError("no valid source range around line %d " % (lineno,))
+
+
--- a/third_party/python/py/py/_error.py
+++ b/third_party/python/py/py/_error.py
@@ -1,88 +1,89 @@
-"""
-create errno-specific classes for IO or os calls.
-
-"""
-import sys, os, errno
-
-class Error(EnvironmentError):
-    def __repr__(self):
-        return "%s.%s %r: %s " %(self.__class__.__module__,
-                               self.__class__.__name__,
-                               self.__class__.__doc__,
-                               " ".join(map(str, self.args)),
-                               #repr(self.args)
-                                )
-
-    def __str__(self):
-        s = "[%s]: %s" %(self.__class__.__doc__,
-                          " ".join(map(str, self.args)),
-                          )
-        return s
-
-_winerrnomap = {
-    2: errno.ENOENT,
-    3: errno.ENOENT,
-    17: errno.EEXIST,
-    13: errno.EBUSY, # empty cd drive, but ENOMEDIUM seems unavailiable
-    22: errno.ENOTDIR,
-    20: errno.ENOTDIR,
-    267: errno.ENOTDIR,
-    5: errno.EACCES,  # anything better?
-}
-
-class ErrorMaker(object):
-    """ lazily provides Exception classes for each possible POSIX errno
-        (as defined per the 'errno' module).  All such instances
-        subclass EnvironmentError.
-    """
-    Error = Error
-    _errno2class = {}
-
-    def __getattr__(self, name):
-        if name[0] == "_":
-            raise AttributeError(name)
-        eno = getattr(errno, name)
-        cls = self._geterrnoclass(eno)
-        setattr(self, name, cls)
-        return cls
-
-    def _geterrnoclass(self, eno):
-        try:
-            return self._errno2class[eno]
-        except KeyError:
-            clsname = errno.errorcode.get(eno, "UnknownErrno%d" %(eno,))
-            errorcls = type(Error)(clsname, (Error,),
-                    {'__module__':'py.error',
-                     '__doc__': os.strerror(eno)})
-            self._errno2class[eno] = errorcls
-            return errorcls
-
-    def checked_call(self, func, *args, **kwargs):
-        """ call a function and raise an errno-exception if applicable. """
-        __tracebackhide__ = True
-        try:
-            return func(*args, **kwargs)
-        except self.Error:
-            raise
-        except (OSError, EnvironmentError):
-            cls, value, tb = sys.exc_info()
-            if not hasattr(value, 'errno'):
-                raise
-            __tracebackhide__ = False
-            errno = value.errno
-            try:
-                if not isinstance(value, WindowsError):
-                    raise NameError
-            except NameError:
-                # we are not on Windows, or we got a proper OSError
-                cls = self._geterrnoclass(errno)
-            else:
-                try:
-                    cls = self._geterrnoclass(_winerrnomap[errno])
-                except KeyError:
-                    raise value
-            raise cls("%s%r" % (func.__name__, args))
-            __tracebackhide__ = True
-            
-
-error = ErrorMaker()
+"""
+create errno-specific classes for IO or os calls.
+
+"""
+import sys, os, errno
+
+class Error(EnvironmentError):
+    def __repr__(self):
+        return "%s.%s %r: %s " %(self.__class__.__module__,
+                               self.__class__.__name__,
+                               self.__class__.__doc__,
+                               " ".join(map(str, self.args)),
+                               #repr(self.args)
+                                )
+
+    def __str__(self):
+        s = "[%s]: %s" %(self.__class__.__doc__,
+                          " ".join(map(str, self.args)),
+                          )
+        return s
+
+_winerrnomap = {
+    2: errno.ENOENT,
+    3: errno.ENOENT,
+    17: errno.EEXIST,
+    18: errno.EXDEV,
+    13: errno.EBUSY, # empty cd drive, but ENOMEDIUM seems unavailiable
+    22: errno.ENOTDIR,
+    20: errno.ENOTDIR,
+    267: errno.ENOTDIR,
+    5: errno.EACCES,  # anything better?
+}
+
+class ErrorMaker(object):
+    """ lazily provides Exception classes for each possible POSIX errno
+        (as defined per the 'errno' module).  All such instances
+        subclass EnvironmentError.
+    """
+    Error = Error
+    _errno2class = {}
+
+    def __getattr__(self, name):
+        if name[0] == "_":
+            raise AttributeError(name)
+        eno = getattr(errno, name)
+        cls = self._geterrnoclass(eno)
+        setattr(self, name, cls)
+        return cls
+
+    def _geterrnoclass(self, eno):
+        try:
+            return self._errno2class[eno]
+        except KeyError:
+            clsname = errno.errorcode.get(eno, "UnknownErrno%d" %(eno,))
+            errorcls = type(Error)(clsname, (Error,),
+                    {'__module__':'py.error',
+                     '__doc__': os.strerror(eno)})
+            self._errno2class[eno] = errorcls
+            return errorcls
+
+    def checked_call(self, func, *args, **kwargs):
+        """ call a function and raise an errno-exception if applicable. """
+        __tracebackhide__ = True
+        try:
+            return func(*args, **kwargs)
+        except self.Error:
+            raise
+        except (OSError, EnvironmentError):
+            cls, value, tb = sys.exc_info()
+            if not hasattr(value, 'errno'):
+                raise
+            __tracebackhide__ = False
+            errno = value.errno
+            try:
+                if not isinstance(value, WindowsError):
+                    raise NameError
+            except NameError:
+                # we are not on Windows, or we got a proper OSError
+                cls = self._geterrnoclass(errno)
+            else:
+                try:
+                    cls = self._geterrnoclass(_winerrnomap[errno])
+                except KeyError:
+                    raise value
+            raise cls("%s%r" % (func.__name__, args))
+            __tracebackhide__ = True
+            
+
+error = ErrorMaker()
--- a/third_party/python/py/py/_iniconfig.py
+++ b/third_party/python/py/py/_iniconfig.py
@@ -1,162 +1,162 @@
-""" brain-dead simple parser for ini-style files.
-(C) Ronny Pfannschmidt, Holger Krekel -- MIT licensed
-"""
-__version__ = "0.2.dev2"
-
-__all__ = ['IniConfig', 'ParseError']
-
-COMMENTCHARS = "#;"
-
-class ParseError(Exception):
-    def __init__(self, path, lineno, msg):
-        Exception.__init__(self, path, lineno, msg)
-        self.path = path
-        self.lineno = lineno
-        self.msg = msg
-
-    def __str__(self):
-        return "%s:%s: %s" %(self.path, self.lineno+1, self.msg)
-
-class SectionWrapper(object):
-    def __init__(self, config, name):
-        self.config = config
-        self.name = name
-
-    def lineof(self, name):
-        return self.config.lineof(self.name, name)
-
-    def get(self, key, default=None, convert=str):
-        return self.config.get(self.name, key, convert=convert, default=default)
-
-    def __getitem__(self, key):
-        return self.config.sections[self.name][key]
-
-    def __iter__(self):
-        section = self.config.sections.get(self.name, [])
-        def lineof(key):
-            return self.config.lineof(self.name, key)
-        for name in sorted(section, key=lineof):
-            yield name
-
-    def items(self):
-        for name in self:
-            yield name, self[name]
-
-
-class IniConfig(object):
-    def __init__(self, path, data=None):
-        self.path = str(path) # convenience
-        if data is None:
-            f = open(self.path)
-            try:
-                tokens = self._parse(iter(f))
-            finally:
-                f.close()
-        else:
-            tokens = self._parse(data.splitlines(True))
-
-        self._sources = {}
-        self.sections = {}
-
-        for lineno, section, name, value in tokens:
-            if section is None:
-                self._raise(lineno, 'no section header defined')
-            self._sources[section, name] = lineno
-            if name is None:
-                if section in self.sections:
-                    self._raise(lineno, 'duplicate section %r'%(section, ))
-                self.sections[section] = {}
-            else:
-                if name in self.sections[section]:
-                    self._raise(lineno, 'duplicate name %r'%(name, ))
-                self.sections[section][name] = value
-
-    def _raise(self, lineno, msg):
-        raise ParseError(self.path, lineno, msg)
-
-    def _parse(self, line_iter):
-        result = []
-        section = None
-        for lineno, line in enumerate(line_iter):
-            name, data = self._parseline(line, lineno)
-            # new value
-            if name is not None and data is not None:
-                result.append((lineno, section, name, data))
-            # new section
-            elif name is not None and data is None:
-                if not name:
-                    self._raise(lineno, 'empty section name')
-                section = name
-                result.append((lineno, section, None, None))
-            # continuation
-            elif name is None and data is not None:
-                if not result:
-                    self._raise(lineno, 'unexpected value continuation')
-                last = result.pop()
-                last_name, last_data = last[-2:]
-                if last_name is None:
-                    self._raise(lineno, 'unexpected value continuation')
-
-                if last_data:
-                    data = '%s\n%s' % (last_data, data)
-                result.append(last[:-1] + (data,))
-        return result
-
-    def _parseline(self, line, lineno):
-        # blank lines
-        if iscommentline(line):
-            line = ""
-        else:
-            line = line.rstrip()
-        if not line:
-            return None, None
-        # section
-        if line[0] == '[':
-            realline = line
-            for c in COMMENTCHARS:
-                line = line.split(c)[0].rstrip()
-            if line[-1] == "]":
-                return line[1:-1], None
-            return None, realline.strip()
-        # value
-        elif not line[0].isspace():
-            try:
-                name, value = line.split('=', 1)
-                if ":" in name:
-                    raise ValueError()
-            except ValueError:
-                try:
-                    name, value = line.split(":", 1)
-                except ValueError:
-                    self._raise(lineno, 'unexpected line: %r' % line)
-            return name.strip(), value.strip()
-        # continuation
-        else:
-            return None, line.strip()
-
-    def lineof(self, section, name=None):
-        lineno = self._sources.get((section, name))
-        if lineno is not None:
-            return lineno + 1
-
-    def get(self, section, name, default=None, convert=str):
-        try:
-            return convert(self.sections[section][name])
-        except KeyError:
-            return default
-
-    def __getitem__(self, name):
-        if name not in self.sections:
-            raise KeyError(name)
-        return SectionWrapper(self, name)
-
-    def __iter__(self):
-        for name in sorted(self.sections, key=self.lineof):
-            yield SectionWrapper(self, name)
-
-    def __contains__(self, arg):
-        return arg in self.sections
-
-def iscommentline(line):
-    c = line.lstrip()[:1]
-    return c in COMMENTCHARS
+""" brain-dead simple parser for ini-style files.
+(C) Ronny Pfannschmidt, Holger Krekel -- MIT licensed
+"""
+__version__ = "0.2.dev2"
+
+__all__ = ['IniConfig', 'ParseError']
+
+COMMENTCHARS = "#;"
+
+class ParseError(Exception):
+    def __init__(self, path, lineno, msg):
+        Exception.__init__(self, path, lineno, msg)
+        self.path = path
+        self.lineno = lineno
+        self.msg = msg
+
+    def __str__(self):
+        return "%s:%s: %s" %(self.path, self.lineno+1, self.msg)
+
+class SectionWrapper(object):
+    def __init__(self, config, name):
+        self.config = config
+        self.name = name
+
+    def lineof(self, name):
+        return self.config.lineof(self.name, name)
+
+    def get(self, key, default=None, convert=str):
+        return self.config.get(self.name, key, convert=convert, default=default)
+
+    def __getitem__(self, key):
+        return self.config.sections[self.name][key]
+
+    def __iter__(self):
+        section = self.config.sections.get(self.name, [])
+        def lineof(key):
+            return self.config.lineof(self.name, key)
+        for name in sorted(section, key=lineof):
+            yield name
+
+    def items(self):
+        for name in self:
+            yield name, self[name]
+
+
+class IniConfig(object):
+    def __init__(self, path, data=None):
+        self.path = str(path) # convenience
+        if data is None:
+            f = open(self.path)
+            try:
+                tokens = self._parse(iter(f))
+            finally:
+                f.close()
+        else:
+            tokens = self._parse(data.splitlines(True))
+
+        self._sources = {}
+        self.sections = {}
+
+        for lineno, section, name, value in tokens:
+            if section is None:
+                self._raise(lineno, 'no section header defined')
+            self._sources[section, name] = lineno
+            if name is None:
+                if section in self.sections:
+                    self._raise(lineno, 'duplicate section %r'%(section, ))
+                self.sections[section] = {}
+            else:
+                if name in self.sections[section]:
+                    self._raise(lineno, 'duplicate name %r'%(name, ))
+                self.sections[section][name] = value
+
+    def _raise(self, lineno, msg):
+        raise ParseError(self.path, lineno, msg)
+
+    def _parse(self, line_iter):
+        result = []
+        section = None
+        for lineno, line in enumerate(line_iter):
+            name, data = self._parseline(line, lineno)
+            # new value
+            if name is not None and data is not None:
+                result.append((lineno, section, name, data))
+            # new section
+            elif name is not None and data is None:
+                if not name:
+                    self._raise(lineno, 'empty section name')
+                section = name
+                result.append((lineno, section, None, None))
+            # continuation
+            elif name is None and data is not None:
+                if not result:
+                    self._raise(lineno, 'unexpected value continuation')
+                last = result.pop()
+                last_name, last_data = last[-2:]
+                if last_name is None:
+                    self._raise(lineno, 'unexpected value continuation')
+
+                if last_data:
+                    data = '%s\n%s' % (last_data, data)
+                result.append(last[:-1] + (data,))
+        return result
+
+    def _parseline(self, line, lineno):
+        # blank lines
+        if iscommentline(line):
+            line = ""
+        else:
+            line = line.rstrip()
+        if not line:
+            return None, None
+        # section
+        if line[0] == '[':
+            realline = line
+            for c in COMMENTCHARS:
+                line = line.split(c)[0].rstrip()
+            if line[-1] == "]":
+                return line[1:-1], None
+            return None, realline.strip()
+        # value
+        elif not line[0].isspace():
+            try:
+                name, value = line.split('=', 1)
+                if ":" in name:
+                    raise ValueError()
+            except ValueError:
+                try:
+                    name, value = line.split(":", 1)
+                except ValueError:
+                    self._raise(lineno, 'unexpected line: %r' % line)
+            return name.strip(), value.strip()
+        # continuation
+        else:
+            return None, line.strip()
+
+    def lineof(self, section, name=None):
+        lineno = self._sources.get((section, name))
+        if lineno is not None:
+            return lineno + 1
+
+    def get(self, section, name, default=None, convert=str):
+        try:
+            return convert(self.sections[section][name])
+        except KeyError:
+            return default
+
+    def __getitem__(self, name):
+        if name not in self.sections:
+            raise KeyError(name)
+        return SectionWrapper(self, name)
+
+    def __iter__(self):
+        for name in sorted(self.sections, key=self.lineof):
+            yield SectionWrapper(self, name)
+
+    def __contains__(self, arg):
+        return arg in self.sections
+
+def iscommentline(line):
+    c = line.lstrip()[:1]
+    return c in COMMENTCHARS
--- a/third_party/python/py/py/_io/__init__.py
+++ b/third_party/python/py/py/_io/__init__.py
@@ -1,1 +1,1 @@
-""" input/output helping """
+""" input/output helping """
--- a/third_party/python/py/py/_io/capture.py
+++ b/third_party/python/py/py/_io/capture.py
@@ -1,371 +1,371 @@
-import os
-import sys
-import py
-import tempfile
-
-try:
-    from io import StringIO
-except ImportError:
-    from StringIO import StringIO
-
-if sys.version_info < (3,0):
-    class TextIO(StringIO):
-        def write(self, data):
-            if not isinstance(data, unicode):
-                data = unicode(data, getattr(self, '_encoding', 'UTF-8'), 'replace')
-            StringIO.write(self, data)
-else:
-    TextIO = StringIO
-
-try:
-    from io import BytesIO
-except ImportError:
-    class BytesIO(StringIO):
-        def write(self, data):
-            if isinstance(data, unicode):
-                raise TypeError("not a byte value: %r" %(data,))
-            StringIO.write(self, data)
-
-patchsysdict = {0: 'stdin', 1: 'stdout', 2: 'stderr'}
-
-class FDCapture:
-    """ Capture IO to/from a given os-level filedescriptor. """
-
-    def __init__(self, targetfd, tmpfile=None, now=True, patchsys=False):
-        """ save targetfd descriptor, and open a new
-            temporary file there.  If no tmpfile is
-            specified a tempfile.Tempfile() will be opened
-            in text mode.
-        """
-        self.targetfd = targetfd
-        if tmpfile is None and targetfd != 0:
-            f = tempfile.TemporaryFile('wb+')
-            tmpfile = dupfile(f, encoding="UTF-8")
-            f.close()
-        self.tmpfile = tmpfile
-        self._savefd = os.dup(self.targetfd)
-        if patchsys:
-            self._oldsys = getattr(sys, patchsysdict[targetfd])
-        if now:
-            self.start()
-
-    def start(self):
-        try:
-            os.fstat(self._savefd)
-        except OSError:
-            raise ValueError("saved filedescriptor not valid, "
-                "did you call start() twice?")
-        if self.targetfd == 0 and not self.tmpfile:
-            fd = os.open(devnullpath, os.O_RDONLY)
-            os.dup2(fd, 0)
-            os.close(fd)
-            if hasattr(self, '_oldsys'):
-                setattr(sys, patchsysdict[self.targetfd], DontReadFromInput())
-        else:
-            os.dup2(self.tmpfile.fileno(), self.targetfd)
-            if hasattr(self, '_oldsys'):
-                setattr(sys, patchsysdict[self.targetfd], self.tmpfile)
-
-    def done(self):
-        """ unpatch and clean up, returns the self.tmpfile (file object)
-        """
-        os.dup2(self._savefd, self.targetfd)
-        os.close(self._savefd)
-        if self.targetfd != 0:
-            self.tmpfile.seek(0)
-        if hasattr(self, '_oldsys'):
-            setattr(sys, patchsysdict[self.targetfd], self._oldsys)
-        return self.tmpfile
-
-    def writeorg(self, data):
-        """ write a string to the original file descriptor
-        """
-        tempfp = tempfile.TemporaryFile()
-        try:
-            os.dup2(self._savefd, tempfp.fileno())
-            tempfp.write(data)
-        finally:
-            tempfp.close()
-
-
-def dupfile(f, mode=None, buffering=0, raising=False, encoding=None):
-    """ return a new open file object that's a duplicate of f
-
-        mode is duplicated if not given, 'buffering' controls
-        buffer size (defaulting to no buffering) and 'raising'
-        defines whether an exception is raised when an incompatible
-        file object is passed in (if raising is False, the file
-        object itself will be returned)
-    """
-    try:
-        fd = f.fileno()
-        mode = mode or f.mode
-    except AttributeError:
-        if raising:
-            raise
-        return f
-    newfd = os.dup(fd)
-    if sys.version_info >= (3,0):
-        if encoding is not None:
-            mode = mode.replace("b", "")
-            buffering = True
-        return os.fdopen(newfd, mode, buffering, encoding, closefd=True)
-    else:
-        f = os.fdopen(newfd, mode, buffering)
-        if encoding is not None:
-            return EncodedFile(f, encoding)
-        return f
-
-class EncodedFile(object):
-    def __init__(self, _stream, encoding):
-        self._stream = _stream
-        self.encoding = encoding
-
-    def write(self, obj):
-        if isinstance(obj, unicode):
-            obj = obj.encode(self.encoding)
-        elif isinstance(obj, str):
-            pass
-        else:
-            obj = str(obj)
-        self._stream.write(obj)
-
-    def writelines(self, linelist):
-        data = ''.join(linelist)
-        self.write(data)
-
-    def __getattr__(self, name):
-        return getattr(self._stream, name)
-
-class Capture(object):
-    def call(cls, func, *args, **kwargs):
-        """ return a (res, out, err) tuple where
-            out and err represent the output/error output
-            during function execution.
-            call the given function with args/kwargs
-            and capture output/error during its execution.
-        """
-        so = cls()
-        try:
-            res = func(*args, **kwargs)
-        finally:
-            out, err = so.reset()
-        return res, out, err
-    call = classmethod(call)
-
-    def reset(self):
-        """ reset sys.stdout/stderr and return captured output as strings. """
-        if hasattr(self, '_reset'):
-            raise ValueError("was already reset")
-        self._reset = True
-        outfile, errfile = self.done(save=False)
-        out, err = "", ""
-        if outfile and not outfile.closed:
-            out = outfile.read()
-            outfile.close()
-        if errfile and errfile != outfile and not errfile.closed:
-            err = errfile.read()
-            errfile.close()
-        return out, err
-
-    def suspend(self):
-        """ return current snapshot captures, memorize tempfiles. """
-        outerr = self.readouterr()
-        outfile, errfile = self.done()
-        return outerr
-
-
-class StdCaptureFD(Capture):
-    """ This class allows to capture writes to FD1 and FD2
-        and may connect a NULL file to FD0 (and prevent
-        reads from sys.stdin).  If any of the 0,1,2 file descriptors
-        is invalid it will not be captured.
-    """
-    def __init__(self, out=True, err=True, mixed=False,
-        in_=True, patchsys=True, now=True):
-        self._options = {
-            "out": out,
-            "err": err,
-            "mixed": mixed,
-            "in_": in_,
-            "patchsys": patchsys,
-            "now": now,
-        }
-        self._save()
-        if now:
-            self.startall()
-
-    def _save(self):
-        in_ = self._options['in_']
-        out = self._options['out']
-        err = self._options['err']
-        mixed = self._options['mixed']
-        patchsys = self._options['patchsys']
-        if in_:
-            try:
-                self.in_ = FDCapture(0, tmpfile=None, now=False,
-                    patchsys=patchsys)
-            except OSError:
-                pass
-        if out:
-            tmpfile = None
-            if hasattr(out, 'write'):
-                tmpfile = out
-            try:
-                self.out = FDCapture(1, tmpfile=tmpfile,
-                           now=False, patchsys=patchsys)
-                self._options['out'] = self.out.tmpfile
-            except OSError:
-                pass
-        if err:
-            if out and mixed:
-                tmpfile = self.out.tmpfile
-            elif hasattr(err, 'write'):
-                tmpfile = err
-            else:
-                tmpfile = None
-            try:
-                self.err = FDCapture(2, tmpfile=tmpfile,
-                           now=False, patchsys=patchsys)
-                self._options['err'] = self.err.tmpfile
-            except OSError:
-                pass
-
-    def startall(self):
-        if hasattr(self, 'in_'):
-            self.in_.start()
-        if hasattr(self, 'out'):
-            self.out.start()
-        if hasattr(self, 'err'):
-            self.err.start()
-
-    def resume(self):
-        """ resume capturing with original temp files. """
-        self.startall()
-
-    def done(self, save=True):
-        """ return (outfile, errfile) and stop capturing. """
-        outfile = errfile = None
-        if hasattr(self, 'out') and not self.out.tmpfile.closed:
-            outfile = self.out.done()
-        if hasattr(self, 'err') and not self.err.tmpfile.closed:
-            errfile = self.err.done()
-        if hasattr(self, 'in_'):
-            tmpfile = self.in_.done()
-        if save:
-            self._save()
-        return outfile, errfile
-
-    def readouterr(self):
-        """ return snapshot value of stdout/stderr capturings. """
-        if hasattr(self, "out"):
-            out = self._readsnapshot(self.out.tmpfile)
-        else:
-            out = ""
-        if hasattr(self, "err"):
-            err = self._readsnapshot(self.err.tmpfile)
-        else:
-            err = ""
-        return [out, err]
-
-    def _readsnapshot(self, f):
-        f.seek(0)
-        res = f.read()
-        enc = getattr(f, "encoding", None)
-        if enc:
-            res = py.builtin._totext(res, enc, "replace")
-        f.truncate(0)
-        f.seek(0)
-        return res
-
-
-class StdCapture(Capture):
-    """ This class allows to capture writes to sys.stdout|stderr "in-memory"
-        and will raise errors on tries to read from sys.stdin. It only
-        modifies sys.stdout|stderr|stdin attributes and does not
-        touch underlying File Descriptors (use StdCaptureFD for that).
-    """
-    def __init__(self, out=True, err=True, in_=True, mixed=False, now=True):
-        self._oldout = sys.stdout
-        self._olderr = sys.stderr
-        self._oldin  = sys.stdin
-        if out and not hasattr(out, 'file'):
-            out = TextIO()
-        self.out = out
-        if err:
-            if mixed:
-                err = out
-            elif not hasattr(err, 'write'):
-                err = TextIO()
-        self.err = err
-        self.in_ = in_
-        if now:
-            self.startall()
-
-    def startall(self):
-        if self.out:
-            sys.stdout = self.out
-        if self.err:
-            sys.stderr = self.err
-        if self.in_:
-            sys.stdin  = self.in_  = DontReadFromInput()
-
-    def done(self, save=True):
-        """ return (outfile, errfile) and stop capturing. """
-        outfile = errfile = None
-        if self.out and not self.out.closed:
-            sys.stdout = self._oldout
-            outfile = self.out
-            outfile.seek(0)
-        if self.err and not self.err.closed:
-            sys.stderr = self._olderr
-            errfile = self.err
-            errfile.seek(0)
-        if self.in_:
-            sys.stdin = self._oldin
-        return outfile, errfile
-
-    def resume(self):
-        """ resume capturing with original temp files. """
-        self.startall()
-
-    def readouterr(self):
-        """ return snapshot value of stdout/stderr capturings. """
-        out = err = ""
-        if self.out:
-            out = self.out.getvalue()
-            self.out.truncate(0)
-            self.out.seek(0)
-        if self.err:
-            err = self.err.getvalue()
-            self.err.truncate(0)
-            self.err.seek(0)
-        return out, err
-
-class DontReadFromInput:
-    """Temporary stub class.  Ideally when stdin is accessed, the
-    capturing should be turned off, with possibly all data captured
-    so far sent to the screen.  This should be configurable, though,
-    because in automated test runs it is better to crash than
-    hang indefinitely.
-    """
-    def read(self, *args):
-        raise IOError("reading from stdin while output is captured")
-    readline = read
-    readlines = read
-    __iter__ = read
-
-    def fileno(self):
-        raise ValueError("redirected Stdin is pseudofile, has no fileno()")
-    def isatty(self):
-        return False
-    def close(self):
-        pass
-
-try:
-    devnullpath = os.devnull
-except AttributeError:
-    if os.name == 'nt':
-        devnullpath = 'NUL'
-    else:
-        devnullpath = '/dev/null'
+import os
+import sys
+import py
+import tempfile
+
+try:
+    from io import StringIO
+except ImportError:
+    from StringIO import StringIO
+
+if sys.version_info < (3,0):
+    class TextIO(StringIO):
+        def write(self, data):
+            if not isinstance(data, unicode):
+                data = unicode(data, getattr(self, '_encoding', 'UTF-8'), 'replace')
+            StringIO.write(self, data)
+else:
+    TextIO = StringIO
+
+try:
+    from io import BytesIO
+except ImportError:
+    class BytesIO(StringIO):
+        def write(self, data):
+            if isinstance(data, unicode):
+                raise TypeError("not a byte value: %r" %(data,))
+            StringIO.write(self, data)
+
+patchsysdict = {0: 'stdin', 1: 'stdout', 2: 'stderr'}
+
+class FDCapture:
+    """ Capture IO to/from a given os-level filedescriptor. """
+
+    def __init__(self, targetfd, tmpfile=None, now=True, patchsys=False):
+        """ save targetfd descriptor, and open a new
+            temporary file there.  If no tmpfile is
+            specified a tempfile.Tempfile() will be opened
+            in text mode.
+        """
+        self.targetfd = targetfd
+        if tmpfile is None and targetfd != 0:
+            f = tempfile.TemporaryFile('wb+')
+            tmpfile = dupfile(f, encoding="UTF-8")
+            f.close()
+        self.tmpfile = tmpfile
+        self._savefd = os.dup(self.targetfd)
+        if patchsys:
+            self._oldsys = getattr(sys, patchsysdict[targetfd])
+        if now:
+            self.start()
+
+    def start(self):
+        try:
+            os.fstat(self._savefd)
+        except OSError:
+            raise ValueError("saved filedescriptor not valid, "
+                "did you call start() twice?")
+        if self.targetfd == 0 and not self.tmpfile:
+            fd = os.open(devnullpath, os.O_RDONLY)
+            os.dup2(fd, 0)
+            os.close(fd)
+            if hasattr(self, '_oldsys'):
+                setattr(sys, patchsysdict[self.targetfd], DontReadFromInput())
+        else:
+            os.dup2(self.tmpfile.fileno(), self.targetfd)
+            if hasattr(self, '_oldsys'):
+                setattr(sys, patchsysdict[self.targetfd], self.tmpfile)
+
+    def done(self):
+        """ unpatch and clean up, returns the self.tmpfile (file object)
+        """
+        os.dup2(self._savefd, self.targetfd)
+        os.close(self._savefd)
+        if self.targetfd != 0:
+            self.tmpfile.seek(0)
+        if hasattr(self, '_oldsys'):
+            setattr(sys, patchsysdict[self.targetfd], self._oldsys)
+        return self.tmpfile
+
+    def writeorg(self, data):
+        """ write a string to the original file descriptor
+        """
+        tempfp = tempfile.TemporaryFile()
+        try:
+            os.dup2(self._savefd, tempfp.fileno())
+            tempfp.write(data)
+        finally:
+            tempfp.close()
+
+
+def dupfile(f, mode=None, buffering=0, raising=False, encoding=None):
+    """ return a new open file object that's a duplicate of f
+
+        mode is duplicated if not given, 'buffering' controls
+        buffer size (defaulting to no buffering) and 'raising'
+        defines whether an exception is raised when an incompatible
+        file object is passed in (if raising is False, the file
+        object itself will be returned)
+    """
+    try:
+        fd = f.fileno()
+        mode = mode or f.mode
+    except AttributeError:
+        if raising:
+            raise
+        return f
+    newfd = os.dup(fd)
+    if sys.version_info >= (3,0):
+        if encoding is not None:
+            mode = mode.replace("b", "")
+            buffering = True
+        return os.fdopen(newfd, mode, buffering, encoding, closefd=True)
+    else:
+        f = os.fdopen(newfd, mode, buffering)
+        if encoding is not None:
+            return EncodedFile(f, encoding)
+        return f
+
+class EncodedFile(object):
+    def __init__(self, _stream, encoding):
+        self._stream = _stream
+        self.encoding = encoding
+
+    def write(self, obj):
+        if isinstance(obj, unicode):
+            obj = obj.encode(self.encoding)
+        elif isinstance(obj, str):
+            pass
+        else:
+            obj = str(obj)
+        self._stream.write(obj)
+
+    def writelines(self, linelist):
+        data = ''.join(linelist)
+        self.write(data)
+
+    def __getattr__(self, name):
+        return getattr(self._stream, name)
+
+class Capture(object):
+    def call(cls, func, *args, **kwargs):
+        """ return a (res, out, err) tuple where
+            out and err represent the output/error output
+            during function execution.
+            call the given function with args/kwargs
+            and capture output/error during its execution.
+        """
+        so = cls()
+        try:
+            res = func(*args, **kwargs)
+        finally:
+            out, err = so.reset()
+        return res, out, err
+    call = classmethod(call)
+
+    def reset(self):
+        """ reset sys.stdout/stderr and return captured output as strings. """
+        if hasattr(self, '_reset'):
+            raise ValueError("was already reset")
+        self._reset = True
+        outfile, errfile = self.done(save=False)
+        out, err = "", ""
+        if outfile and not outfile.closed:
+            out = outfile.read()
+            outfile.close()
+        if errfile and errfile != outfile and not errfile.closed:
+            err = errfile.read()
+            errfile.close()
+        return out, err
+
+    def suspend(self):
+        """ return current snapshot captures, memorize tempfiles. """
+        outerr = self.readouterr()
+        outfile, errfile = self.done()
+        return outerr
+
+
+class StdCaptureFD(Capture):
+    """ This class allows to capture writes to FD1 and FD2
+        and may connect a NULL file to FD0 (and prevent
+        reads from sys.stdin).  If any of the 0,1,2 file descriptors
+        is invalid it will not be captured.
+    """
+    def __init__(self, out=True, err=True, mixed=False,
+        in_=True, patchsys=True, now=True):
+        self._options = {
+            "out": out,
+            "err": err,
+            "mixed": mixed,
+            "in_": in_,
+            "patchsys": patchsys,
+            "now": now,
+        }
+        self._save()
+        if now:
+            self.startall()
+
+    def _save(self):
+        in_ = self._options['in_']
+        out = self._options['out']
+        err = self._options['err']
+        mixed = self._options['mixed']
+        patchsys = self._options['patchsys']
+        if in_:
+            try:
+                self.in_ = FDCapture(0, tmpfile=None, now=False,
+                    patchsys=patchsys)
+            except OSError:
+                pass
+        if out:
+            tmpfile = None
+            if hasattr(out, 'write'):
+                tmpfile = out
+            try:
+                self.out = FDCapture(1, tmpfile=tmpfile,
+                           now=False, patchsys=patchsys)
+                self._options['out'] = self.out.tmpfile
+            except OSError:
+                pass
+        if err:
+            if out and mixed:
+                tmpfile = self.out.tmpfile
+            elif hasattr(err, 'write'):
+                tmpfile = err
+            else:
+                tmpfile = None
+            try:
+                self.err = FDCapture(2, tmpfile=tmpfile,
+                           now=False, patchsys=patchsys)
+                self._options['err'] = self.err.tmpfile
+            except OSError:
+                pass
+
+    def startall(self):
+        if hasattr(self, 'in_'):
+            self.in_.start()
+        if hasattr(self, 'out'):
+            self.out.start()
+        if hasattr(self, 'err'):
+            self.err.start()
+
+    def resume(self):
+        """ resume capturing with original temp files. """
+        self.startall()
+
+    def done(self, save=True):
+        """ return (outfile, errfile) and stop capturing. """
+        outfile = errfile = None
+        if hasattr(self, 'out') and not self.out.tmpfile.closed:
+            outfile = self.out.done()
+        if hasattr(self, 'err') and not self.err.tmpfile.closed:
+            errfile = self.err.done()
+        if hasattr(self, 'in_'):
+            tmpfile = self.in_.done()
+        if save:
+            self._save()
+        return outfile, errfile
+
+    def readouterr(self):
+        """ return snapshot value of stdout/stderr capturings. """
+        if hasattr(self, "out"):
+            out = self._readsnapshot(self.out.tmpfile)
+        else:
+            out = ""
+        if hasattr(self, "err"):
+            err = self._readsnapshot(self.err.tmpfile)
+        else:
+            err = ""
+        return [out, err]
+
+    def _readsnapshot(self, f):
+        f.seek(0)
+        res = f.read()
+        enc = getattr(f, "encoding", None)
+        if enc:
+            res = py.builtin._totext(res, enc, "replace")
+        f.truncate(0)
+        f.seek(0)
+        return res
+
+
+class StdCapture(Capture):
+    """ This class allows to capture writes to sys.stdout|stderr "in-memory"
+        and will raise errors on tries to read from sys.stdin. It only
+        modifies sys.stdout|stderr|stdin attributes and does not
+        touch underlying File Descriptors (use StdCaptureFD for that).
+    """
+    def __init__(self, out=True, err=True, in_=True, mixed=False, now=True):
+        self._oldout = sys.stdout
+        self._olderr = sys.stderr
+        self._oldin  = sys.stdin
+        if out and not hasattr(out, 'file'):
+            out = TextIO()
+        self.out = out
+        if err:
+            if mixed:
+                err = out
+            elif not hasattr(err, 'write'):
+                err = TextIO()
+        self.err = err
+        self.in_ = in_
+        if now:
+            self.startall()
+
+    def startall(self):
+        if self.out:
+            sys.stdout = self.out
+        if self.err:
+            sys.stderr = self.err
+        if self.in_:
+            sys.stdin  = self.in_  = DontReadFromInput()
+
+    def done(self, save=True):
+        """ return (outfile, errfile) and stop capturing. """
+        outfile = errfile = None
+        if self.out and not self.out.closed:
+            sys.stdout = self._oldout
+            outfile = self.out
+            outfile.seek(0)
+        if self.err and not self.err.closed:
+            sys.stderr = self._olderr
+            errfile = self.err
+            errfile.seek(0)
+        if self.in_:
+            sys.stdin = self._oldin
+        return outfile, errfile
+
+    def resume(self):
+        """ resume capturing with original temp files. """
+        self.startall()
+
+    def readouterr(self):
+        """ return snapshot value of stdout/stderr capturings. """
+        out = err = ""
+        if self.out:
+            out = self.out.getvalue()
+            self.out.truncate(0)
+            self.out.seek(0)
+        if self.err:
+            err = self.err.getvalue()
+            self.err.truncate(0)
+            self.err.seek(0)
+        return out, err
+
+class DontReadFromInput:
+    """Temporary stub class.  Ideally when stdin is accessed, the
+    capturing should be turned off, with possibly all data captured
+    so far sent to the screen.  This should be configurable, though,
+    because in automated test runs it is better to crash than
+    hang indefinitely.
+    """
+    def read(self, *args):
+        raise IOError("reading from stdin while output is captured")
+    readline = read
+    readlines = read
+    __iter__ = read
+
+    def fileno(self):
+        raise ValueError("redirected Stdin is pseudofile, has no fileno()")
+    def isatty(self):
+        return False
+    def close(self):
+        pass
+
+try:
+    devnullpath = os.devnull
+except AttributeError:
+    if os.name == 'nt':
+        devnullpath = 'NUL'
+    else:
+        devnullpath = '/dev/null'
--- a/third_party/python/py/py/_io/saferepr.py
+++ b/third_party/python/py/py/_io/saferepr.py
@@ -1,71 +1,71 @@
-import py
-import sys
-
-builtin_repr = repr
-
-reprlib = py.builtin._tryimport('repr', 'reprlib')
-
-class SafeRepr(reprlib.Repr):
-    """ subclass of repr.Repr that limits the resulting size of repr()
-        and includes information on exceptions raised during the call.
-    """
-    def repr(self, x):
-        return self._callhelper(reprlib.Repr.repr, self, x)
-
-    def repr_unicode(self, x, level):
-        # Strictly speaking wrong on narrow builds
-        def repr(u):
-            if "'" not in u:
-                return py.builtin._totext("'%s'") % u
-            elif '"' not in u:
-                return py.builtin._totext('"%s"') % u
-            else:
-                return py.builtin._totext("'%s'") % u.replace("'", r"\'")
-        s = repr(x[:self.maxstring])
-        if len(s) > self.maxstring:
-            i = max(0, (self.maxstring-3)//2)
-            j = max(0, self.maxstring-3-i)
-            s = repr(x[:i] + x[len(x)-j:])
-            s = s[:i] + '...' + s[len(s)-j:]
-        return s
-
-    def repr_instance(self, x, level):
-        return self._callhelper(builtin_repr, x)
-
-    def _callhelper(self, call, x, *args):
-        try:
-            # Try the vanilla repr and make sure that the result is a string
-            s = call(x, *args)
-        except py.builtin._sysex:
-            raise
-        except:
-            cls, e, tb = sys.exc_info()
-            exc_name = getattr(cls, '__name__', 'unknown')
-            try:
-                exc_info = str(e)
-            except py.builtin._sysex:
-                raise
-            except:
-                exc_info = 'unknown'
-            return '<[%s("%s") raised in repr()] %s object at 0x%x>' % (
-                exc_name, exc_info, x.__class__.__name__, id(x))
-        else:
-            if len(s) > self.maxsize:
-                i = max(0, (self.maxsize-3)//2)
-                j = max(0, self.maxsize-3-i)
-                s = s[:i] + '...' + s[len(s)-j:]
-            return s
-
-def saferepr(obj, maxsize=240):
-    """ return a size-limited safe repr-string for the given object.
-    Failing __repr__ functions of user instances will be represented
-    with a short exception info and 'saferepr' generally takes
-    care to never raise exceptions itself.  This function is a wrapper
-    around the Repr/reprlib functionality of the standard 2.6 lib.
-    """
-    # review exception handling
-    srepr = SafeRepr()
-    srepr.maxstring = maxsize
-    srepr.maxsize = maxsize
-    srepr.maxother = 160
-    return srepr.repr(obj)
+import py
+import sys
+
+builtin_repr = repr
+
+reprlib = py.builtin._tryimport('repr', 'reprlib')
+
+class SafeRepr(reprlib.Repr):
+    """ subclass of repr.Repr that limits the resulting size of repr()
+        and includes information on exceptions raised during the call.
+    """
+    def repr(self, x):
+        return self._callhelper(reprlib.Repr.repr, self, x)
+
+    def repr_unicode(self, x, level):
+        # Strictly speaking wrong on narrow builds
+        def repr(u):
+            if "'" not in u:
+                return py.builtin._totext("'%s'") % u
+            elif '"' not in u:
+                return py.builtin._totext('"%s"') % u
+            else:
+                return py.builtin._totext("'%s'") % u.replace("'", r"\'")
+        s = repr(x[:self.maxstring])
+        if len(s) > self.maxstring:
+            i = max(0, (self.maxstring-3)//2)
+            j = max(0, self.maxstring-3-i)
+            s = repr(x[:i] + x[len(x)-j:])
+            s = s[:i] + '...' + s[len(s)-j:]
+        return s
+
+    def repr_instance(self, x, level):
+        return self._callhelper(builtin_repr, x)
+
+    def _callhelper(self, call, x, *args):
+        try:
+            # Try the vanilla repr and make sure that the result is a string
+            s = call(x, *args)
+        except py.builtin._sysex:
+            raise
+        except:
+            cls, e, tb = sys.exc_info()
+            exc_name = getattr(cls, '__name__', 'unknown')
+            try:
+                exc_info = str(e)
+            except py.builtin._sysex:
+                raise
+            except:
+                exc_info = 'unknown'
+            return '<[%s("%s") raised in repr()] %s object at 0x%x>' % (
+                exc_name, exc_info, x.__class__.__name__, id(x))
+        else:
+            if len(s) > self.maxsize:
+                i = max(0, (self.maxsize-3)//2)
+                j = max(0, self.maxsize-3-i)
+                s = s[:i] + '...' + s[len(s)-j:]
+            return s
+
+def saferepr(obj, maxsize=240):
+    """ return a size-limited safe repr-string for the given object.
+    Failing __repr__ functions of user instances will be represented
+    with a short exception info and 'saferepr' generally takes
+    care to never raise exceptions itself.  This function is a wrapper
+    around the Repr/reprlib functionality of the standard 2.6 lib.
+    """
+    # review exception handling
+    srepr = SafeRepr()
+    srepr.maxstring = maxsize
+    srepr.maxsize = maxsize
+    srepr.maxother = 160
+    return srepr.repr(obj)
--- a/third_party/python/py/py/_io/terminalwriter.py
+++ b/third_party/python/py/py/_io/terminalwriter.py
@@ -1,348 +1,357 @@
-"""
-
-Helper functions for writing to terminals and files.
-
-"""
-
-
-import sys, os
-import py
-py3k = sys.version_info[0] >= 3
-from py.builtin import text, bytes
-
-win32_and_ctypes = False
-colorama = None
-if sys.platform == "win32":
-    try:
-        import colorama
-    except ImportError:
-        try:
-            import ctypes
-            win32_and_ctypes = True
-        except ImportError:
-            pass
-
-
-def _getdimensions():
-    import termios,fcntl,struct
-    call = fcntl.ioctl(1,termios.TIOCGWINSZ,"\000"*8)
-    height,width = struct.unpack( "hhhh", call ) [:2]
-    return height, width
-
-
-def get_terminal_width():
-    height = width = 0
-    try:
-        height, width = _getdimensions()
-    except py.builtin._sysex:
-        raise
-    except:
-        # pass to fallback below
-        pass
-
-    if width == 0:
-        # FALLBACK:
-        # * some exception happened
-        # * or this is emacs terminal which reports (0,0)
-        width = int(os.environ.get('COLUMNS', 80))
-
-    # XXX the windows getdimensions may be bogus, let's sanify a bit
-    if width < 40:
-        width = 80
-    return width
-
-terminal_width = get_terminal_width()
-
-# XXX unify with _escaped func below
-def ansi_print(text, esc, file=None, newline=True, flush=False):
-    if file is None:
-        file = sys.stderr
-    text = text.rstrip()
-    if esc and not isinstance(esc, tuple):
-        esc = (esc,)
-    if esc and sys.platform != "win32" and file.isatty():
-        text = (''.join(['\x1b[%sm' % cod for cod in esc])  +
-                text +
-                '\x1b[0m')     # ANSI color code "reset"
-    if newline:
-        text += '\n'
-
-    if esc and win32_and_ctypes and file.isatty():
-        if 1 in esc:
-            bold = True
-            esc = tuple([x for x in esc if x != 1])
-        else:
-            bold = False
-        esctable = {()   : FOREGROUND_WHITE,                 # normal
-                    (31,): FOREGROUND_RED,                   # red
-                    (32,): FOREGROUND_GREEN,                 # green
-                    (33,): FOREGROUND_GREEN|FOREGROUND_RED,  # yellow
-                    (34,): FOREGROUND_BLUE,                  # blue
-                    (35,): FOREGROUND_BLUE|FOREGROUND_RED,   # purple
-                    (36,): FOREGROUND_BLUE|FOREGROUND_GREEN, # cyan
-                    (37,): FOREGROUND_WHITE,                 # white
-                    (39,): FOREGROUND_WHITE,                 # reset
-                    }
-        attr = esctable.get(esc, FOREGROUND_WHITE)
-        if bold:
-            attr |= FOREGROUND_INTENSITY
-        STD_OUTPUT_HANDLE = -11
-        STD_ERROR_HANDLE = -12
-        if file is sys.stderr:
-            handle = GetStdHandle(STD_ERROR_HANDLE)
-        else:
-            handle = GetStdHandle(STD_OUTPUT_HANDLE)
-        oldcolors = GetConsoleInfo(handle).wAttributes
-        attr |= (oldcolors & 0x0f0)
-        SetConsoleTextAttribute(handle, attr)
-        while len(text) > 32768:
-            file.write(text[:32768])
-            text = text[32768:]
-        if text:
-            file.write(text)
-        SetConsoleTextAttribute(handle, oldcolors)
-    else:
-        file.write(text)
-
-    if flush:
-        file.flush()
-
-def should_do_markup(file):
-    if os.environ.get('PY_COLORS') == '1':
-        return True
-    if os.environ.get('PY_COLORS') == '0':
-        return False
-    return hasattr(file, 'isatty') and file.isatty() \
-           and os.environ.get('TERM') != 'dumb' \
-           and not (sys.platform.startswith('java') and os._name == 'nt')
-
-class TerminalWriter(object):
-    _esctable = dict(black=30, red=31, green=32, yellow=33,
-                     blue=34, purple=35, cyan=36, white=37,
-                     Black=40, Red=41, Green=42, Yellow=43,
-                     Blue=44, Purple=45, Cyan=46, White=47,
-                     bold=1, light=2, blink=5, invert=7)
-
-    # XXX deprecate stringio argument
-    def __init__(self, file=None, stringio=False, encoding=None):
-        if file is None:
-            if stringio:
-                self.stringio = file = py.io.TextIO()
-            else:
-                file = py.std.sys.stdout
-        elif py.builtin.callable(file) and not (
-             hasattr(file, "write") and hasattr(file, "flush")):
-            file = WriteFile(file, encoding=encoding)
-        if hasattr(file, "isatty") and file.isatty() and colorama:
-            file = colorama.AnsiToWin32(file).stream
-        self.encoding = encoding or getattr(file, 'encoding', "utf-8")
-        self._file = file
-        self.fullwidth = get_terminal_width()
-        self.hasmarkup = should_do_markup(file)
-        self._lastlen = 0
-
-    def _escaped(self, text, esc):
-        if esc and self.hasmarkup:
-            text = (''.join(['\x1b[%sm' % cod for cod in esc])  +
-                text +'\x1b[0m')
-        return text
-
-    def markup(self, text, **kw):
-        esc = []
-        for name in kw:
-            if name not in self._esctable:
-                raise ValueError("unknown markup: %r" %(name,))
-            if kw[name]:
-                esc.append(self._esctable[name])
-        return self._escaped(text, tuple(esc))
-
-    def sep(self, sepchar, title=None, fullwidth=None, **kw):
-        if fullwidth is None:
-            fullwidth = self.fullwidth
-        # the goal is to have the line be as long as possible
-        # under the condition that len(line) <= fullwidth
-        if sys.platform == "win32":
-            # if we print in the last column on windows we are on a
-            # new line but there is no way to verify/neutralize this
-            # (we may not know the exact line width)
-            # so let's be defensive to avoid empty lines in the output
-            fullwidth -= 1
-        if title is not None:
-            # we want 2 + 2*len(fill) + len(title) <= fullwidth
-            # i.e.    2 + 2*len(sepchar)*N + len(title) <= fullwidth
-            #         2*len(sepchar)*N <= fullwidth - len(title) - 2
-            #         N <= (fullwidth - len(title) - 2) // (2*len(sepchar))
-            N = (fullwidth - len(title) - 2) // (2*len(sepchar))
-            fill = sepchar * N
-            line = "%s %s %s" % (fill, title, fill)
-        else:
-            # we want len(sepchar)*N <= fullwidth
-            # i.e.    N <= fullwidth // len(sepchar)
-            line = sepchar * (fullwidth // len(sepchar))
-        # in some situations there is room for an extra sepchar at the right,
-        # in particular if we consider that with a sepchar like "_ " the
-        # trailing space is not important at the end of the line
-        if len(line) + len(sepchar.rstrip()) <= fullwidth:
-            line += sepchar.rstrip()
-
-        self.line(line, **kw)
-
-    def write(self, msg, **kw):
-        if msg:
-            if not isinstance(msg, (bytes, text)):
-                msg = text(msg)
-            if self.hasmarkup and kw:
-                markupmsg = self.markup(msg, **kw)
-            else:
-                markupmsg = msg
-            write_out(self._file, markupmsg)
-
-    def line(self, s='', **kw):
-        self.write(s, **kw)
-        self._checkfill(s)
-        self.write('\n')
-
-    def reline(self, line, **kw):
-        if not self.hasmarkup:
-            raise ValueError("cannot use rewrite-line without terminal")
-        self.write(line, **kw)
-        self._checkfill(line)
-        self.write('\r')
-        self._lastlen = len(line)
-
-    def _checkfill(self, line):
-        diff2last = self._lastlen - len(line)
-        if diff2last > 0:
-            self.write(" " * diff2last)
-
-class Win32ConsoleWriter(TerminalWriter):
-    def write(self, msg, **kw):
-        if msg:
-            if not isinstance(msg, (bytes, text)):
-                msg = text(msg)
-            oldcolors = None
-            if self.hasmarkup and kw:
-                handle = GetStdHandle(STD_OUTPUT_HANDLE)
-                oldcolors = GetConsoleInfo(handle).wAttributes
-                default_bg = oldcolors & 0x00F0
-                attr = default_bg
-                if kw.pop('bold', False):
-                    attr |= FOREGROUND_INTENSITY
-
-                if kw.pop('red', False):
-                    attr |= FOREGROUND_RED
-                elif kw.pop('blue', False):
-                    attr |= FOREGROUND_BLUE
-                elif kw.pop('green', False):
-                    attr |= FOREGROUND_GREEN
-                elif kw.pop('yellow', False):
-                    attr |= FOREGROUND_GREEN|FOREGROUND_RED
-                else:
-                    attr |= oldcolors & 0x0007
-
-                SetConsoleTextAttribute(handle, attr)
-            write_out(self._file, msg)
-            if oldcolors:
-                SetConsoleTextAttribute(handle, oldcolors)
-
-class WriteFile(object):
-    def __init__(self, writemethod, encoding=None):
-        self.encoding = encoding
-        self._writemethod = writemethod
-
-    def write(self, data):
-        if self.encoding:
-            data = data.encode(self.encoding, "replace")
-        self._writemethod(data)
-
-    def flush(self):
-        return
-
-
-if win32_and_ctypes:
-    TerminalWriter = Win32ConsoleWriter
-    import ctypes
-    from ctypes import wintypes
-
-    # ctypes access to the Windows console
-    STD_OUTPUT_HANDLE = -11
-    STD_ERROR_HANDLE  = -12
-    FOREGROUND_BLACK     = 0x0000 # black text
-    FOREGROUND_BLUE      = 0x0001 # text color contains blue.
-    FOREGROUND_GREEN     = 0x0002 # text color contains green.
-    FOREGROUND_RED       = 0x0004 # text color contains red.
-    FOREGROUND_WHITE     = 0x0007
-    FOREGROUND_INTENSITY = 0x0008 # text color is intensified.
-    BACKGROUND_BLACK     = 0x0000 # background color black
-    BACKGROUND_BLUE      = 0x0010 # background color contains blue.
-    BACKGROUND_GREEN     = 0x0020 # background color contains green.
-    BACKGROUND_RED       = 0x0040 # background color contains red.
-    BACKGROUND_WHITE     = 0x0070
-    BACKGROUND_INTENSITY = 0x0080 # background color is intensified.
-
-    SHORT = ctypes.c_short
-    class COORD(ctypes.Structure):
-        _fields_ = [('X', SHORT),
-                    ('Y', SHORT)]
-    class SMALL_RECT(ctypes.Structure):
-        _fields_ = [('Left', SHORT),
-                    ('Top', SHORT),
-                    ('Right', SHORT),
-                    ('Bottom', SHORT)]
-    class CONSOLE_SCREEN_BUFFER_INFO(ctypes.Structure):
-        _fields_ = [('dwSize', COORD),
-                    ('dwCursorPosition', COORD),
-                    ('wAttributes', wintypes.WORD),
-                    ('srWindow', SMALL_RECT),
-                    ('dwMaximumWindowSize', COORD)]
-
-    _GetStdHandle = ctypes.windll.kernel32.GetStdHandle
-    _GetStdHandle.argtypes = [wintypes.DWORD]
-    _GetStdHandle.restype = wintypes.HANDLE
-    def GetStdHandle(kind):
-        return _GetStdHandle(kind)
-
-    SetConsoleTextAttribute = ctypes.windll.kernel32.SetConsoleTextAttribute
-    SetConsoleTextAttribute.argtypes = [wintypes.HANDLE, wintypes.WORD]
-    SetConsoleTextAttribute.restype = wintypes.BOOL
-
-    _GetConsoleScreenBufferInfo = \
-        ctypes.windll.kernel32.GetConsoleScreenBufferInfo
-    _GetConsoleScreenBufferInfo.argtypes = [wintypes.HANDLE,
-                                ctypes.POINTER(CONSOLE_SCREEN_BUFFER_INFO)]
-    _GetConsoleScreenBufferInfo.restype = wintypes.BOOL
-    def GetConsoleInfo(handle):
-        info = CONSOLE_SCREEN_BUFFER_INFO()
-        _GetConsoleScreenBufferInfo(handle, ctypes.byref(info))
-        return info
-
-    def _getdimensions():
-        handle = GetStdHandle(STD_OUTPUT_HANDLE)
-        info = GetConsoleInfo(handle)
-        # Substract one from the width, otherwise the cursor wraps
-        # and the ending \n causes an empty line to display.
-        return info.dwSize.Y, info.dwSize.X - 1
-
-def write_out(fil, msg):
-    # XXX sometimes "msg" is of type bytes, sometimes text which
-    # complicates the situation.  Should we try to enforce unicode?
-    try:
-        # on py27 and above writing out to sys.stdout with an encoding
-        # should usually work for unicode messages (if the encoding is
-        # capable of it)
-        fil.write(msg)
-    except UnicodeEncodeError:
-        # on py26 it might not work because stdout expects bytes
-        if fil.encoding:
-            try:
-                fil.write(msg.encode(fil.encoding))
-            except UnicodeEncodeError:
-                # it might still fail if the encoding is not capable
-                pass
-            else:
-                fil.flush()
-                return
-        # fallback: escape all unicode characters
-        msg = msg.encode("unicode-escape").decode("ascii")
-        fil.write(msg)
-    fil.flush()
+"""
+
+Helper functions for writing to terminals and files.
+
+"""
+
+
+import sys, os
+import py
+py3k = sys.version_info[0] >= 3
+from py.builtin import text, bytes
+
+win32_and_ctypes = False
+colorama = None
+if sys.platform == "win32":
+    try:
+        import colorama
+    except ImportError:
+        try:
+            import ctypes
+            win32_and_ctypes = True
+        except ImportError:
+            pass
+
+
+def _getdimensions():
+    import termios,fcntl,struct
+    call = fcntl.ioctl(1,termios.TIOCGWINSZ,"\000"*8)
+    height,width = struct.unpack( "hhhh", call ) [:2]
+    return height, width
+
+
+def get_terminal_width():
+    height = width = 0
+    try:
+        height, width = _getdimensions()
+    except py.builtin._sysex:
+        raise
+    except:
+        # pass to fallback below
+        pass
+
+    if width == 0:
+        # FALLBACK:
+        # * some exception happened
+        # * or this is emacs terminal which reports (0,0)
+        width = int(os.environ.get('COLUMNS', 80))
+
+    # XXX the windows getdimensions may be bogus, let's sanify a bit
+    if width < 40:
+        width = 80
+    return width
+
+terminal_width = get_terminal_width()
+
+# XXX unify with _escaped func below
+def ansi_print(text, esc, file=None, newline=True, flush=False):
+    if file is None:
+        file = sys.stderr
+    text = text.rstrip()
+    if esc and not isinstance(esc, tuple):
+        esc = (esc,)
+    if esc and sys.platform != "win32" and file.isatty():
+        text = (''.join(['\x1b[%sm' % cod for cod in esc])  +
+                text +
+                '\x1b[0m')     # ANSI color code "reset"
+    if newline:
+        text += '\n'
+
+    if esc and win32_and_ctypes and file.isatty():
+        if 1 in esc:
+            bold = True
+            esc = tuple([x for x in esc if x != 1])
+        else:
+            bold = False
+        esctable = {()   : FOREGROUND_WHITE,                 # normal
+                    (31,): FOREGROUND_RED,                   # red
+                    (32,): FOREGROUND_GREEN,                 # green
+                    (33,): FOREGROUND_GREEN|FOREGROUND_RED,  # yellow
+                    (34,): FOREGROUND_BLUE,                  # blue
+                    (35,): FOREGROUND_BLUE|FOREGROUND_RED,   # purple
+                    (36,): FOREGROUND_BLUE|FOREGROUND_GREEN, # cyan
+                    (37,): FOREGROUND_WHITE,                 # white
+                    (39,): FOREGROUND_WHITE,                 # reset
+                    }
+        attr = esctable.get(esc, FOREGROUND_WHITE)
+        if bold:
+            attr |= FOREGROUND_INTENSITY
+        STD_OUTPUT_HANDLE = -11
+        STD_ERROR_HANDLE = -12
+        if file is sys.stderr:
+            handle = GetStdHandle(STD_ERROR_HANDLE)
+        else:
+            handle = GetStdHandle(STD_OUTPUT_HANDLE)
+        oldcolors = GetConsoleInfo(handle).wAttributes
+        attr |= (oldcolors & 0x0f0)
+        SetConsoleTextAttribute(handle, attr)
+        while len(text) > 32768:
+            file.write(text[:32768])
+            text = text[32768:]
+        if text:
+            file.write(text)
+        SetConsoleTextAttribute(handle, oldcolors)
+    else:
+        file.write(text)
+
+    if flush:
+        file.flush()
+
+def should_do_markup(file):
+    if os.environ.get('PY_COLORS') == '1':
+        return True
+    if os.environ.get('PY_COLORS') == '0':
+        return False
+    return hasattr(file, 'isatty') and file.isatty() \
+           and os.environ.get('TERM') != 'dumb' \
+           and not (sys.platform.startswith('java') and os._name == 'nt')
+
+class TerminalWriter(object):
+    _esctable = dict(black=30, red=31, green=32, yellow=33,
+                     blue=34, purple=35, cyan=36, white=37,
+                     Black=40, Red=41, Green=42, Yellow=43,
+                     Blue=44, Purple=45, Cyan=46, White=47,
+                     bold=1, light=2, blink=5, invert=7)
+
+    # XXX deprecate stringio argument
+    def __init__(self, file=None, stringio=False, encoding=None):
+        if file is None:
+            if stringio:
+                self.stringio = file = py.io.TextIO()
+            else:
+                file = py.std.sys.stdout
+        elif py.builtin.callable(file) and not (
+             hasattr(file, "write") and hasattr(file, "flush")):
+            file = WriteFile(file, encoding=encoding)
+        if hasattr(file, "isatty") and file.isatty() and colorama:
+            file = colorama.AnsiToWin32(file).stream
+        self.encoding = encoding or getattr(file, 'encoding', "utf-8")
+        self._file = file
+        self.hasmarkup = should_do_markup(file)
+        self._lastlen = 0
+
+    @property
+    def fullwidth(self):
+        if hasattr(self, '_terminal_width'):
+            return self._terminal_width
+        return get_terminal_width()
+
+    @fullwidth.setter
+    def fullwidth(self, value):
+        self._terminal_width = value
+
+    def _escaped(self, text, esc):
+        if esc and self.hasmarkup:
+            text = (''.join(['\x1b[%sm' % cod for cod in esc])  +
+                text +'\x1b[0m')
+        return text
+
+    def markup(self, text, **kw):
+        esc = []
+        for name in kw:
+            if name not in self._esctable:
+                raise ValueError("unknown markup: %r" %(name,))
+            if kw[name]:
+                esc.append(self._esctable[name])
+        return self._escaped(text, tuple(esc))
+
+    def sep(self, sepchar, title=None, fullwidth=None, **kw):
+        if fullwidth is None:
+            fullwidth = self.fullwidth
+        # the goal is to have the line be as long as possible
+        # under the condition that len(line) <= fullwidth
+        if sys.platform == "win32":
+            # if we print in the last column on windows we are on a
+            # new line but there is no way to verify/neutralize this
+            # (we may not know the exact line width)
+            # so let's be defensive to avoid empty lines in the output
+            fullwidth -= 1
+        if title is not None:
+            # we want 2 + 2*len(fill) + len(title) <= fullwidth
+            # i.e.    2 + 2*len(sepchar)*N + len(title) <= fullwidth
+            #         2*len(sepchar)*N <= fullwidth - len(title) - 2
+            #         N <= (fullwidth - len(title) - 2) // (2*len(sepchar))
+            N = (fullwidth - len(title) - 2) // (2*len(sepchar))
+            fill = sepchar * N
+            line = "%s %s %s" % (fill, title, fill)
+        else:
+            # we want len(sepchar)*N <= fullwidth
+            # i.e.    N <= fullwidth // len(sepchar)
+            line = sepchar * (fullwidth // len(sepchar))
+        # in some situations there is room for an extra sepchar at the right,
+        # in particular if we consider that with a sepchar like "_ " the
+        # trailing space is not important at the end of the line
+        if len(line) + len(sepchar.rstrip()) <= fullwidth:
+            line += sepchar.rstrip()
+
+        self.line(line, **kw)
+
+    def write(self, msg, **kw):
+        if msg:
+            if not isinstance(msg, (bytes, text)):
+                msg = text(msg)
+            if self.hasmarkup and kw:
+                markupmsg = self.markup(msg, **kw)
+            else:
+                markupmsg = msg
+            write_out(self._file, markupmsg)
+
+    def line(self, s='', **kw):
+        self.write(s, **kw)
+        self._checkfill(s)
+        self.write('\n')
+
+    def reline(self, line, **kw):
+        if not self.hasmarkup:
+            raise ValueError("cannot use rewrite-line without terminal")
+        self.write(line, **kw)
+        self._checkfill(line)
+        self.write('\r')
+        self._lastlen = len(line)
+
+    def _checkfill(self, line):
+        diff2last = self._lastlen - len(line)
+        if diff2last > 0:
+            self.write(" " * diff2last)
+
+class Win32ConsoleWriter(TerminalWriter):
+    def write(self, msg, **kw):
+        if msg:
+            if not isinstance(msg, (bytes, text)):
+                msg = text(msg)
+            oldcolors = None
+            if self.hasmarkup and kw:
+                handle = GetStdHandle(STD_OUTPUT_HANDLE)
+                oldcolors = GetConsoleInfo(handle).wAttributes
+                default_bg = oldcolors & 0x00F0
+                attr = default_bg
+                if kw.pop('bold', False):
+                    attr |= FOREGROUND_INTENSITY
+
+                if kw.pop('red', False):
+                    attr |= FOREGROUND_RED
+                elif kw.pop('blue', False):
+                    attr |= FOREGROUND_BLUE
+                elif kw.pop('green', False):
+                    attr |= FOREGROUND_GREEN
+                elif kw.pop('yellow', False):
+                    attr |= FOREGROUND_GREEN|FOREGROUND_RED
+                else:
+                    attr |= oldcolors & 0x0007
+
+                SetConsoleTextAttribute(handle, attr)
+            write_out(self._file, msg)
+            if oldcolors:
+                SetConsoleTextAttribute(handle, oldcolors)
+
+class WriteFile(object):
+    def __init__(self, writemethod, encoding=None):
+        self.encoding = encoding
+        self._writemethod = writemethod
+
+    def write(self, data):
+        if self.encoding:
+            data = data.encode(self.encoding, "replace")
+        self._writemethod(data)
+
+    def flush(self):
+        return
+
+
+if win32_and_ctypes:
+    TerminalWriter = Win32ConsoleWriter
+    import ctypes
+    from ctypes import wintypes
+
+    # ctypes access to the Windows console
+    STD_OUTPUT_HANDLE = -11
+    STD_ERROR_HANDLE  = -12
+    FOREGROUND_BLACK     = 0x0000 # black text
+    FOREGROUND_BLUE      = 0x0001 # text color contains blue.
+    FOREGROUND_GREEN     = 0x0002 # text color contains green.
+    FOREGROUND_RED       = 0x0004 # text color contains red.
+    FOREGROUND_WHITE     = 0x0007
+    FOREGROUND_INTENSITY = 0x0008 # text color is intensified.
+    BACKGROUND_BLACK     = 0x0000 # background color black
+    BACKGROUND_BLUE      = 0x0010 # background color contains blue.
+    BACKGROUND_GREEN     = 0x0020 # background color contains green.
+    BACKGROUND_RED       = 0x0040 # background color contains red.
+    BACKGROUND_WHITE     = 0x0070
+    BACKGROUND_INTENSITY = 0x0080 # background color is intensified.
+
+    SHORT = ctypes.c_short
+    class COORD(ctypes.Structure):
+        _fields_ = [('X', SHORT),
+                    ('Y', SHORT)]
+    class SMALL_RECT(ctypes.Structure):
+        _fields_ = [('Left', SHORT),
+                    ('Top', SHORT),
+                    ('Right', SHORT),
+                    ('Bottom', SHORT)]
+    class CONSOLE_SCREEN_BUFFER_INFO(ctypes.Structure):
+        _fields_ = [('dwSize', COORD),
+                    ('dwCursorPosition', COORD),
+                    ('wAttributes', wintypes.WORD),
+                    ('srWindow', SMALL_RECT),
+                    ('dwMaximumWindowSize', COORD)]
+
+    _GetStdHandle = ctypes.windll.kernel32.GetStdHandle
+    _GetStdHandle.argtypes = [wintypes.DWORD]
+    _GetStdHandle.restype = wintypes.HANDLE
+    def GetStdHandle(kind):
+        return _GetStdHandle(kind)
+
+    SetConsoleTextAttribute = ctypes.windll.kernel32.SetConsoleTextAttribute
+    SetConsoleTextAttribute.argtypes = [wintypes.HANDLE, wintypes.WORD]
+    SetConsoleTextAttribute.restype = wintypes.BOOL
+
+    _GetConsoleScreenBufferInfo = \
+        ctypes.windll.kernel32.GetConsoleScreenBufferInfo
+    _GetConsoleScreenBufferInfo.argtypes = [wintypes.HANDLE,
+                                ctypes.POINTER(CONSOLE_SCREEN_BUFFER_INFO)]
+    _GetConsoleScreenBufferInfo.restype = wintypes.BOOL
+    def GetConsoleInfo(handle):
+        info = CONSOLE_SCREEN_BUFFER_INFO()
+        _GetConsoleScreenBufferInfo(handle, ctypes.byref(info))
+        return info
+
+    def _getdimensions():
+        handle = GetStdHandle(STD_OUTPUT_HANDLE)
+        info = GetConsoleInfo(handle)
+        # Substract one from the width, otherwise the cursor wraps
+        # and the ending \n causes an empty line to display.
+        return info.dwSize.Y, info.dwSize.X - 1
+
+def write_out(fil, msg):
+    # XXX sometimes "msg" is of type bytes, sometimes text which
+    # complicates the situation.  Should we try to enforce unicode?
+    try:
+        # on py27 and above writing out to sys.stdout with an encoding
+        # should usually work for unicode messages (if the encoding is
+        # capable of it)
+        fil.write(msg)
+    except UnicodeEncodeError:
+        # on py26 it might not work because stdout expects bytes
+        if fil.encoding:
+            try:
+                fil.write(msg.encode(fil.encoding))
+            except UnicodeEncodeError:
+                # it might still fail if the encoding is not capable
+                pass
+            else:
+                fil.flush()
+                return
+        # fallback: escape all unicode characters
+        msg = msg.encode("unicode-escape").decode("ascii")
+        fil.write(msg)
+    fil.flush()
--- a/third_party/python/py/py/_log/__init__.py
+++ b/third_party/python/py/py/_log/__init__.py
@@ -1,2 +1,2 @@
-""" logging API ('producers' and 'consumers' connected via keywords) """
-
+""" logging API ('producers' and 'consumers' connected via keywords) """
+
--- a/third_party/python/py/py/_log/log.py
+++ b/third_party/python/py/py/_log/log.py
@@ -1,186 +1,186 @@
-"""
-basic logging functionality based on a producer/consumer scheme.
-
-XXX implement this API: (maybe put it into slogger.py?)
-
-        log = Logger(
-                    info=py.log.STDOUT,
-                    debug=py.log.STDOUT,
-                    command=None)
-        log.info("hello", "world")
-        log.command("hello", "world")
-
-        log = Logger(info=Logger(something=...),
-                     debug=py.log.STDOUT,
-                     command=None)
-"""
-import py, sys
-
-class Message(object):
-    def __init__(self, keywords, args):
-        self.keywords = keywords
-        self.args = args
-
-    def content(self):
-        return " ".join(map(str, self.args))
-
-    def prefix(self):
-        return "[%s] " % (":".join(self.keywords))
-
-    def __str__(self):
-        return self.prefix() + self.content()
-
-
-class Producer(object):
-    """ (deprecated) Log producer API which sends messages to be logged
-        to a 'consumer' object, which then prints them to stdout,
-        stderr, files, etc. Used extensively by PyPy-1.1.
-    """
-
-    Message = Message  # to allow later customization
-    keywords2consumer = {}
-
-    def __init__(self, keywords, keywordmapper=None, **kw):
-        if hasattr(keywords, 'split'):
-            keywords = tuple(keywords.split())
-        self._keywords = keywords
-        if keywordmapper is None:
-            keywordmapper = default_keywordmapper
-        self._keywordmapper = keywordmapper
-
-    def __repr__(self):
-        return "<py.log.Producer %s>" % ":".join(self._keywords)
-
-    def __getattr__(self, name):
-        if '_' in name:
-            raise AttributeError(name)
-        producer = self.__class__(self._keywords + (name,))
-        setattr(self, name, producer)
-        return producer
-
-    def __call__(self, *args):
-        """ write a message to the appropriate consumer(s) """
-        func = self._keywordmapper.getconsumer(self._keywords)
-        if func is not None:
-            func(self.Message(self._keywords, args))
-
-class KeywordMapper:
-    def __init__(self):
-        self.keywords2consumer = {}
-
-    def getstate(self):
-        return self.keywords2consumer.copy()
-    def setstate(self, state):
-        self.keywords2consumer.clear()
-        self.keywords2consumer.update(state)
-
-    def getconsumer(self, keywords):
-        """ return a consumer matching the given keywords.
-
-            tries to find the most suitable consumer by walking, starting from
-            the back, the list of keywords, the first consumer matching a
-            keyword is returned (falling back to py.log.default)
-        """
-        for i in range(len(keywords), 0, -1):
-            try:
-                return self.keywords2consumer[keywords[:i]]
-            except KeyError:
-                continue
-        return self.keywords2consumer.get('default', default_consumer)
-
-    def setconsumer(self, keywords, consumer):
-        """ set a consumer for a set of keywords. """
-        # normalize to tuples
-        if isinstance(keywords, str):
-            keywords = tuple(filter(None, keywords.split()))
-        elif hasattr(keywords, '_keywords'):
-            keywords = keywords._keywords
-        elif not isinstance(keywords, tuple):
-            raise TypeError("key %r is not a string or tuple" % (keywords,))
-        if consumer is not None and not py.builtin.callable(consumer):
-            if not hasattr(consumer, 'write'):
-                raise TypeError(
-                    "%r should be None, callable or file-like" % (consumer,))
-            consumer = File(consumer)
-        self.keywords2consumer[keywords] = consumer
-
-def default_consumer(msg):
-    """ the default consumer, prints the message to stdout (using 'print') """
-    sys.stderr.write(str(msg)+"\n")
-
-default_keywordmapper = KeywordMapper()
-
-def setconsumer(keywords, consumer):
-    default_keywordmapper.setconsumer(keywords, consumer)
-
-def setstate(state):
-    default_keywordmapper.setstate(state)
-def getstate():
-    return default_keywordmapper.getstate()
-
-#
-# Consumers
-#
-
-class File(object):
-    """ log consumer wrapping a file(-like) object """
-    def __init__(self, f):
-        assert hasattr(f, 'write')
-        #assert isinstance(f, file) or not hasattr(f, 'open')
-        self._file = f
-
-    def __call__(self, msg):
-        """ write a message to the log """
-        self._file.write(str(msg) + "\n")
-        if hasattr(self._file, 'flush'):
-            self._file.flush()
-
-class Path(object):
-    """ log consumer that opens and writes to a Path """
-    def __init__(self, filename, append=False,
-                 delayed_create=False, buffering=False):
-        self._append = append
-        self._filename = str(filename)
-        self._buffering = buffering
-        if not delayed_create:
-            self._openfile()
-
-    def _openfile(self):
-        mode = self._append and 'a' or 'w'
-        f = open(self._filename, mode)
-        self._file = f
-
-    def __call__(self, msg):
-        """ write a message to the log """
-        if not hasattr(self, "_file"):
-            self._openfile()
-        self._file.write(str(msg) + "\n")
-        if not self._buffering:
-            self._file.flush()
-
-def STDOUT(msg):
-    """ consumer that writes to sys.stdout """
-    sys.stdout.write(str(msg)+"\n")
-
-def STDERR(msg):
-    """ consumer that writes to sys.stderr """
-    sys.stderr.write(str(msg)+"\n")
-
-class Syslog:
-    """ consumer that writes to the syslog daemon """
-
-    def __init__(self, priority = None):
-        if priority is None:
-            priority = self.LOG_INFO
-        self.priority = priority
-
-    def __call__(self, msg):
-        """ write a message to the log """
-        py.std.syslog.syslog(self.priority, str(msg))
-
-for _prio in "EMERG ALERT CRIT ERR WARNING NOTICE INFO DEBUG".split():
-    _prio = "LOG_" + _prio
-    try:
-        setattr(Syslog, _prio, getattr(py.std.syslog, _prio))
-    except AttributeError:
-        pass
+"""
+basic logging functionality based on a producer/consumer scheme.
+
+XXX implement this API: (maybe put it into slogger.py?)
+
+        log = Logger(
+                    info=py.log.STDOUT,
+                    debug=py.log.STDOUT,
+                    command=None)
+        log.info("hello", "world")
+        log.command("hello", "world")
+
+        log = Logger(info=Logger(something=...),
+                     debug=py.log.STDOUT,
+                     command=None)
+"""
+import py, sys
+
+class Message(object):
+    def __init__(self, keywords, args):
+        self.keywords = keywords
+        self.args = args
+
+    def content(self):
+        return " ".join(map(str, self.args))
+
+    def prefix(self):
+        return "[%s] " % (":".join(self.keywords))
+
+    def __str__(self):
+        return self.prefix() + self.content()
+
+
+class Producer(object):
+    """ (deprecated) Log producer API which sends messages to be logged
+        to a 'consumer' object, which then prints them to stdout,
+        stderr, files, etc. Used extensively by PyPy-1.1.
+    """
+
+    Message = Message  # to allow later customization
+    keywords2consumer = {}
+
+    def __init__(self, keywords, keywordmapper=None, **kw):
+        if hasattr(keywords, 'split'):
+            keywords = tuple(keywords.split())
+        self._keywords = keywords
+        if keywordmapper is None:
+            keywordmapper = default_keywordmapper
+        self._keywordmapper = keywordmapper
+
+    def __repr__(self):
+        return "<py.log.Producer %s>" % ":".join(self._keywords)
+
+    def __getattr__(self, name):
+        if '_' in name:
+            raise AttributeError(name)
+        producer = self.__class__(self._keywords + (name,))
+        setattr(self, name, producer)
+        return producer
+
+    def __call__(self, *args):
+        """ write a message to the appropriate consumer(s) """
+        func = self._keywordmapper.getconsumer(self._keywords)
+        if func is not None:
+            func(self.Message(self._keywords, args))
+
+class KeywordMapper:
+    def __init__(self):
+        self.keywords2consumer = {}
+
+    def getstate(self):
+        return self.keywords2consumer.copy()
+    def setstate(self, state):
+        self.keywords2consumer.clear()
+        self.keywords2consumer.update(state)
+
+    def getconsumer(self, keywords):
+        """ return a consumer matching the given keywords.
+
+            tries to find the most suitable consumer by walking, starting from
+            the back, the list of keywords, the first consumer matching a
+            keyword is returned (falling back to py.log.default)
+        """
+        for i in range(len(keywords), 0, -1):
+            try:
+                return self.keywords2consumer[keywords[:i]]
+            except KeyError:
+                continue
+        return self.keywords2consumer.get('default', default_consumer)
+
+    def setconsumer(self, keywords, consumer):
+        """ set a consumer for a set of keywords. """
+        # normalize to tuples
+        if isinstance(keywords, str):
+            keywords = tuple(filter(None, keywords.split()))
+        elif hasattr(keywords, '_keywords'):
+            keywords = keywords._keywords
+        elif not isinstance(keywords, tuple):
+            raise TypeError("key %r is not a string or tuple" % (keywords,))
+        if consumer is not None and not py.builtin.callable(consumer):
+            if not hasattr(consumer, 'write'):
+                raise TypeError(
+                    "%r should be None, callable or file-like" % (consumer,))
+            consumer = File(consumer)
+        self.keywords2consumer[keywords] = consumer
+
+def default_consumer(msg):
+    """ the default consumer, prints the message to stdout (using 'print') """
+    sys.stderr.write(str(msg)+"\n")
+
+default_keywordmapper = KeywordMapper()
+
+def setconsumer(keywords, consumer):
+    default_keywordmapper.setconsumer(keywords, consumer)
+
+def setstate(state):
+    default_keywordmapper.setstate(state)
+def getstate():
+    return default_keywordmapper.getstate()
+
+#
+# Consumers
+#
+
+class File(object):
+    """ log consumer wrapping a file(-like) object """
+    def __init__(self, f):
+        assert hasattr(f, 'write')
+        #assert isinstance(f, file) or not hasattr(f, 'open')
+        self._file = f
+
+    def __call__(self, msg):
+        """ write a message to the log """
+        self._file.write(str(msg) + "\n")
+        if hasattr(self._file, 'flush'):
+            self._file.flush()
+
+class Path(object):
+    """ log consumer that opens and writes to a Path """
+    def __init__(self, filename, append=False,
+                 delayed_create=False, buffering=False):
+        self._append = append
+        self._filename = str(filename)
+        self._buffering = buffering
+        if not delayed_create:
+            self._openfile()
+
+    def _openfile(self):
+        mode = self._append and 'a' or 'w'
+        f = open(self._filename, mode)
+        self._file = f
+
+    def __call__(self, msg):
+        """ write a message to the log """
+        if not hasattr(self, "_file"):
+            self._openfile()
+        self._file.write(str(msg) + "\n")
+        if not self._buffering:
+            self._file.flush()
+
+def STDOUT(msg):
+    """ consumer that writes to sys.stdout """
+    sys.stdout.write(str(msg)+"\n")
+
+def STDERR(msg):
+    """ consumer that writes to sys.stderr """
+    sys.stderr.write(str(msg)+"\n")
+
+class Syslog:
+    """ consumer that writes to the syslog daemon """
+
+    def __init__(self, priority = None):
+        if priority is None:
+            priority = self.LOG_INFO
+        self.priority = priority
+
+    def __call__(self, msg):
+        """ write a message to the log """
+        py.std.syslog.syslog(self.priority, str(msg))
+
+for _prio in "EMERG ALERT CRIT ERR WARNING NOTICE INFO DEBUG".split():
+    _prio = "LOG_" + _prio
+    try:
+        setattr(Syslog, _prio, getattr(py.std.syslog, _prio))
+    except AttributeError:
+        pass
--- a/third_party/python/py/py/_log/warning.py
+++ b/third_party/python/py/py/_log/warning.py
@@ -1,76 +1,76 @@
-import py, sys
-
-class DeprecationWarning(DeprecationWarning):
-    def __init__(self, msg, path, lineno):
-        self.msg = msg
-        self.path = path
-        self.lineno = lineno
-    def __repr__(self):
-        return "%s:%d: %s" %(self.path, self.lineno+1, self.msg)
-    def __str__(self):
-        return self.msg
-
-def _apiwarn(startversion, msg, stacklevel=2, function=None):
-    # below is mostly COPIED from python2.4/warnings.py's def warn()
-    # Get context information
-    if isinstance(stacklevel, str):
-        frame = sys._getframe(1)
-        level = 1
-        found = frame.f_code.co_filename.find(stacklevel) != -1
-        while frame:
-            co = frame.f_code
-            if co.co_filename.find(stacklevel) == -1:
-                if found:
-                    stacklevel = level
-                    break
-            else:
-                found = True
-            level += 1
-            frame = frame.f_back
-        else:
-            stacklevel = 1
-    msg = "%s (since version %s)" %(msg, startversion)
-    warn(msg, stacklevel=stacklevel+1, function=function)
-
-def warn(msg, stacklevel=1, function=None):
-    if function is not None:
-        filename = py.std.inspect.getfile(function)
-        lineno = py.code.getrawcode(function).co_firstlineno
-    else:
-        try:
-            caller = sys._getframe(stacklevel)
-        except ValueError:
-            globals = sys.__dict__
-            lineno = 1
-        else:
-            globals = caller.f_globals
-            lineno = caller.f_lineno
-        if '__name__' in globals:
-            module = globals['__name__']
-        else:
-            module = "<string>"
-        filename = globals.get('__file__')
-    if filename:
-        fnl = filename.lower()
-        if fnl.endswith(".pyc") or fnl.endswith(".pyo"):
-            filename = filename[:-1]
-        elif fnl.endswith("$py.class"):
-            filename = filename.replace('$py.class', '.py')
-    else:
-        if module == "__main__":
-            try:
-                filename = sys.argv[0]
-            except AttributeError:
-                # embedded interpreters don't have sys.argv, see bug #839151
-                filename = '__main__'
-        if not filename:
-            filename = module
-    path = py.path.local(filename)
-    warning = DeprecationWarning(msg, path, lineno)
-    py.std.warnings.warn_explicit(warning, category=Warning,
-        filename=str(warning.path),
-        lineno=warning.lineno,
-        registry=py.std.warnings.__dict__.setdefault(
-            "__warningsregistry__", {})
-    )
-
+import py, sys
+
+class DeprecationWarning(DeprecationWarning):
+    def __init__(self, msg, path, lineno):
+        self.msg = msg
+        self.path = path
+        self.lineno = lineno
+    def __repr__(self):
+        return "%s:%d: %s" %(self.path, self.lineno+1, self.msg)
+    def __str__(self):
+        return self.msg
+
+def _apiwarn(startversion, msg, stacklevel=2, function=None):
+    # below is mostly COPIED from python2.4/warnings.py's def warn()
+    # Get context information
+    if isinstance(stacklevel, str):
+        frame = sys._getframe(1)
+        level = 1
+        found = frame.f_code.co_filename.find(stacklevel) != -1
+        while frame:
+            co = frame.f_code
+            if co.co_filename.find(stacklevel) == -1:
+                if found:
+                    stacklevel = level
+                    break
+            else:
+                found = True
+            level += 1
+            frame = frame.f_back
+        else:
+            stacklevel = 1
+    msg = "%s (since version %s)" %(msg, startversion)
+    warn(msg, stacklevel=stacklevel+1, function=function)
+
+def warn(msg, stacklevel=1, function=None):
+    if function is not None:
+        filename = py.std.inspect.getfile(function)
+        lineno = py.code.getrawcode(function).co_firstlineno
+    else:
+        try:
+            caller = sys._getframe(stacklevel)
+        except ValueError:
+            globals = sys.__dict__
+            lineno = 1
+        else:
+            globals = caller.f_globals
+            lineno = caller.f_lineno
+        if '__name__' in globals:
+            module = globals['__name__']
+        else:
+            module = "<string>"
+        filename = globals.get('__file__')
+    if filename:
+        fnl = filename.lower()
+        if fnl.endswith(".pyc") or fnl.endswith(".pyo"):
+            filename = filename[:-1]
+        elif fnl.endswith("$py.class"):
+            filename = filename.replace('$py.class', '.py')
+    else:
+        if module == "__main__":
+            try:
+                filename = sys.argv[0]
+            except AttributeError:
+                # embedded interpreters don't have sys.argv, see bug #839151
+                filename = '__main__'
+        if not filename:
+            filename = module
+    path = py.path.local(filename)
+    warning = DeprecationWarning(msg, path, lineno)
+    py.std.warnings.warn_explicit(warning, category=Warning,
+        filename=str(warning.path),
+        lineno=warning.lineno,
+        registry=py.std.warnings.__dict__.setdefault(
+            "__warningsregistry__", {})
+    )
+
--- a/third_party/python/py/py/_path/__init__.py
+++ b/third_party/python/py/py/_path/__init__.py
@@ -1,1 +1,1 @@
-""" unified file system api """
+""" unified file system api """
--- a/third_party/python/py/py/_path/cacheutil.py
+++ b/third_party/python/py/py/_path/cacheutil.py
@@ -1,114 +1,114 @@
-"""
-This module contains multithread-safe cache implementations.
-
-All Caches have
-
-    getorbuild(key, builder)
-    delentry(key)
-
-methods and allow configuration when instantiating the cache class.
-"""
-from time import time as gettime
-
-class BasicCache(object):
-    def __init__(self, maxentries=128):
-        self.maxentries = maxentries
-        self.prunenum = int(maxentries - maxentries/8)
-        self._dict = {}
-
-    def clear(self):
-        self._dict.clear()
-
-    def _getentry(self, key):
-        return self._dict[key]
-
-    def _putentry(self, key, entry):
-        self._prunelowestweight()
-        self._dict[key] = entry
-
-    def delentry(self, key, raising=False):
-        try:
-            del self._dict[key]
-        except KeyError:
-            if raising:
-                raise
-
-    def getorbuild(self, key, builder):
-        try:
-            entry = self._getentry(key)
-        except KeyError:
-            entry = self._build(key, builder)
-            self._putentry(key, entry)
-        return entry.value
-
-    def _prunelowestweight(self):
-        """ prune out entries with lowest weight. """
-        numentries = len(self._dict)
-        if numentries >= self.maxentries:
-            # evict according to entry's weight
-            items = [(entry.weight, key)
-                        for key, entry in self._dict.items()]
-            items.sort()
-            index = numentries - self.prunenum
-            if index > 0:
-                for weight, key in items[:index]:
-                    # in MT situations the element might be gone
-                    self.delentry(key, raising=False)
-
-class BuildcostAccessCache(BasicCache):
-    """ A BuildTime/Access-counting cache implementation.
-        the weight of a value is computed as the product of
-
-            num-accesses-of-a-value * time-to-build-the-value
-
-        The values with the least such weights are evicted
-        if the cache maxentries threshold is superceded.
-        For implementation flexibility more than one object
-        might be evicted at a time.
-    """
-    # time function to use for measuring build-times
-
-    def _build(self, key, builder):
-        start = gettime()
-        val = builder()
-        end = gettime()
-        return WeightedCountingEntry(val, end-start)
-
-
-class WeightedCountingEntry(object):
-    def __init__(self, value, oneweight):
-        self._value = value
-        self.weight = self._oneweight = oneweight
-
-    def value(self):
-        self.weight += self._oneweight
-        return self._value
-    value = property(value)
-
-class AgingCache(BasicCache):
-    """ This cache prunes out cache entries that are too old.
-    """
-    def __init__(self, maxentries=128, maxseconds=10.0):
-        super(AgingCache, self).__init__(maxentries)
-        self.maxseconds = maxseconds
-
-    def _getentry(self, key):
-        entry = self._dict[key]
-        if entry.isexpired():
-            self.delentry(key)
-            raise KeyError(key)
-        return entry
-
-    def _build(self, key, builder):
-        val = builder()
-        entry = AgingEntry(val, gettime() + self.maxseconds)
-        return entry
-
-class AgingEntry(object):
-    def __init__(self, value, expirationtime):
-        self.value = value
-        self.weight = expirationtime
-
-    def isexpired(self):
-        t = gettime()
-        return t >= self.weight
+"""
+This module contains multithread-safe cache implementations.
+
+All Caches have
+
+    getorbuild(key, builder)
+    delentry(key)
+
+methods and allow configuration when instantiating the cache class.
+"""
+from time import time as gettime
+
+class BasicCache(object):
+    def __init__(self, maxentries=128):
+        self.maxentries = maxentries
+        self.prunenum = int(maxentries - maxentries/8)
+        self._dict = {}
+
+    def clear(self):
+        self._dict.clear()
+
+    def _getentry(self, key):
+        return self._dict[key]
+
+    def _putentry(self, key, entry):
+        self._prunelowestweight()
+        self._dict[key] = entry
+
+    def delentry(self, key, raising=False):
+        try:
+            del self._dict[key]
+        except KeyError:
+            if raising:
+                raise
+
+    def getorbuild(self, key, builder):
+        try:
+            entry = self._getentry(key)
+        except KeyError:
+            entry = self._build(key, builder)
+            self._putentry(key, entry)
+        return entry.value
+
+    def _prunelowestweight(self):
+        """ prune out entries with lowest weight. """
+        numentries = len(self._dict)
+        if numentries >= self.maxentries:
+            # evict according to entry's weight
+            items = [(entry.weight, key)
+                        for key, entry in self._dict.items()]
+            items.sort()
+            index = numentries - self.prunenum
+            if index > 0:
+                for weight, key in items[:index]:
+                    # in MT situations the element might be gone
+                    self.delentry(key, raising=False)
+
+class BuildcostAccessCache(BasicCache):
+    """ A BuildTime/Access-counting cache implementation.
+        the weight of a value is computed as the product of
+
+            num-accesses-of-a-value * time-to-build-the-value
+
+        The values with the least such weights are evicted
+        if the cache maxentries threshold is superceded.
+        For implementation flexibility more than one object
+        might be evicted at a time.
+    """
+    # time function to use for measuring build-times
+
+    def _build(self, key, builder):
+        start = gettime()
+        val = builder()
+        end = gettime()
+        return WeightedCountingEntry(val, end-start)
+
+
+class WeightedCountingEntry(object):
+    def __init__(self, value, oneweight):
+        self._value = value
+        self.weight = self._oneweight = oneweight
+
+    def value(self):
+        self.weight += self._oneweight
+        return self._value
+    value = property(value)
+
+class AgingCache(BasicCache):
+    """ This cache prunes out cache entries that are too old.
+    """
+    def __init__(self, maxentries=128, maxseconds=10.0):
+        super(AgingCache, self).__init__(maxentries)
+        self.maxseconds = maxseconds
+
+    def _getentry(self, key):
+        entry = self._dict[key]
+        if entry.isexpired():
+            self.delentry(key)
+            raise KeyError(key)
+        return entry
+
+    def _build(self, key, builder):
+        val = builder()
+        entry = AgingEntry(val, gettime() + self.maxseconds)
+        return entry
+
+class AgingEntry(object):
+    def __init__(self, value, expirationtime):
+        self.value = value
+        self.weight = expirationtime
+
+    def isexpired(self):
+        t = gettime()
+        return t >= self.weight
--- a/third_party/python/py/py/_path/common.py
+++ b/third_party/python/py/py/_path/common.py
@@ -1,403 +1,445 @@
-"""
-"""
-import os, sys, posixpath
-import py
-
-# Moved from local.py.
-iswin32 = sys.platform == "win32" or (getattr(os, '_name', False) == 'nt')
-
-class Checkers:
-    _depend_on_existence = 'exists', 'link', 'dir', 'file'
-
-    def __init__(self, path):
-        self.path = path
-
-    def dir(self):
-        raise NotImplementedError
-
-    def file(self):
-        raise NotImplementedError
-
-    def dotfile(self):
-        return self.path.basename.startswith('.')
-
-    def ext(self, arg):
-        if not arg.startswith('.'):
-            arg = '.' + arg
-        return self.path.ext == arg
-
-    def exists(self):
-        raise NotImplementedError
-
-    def basename(self, arg):
-        return self.path.basename == arg
-
-    def basestarts(self, arg):
-        return self.path.basename.startswith(arg)
-
-    def relto(self, arg):
-        return self.path.relto(arg)
-
-    def fnmatch(self, arg):
-        return self.path.fnmatch(arg)
-
-    def endswith(self, arg):
-        return str(self.path).endswith(arg)
-
-    def _evaluate(self, kw):
-        for name, value in kw.items():
-            invert = False
-            meth = None
-            try:
-                meth = getattr(self, name)
-            except AttributeError:
-                if name[:3] == 'not':
-                    invert = True
-                    try:
-                        meth = getattr(self, name[3:])
-                    except AttributeError:
-                        pass
-            if meth is None:
-                raise TypeError(
-                    "no %r checker available for %r" % (name, self.path))
-            try:
-                if py.code.getrawcode(meth).co_argcount > 1:
-                    if (not meth(value)) ^ invert:
-                        return False
-                else:
-                    if bool(value) ^ bool(meth()) ^ invert:
-                        return False
-            except (py.error.ENOENT, py.error.ENOTDIR, py.error.EBUSY):
-                # EBUSY feels not entirely correct,
-                # but its kind of necessary since ENOMEDIUM
-                # is not accessible in python
-                for name in self._depend_on_existence:
-                    if name in kw:
-                        if kw.get(name):
-                            return False
-                    name = 'not' + name
-                    if name in kw:
-                        if not kw.get(name):
-                            return False
-        return True
-
-class NeverRaised(Exception):
-    pass
-
-class PathBase(object):
-    """ shared implementation for filesystem path objects."""
-    Checkers = Checkers
-
-    def __div__(self, other):
-        return self.join(str(other))
-    __truediv__ = __div__ # py3k
-
-    def basename(self):
-        """ basename part of path. """
-        return self._getbyspec('basename')[0]
-    basename = property(basename, None, None, basename.__doc__)
-
-    def dirname(self):
-        """ dirname part of path. """
-        return self._getbyspec('dirname')[0]
-    dirname = property(dirname, None, None, dirname.__doc__)
-
-    def purebasename(self):
-        """ pure base name of the path."""
-        return self._getbyspec('purebasename')[0]
-    purebasename = property(purebasename, None, None, purebasename.__doc__)
-
-    def ext(self):
-        """ extension of the path (including the '.')."""
-        return self._getbyspec('ext')[0]
-    ext = property(ext, None, None, ext.__doc__)
-
-    def dirpath(self, *args, **kwargs):
-        """ return the directory path joined with any given path arguments.  """
-        return self.new(basename='').join(*args, **kwargs)
-
-    def read_binary(self):
-        """ read and return a bytestring from reading the path. """
-        with self.open('rb') as f:
-            return f.read()
-
-    def read_text(self, encoding):
-        """ read and return a Unicode string from reading the path. """
-        with self.open("r", encoding=encoding) as f:
-            return f.read()
-
-
-    def read(self, mode='r'):
-        """ read and return a bytestring from reading the path. """
-        with self.open(mode) as f:
-            return f.read()
-
-    def readlines(self, cr=1):
-        """ read and return a list of lines from the path. if cr is False, the
-newline will be removed from the end of each line. """
-        if not cr:
-            content = self.read('rU')
-            return content.split('\n')
-        else: