Hello community, here is the log from the commit of package python-py for openSUSE:Factory checked in at 2014-01-07 13:59:29 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-py (Old) and /work/SRC/openSUSE:Factory/.python-py.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-py" Changes: -------- --- /work/SRC/openSUSE:Factory/python-py/python-py.changes 2013-12-09 17:01:35.000000000 +0100 +++ /work/SRC/openSUSE:Factory/.python-py.new/python-py.changes 2014-01-07 13:59:30.000000000 +0100 @@ -1,0 +2,15 @@ +Fri Jan 3 08:30:42 UTC 2014 - mvysko...@suse.com + +- update to 1.4.19: + - merge in apipkg fixes + - some micro-optimizations in py/_code/code.py for speeding + up pytest runs. Thanks Alex Gaynor for initiative. + - check PY_COLORS=1 or PY_COLORS=0 to force coloring/not-coloring + for py.io.TerminalWriter() independently from capabilities + of the output file. Thanks Marc Abramowitz for the PR. + - some fixes to unicode handling in assertion handling. + Thanks for the PR to Floris Bruynooghe. (This helps + to fix pytest issue 319). + - depend on setuptools presence, remove distribute_setup + +------------------------------------------------------------------- Old: ---- py-1.4.18.tar.gz New: ---- py-1.4.19.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-py.spec ++++++ --- /var/tmp/diff_new_pack.6eya8i/_old 2014-01-07 13:59:30.000000000 +0100 +++ /var/tmp/diff_new_pack.6eya8i/_new 2014-01-07 13:59:30.000000000 +0100 @@ -1,7 +1,7 @@ # # spec file for package python-py # -# Copyright (c) 2013 SUSE LINUX Products GmbH, Nuernberg, Germany. +# Copyright (c) 2014 SUSE LINUX Products GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -17,7 +17,7 @@ Name: python-py -Version: 1.4.18 +Version: 1.4.19 Release: 0 Summary: Library with cross-python path, ini-parsing, io, code, log facilities License: MIT ++++++ py-1.4.18.tar.gz -> py-1.4.19.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/py-1.4.18/CHANGELOG new/py-1.4.19/CHANGELOG --- old/py-1.4.18/CHANGELOG 2013-10-29 11:34:25.000000000 +0100 +++ new/py-1.4.19/CHANGELOG 2013-12-12 12:07:15.000000000 +0100 @@ -1,3 +1,21 @@ +Changes between 1.4.18 and 1.4.19 +================================================== + +- merge in apipkg fixes + +- some micro-optimizations in py/_code/code.py for speeding + up pytest runs. Thanks Alex Gaynor for initiative. + +- check PY_COLORS=1 or PY_COLORS=0 to force coloring/not-coloring + for py.io.TerminalWriter() independently from capabilities + of the output file. Thanks Marc Abramowitz for the PR. + +- some fixes to unicode handling in assertion handling. + Thanks for the PR to Floris Bruynooghe. (This helps + to fix pytest issue 319). + +- depend on setuptools presence, remove distribute_setup + Changes between 1.4.17 and 1.4.18 ================================================== diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/py-1.4.18/PKG-INFO new/py-1.4.19/PKG-INFO --- old/py-1.4.18/PKG-INFO 2013-10-29 11:34:25.000000000 +0100 +++ new/py-1.4.19/PKG-INFO 2013-12-12 12:07:15.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: py -Version: 1.4.18 +Version: 1.4.19 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 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/py-1.4.18/distribute_setup.py new/py-1.4.19/distribute_setup.py --- old/py-1.4.18/distribute_setup.py 2013-10-29 11:34:25.000000000 +0100 +++ new/py-1.4.19/distribute_setup.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,497 +0,0 @@ -#!python -"""Bootstrap distribute installation - -If you want to use setuptools in your package's setup.py, just include this -file in the same directory with it, and add this to the top of your setup.py:: - - from distribute_setup import use_setuptools - use_setuptools() - -If you want to require a specific version of setuptools, set a download -mirror, or use an alternate download directory, you can do so by supplying -the appropriate options to ``use_setuptools()``. - -This file can also be run as a script to install or upgrade setuptools. -""" -import os -import sys -import time -import fnmatch -import tempfile -import tarfile -from distutils import log - -try: - from site import USER_SITE -except ImportError: - USER_SITE = None - -try: - import subprocess - - def _python_cmd(*args): - args = (sys.executable,) + args - return subprocess.call(args) == 0 - -except ImportError: - # will be used for python 2.3 - def _python_cmd(*args): - args = (sys.executable,) + args - # quoting arguments if windows - if sys.platform == 'win32': - def quote(arg): - if ' ' in arg: - return '"%s"' % arg - return arg - args = [quote(arg) for arg in args] - return os.spawnl(os.P_WAIT, sys.executable, *args) == 0 - -DEFAULT_VERSION = "0.6.27" -DEFAULT_URL = "http://pypi.python.org/packages/source/d/distribute/" -SETUPTOOLS_FAKED_VERSION = "0.6c11" - -SETUPTOOLS_PKG_INFO = """\ -Metadata-Version: 1.0 -Name: setuptools -Version: %s -Summary: xxxx -Home-page: xxx -Author: xxx -Author-email: xxx -License: xxx -Description: xxx -""" % SETUPTOOLS_FAKED_VERSION - - -def _install(tarball, install_args=()): - # extracting the tarball - tmpdir = tempfile.mkdtemp() - log.warn('Extracting in %s', tmpdir) - old_wd = os.getcwd() - try: - os.chdir(tmpdir) - tar = tarfile.open(tarball) - _extractall(tar) - tar.close() - - # going in the directory - subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0]) - os.chdir(subdir) - log.warn('Now working in %s', subdir) - - # installing - log.warn('Installing Distribute') - if not _python_cmd('setup.py', 'install', *install_args): - log.warn('Something went wrong during the installation.') - log.warn('See the error message above.') - finally: - os.chdir(old_wd) - - -def _build_egg(egg, tarball, to_dir): - # extracting the tarball - tmpdir = tempfile.mkdtemp() - log.warn('Extracting in %s', tmpdir) - old_wd = os.getcwd() - try: - os.chdir(tmpdir) - tar = tarfile.open(tarball) - _extractall(tar) - tar.close() - - # going in the directory - subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0]) - os.chdir(subdir) - log.warn('Now working in %s', subdir) - - # building an egg - log.warn('Building a Distribute egg in %s', to_dir) - _python_cmd('setup.py', '-q', 'bdist_egg', '--dist-dir', to_dir) - - finally: - os.chdir(old_wd) - # returning the result - log.warn(egg) - if not os.path.exists(egg): - raise IOError('Could not build the egg.') - - -def _do_download(version, download_base, to_dir, download_delay): - egg = os.path.join(to_dir, 'distribute-%s-py%d.%d.egg' - % (version, sys.version_info[0], sys.version_info[1])) - if not os.path.exists(egg): - tarball = download_setuptools(version, download_base, - to_dir, download_delay) - _build_egg(egg, tarball, to_dir) - sys.path.insert(0, egg) - import setuptools - setuptools.bootstrap_install_from = egg - - -def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL, - to_dir=os.curdir, download_delay=15, no_fake=True): - # making sure we use the absolute path - to_dir = os.path.abspath(to_dir) - was_imported = 'pkg_resources' in sys.modules or \ - 'setuptools' in sys.modules - try: - try: - import pkg_resources - if not hasattr(pkg_resources, '_distribute'): - if not no_fake: - _fake_setuptools() - raise ImportError - except ImportError: - return _do_download(version, download_base, to_dir, download_delay) - try: - pkg_resources.require("distribute>="+version) - return - except pkg_resources.VersionConflict: - e = sys.exc_info()[1] - if was_imported: - sys.stderr.write( - "The required version of distribute (>=%s) is not available,\n" - "and can't be installed while this script is running. Please\n" - "install a more recent version first, using\n" - "'easy_install -U distribute'." - "\n\n(Currently using %r)\n" % (version, e.args[0])) - sys.exit(2) - else: - del pkg_resources, sys.modules['pkg_resources'] # reload ok - return _do_download(version, download_base, to_dir, - download_delay) - except pkg_resources.DistributionNotFound: - return _do_download(version, download_base, to_dir, - download_delay) - finally: - if not no_fake: - _create_fake_setuptools_pkg_info(to_dir) - -def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL, - to_dir=os.curdir, delay=15): - """Download distribute from a specified location and return its filename - - `version` should be a valid distribute version number that is available - as an egg for download under the `download_base` URL (which should end - with a '/'). `to_dir` is the directory where the egg will be downloaded. - `delay` is the number of seconds to pause before an actual download - attempt. - """ - # making sure we use the absolute path - to_dir = os.path.abspath(to_dir) - try: - from urllib.request import urlopen - except ImportError: - from urllib2 import urlopen - tgz_name = "distribute-%s.tar.gz" % version - url = download_base + tgz_name - saveto = os.path.join(to_dir, tgz_name) - src = dst = None - if not os.path.exists(saveto): # Avoid repeated downloads - try: - log.warn("Downloading %s", url) - src = urlopen(url) - # Read/write all in one block, so we don't create a corrupt file - # if the download is interrupted. - data = src.read() - dst = open(saveto, "wb") - dst.write(data) - finally: - if src: - src.close() - if dst: - dst.close() - return os.path.realpath(saveto) - -def _no_sandbox(function): - def __no_sandbox(*args, **kw): - try: - from setuptools.sandbox import DirectorySandbox - if not hasattr(DirectorySandbox, '_old'): - def violation(*args): - pass - DirectorySandbox._old = DirectorySandbox._violation - DirectorySandbox._violation = violation - patched = True - else: - patched = False - except ImportError: - patched = False - - try: - return function(*args, **kw) - finally: - if patched: - DirectorySandbox._violation = DirectorySandbox._old - del DirectorySandbox._old - - return __no_sandbox - -def _patch_file(path, content): - """Will backup the file then patch it""" - existing_content = open(path).read() - if existing_content == content: - # already patched - log.warn('Already patched.') - return False - log.warn('Patching...') - _rename_path(path) - f = open(path, 'w') - try: - f.write(content) - finally: - f.close() - return True - -_patch_file = _no_sandbox(_patch_file) - -def _same_content(path, content): - return open(path).read() == content - -def _rename_path(path): - new_name = path + '.OLD.%s' % time.time() - log.warn('Renaming %s into %s', path, new_name) - os.rename(path, new_name) - return new_name - -def _remove_flat_installation(placeholder): - if not os.path.isdir(placeholder): - log.warn('Unkown installation at %s', placeholder) - return False - found = False - for file in os.listdir(placeholder): - if fnmatch.fnmatch(file, 'setuptools*.egg-info'): - found = True - break - if not found: - log.warn('Could not locate setuptools*.egg-info') - return - - log.warn('Removing elements out of the way...') - pkg_info = os.path.join(placeholder, file) - if os.path.isdir(pkg_info): - patched = _patch_egg_dir(pkg_info) - else: - patched = _patch_file(pkg_info, SETUPTOOLS_PKG_INFO) - - if not patched: - log.warn('%s already patched.', pkg_info) - return False - # now let's move the files out of the way - for element in ('setuptools', 'pkg_resources.py', 'site.py'): - element = os.path.join(placeholder, element) - if os.path.exists(element): - _rename_path(element) - else: - log.warn('Could not find the %s element of the ' - 'Setuptools distribution', element) - return True - -_remove_flat_installation = _no_sandbox(_remove_flat_installation) - -def _after_install(dist): - log.warn('After install bootstrap.') - placeholder = dist.get_command_obj('install').install_purelib - _create_fake_setuptools_pkg_info(placeholder) - -def _create_fake_setuptools_pkg_info(placeholder): - if not placeholder or not os.path.exists(placeholder): - log.warn('Could not find the install location') - return - pyver = '%s.%s' % (sys.version_info[0], sys.version_info[1]) - setuptools_file = 'setuptools-%s-py%s.egg-info' % \ - (SETUPTOOLS_FAKED_VERSION, pyver) - pkg_info = os.path.join(placeholder, setuptools_file) - if os.path.exists(pkg_info): - log.warn('%s already exists', pkg_info) - return - - if not os.access(pkg_info, os.W_OK): - log.warn("Don't have permissions to write %s, skipping", pkg_info) - - log.warn('Creating %s', pkg_info) - f = open(pkg_info, 'w') - try: - f.write(SETUPTOOLS_PKG_INFO) - finally: - f.close() - - pth_file = os.path.join(placeholder, 'setuptools.pth') - log.warn('Creating %s', pth_file) - f = open(pth_file, 'w') - try: - f.write(os.path.join(os.curdir, setuptools_file)) - finally: - f.close() - -_create_fake_setuptools_pkg_info = _no_sandbox(_create_fake_setuptools_pkg_info) - -def _patch_egg_dir(path): - # let's check if it's already patched - pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO') - if os.path.exists(pkg_info): - if _same_content(pkg_info, SETUPTOOLS_PKG_INFO): - log.warn('%s already patched.', pkg_info) - return False - _rename_path(path) - os.mkdir(path) - os.mkdir(os.path.join(path, 'EGG-INFO')) - pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO') - f = open(pkg_info, 'w') - try: - f.write(SETUPTOOLS_PKG_INFO) - finally: - f.close() - return True - -_patch_egg_dir = _no_sandbox(_patch_egg_dir) - -def _before_install(): - log.warn('Before install bootstrap.') - _fake_setuptools() - - -def _under_prefix(location): - if 'install' not in sys.argv: - return True - args = sys.argv[sys.argv.index('install')+1:] - for index, arg in enumerate(args): - for option in ('--root', '--prefix'): - if arg.startswith('%s=' % option): - top_dir = arg.split('root=')[-1] - return location.startswith(top_dir) - elif arg == option: - if len(args) > index: - top_dir = args[index+1] - return location.startswith(top_dir) - if arg == '--user' and USER_SITE is not None: - return location.startswith(USER_SITE) - return True - - -def _fake_setuptools(): - log.warn('Scanning installed packages') - try: - import pkg_resources - except ImportError: - # we're cool - log.warn('Setuptools or Distribute does not seem to be installed.') - return - ws = pkg_resources.working_set - try: - setuptools_dist = ws.find(pkg_resources.Requirement.parse('setuptools', - replacement=False)) - except TypeError: - # old distribute API - setuptools_dist = ws.find(pkg_resources.Requirement.parse('setuptools')) - - if setuptools_dist is None: - log.warn('No setuptools distribution found') - return - # detecting if it was already faked - setuptools_location = setuptools_dist.location - log.warn('Setuptools installation detected at %s', setuptools_location) - - # if --root or --preix was provided, and if - # setuptools is not located in them, we don't patch it - if not _under_prefix(setuptools_location): - log.warn('Not patching, --root or --prefix is installing Distribute' - ' in another location') - return - - # let's see if its an egg - if not setuptools_location.endswith('.egg'): - log.warn('Non-egg installation') - res = _remove_flat_installation(setuptools_location) - if not res: - return - else: - log.warn('Egg installation') - pkg_info = os.path.join(setuptools_location, 'EGG-INFO', 'PKG-INFO') - if (os.path.exists(pkg_info) and - _same_content(pkg_info, SETUPTOOLS_PKG_INFO)): - log.warn('Already patched.') - return - log.warn('Patching...') - # let's create a fake egg replacing setuptools one - res = _patch_egg_dir(setuptools_location) - if not res: - return - log.warn('Patched done.') - _relaunch() - - -def _relaunch(): - log.warn('Relaunching...') - # we have to relaunch the process - # pip marker to avoid a relaunch bug - if sys.argv[:3] == ['-c', 'install', '--single-version-externally-managed']: - sys.argv[0] = 'setup.py' - args = [sys.executable] + sys.argv - sys.exit(subprocess.call(args)) - - -def _extractall(self, path=".", members=None): - """Extract all members from the archive to the current working - directory and set owner, modification time and permissions on - directories afterwards. `path' specifies a different directory - to extract to. `members' is optional and must be a subset of the - list returned by getmembers(). - """ - import copy - import operator - from tarfile import ExtractError - directories = [] - - if members is None: - members = self - - for tarinfo in members: - if tarinfo.isdir(): - # Extract directories with a safe mode. - directories.append(tarinfo) - tarinfo = copy.copy(tarinfo) - tarinfo.mode = 448 # decimal for oct 0700 - self.extract(tarinfo, path) - - # Reverse sort directories. - if sys.version_info < (2, 4): - def sorter(dir1, dir2): - return cmp(dir1.name, dir2.name) - directories.sort(sorter) - directories.reverse() - else: - directories.sort(key=operator.attrgetter('name'), reverse=True) - - # Set correct owner, mtime and filemode on directories. - for tarinfo in directories: - dirpath = os.path.join(path, tarinfo.name) - try: - self.chown(tarinfo, dirpath) - self.utime(tarinfo, dirpath) - self.chmod(tarinfo, dirpath) - except ExtractError: - e = sys.exc_info()[1] - if self.errorlevel > 1: - raise - else: - self._dbg(1, "tarfile: %s" % e) - -def _build_install_args(argv): - install_args = [] - user_install = '--user' in argv - if user_install and sys.version_info < (2,6): - log.warn("--user requires Python 2.6 or later") - raise SystemExit(1) - if user_install: - install_args.append('--user') - return install_args - -def main(argv, version=DEFAULT_VERSION): - """Install or upgrade setuptools and EasyInstall""" - tarball = download_setuptools() - _install(tarball, _build_install_args(argv)) - - -if __name__ == '__main__': - main(sys.argv[1:]) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/py-1.4.18/py/__init__.py new/py-1.4.19/py/__init__.py --- old/py-1.4.18/py/__init__.py 2013-10-29 11:34:25.000000000 +0100 +++ new/py-1.4.19/py/__init__.py 2013-12-12 12:07:15.000000000 +0100 @@ -8,7 +8,7 @@ (c) Holger Krekel and others, 2004-2013 """ -__version__ = '1.4.18' +__version__ = '1.4.19' from py import _apipkg diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/py-1.4.18/py/_apipkg.py new/py-1.4.19/py/_apipkg.py --- old/py-1.4.18/py/_apipkg.py 2013-10-29 11:34:25.000000000 +0100 +++ new/py-1.4.19/py/_apipkg.py 2013-12-12 12:07:15.000000000 +0100 @@ -9,7 +9,17 @@ import sys from types import ModuleType -__version__ = '1.2' +__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. """ @@ -17,14 +27,14 @@ d = {} f = getattr(oldmod, '__file__', None) if f: - f = os.path.abspath(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__'] = [os.path.abspath(p) for p in 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) @@ -164,4 +174,4 @@ def __delattr__(self, name): delattr(getmod(), name) - return AliasModule(modname) + return AliasModule(str(modname)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/py-1.4.18/py/_code/code.py new/py-1.4.19/py/_code/code.py --- old/py-1.4.18/py/_code/code.py 2013-10-29 11:34:25.000000000 +0100 +++ new/py-1.4.19/py/_code/code.py 2013-12-12 12:07:15.000000000 +0100 @@ -9,14 +9,15 @@ class Code(object): """ wrapper around Python code objects """ def __init__(self, rawcode): - rawcode = py.code.getrawcode(rawcode) - self.raw = 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 @@ -24,25 +25,25 @@ def __ne__(self, other): return not self == other + @property def path(self): - """ return a path object pointing to source code""" + """ 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 - path = property(path, None, None, "path of this code object") - + @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 - fullsource = property(fullsource, None, None, - "full source containing this code object") def source(self): """ return a py.code.Source object for the code object's source only @@ -69,18 +70,18 @@ in which expressions can be evaluated.""" def __init__(self, frame): - self.code = py.code.Code(frame.f_code) 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) - statement = property(statement, None, None, - "statement this frame is at") def eval(self, code, **vars): """ evaluate 'code' in the frame @@ -131,26 +132,29 @@ def __init__(self, rawentry): self._rawentry = rawentry - self.frame = py.code.Frame(rawentry.tb_frame) - # Ugh. 2.4 and 2.5 differs here when encountering - # multi-line statements. Not sure about the solution, but - # should be portable self.lineno = rawentry.tb_lineno - 1 - self.relline = self.lineno - self.frame.code.firstlineno + + @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): - """ return a py.code.Source object for the current statement """ + """ py.code.Source object for the current statement """ source = self.frame.code.fullsource return source.getstatement(self.lineno) - statement = property(statement, None, None, - "statement of this traceback entry.") + @property def path(self): + """ path to the source code """ return self.frame.code.path - path = property(path, None, None, "path to the full source code") def getlocals(self): return self.frame.f_locals @@ -204,11 +208,12 @@ mostly for internal use """ try: - return self.frame.eval("__tracebackhide__") - except py.builtin._sysex: - raise - except: - return False + return self.frame.f_locals['__tracebackhide__'] + except KeyError: + try: + return self.frame.f_globals['__tracebackhide__'] + except KeyError: + return False def __str__(self): try: @@ -287,10 +292,11 @@ """ return last non-hidden traceback entry that lead to the exception of a traceback. """ - tb = self.filter() - if not tb: - tb = self - return tb[-1] + 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 @@ -336,7 +342,7 @@ if exprinfo and exprinfo.startswith('assert '): self._striptext = 'AssertionError: ' self._excinfo = tup - self.type, self.value, tb = self._excinfo + self.type, self.value, tb = tup self.typename = self.type.__name__ self.traceback = py.code.Traceback(tb) @@ -351,7 +357,7 @@ the exception representation is returned (so 'AssertionError: ' is removed from the beginning) """ - lines = py.std.traceback.format_exception_only(self.type, self.value) + lines = self._format_exception_only(self.type, self.value) text = ''.join(lines) text = text.rstrip() if tryshort: @@ -359,6 +365,17 @@ text = text[len(self._striptext):] return text + def _format_exception_only(self, etype, value): + """Format the exception part of a traceback + + Since traceback.format_exception_only() destroys unicode on + python 2 we handle plain AsssertionErrors separately here. + """ + if isinstance(value, AssertionError) and hasattr(value, 'msg'): + return ['AssertionError: ' + value.msg] + else: + return py.std.traceback.format_exception_only(etype, value) + def errisinstance(self, exc): """ return True if the exception is an instance of exc """ return isinstance(self.value, exc) @@ -366,9 +383,8 @@ def _getreprcrash(self): exconly = self.exconly(tryshort=True) entry = self.traceback.getcrashentry() - path, lineno = entry.path, entry.lineno - reprcrash = ReprFileLocation(path, lineno+1, exconly) - return reprcrash + 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): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/py-1.4.18/py/_io/saferepr.py new/py-1.4.19/py/_io/saferepr.py --- old/py-1.4.18/py/_io/saferepr.py 2013-10-29 11:34:25.000000000 +0100 +++ new/py-1.4.19/py/_io/saferepr.py 2013-12-12 12:07:15.000000000 +0100 @@ -12,6 +12,23 @@ 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) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/py-1.4.18/py/_io/terminalwriter.py new/py-1.4.19/py/_io/terminalwriter.py --- old/py-1.4.18/py/_io/terminalwriter.py 2013-10-29 11:34:25.000000000 +0100 +++ new/py-1.4.19/py/_io/terminalwriter.py 2013-12-12 12:07:15.000000000 +0100 @@ -101,6 +101,10 @@ 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') @@ -184,12 +188,7 @@ markupmsg = self.markup(msg, **kw) else: markupmsg = msg - try: - self._file.write(markupmsg) - except UnicodeEncodeError: - msg = msg.encode("unicode-escape").decode("ascii") - self._file.write(msg) - self._file.flush() + write_out(self._file, markupmsg) def line(self, s='', **kw): self.write(s, **kw) @@ -235,12 +234,7 @@ attr |= oldcolors & 0x0007 SetConsoleTextAttribute(handle, attr) - try: - self._file.write(msg) - except UnicodeEncodeError: - msg = msg.encode("unicode-escape").decode("ascii") - self._file.write(msg) - self._file.flush() + write_out(self._file, msg) if oldcolors: SetConsoleTextAttribute(handle, oldcolors) @@ -322,3 +316,26 @@ # 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() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/py-1.4.18/py/_path/local.py new/py-1.4.19/py/_path/local.py --- old/py-1.4.18/py/_path/local.py 2013-10-29 11:34:25.000000000 +0100 +++ new/py-1.4.19/py/_path/local.py 2013-12-12 12:07:15.000000000 +0100 @@ -7,7 +7,7 @@ from py._path import common from stat import S_ISLNK, S_ISDIR, S_ISREG -from os.path import normpath, isabs, exists, isdir, isfile, islink +from os.path import abspath, normpath, isabs, exists, isdir, isfile, islink iswin32 = sys.platform == "win32" or (getattr(os, '_name', False) == 'nt') @@ -151,11 +151,10 @@ elif isinstance(path, py.builtin._basestring): if expanduser: path = os.path.expanduser(path) - self.strpath = os.path.abspath(normpath(str(path))) + self.strpath = abspath(normpath(path)) else: raise ValueError("can only pass None, Path instances " "or non-empty strings to LocalPath") - assert isinstance(self.strpath, py.builtin._basestring) def __hash__(self): return hash(self.strpath) @@ -184,8 +183,8 @@ """ return True if 'other' references the same file as 'self'. """ other = getattr(other, "strpath", other) - if not os.path.isabs(other): - other = os.path.abspath(other) + if not isabs(other): + other = abspath(other) if self == other: return True if iswin32: @@ -369,7 +368,7 @@ if isinstance(fil, py.builtin._basestring): if not self._patternchars.intersection(fil): child = self._fastjoin(fil) - if os.path.exists(child.strpath): + if exists(child.strpath): return [child] return [] fil = common.FNMatcher(fil) @@ -682,7 +681,7 @@ Note: This is probably not working on plain win32 systems but may work on cygwin. """ - if os.path.isabs(name): + if isabs(name): p = py.path.local(name) if p.check(file=1): return p diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/py-1.4.18/py.egg-info/PKG-INFO new/py-1.4.19/py.egg-info/PKG-INFO --- old/py-1.4.18/py.egg-info/PKG-INFO 2013-10-29 11:34:25.000000000 +0100 +++ new/py-1.4.19/py.egg-info/PKG-INFO 2013-12-12 12:07:15.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: py -Version: 1.4.18 +Version: 1.4.19 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 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/py-1.4.18/py.egg-info/SOURCES.txt new/py-1.4.19/py.egg-info/SOURCES.txt --- old/py-1.4.18/py.egg-info/SOURCES.txt 2013-10-29 11:34:25.000000000 +0100 +++ new/py-1.4.19/py.egg-info/SOURCES.txt 2013-12-12 12:07:15.000000000 +0100 @@ -3,7 +3,6 @@ MANIFEST.in README.txt conftest.py -distribute_setup.py setup.py tox.ini doc/Makefile diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/py-1.4.18/setup.py new/py-1.4.19/setup.py --- old/py-1.4.18/setup.py 2013-10-29 11:34:25.000000000 +0100 +++ new/py-1.4.19/setup.py 2013-12-12 12:07:15.000000000 +0100 @@ -1,18 +1,13 @@ import os, sys -try: - from setuptools import setup -except ImportError: - from distribute_setup import use_setuptools - use_setuptools() - from setuptools import setup +from setuptools import setup def main(): setup( name='py', description='library with cross-python path, ini-parsing, io, code, log facilities', long_description = open('README.txt').read(), - version='1.4.18', + version='1.4.19', url='http://pylib.readthedocs.org/', license='MIT license', platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'], diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/py-1.4.18/testing/code/test_excinfo.py new/py-1.4.19/testing/code/test_excinfo.py --- old/py-1.4.18/testing/code/test_excinfo.py 2013-10-29 11:34:25.000000000 +0100 +++ new/py-1.4.19/testing/code/test_excinfo.py 2013-12-12 12:07:15.000000000 +0100 @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- import py from py._code.code import FormattedExcinfo, ReprExceptionInfo @@ -13,6 +14,10 @@ else: invalidate_import_caches = getattr(importlib, "invalidate_caches", None) +import pytest +pytest_version_info = tuple(map(int, pytest.__version__.split(".")[:3])) +pytest25 = pytest.mark.skipif(pytest_version_info < (2,5), reason="requires pytest-2.5") + class TWMock: def __init__(self): self.lines = [] @@ -239,6 +244,15 @@ assert msg.startswith('ValueError') assert msg.endswith("world") +@pytest25 +def test_excinfo_exconly_unicode_AssertionError(): + val = py.builtin._totext('£€', 'utf-8') + def fail(): + raise AssertionError(val) + excinfo = py.test.raises(Exception, fail) + msg = excinfo.exconly(tryshort=True) + assert msg == 'AssertionError: ' + val + def test_excinfo_repr(): excinfo = py.test.raises(ValueError, h) s = repr(excinfo) @@ -385,6 +399,8 @@ pr = FormattedExcinfo() class FakeCode(object): + class raw: + co_filename = '?' path = '?' firstlineno = 5 @@ -395,12 +411,16 @@ class FakeFrame(object): code = FakeCode() f_locals = {} + f_globals = {} class FakeTracebackEntry(py.code.Traceback.Entry): def __init__(self, tb): - self.frame = FakeFrame() self.lineno = 5+3 + @property + def frame(self): + return FakeFrame() + class Traceback(py.code.Traceback): Entry = FakeTracebackEntry diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/py-1.4.18/testing/io_/test_saferepr.py new/py-1.4.19/testing/io_/test_saferepr.py --- old/py-1.4.18/testing/io_/test_saferepr.py 2013-10-29 11:34:25.000000000 +0100 +++ new/py-1.4.19/testing/io_/test_saferepr.py 2013-12-12 12:07:15.000000000 +0100 @@ -1,3 +1,5 @@ +# -*- coding: utf-8 -*- + from __future__ import generators import py import sys @@ -60,6 +62,11 @@ except Exception: py.test.fail("saferepr failed for newstyle class") + def test_unicode(self): + val = py.builtin._totext('£€', 'utf-8') + reprval = py.builtin._totext("'£€'", 'utf-8') + assert saferepr(val) == reprval + def test_unicode_handling(): value = py.builtin._totext('\xc4\x85\xc4\x87\n', 'utf-8').encode('utf8') def f(): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/py-1.4.18/testing/io_/test_terminalwriter.py new/py-1.4.19/testing/io_/test_terminalwriter.py --- old/py-1.4.18/testing/io_/test_terminalwriter.py 2013-10-29 11:34:25.000000000 +0100 +++ new/py-1.4.19/testing/io_/test_terminalwriter.py 2013-12-12 12:07:15.000000000 +0100 @@ -218,14 +218,18 @@ assert l == set(["2"]) +@pytest.mark.skipif(sys.platform == "win32", reason="win32 has no native ansi") def test_attr_hasmarkup(): tw = py.io.TerminalWriter(stringio=True) assert not tw.hasmarkup tw.hasmarkup = True tw.line("hello", bold=True) s = tw.stringio.getvalue() - assert len(s) > len("hello") + assert len(s) > len("hello\n") + assert '\x1b[1m' in s + assert '\x1b[0m' in s +@pytest.mark.skipif(sys.platform == "win32", reason="win32 has no native ansi") def test_ansi_print(): # we have no easy way to construct a file that # represents a terminal @@ -234,4 +238,27 @@ py.io.ansi_print("hello", 0x32, file=f) text2 = f.getvalue() assert text2.find("hello") != -1 - assert len(text2) >= len("hello") + assert len(text2) >= len("hello\n") + assert '\x1b[50m' in text2 + assert '\x1b[0m' in text2 + +def test_should_do_markup_PY_COLORS_eq_1(monkeypatch): + monkeypatch.setitem(os.environ, 'PY_COLORS', '1') + tw = py.io.TerminalWriter(stringio=True) + assert tw.hasmarkup + tw.line("hello", bold=True) + s = tw.stringio.getvalue() + assert len(s) > len("hello\n") + assert '\x1b[1m' in s + assert '\x1b[0m' in s + +def test_should_do_markup_PY_COLORS_eq_0(monkeypatch): + monkeypatch.setitem(os.environ, 'PY_COLORS', '0') + f = py.io.TextIO() + f.isatty = lambda: True + tw = py.io.TerminalWriter(file=f) + assert not tw.hasmarkup + tw.line("hello", bold=True) + s = f.getvalue() + assert s == "hello\n" + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/py-1.4.18/tox.ini new/py-1.4.19/tox.ini --- old/py-1.4.18/tox.ini 2013-10-29 11:34:25.000000000 +0100 +++ new/py-1.4.19/tox.ini 2013-12-12 12:07:15.000000000 +0100 @@ -1,5 +1,5 @@ [tox] -envlist=py25,py26,py27,py32,py33,external +envlist=py26,py27,py32,py33,external # py27-xdist causes problems with svn, py25 requires virtualenv==1.9.1 #indexserver= # default=http://pypi.testrun.org -- To unsubscribe, e-mail: opensuse-commit+unsubscr...@opensuse.org For additional commands, e-mail: opensuse-commit+h...@opensuse.org