[Python-modules-commits] [logilab-common] 02/07: Import logilab-common_1.1.0.orig.tar.gz
Sandro Tosi
morph at moszumanska.debian.org
Sun Jan 17 22:15:42 UTC 2016
This is an automated email from the git hooks/post-receive script.
morph pushed a commit to branch master
in repository logilab-common.
commit 1391537bd4f9010917838322a2b72d38f53fd832
Author: Sandro Tosi <morph at debian.org>
Date: Sun Jan 17 21:35:40 2016 +0000
Import logilab-common_1.1.0.orig.tar.gz
---
ChangeLog | 12 +
PKG-INFO | 2 +-
__pkginfo__.py | 2 +-
logilab/common/configuration.py | 4 +-
logilab/common/modutils.py | 6 +-
logilab/common/optik_ext.py | 6 +-
logilab/common/pytest.py | 157 ++++++++-
logilab/common/shellutils.py | 56 ----
logilab/common/testlib.py | 696 +--------------------------------------
logilab/common/umessage.py | 107 +++---
logilab_common.egg-info/PKG-INFO | 2 +-
test/unittest_configuration.py | 52 ++-
test/unittest_shellutils.py | 44 +--
test/unittest_testlib.py | 81 ++---
test/unittest_umessage.py | 31 +-
15 files changed, 352 insertions(+), 906 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index b698981..9a47911 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,18 @@
ChangeLog for logilab.common
============================
+2015-10-12 -- 1.1.0
+ * configuration: have a stable order for sections (#298658)
+
+ * testlib: clean out deprecated TestCase methods (#1716063), move pytest
+ specifics to pytest.py (#1716053)
+
+ * fix a few python3 bugs in umessage, configuration and optik_ext modules
+
+ * testlib: report failures and skips in generative tests properly
+
+ * optik_ext: return bytes as ints and not floats (#2086835)
+
2015-07-08 -- 1.0.2
* declare setuptools requirement in __pkginfo__/setup.py
diff --git a/PKG-INFO b/PKG-INFO
index 45d93ef..6101c77 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: logilab-common
-Version: 1.0.2
+Version: 1.1.0
Summary: collection of low-level Python packages and modules used by Logilab projects
Home-page: http://www.logilab.org/project/logilab-common
Author: Logilab
diff --git a/__pkginfo__.py b/__pkginfo__.py
index 7f418d3..8b50d7d 100644
--- a/__pkginfo__.py
+++ b/__pkginfo__.py
@@ -25,7 +25,7 @@ modname = 'common'
subpackage_of = 'logilab'
subpackage_master = True
-numversion = (1, 0, 2)
+numversion = (1, 1, 0)
version = '.'.join([str(num) for num in numversion])
license = 'LGPL' # 2.1 or later
diff --git a/logilab/common/configuration.py b/logilab/common/configuration.py
index b292427..38af31d 100644
--- a/logilab/common/configuration.py
+++ b/logilab/common/configuration.py
@@ -909,7 +909,7 @@ class OptionsProviderMixIn(object):
(optname, optdict, self.option_value(optname)))
if None in sections:
yield None, sections.pop(None)
- for section, options in sections.items():
+ for section, options in sorted(sections.items()):
yield section.upper(), options
def options_and_values(self, options=None):
@@ -954,7 +954,7 @@ class ConfigurationMixIn(OptionsManagerMixIn, OptionsProviderMixIn):
OptionsProviderMixIn.load_defaults(self)
def __iter__(self):
- return iter(self.config.__dict__.iteritems())
+ return iter(self.config.__dict__.items())
def __getitem__(self, key):
try:
diff --git a/logilab/common/modutils.py b/logilab/common/modutils.py
index dd725d2..e70a1a9 100644
--- a/logilab/common/modutils.py
+++ b/logilab/common/modutils.py
@@ -165,7 +165,11 @@ def load_module_from_modpath(parts, path=None, use_sys=True):
module = sys.modules.get(curname)
if module is None:
mp_file, mp_filename, mp_desc = find_module(part, path)
- module = load_module(curname, mp_file, mp_filename, mp_desc)
+ try:
+ module = load_module(curname, mp_file, mp_filename, mp_desc)
+ finally:
+ if mp_file is not None:
+ mp_file.close()
if prevmodule:
setattr(prevmodule, part, module)
_file = getattr(module, '__file__', '')
diff --git a/logilab/common/optik_ext.py b/logilab/common/optik_ext.py
index 1fd2a7f..95489c2 100644
--- a/logilab/common/optik_ext.py
+++ b/logilab/common/optik_ext.py
@@ -56,6 +56,8 @@ import time
from copy import copy
from os.path import exists
+from six import integer_types
+
# python >= 2.3
from optparse import OptionParser as BaseParser, Option as BaseOption, \
OptionGroup, OptionContainer, OptionValueError, OptionError, \
@@ -169,14 +171,14 @@ def check_color(option, opt, value):
raise OptionValueError(msg % (opt, value))
def check_time(option, opt, value):
- if isinstance(value, (int, long, float)):
+ if isinstance(value, integer_types + (float,)):
return value
return apply_units(value, TIME_UNITS)
def check_bytes(option, opt, value):
if hasattr(value, '__int__'):
return value
- return apply_units(value, BYTE_UNITS)
+ return apply_units(value, BYTE_UNITS, final=int)
class Option(BaseOption):
diff --git a/logilab/common/pytest.py b/logilab/common/pytest.py
index 3d8aca3..c1dca63 100644
--- a/logilab/common/pytest.py
+++ b/logilab/common/pytest.py
@@ -118,9 +118,12 @@ import os.path as osp
from time import time, clock
import warnings
import types
+import inspect
+import traceback
from inspect import isgeneratorfunction, isclass
from contextlib import contextmanager
from random import shuffle
+from itertools import dropwhile
from logilab.common.fileutils import abspath_listdir
from logilab.common import textutils
@@ -128,6 +131,7 @@ from logilab.common import testlib, STD_BLACKLIST
# use the same unittest module as testlib
from logilab.common.testlib import unittest, start_interactive_mode
from logilab.common.deprecation import deprecated
+from logilab.common.debugger import Debugger, colorize_source
import doctest
import unittest as unittest_legacy
@@ -938,7 +942,7 @@ class SkipAwareTextTestRunner(unittest.TextTestRunner):
return True # no pattern
def _makeResult(self):
- return testlib.SkipAwareTestResult(self.stream, self.descriptions,
+ return SkipAwareTestResult(self.stream, self.descriptions,
self.verbosity, self.exitfirst,
self.pdbmode, self.cvg, self.colorize)
@@ -983,6 +987,155 @@ class SkipAwareTextTestRunner(unittest.TextTestRunner):
self.stream.writeln("")
return result
+
+class SkipAwareTestResult(unittest._TextTestResult):
+
+ def __init__(self, stream, descriptions, verbosity,
+ exitfirst=False, pdbmode=False, cvg=None, colorize=False):
+ super(SkipAwareTestResult, self).__init__(stream,
+ descriptions, verbosity)
+ self.skipped = []
+ self.debuggers = []
+ self.fail_descrs = []
+ self.error_descrs = []
+ self.exitfirst = exitfirst
+ self.pdbmode = pdbmode
+ self.cvg = cvg
+ self.colorize = colorize
+ self.pdbclass = Debugger
+ self.verbose = verbosity > 1
+
+ def descrs_for(self, flavour):
+ return getattr(self, '%s_descrs' % flavour.lower())
+
+ def _create_pdb(self, test_descr, flavour):
+ self.descrs_for(flavour).append( (len(self.debuggers), test_descr) )
+ if self.pdbmode:
+ self.debuggers.append(self.pdbclass(sys.exc_info()[2]))
+
+ def _iter_valid_frames(self, frames):
+ """only consider non-testlib frames when formatting traceback"""
+ lgc_testlib = osp.abspath(__file__)
+ std_testlib = osp.abspath(unittest.__file__)
+ invalid = lambda fi: osp.abspath(fi[1]) in (lgc_testlib, std_testlib)
+ for frameinfo in dropwhile(invalid, frames):
+ yield frameinfo
+
+ def _exc_info_to_string(self, err, test):
+ """Converts a sys.exc_info()-style tuple of values into a string.
+
+ This method is overridden here because we want to colorize
+ lines if --color is passed, and display local variables if
+ --verbose is passed
+ """
+ exctype, exc, tb = err
+ output = ['Traceback (most recent call last)']
+ frames = inspect.getinnerframes(tb)
+ colorize = self.colorize
+ frames = enumerate(self._iter_valid_frames(frames))
+ for index, (frame, filename, lineno, funcname, ctx, ctxindex) in frames:
+ filename = osp.abspath(filename)
+ if ctx is None: # pyc files or C extensions for instance
+ source = '<no source available>'
+ else:
+ source = ''.join(ctx)
+ if colorize:
+ filename = textutils.colorize_ansi(filename, 'magenta')
+ source = colorize_source(source)
+ output.append(' File "%s", line %s, in %s' % (filename, lineno, funcname))
+ output.append(' %s' % source.strip())
+ if self.verbose:
+ output.append('%r == %r' % (dir(frame), test.__module__))
+ output.append('')
+ output.append(' ' + ' local variables '.center(66, '-'))
+ for varname, value in sorted(frame.f_locals.items()):
+ output.append(' %s: %r' % (varname, value))
+ if varname == 'self': # special handy processing for self
+ for varname, value in sorted(vars(value).items()):
+ output.append(' self.%s: %r' % (varname, value))
+ output.append(' ' + '-' * 66)
+ output.append('')
+ output.append(''.join(traceback.format_exception_only(exctype, exc)))
+ return '\n'.join(output)
+
+ def addError(self, test, err):
+ """err -> (exc_type, exc, tcbk)"""
+ exc_type, exc, _ = err
+ if isinstance(exc, testlib.SkipTest):
+ assert exc_type == SkipTest
+ self.addSkip(test, exc)
+ else:
+ if self.exitfirst:
+ self.shouldStop = True
+ descr = self.getDescription(test)
+ super(SkipAwareTestResult, self).addError(test, err)
+ self._create_pdb(descr, 'error')
+
+ def addFailure(self, test, err):
+ if self.exitfirst:
+ self.shouldStop = True
+ descr = self.getDescription(test)
+ super(SkipAwareTestResult, self).addFailure(test, err)
+ self._create_pdb(descr, 'fail')
+
+ def addSkip(self, test, reason):
+ self.skipped.append((test, reason))
+ if self.showAll:
+ self.stream.writeln("SKIPPED")
+ elif self.dots:
+ self.stream.write('S')
+
+ def printErrors(self):
+ super(SkipAwareTestResult, self).printErrors()
+ self.printSkippedList()
+
+ def printSkippedList(self):
+ # format (test, err) compatible with unittest2
+ for test, err in self.skipped:
+ descr = self.getDescription(test)
+ self.stream.writeln(self.separator1)
+ self.stream.writeln("%s: %s" % ('SKIPPED', descr))
+ self.stream.writeln("\t%s" % err)
+
+ def printErrorList(self, flavour, errors):
+ for (_, descr), (test, err) in zip(self.descrs_for(flavour), errors):
+ self.stream.writeln(self.separator1)
+ self.stream.writeln("%s: %s" % (flavour, descr))
+ self.stream.writeln(self.separator2)
+ self.stream.writeln(err)
+ self.stream.writeln('no stdout'.center(len(self.separator2)))
+ self.stream.writeln('no stderr'.center(len(self.separator2)))
+
+
+from .decorators import monkeypatch
+orig_call = testlib.TestCase.__call__
+ at monkeypatch(testlib.TestCase, '__call__')
+def call(self, result=None, runcondition=None, options=None):
+ orig_call(self, result=result, runcondition=runcondition, options=options)
+ if hasattr(options, "exitfirst") and options.exitfirst:
+ # add this test to restart file
+ try:
+ restartfile = open(FILE_RESTART, 'a')
+ try:
+ descr = '.'.join((self.__class__.__module__,
+ self.__class__.__name__,
+ self._testMethodName))
+ restartfile.write(descr+os.linesep)
+ finally:
+ restartfile.close()
+ except Exception:
+ print("Error while saving succeeded test into",
+ osp.join(os.getcwd(), FILE_RESTART),
+ file=sys.__stderr__)
+ raise
+
+
+ at monkeypatch(testlib.TestCase)
+def defaultTestResult(self):
+ """return a new instance of the defaultTestResult"""
+ return SkipAwareTestResult()
+
+
class NonStrictTestLoader(unittest.TestLoader):
"""
Overrides default testloader to be able to omit classname when
@@ -1186,7 +1339,7 @@ def enable_dbc(*args):
# monkeypatch unittest and doctest (ouch !)
-unittest._TextTestResult = testlib.SkipAwareTestResult
+unittest._TextTestResult = SkipAwareTestResult
unittest.TextTestRunner = SkipAwareTextTestRunner
unittest.TestLoader = NonStrictTestLoader
unittest.TestProgram = SkipAwareTestProgram
diff --git a/logilab/common/shellutils.py b/logilab/common/shellutils.py
index 4e68956..b4abbf1 100644
--- a/logilab/common/shellutils.py
+++ b/logilab/common/shellutils.py
@@ -44,15 +44,6 @@ from logilab.common import STD_BLACKLIST, _handle_blacklist
from logilab.common.compat import str_to_bytes
from logilab.common.deprecation import deprecated
-try:
- from logilab.common.proc import ProcInfo, NoSuchProcess
-except ImportError:
- # windows platform
- class NoSuchProcess(Exception): pass
-
- def ProcInfo(pid):
- raise NoSuchProcess()
-
class tempdir(object):
@@ -245,53 +236,6 @@ class Execute:
Execute = deprecated('Use subprocess.Popen instead')(Execute)
-def acquire_lock(lock_file, max_try=10, delay=10, max_delay=3600):
- """Acquire a lock represented by a file on the file system
-
- If the process written in lock file doesn't exist anymore, we remove the
- lock file immediately
- If age of the lock_file is greater than max_delay, then we raise a UserWarning
- """
- count = abs(max_try)
- while count:
- try:
- fd = os.open(lock_file, os.O_EXCL | os.O_RDWR | os.O_CREAT)
- os.write(fd, str_to_bytes(str(os.getpid())) )
- os.close(fd)
- return True
- except OSError as e:
- if e.errno == errno.EEXIST:
- try:
- fd = open(lock_file, "r")
- pid = int(fd.readline())
- pi = ProcInfo(pid)
- age = (time.time() - os.stat(lock_file)[stat.ST_MTIME])
- if age / max_delay > 1 :
- raise UserWarning("Command '%s' (pid %s) has locked the "
- "file '%s' for %s minutes"
- % (pi.name(), pid, lock_file, age/60))
- except UserWarning:
- raise
- except NoSuchProcess:
- os.remove(lock_file)
- except Exception:
- # The try block is not essential. can be skipped.
- # Note: ProcInfo object is only available for linux
- # process information are not accessible...
- # or lock_file is no more present...
- pass
- else:
- raise
- count -= 1
- time.sleep(delay)
- else:
- raise Exception('Unable to acquire %s' % lock_file)
-
-def release_lock(lock_file):
- """Release a lock represented by a file on the file system."""
- os.remove(lock_file)
-
-
class ProgressBar(object):
"""A simple text progression bar."""
diff --git a/logilab/common/testlib.py b/logilab/common/testlib.py
index a6b4b1e..9fafdfa 100644
--- a/logilab/common/testlib.py
+++ b/logilab/common/testlib.py
@@ -47,15 +47,12 @@ __docformat__ = "restructuredtext en"
import sys
import os, os.path as osp
import re
-import traceback
-import inspect
import difflib
import tempfile
import math
import warnings
from shutil import rmtree
from operator import itemgetter
-from itertools import dropwhile
from inspect import isgeneratorfunction
from six import string_types
@@ -71,17 +68,17 @@ if not getattr(unittest_legacy, "__package__", None):
except ImportError:
raise ImportError("You have to install python-unittest2 to use %s" % __name__)
else:
- import unittest
+ import unittest as unittest
from unittest import SkipTest
from functools import wraps
-from logilab.common.debugger import Debugger, colorize_source
+from logilab.common.debugger import Debugger
from logilab.common.decorators import cached, classproperty
from logilab.common import textutils
-__all__ = ['main', 'unittest_main', 'find_tests', 'run_test', 'spawn']
+__all__ = ['unittest_main', 'find_tests']
DEFAULT_PREFIXES = ('test', 'regrtest', 'smoketest', 'unittest',
'func', 'validation')
@@ -204,123 +201,6 @@ def start_interactive_mode(result):
# test utils ##################################################################
-class SkipAwareTestResult(unittest._TextTestResult):
-
- def __init__(self, stream, descriptions, verbosity,
- exitfirst=False, pdbmode=False, cvg=None, colorize=False):
- super(SkipAwareTestResult, self).__init__(stream,
- descriptions, verbosity)
- self.skipped = []
- self.debuggers = []
- self.fail_descrs = []
- self.error_descrs = []
- self.exitfirst = exitfirst
- self.pdbmode = pdbmode
- self.cvg = cvg
- self.colorize = colorize
- self.pdbclass = Debugger
- self.verbose = verbosity > 1
-
- def descrs_for(self, flavour):
- return getattr(self, '%s_descrs' % flavour.lower())
-
- def _create_pdb(self, test_descr, flavour):
- self.descrs_for(flavour).append( (len(self.debuggers), test_descr) )
- if self.pdbmode:
- self.debuggers.append(self.pdbclass(sys.exc_info()[2]))
-
- def _iter_valid_frames(self, frames):
- """only consider non-testlib frames when formatting traceback"""
- lgc_testlib = osp.abspath(__file__)
- std_testlib = osp.abspath(unittest.__file__)
- invalid = lambda fi: osp.abspath(fi[1]) in (lgc_testlib, std_testlib)
- for frameinfo in dropwhile(invalid, frames):
- yield frameinfo
-
- def _exc_info_to_string(self, err, test):
- """Converts a sys.exc_info()-style tuple of values into a string.
-
- This method is overridden here because we want to colorize
- lines if --color is passed, and display local variables if
- --verbose is passed
- """
- exctype, exc, tb = err
- output = ['Traceback (most recent call last)']
- frames = inspect.getinnerframes(tb)
- colorize = self.colorize
- frames = enumerate(self._iter_valid_frames(frames))
- for index, (frame, filename, lineno, funcname, ctx, ctxindex) in frames:
- filename = osp.abspath(filename)
- if ctx is None: # pyc files or C extensions for instance
- source = '<no source available>'
- else:
- source = ''.join(ctx)
- if colorize:
- filename = textutils.colorize_ansi(filename, 'magenta')
- source = colorize_source(source)
- output.append(' File "%s", line %s, in %s' % (filename, lineno, funcname))
- output.append(' %s' % source.strip())
- if self.verbose:
- output.append('%r == %r' % (dir(frame), test.__module__))
- output.append('')
- output.append(' ' + ' local variables '.center(66, '-'))
- for varname, value in sorted(frame.f_locals.items()):
- output.append(' %s: %r' % (varname, value))
- if varname == 'self': # special handy processing for self
- for varname, value in sorted(vars(value).items()):
- output.append(' self.%s: %r' % (varname, value))
- output.append(' ' + '-' * 66)
- output.append('')
- output.append(''.join(traceback.format_exception_only(exctype, exc)))
- return '\n'.join(output)
-
- def addError(self, test, err):
- """err -> (exc_type, exc, tcbk)"""
- exc_type, exc, _ = err
- if isinstance(exc, SkipTest):
- assert exc_type == SkipTest
- self.addSkip(test, exc)
- else:
- if self.exitfirst:
- self.shouldStop = True
- descr = self.getDescription(test)
- super(SkipAwareTestResult, self).addError(test, err)
- self._create_pdb(descr, 'error')
-
- def addFailure(self, test, err):
- if self.exitfirst:
- self.shouldStop = True
- descr = self.getDescription(test)
- super(SkipAwareTestResult, self).addFailure(test, err)
- self._create_pdb(descr, 'fail')
-
- def addSkip(self, test, reason):
- self.skipped.append((test, reason))
- if self.showAll:
- self.stream.writeln("SKIPPED")
- elif self.dots:
- self.stream.write('S')
-
- def printErrors(self):
- super(SkipAwareTestResult, self).printErrors()
- self.printSkippedList()
-
- def printSkippedList(self):
- # format (test, err) compatible with unittest2
- for test, err in self.skipped:
- descr = self.getDescription(test)
- self.stream.writeln(self.separator1)
- self.stream.writeln("%s: %s" % ('SKIPPED', descr))
- self.stream.writeln("\t%s" % err)
-
- def printErrorList(self, flavour, errors):
- for (_, descr), (test, err) in zip(self.descrs_for(flavour), errors):
- self.stream.writeln(self.separator1)
- self.stream.writeln("%s: %s" % (flavour, descr))
- self.stream.writeln(self.separator2)
- self.stream.writeln(err)
- self.stream.writeln('no stdout'.center(len(self.separator2)))
- self.stream.writeln('no stderr'.center(len(self.separator2)))
# Add deprecation warnings about new api used by module level fixtures in unittest2
# http://www.voidspace.org.uk/python/articles/unittest2.shtml#setupmodule-and-teardownmodule
@@ -487,10 +367,8 @@ class TestCase(unittest.TestCase):
This is mostly a copy/paste from unittest.py (i.e same
variable names, same logic, except for the generative tests part)
"""
- from logilab.common.pytest import FILE_RESTART
if result is None:
result = self.defaultTestResult()
- result.pdbclass = self.pdbclass
self._options_ = options
# if result.cvg:
# result.cvg.start()
@@ -501,7 +379,12 @@ class TestCase(unittest.TestCase):
try:
skip_why = (getattr(self.__class__, '__unittest_skip_why__', '')
or getattr(testMethod, '__unittest_skip_why__', ''))
- self._addSkip(result, skip_why)
+ if hasattr(result, 'addSkip'):
+ result.addSkip(self, skip_why)
+ else:
+ warnings.warn("TestResult has no addSkip method, skips not reported",
+ RuntimeWarning, 2)
+ result.addSuccess(self)
finally:
result.stopTest(self)
return
@@ -522,22 +405,6 @@ class TestCase(unittest.TestCase):
if not self.quiet_run(result, self.tearDown):
return
if not generative and success:
- if hasattr(options, "exitfirst") and options.exitfirst:
- # add this test to restart file
- try:
- restartfile = open(FILE_RESTART, 'a')
- try:
- descr = '.'.join((self.__class__.__module__,
- self.__class__.__name__,
- self._testMethodName))
- restartfile.write(descr+os.linesep)
- finally:
- restartfile.close()
- except Exception:
- print("Error while saving succeeded test into",
- osp.join(os.getcwd(), FILE_RESTART),
- file=sys.__stderr__)
- raise
result.addSuccess(self)
finally:
# if result.cvg:
@@ -572,6 +439,11 @@ class TestCase(unittest.TestCase):
# result.shouldStop = True
if result.shouldStop: # either on error or on exitfirst + error
break
+ except self.failureException:
+ result.addFailure(self, self.__exc_info())
+ success = False
+ except SkipTest as e:
+ result.addSkip(self, e)
except:
# if an error occurs between two yield
result.addError(self, self.__exc_info())
@@ -605,521 +477,15 @@ class TestCase(unittest.TestCase):
return 2
return 0
- def defaultTestResult(self):
- """return a new instance of the defaultTestResult"""
- return SkipAwareTestResult()
-
- skip = _deprecate(unittest.TestCase.skipTest)
- assertEquals = _deprecate(unittest.TestCase.assertEqual)
- assertNotEquals = _deprecate(unittest.TestCase.assertNotEqual)
- assertAlmostEquals = _deprecate(unittest.TestCase.assertAlmostEqual)
- assertNotAlmostEquals = _deprecate(unittest.TestCase.assertNotAlmostEqual)
-
def innerSkip(self, msg=None):
"""mark a generative test as skipped for the <msg> reason"""
msg = msg or 'test was skipped'
raise InnerTestSkipped(msg)
- @deprecated('Please use assertDictEqual instead.')
- def assertDictEquals(self, dict1, dict2, msg=None, context=None):
- """compares two dicts
-
- If the two dict differ, the first difference is shown in the error
- message
- :param dict1: a Python Dictionary
- :param dict2: a Python Dictionary
- :param msg: custom message (String) in case of failure
- """
- dict1 = dict(dict1)
- msgs = []
- for key, value in dict2.items():
- try:
- if dict1[key] != value:
- msgs.append('%r != %r for key %r' % (dict1[key], value,
- key))
- del dict1[key]
- except KeyError:
- msgs.append('missing %r key' % key)
- if dict1:
- msgs.append('dict2 is lacking %r' % dict1)
- if msg:
- self.failureException(msg)
- elif msgs:
- if context is not None:
- base = '%s\n' % context
- else:
- base = ''
- self.fail(base + '\n'.join(msgs))
-
- @deprecated('Please use assertCountEqual instead.')
- def assertUnorderedIterableEquals(self, got, expected, msg=None):
- """compares two iterable and shows difference between both
-
- :param got: the unordered Iterable that we found
- :param expected: the expected unordered Iterable
- :param msg: custom message (String) in case of failure
- """
- got, expected = list(got), list(expected)
- self.assertSetEqual(set(got), set(expected), msg)
- if len(got) != len(expected):
- if msg is None:
- msg = ['Iterable have the same elements but not the same number',
- '\t<element>\t<expected>i\t<got>']
- got_count = {}
- expected_count = {}
- for element in got:
- got_count[element] = got_count.get(element, 0) + 1
- for element in expected:
- expected_count[element] = expected_count.get(element, 0) + 1
- # we know that got_count.key() == expected_count.key()
- # because of assertSetEqual
- for element, count in got_count.iteritems():
- other_count = expected_count[element]
- if other_count != count:
- msg.append('\t%s\t%s\t%s' % (element, other_count, count))
-
- self.fail(msg)
-
- assertUnorderedIterableEqual = assertUnorderedIterableEquals
- assertUnordIterEquals = assertUnordIterEqual = assertUnorderedIterableEqual
-
- @deprecated('Please use assertSetEqual instead.')
- def assertSetEquals(self,got,expected, msg=None):
- """compares two sets and shows difference between both
-
- Don't use it for iterables other than sets.
-
- :param got: the Set that we found
- :param expected: the second Set to be compared to the first one
- :param msg: custom message (String) in case of failure
- """
-
- if not(isinstance(got, set) and isinstance(expected, set)):
- warnings.warn("the assertSetEquals function if now intended for set only."\
- "use assertUnorderedIterableEquals instead.",
- DeprecationWarning, 2)
- return self.assertUnorderedIterableEquals(got, expected, msg)
-
- items={}
- items['missing'] = expected - got
- items['unexpected'] = got - expected
- if any(items.itervalues()):
- if msg is None:
- msg = '\n'.join('%s:\n\t%s' % (key, "\n\t".join(str(value) for value in values))
- for key, values in items.iteritems() if values)
- self.fail(msg)
-
- @deprecated('Please use assertListEqual instead.')
- def assertListEquals(self, list_1, list_2, msg=None):
- """compares two lists
-
- If the two list differ, the first difference is shown in the error
- message
-
- :param list_1: a Python List
- :param list_2: a second Python List
- :param msg: custom message (String) in case of failure
- """
- _l1 = list_1[:]
- for i, value in enumerate(list_2):
- try:
- if _l1[0] != value:
- from pprint import pprint
- pprint(list_1)
- pprint(list_2)
- self.fail('%r != %r for index %d' % (_l1[0], value, i))
- del _l1[0]
- except IndexError:
- if msg is None:
- msg = 'list_1 has only %d elements, not %s '\
- '(at least %r missing)'% (i, len(list_2), value)
- self.fail(msg)
- if _l1:
- if msg is None:
- msg = 'list_2 is lacking %r' % _l1
- self.fail(msg)
-
- @deprecated('Non-standard. Please use assertMultiLineEqual instead.')
- def assertLinesEquals(self, string1, string2, msg=None, striplines=False):
- """compare two strings and assert that the text lines of the strings
- are equal.
-
- :param string1: a String
- :param string2: a String
- :param msg: custom message (String) in case of failure
- :param striplines: Boolean to trigger line stripping before comparing
- """
- lines1 = string1.splitlines()
- lines2 = string2.splitlines()
- if striplines:
- lines1 = [l.strip() for l in lines1]
- lines2 = [l.strip() for l in lines2]
- self.assertListEqual(lines1, lines2, msg)
- assertLineEqual = assertLinesEquals
-
- @deprecated('Non-standard: please copy test method to your TestCase class')
- def assertXMLWellFormed(self, stream, msg=None, context=2):
- """asserts the XML stream is well-formed (no DTD conformance check)
-
- :param context: number of context lines in standard message
- (show all data if negative).
- Only available with element tree
- """
- try:
- from xml.etree.ElementTree import parse
- self._assertETXMLWellFormed(stream, parse, msg)
- except ImportError:
- from xml.sax import make_parser, SAXParseException
- parser = make_parser()
- try:
- parser.parse(stream)
- except SAXParseException as ex:
- if msg is None:
- stream.seek(0)
- for _ in range(ex.getLineNumber()):
- line = stream.readline()
- pointer = ('' * (ex.getLineNumber() - 1)) + '^'
- msg = 'XML stream not well formed: %s\n%s%s' % (ex, line, pointer)
- self.fail(msg)
-
- @deprecated('Non-standard: please copy test method to your TestCase class')
- def assertXMLStringWellFormed(self, xml_string, msg=None, context=2):
- """asserts the XML string is well-formed (no DTD conformance check)
-
- :param context: number of context lines in standard message
- (show all data if negative).
- Only available with element tree
- """
- try:
- from xml.etree.ElementTree import fromstring
- except ImportError:
- from elementtree.ElementTree import fromstring
- self._assertETXMLWellFormed(xml_string, fromstring, msg)
-
- def _assertETXMLWellFormed(self, data, parse, msg=None, context=2):
- """internal function used by /assertXML(String)?WellFormed/ functions
-
- :param data: xml_data
- :param parse: appropriate parser function for this data
- :param msg: error message
- :param context: number of context lines in standard message
- (show all data if negative).
- Only available with element tree
- """
- from xml.parsers.expat import ExpatError
- try:
- from xml.etree.ElementTree import ParseError
- except ImportError:
- # compatibility for <python2.7
- ParseError = ExpatError
- try:
- parse(data)
- except (ExpatError, ParseError) as ex:
- if msg is None:
- if hasattr(data, 'readlines'): #file like object
- data.seek(0)
- lines = data.readlines()
- else:
- lines = data.splitlines(True)
- nb_lines = len(lines)
- context_lines = []
-
- # catch when ParseError doesn't set valid lineno
- if ex.lineno is not None:
- if context < 0:
- start = 1
- end = nb_lines
- else:
- start = max(ex.lineno-context, 1)
- end = min(ex.lineno+context, nb_lines)
- line_number_length = len('%i' % end)
- line_pattern = " %%%ii: %%s" % line_number_length
-
- for line_no in range(start, ex.lineno):
- context_lines.append(line_pattern % (line_no, lines[line_no-1]))
- context_lines.append(line_pattern % (ex.lineno, lines[ex.lineno-1]))
- context_lines.append('%s^\n' % (' ' * (1 + line_number_length + 2 +ex.offset)))
- for line_no in range(ex.lineno+1, end+1):
- context_lines.append(line_pattern % (line_no, lines[line_no-1]))
-
- rich_context = ''.join(context_lines)
- msg = 'XML stream not well formed: %s\n%s' % (ex, rich_context)
- self.fail(msg)
-
- @deprecated('Non-standard: please copy test method to your TestCase class')
- def assertXMLEqualsTuple(self, element, tup):
- """compare an ElementTree Element to a tuple formatted as follow:
- (tagname, [attrib[, children[, text[, tail]]]])"""
- # check tag
- self.assertTextEquals(element.tag, tup[0])
- # check attrib
- if len(element.attrib) or len(tup)>1:
- if len(tup)<=1:
- self.fail( "tuple %s has no attributes (%s expected)"%(tup,
- dict(element.attrib)))
- self.assertDictEqual(element.attrib, tup[1])
- # check children
- if len(element) or len(tup)>2:
- if len(tup)<=2:
- self.fail( "tuple %s has no children (%i expected)"%(tup,
- len(element)))
- if len(element) != len(tup[2]):
- self.fail( "tuple %s has %i children%s (%i expected)"%(tup,
- len(tup[2]),
- ('', 's')[len(tup[2])>1], len(element)))
- for index in range(len(tup[2])):
- self.assertXMLEqualsTuple(element[index], tup[2][index])
- #check text
- if element.text or len(tup)>3:
- if len(tup)<=3:
- self.fail( "tuple %s has no text value (%r expected)"%(tup,
- element.text))
- self.assertTextEquals(element.text, tup[3])
- #check tail
- if element.tail or len(tup)>4:
- if len(tup)<=4:
- self.fail( "tuple %s has no tail value (%r expected)"%(tup,
- element.tail))
- self.assertTextEquals(element.tail, tup[4])
-
- def _difftext(self, lines1, lines2, junk=None, msg_prefix='Texts differ'):
- junk = junk or (' ', '\t')
- # result is a generator
- result = difflib.ndiff(lines1, lines2, charjunk=lambda x: x in junk)
- read = []
- for line in result:
- read.append(line)
- # lines that don't start with a ' ' are diff ones
- if not line.startswith(' '):
- self.fail('\n'.join(['%s\n'%msg_prefix]+read + list(result)))
-
- @deprecated('Non-standard. Please use assertMultiLineEqual instead.')
- def assertTextEquals(self, text1, text2, junk=None,
- msg_prefix='Text differ', striplines=False):
- """compare two multiline strings (using difflib and splitlines())
-
- :param text1: a Python BaseString
- :param text2: a second Python Basestring
- :param junk: List of Caracters
- :param msg_prefix: String (message prefix)
- :param striplines: Boolean to trigger line stripping before comparing
- """
- msg = []
- if not isinstance(text1, string_types):
- msg.append('text1 is not a string (%s)'%(type(text1)))
- if not isinstance(text2, string_types):
- msg.append('text2 is not a string (%s)'%(type(text2)))
- if msg:
- self.fail('\n'.join(msg))
- lines1 = text1.strip().splitlines(True)
- lines2 = text2.strip().splitlines(True)
- if striplines:
- lines1 = [line.strip() for line in lines1]
- lines2 = [line.strip() for line in lines2]
- self._difftext(lines1, lines2, junk, msg_prefix)
- assertTextEqual = assertTextEquals
-
- @deprecated('Non-standard: please copy test method to your TestCase class')
- def assertStreamEquals(self, stream1, stream2, junk=None,
- msg_prefix='Stream differ'):
- """compare two streams (using difflib and readlines())"""
- # if stream2 is stream2, readlines() on stream1 will also read lines
- # in stream2, so they'll appear different, although they're not
- if stream1 is stream2:
- return
- # make sure we compare from the beginning of the stream
- stream1.seek(0)
- stream2.seek(0)
- # compare
- self._difftext(stream1.readlines(), stream2.readlines(), junk,
- msg_prefix)
-
- assertStreamEqual = assertStreamEquals
-
- @deprecated('Non-standard: please copy test method to your TestCase class')
- def assertFileEquals(self, fname1, fname2, junk=(' ', '\t')):
- """compares two files using difflib"""
- self.assertStreamEqual(open(fname1), open(fname2), junk,
- msg_prefix='Files differs\n-:%s\n+:%s\n'%(fname1, fname2))
-
- assertFileEqual = assertFileEquals
-
- @deprecated('Non-standard: please copy test method to your TestCase class')
- def assertDirEquals(self, path_a, path_b):
- """compares two files using difflib"""
- assert osp.exists(path_a), "%s doesn't exists" % path_a
- assert osp.exists(path_b), "%s doesn't exists" % path_b
-
- all_a = [ (ipath[len(path_a):].lstrip('/'), idirs, ifiles)
- for ipath, idirs, ifiles in os.walk(path_a)]
- all_a.sort(key=itemgetter(0))
-
- all_b = [ (ipath[len(path_b):].lstrip('/'), idirs, ifiles)
- for ipath, idirs, ifiles in os.walk(path_b)]
- all_b.sort(key=itemgetter(0))
-
- iter_a, iter_b = iter(all_a), iter(all_b)
- partial_iter = True
- ipath_a, idirs_a, ifiles_a = data_a = None, None, None
- while True:
- try:
... 786 lines suppressed ...
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/logilab-common.git
More information about the Python-modules-commits
mailing list