Hello community, here is the log from the commit of package python-unittest2 for openSUSE:Factory checked in at 2015-10-24 10:22:56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-unittest2 (Old) and /work/SRC/openSUSE:Factory/.python-unittest2.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-unittest2" Changes: -------- --- /work/SRC/openSUSE:Factory/python-unittest2/python-unittest2.changes 2014-12-03 22:48:16.000000000 +0100 +++ /work/SRC/openSUSE:Factory/.python-unittest2.new/python-unittest2.changes 2015-10-24 10:23:07.000000000 +0200 @@ -1,0 +2,27 @@ +Tue Oct 13 08:52:12 UTC 2015 - [email protected] + +- Implement update-alternatives + +------------------------------------------------------------------- +Mon Oct 12 11:10:43 UTC 2015 - [email protected] + +- update to version 1.1.0: + * Issue #15836: assertRaises(), assertRaisesRegex(), assertWarns() + and assertWarnsRegex() assertments now check the type of the first + argument to prevent possible user error. Based on patch by Daniel + Wagner-Hall. + * Issue #24134: assertRaises(), assertRaisesRegex(), assertWarns() + and assertWarnsRegex() checks now emits a deprecation warning when + callable is None or keyword arguments except msg is passed in the + context manager mode. + * Issue #22903: The fake test case created by unittest.loader when + it fails importing a test module is now picklable. +- update to version 1.0.1: + * Unittest2 issue #94: Need at least 1.4 of six. +- update to version 1.0.0: + * Issue #22936: Permit showing local variables in tracebacks. +- specfile: + * added traceback2, linecache2 requirement + * Implement update-alternatives + +------------------------------------------------------------------- Old: ---- unittest2-0.8.0.tar.gz New: ---- unittest2-1.1.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-unittest2.spec ++++++ --- /var/tmp/diff_new_pack.UUjW5W/_old 2015-10-24 10:23:08.000000000 +0200 +++ /var/tmp/diff_new_pack.UUjW5W/_new 2015-10-24 10:23:08.000000000 +0200 @@ -17,7 +17,7 @@ Name: python-unittest2 -Version: 0.8.0 +Version: 1.1.0 Release: 0 Url: http://pypi.python.org/pypi/unittest2 Summary: The new features in unittest for Python 2.7 backported to Python 2.3+ @@ -25,19 +25,23 @@ Group: Development/Languages/Python Source: http://pypi.python.org/packages/source/u/unittest2/unittest2-%{version}.tar.gz BuildRoot: %{_tmppath}/%{name}-%{version}-build -BuildRequires: python-argparse BuildRequires: python-devel -BuildRequires: python-distribute +BuildRequires: python-argparse +BuildRequires: python-linecache2 +BuildRequires: python-setuptools BuildRequires: python-six +BuildRequires: python-traceback2 Requires: python-argparse +Requires: python-linecache2 Requires: python-six -%if 0%{?suse_version} -%py_requires -%if 0%{?suse_version} > 1110 +Requires: python-traceback2 +Requires(post): update-alternatives +Requires(postun): update-alternatives +%if 0%{?suse_version} && 0%{?suse_version} > 1110 BuildArch: noarch +%else +%{!?python_sitelib: %global python_sitelib %(python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")} %endif -%endif -%{!?python_sitelib: %global python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")} %description unittest2 is a backport of the new features added to the unittest testing @@ -52,11 +56,29 @@ %install python setup.py install --prefix=%{_prefix} --root=%{buildroot} +# Prepare for update-alternatives usage +mkdir -p %{buildroot}%{_sysconfdir}/alternatives +mv %{buildroot}%{_bindir}/unit2 %{buildroot}%{_bindir}/unit2-%{py_ver} +ln -s -f %{_sysconfdir}/alternatives/unit2 %{buildroot}%{_bindir}/unit2 +# create a dummy target for /etc/alternatives/unit2 +touch %{buildroot}%{_sysconfdir}/alternatives/unit2 + +%post +"%_sbindir/update-alternatives" \ + --install %{_bindir}/unit2 unit2 %{_bindir}/unit2-%{py_ver} 30 + +%postun +if [ $1 -eq 0 ] ; then + "%_sbindir/update-alternatives" --remove unit2 %{_bindir}/unit2-%{py_ver} +fi + %files %defattr(-,root,root,-) %doc README.txt -%{_bindir}/unit2* +%{_bindir}/unit2 +%{_bindir}/unit2-%{py_ver} +%ghost %{_sysconfdir}/alternatives/unit2 %{python_sitelib}/unittest2 -%{python_sitelib}/unittest2-%{version}-py%{py_ver}.egg-info +%{python_sitelib}/unittest2-%{version}-py*.egg-info %changelog ++++++ unittest2-0.8.0.tar.gz -> unittest2-1.1.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unittest2-0.8.0/PKG-INFO new/unittest2-1.1.0/PKG-INFO --- old/unittest2-0.8.0/PKG-INFO 2014-11-04 16:26:25.000000000 +0100 +++ new/unittest2-1.1.0/PKG-INFO 2015-06-30 08:48:20.000000000 +0200 @@ -1,10 +1,10 @@ Metadata-Version: 1.1 Name: unittest2 -Version: 0.8.0 +Version: 1.1.0 Summary: The new features in unittest backported to Python 2.4+. Home-page: http://pypi.python.org/pypi/unittest2 -Author: Michael Foord -Author-email: [email protected] +Author: Robert Collins +Author-email: [email protected] License: UNKNOWN Description: unittest2 is a backport of the new features added to the unittest testing framework in Python 2.7 and onwards. It is tested to run on Python 2.6, 2.7, @@ -30,8 +30,9 @@ * `Download unittest2 0.5.1 for Python 2.3 <http://voidspace.org.uk/downloads/unittest2-0.5.1-python2.3.zip>`_ - There is also a version of unittest2 for Python 3. This has the project name - "unittest2py3k" but uses the same package name ("unittest2"): + There was a separate version of unittest2 for Python 3. This is no longer + needed, but still exists on PyPI. This had the project name "unittest2py3k" but + uses the same package name ("unittest2"): * `unittest2 for Python 3 <http://pypi.python.org/pypi/unittest2py3k>`_ @@ -43,6 +44,11 @@ will work with the standard unittest test loaders, runners result objects however. + In general for documentation on unittest2 see the current latest documented of + CPython: + + * `CPython unittest documentation <https://docs.python.org/dev/library/unittest.html>`_ + New features include: * ``addCleanups`` - better resource management @@ -169,11 +175,39 @@ CHANGELOG ========= + 2015-06-20 - 1.1.0 + ------------------ + + - Issue #15836: assertRaises(), assertRaisesRegex(), assertWarns() and + assertWarnsRegex() assertments now check the type of the first argument + to prevent possible user error. Based on patch by Daniel Wagner-Hall. + + - Issue #24134: assertRaises(), assertRaisesRegex(), assertWarns() and + assertWarnsRegex() checks now emits a deprecation warning when callable is + None or keyword arguments except msg is passed in the context manager mode. + + - Issue #22903: The fake test case created by unittest.loader when it fails + importing a test module is now picklable. + + + 2015-03-12 - 1.0.1 + ------------------ + + - Unittest2 issue #94: Need at least 1.4 of six. + + 2015-03-06 - 1.0.0 + ------------------ + + - Issue #22936: Permit showing local variables in tracebacks. + 2014/11/05 - 0.8 ---------------- - Issue #22457: Honour load_tests in the start_dir of discovery. + - Issue #22894: TestCase.subTest() would cause the test suite to be stopped + when in failfast mode, even in the absence of failures. + 2014/10/31 - 0.7.1 ------------------ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unittest2-0.8.0/README.txt new/unittest2-1.1.0/README.txt --- old/unittest2-0.8.0/README.txt 2014-11-04 16:25:37.000000000 +0100 +++ new/unittest2-1.1.0/README.txt 2015-06-30 05:20:46.000000000 +0200 @@ -22,8 +22,9 @@ * `Download unittest2 0.5.1 for Python 2.3 <http://voidspace.org.uk/downloads/unittest2-0.5.1-python2.3.zip>`_ -There is also a version of unittest2 for Python 3. This has the project name -"unittest2py3k" but uses the same package name ("unittest2"): +There was a separate version of unittest2 for Python 3. This is no longer +needed, but still exists on PyPI. This had the project name "unittest2py3k" but +uses the same package name ("unittest2"): * `unittest2 for Python 3 <http://pypi.python.org/pypi/unittest2py3k>`_ @@ -35,6 +36,11 @@ will work with the standard unittest test loaders, runners result objects however. +In general for documentation on unittest2 see the current latest documented of +CPython: + +* `CPython unittest documentation <https://docs.python.org/dev/library/unittest.html>`_ + New features include: * ``addCleanups`` - better resource management @@ -161,11 +167,39 @@ CHANGELOG ========= +2015-06-20 - 1.1.0 +------------------ + +- Issue #15836: assertRaises(), assertRaisesRegex(), assertWarns() and + assertWarnsRegex() assertments now check the type of the first argument + to prevent possible user error. Based on patch by Daniel Wagner-Hall. + +- Issue #24134: assertRaises(), assertRaisesRegex(), assertWarns() and + assertWarnsRegex() checks now emits a deprecation warning when callable is + None or keyword arguments except msg is passed in the context manager mode. + +- Issue #22903: The fake test case created by unittest.loader when it fails + importing a test module is now picklable. + + +2015-03-12 - 1.0.1 +------------------ + +- Unittest2 issue #94: Need at least 1.4 of six. + +2015-03-06 - 1.0.0 +------------------ + +- Issue #22936: Permit showing local variables in tracebacks. + 2014/11/05 - 0.8 ---------------- - Issue #22457: Honour load_tests in the start_dir of discovery. +- Issue #22894: TestCase.subTest() would cause the test suite to be stopped + when in failfast mode, even in the absence of failures. + 2014/10/31 - 0.7.1 ------------------ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unittest2-0.8.0/setup.cfg new/unittest2-1.1.0/setup.cfg --- old/unittest2-0.8.0/setup.cfg 2014-11-04 16:26:26.000000000 +0100 +++ new/unittest2-1.1.0/setup.cfg 2015-06-30 08:48:20.000000000 +0200 @@ -1,6 +1,9 @@ [sdist] force-manifest = 1 +[bdist_wheel] +universal = 1 + [egg_info] tag_build = tag_date = 0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unittest2-0.8.0/setup.py new/unittest2-1.1.0/setup.py --- old/unittest2-0.8.0/setup.py 2014-11-04 15:51:22.000000000 +0100 +++ new/unittest2-1.1.0/setup.py 2015-06-30 08:47:44.000000000 +0200 @@ -48,16 +48,16 @@ 'Topic :: Software Development :: Testing', ] -AUTHOR = 'Michael Foord' +AUTHOR = 'Robert Collins' -AUTHOR_EMAIL = '[email protected]' +AUTHOR_EMAIL = '[email protected]' KEYWORDS = "unittest testing tests".split(' ') # Both install and setup requires - because we read VERSION from within the # package, and the package also exports all the APIs. # six for compat helpers -REQUIRES = ['argparse', 'six'], +REQUIRES = ['argparse', 'six>=1.4', 'traceback2'], params = dict( name=NAME, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unittest2-0.8.0/unittest2/__init__.py new/unittest2-1.1.0/unittest2/__init__.py --- old/unittest2-0.8.0/unittest2/__init__.py 2014-11-04 16:25:51.000000000 +0100 +++ new/unittest2-1.1.0/unittest2/__init__.py 2015-06-30 08:47:26.000000000 +0200 @@ -31,7 +31,7 @@ 'defaultTestLoader', 'SkipTest', 'skip', 'skipIf', 'skipUnless', 'expectedFailure', 'TextTestResult', '__version__', 'collector'] -__version__ = '0.8.0' +__version__ = '1.1.0' # Expose obsolete functions for backwards compatibility __all__.extend(['getTestCaseNames', 'makeSuite', 'findTestCases']) @@ -75,13 +75,3 @@ return loader.discover(start_dir=this_dir, pattern=pattern) __unittest = True - -def load_tests(loader, tests, pattern): - # All our tests are in test/ - the test objects found in unittest2 itself - # are base classes not intended to be executed. This load_tests intercepts - # discovery to prevent that. - import unittest2.test - result = loader.suiteClass() - for path in unittest2.test.__path__: - result.addTests(loader.discover(path, pattern=pattern)) - return result diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unittest2-0.8.0/unittest2/case.py new/unittest2-1.1.0/unittest2/case.py --- old/unittest2-0.8.0/unittest2/case.py 2014-10-30 21:57:36.000000000 +0100 +++ new/unittest2-1.1.0/unittest2/case.py 2015-06-30 08:17:28.000000000 +0200 @@ -7,7 +7,7 @@ import logging import pprint import re -import traceback +import traceback2 as traceback import types import unittest import warnings @@ -135,6 +135,10 @@ test_item.__unittest_expecting_failure__ = True return test_item +def _is_subtype(expected, basetype): + if isinstance(expected, tuple): + return all(_is_subtype(e, basetype) for e in expected) + return isinstance(expected, type) and issubclass(expected, basetype) class _BaseTestCaseContext: @@ -148,32 +152,44 @@ class _AssertRaisesBaseContext(_BaseTestCaseContext): - def __init__(self, expected, test_case, callable_obj=None, - expected_regex=None): + def __init__(self, expected, test_case, expected_regex=None): _BaseTestCaseContext.__init__(self, test_case) self.expected = expected self.failureException = test_case.failureException - if callable_obj is not None: - try: - self.obj_name = callable_obj.__name__ - except AttributeError: - self.obj_name = str(callable_obj) - else: - self.obj_name = None if expected_regex is not None: expected_regex = re.compile(expected_regex) self.expected_regex = expected_regex + self.obj_name = None self.msg = None - def handle(self, name, callable_obj, args, kwargs): + def handle(self, name, args, kwargs): """ - If callable_obj is None, assertRaises/Warns is being used as a + If args is empty, assertRaises/Warns is being used as a context manager, so check for a 'msg' kwarg and return self. - If callable_obj is not None, call it passing args and kwargs. + If args is not empty, call a callable passing positional and keyword + arguments. """ - if callable_obj is None: + if not _is_subtype(self.expected, self._base_type): + raise TypeError('%s() arg 1 must be %s' % + (name, self._base_type_str)) + if args and args[0] is None: + warnings.warn("callable is None", + DeprecationWarning, 3) + args = () + if not args: self.msg = kwargs.pop('msg', None) + if kwargs: + warnings.warn('%r is an invalid keyword argument for ' + 'this function' % next(iter(kwargs)), + DeprecationWarning, 3) return self + + callable_obj = args[0] + args = args[1:] + try: + self.obj_name = callable_obj.__name__ + except AttributeError: + self.obj_name = str(callable_obj) with self: callable_obj(*args, **kwargs) @@ -181,6 +197,9 @@ class _AssertRaisesContext(_AssertRaisesBaseContext): """A context manager used to implement TestCase.assertRaises* methods.""" + _base_type = BaseException + _base_type_str = 'an exception type or tuple of exception types' + def __enter__(self): return self @@ -190,11 +209,13 @@ exc_name = self.expected.__name__ except AttributeError: exc_name = str(self.expected) - raise self.failureException( - "%s not raised" % (exc_name,)) - #else: - # if getattr(traceback, 'clear_frames', None): - # traceback.clear_frames(tb) + if self.obj_name: + self._raiseFailure("{0} not raised by {1}".format(exc_name, + self.obj_name)) + else: + self._raiseFailure("{0} not raised".format(exc_name)) + else: + traceback.clear_frames(tb) if not issubclass(exc_type, self.expected): # let unexpected exceptions pass through return False @@ -212,6 +233,9 @@ class _AssertWarnsContext(_AssertRaisesBaseContext): """A context manager used to implement TestCase.assertWarns* methods.""" + _base_type = Warning + _base_type_str = 'a warning type or tuple of warning types' + def __enter__(self): # The __warningregistry__'s need to be in a pristine state for tests # to work properly. @@ -697,15 +721,15 @@ return '%s : %s' % (safe_str(standardMsg), safe_str(msg)) - def assertRaises(self, excClass, callableObj=None, *args, **kwargs): - """Fail unless an exception of class excClass is raised - by callableObj when invoked with arguments args and keyword - arguments kwargs. If a different type of exception is + def assertRaises(self, expected_exception, *args, **kwargs): + """Fail unless an exception of class expected_exception is raised + by the callable when invoked with specified positional and + keyword arguments. If a different type of exception is raised, it will not be caught, and the test case will be deemed to have suffered an error, exactly as for an unexpected exception. - If called with callableObj omitted or None, will return a + If called with the callable and arguments omitted, will return a context object used like this:: with self.assertRaises(SomeException): @@ -720,28 +744,18 @@ the_exception = cm.exception self.assertEqual(the_exception.error_code, 3) """ - if callableObj is None: - return _AssertRaisesContext(excClass, self) - try: - callableObj(*args, **kwargs) - except excClass: - return - - if hasattr(excClass,'__name__'): - excName = excClass.__name__ - else: - excName = str(excClass) - raise self.failureException("%s not raised" % excName) + context = _AssertRaisesContext(expected_exception, self) + return context.handle('assertRaises', args, kwargs) - def assertWarns(self, expected_warning, callable_obj=None, *args, **kwargs): + def assertWarns(self, expected_warning, *args, **kwargs): """Fail unless a warning of class warnClass is triggered - by callableObj when invoked with arguments args and keyword - arguments kwargs. If a different type of warning is + by the callable when invoked with specified positional and + keyword arguments. If a different type of warning is triggered, it will not be handled: depending on the other warning filtering rules in effect, it might be silenced, printed out, or raised as an exception. - If called with callableObj omitted or None, will return a + If called with the callable and arguments omitted, will return a context object used like this:: with self.assertWarns(SomeWarning): @@ -749,7 +763,7 @@ The context manager keeps a reference to the first matching warning as the 'warning' attribute; similarly, the 'filename' - and 'lineno' attributes give you information about the line + and 'lineno' attributes give you information about the line of Python code from which the warning was triggered. This allows you to inspect the warning after the assertion:: @@ -758,19 +772,8 @@ the_warning = cm.warning self.assertEqual(the_warning.some_attribute, 147) """ - context = _AssertWarnsContext(expected_warning, self, callable_obj) - if callable_obj is None: - return context - context.__enter__() - try: - callable_obj(*args, **kwargs) - except: - if not context.__exit__(*sys.exc_info()): - raise - else: - return - else: - context.__exit__(None, None, None) + context = _AssertWarnsContext(expected_warning, self) + return context.handle('assertWarns', args, kwargs) def assertLogs(self, logger=None, level=None): """Fail unless a log message of level *level* or higher is emitted @@ -1261,23 +1264,21 @@ self.fail(self._formatMessage(msg, standardMsg)) def assertRaisesRegex(self, expected_exception, expected_regex, - callable_obj=None, *args, **kwargs): + *args, **kwargs): """Asserts that the message in a raised exception matches a regex. Args: expected_exception: Exception class expected to be raised. expected_regex: Regex (re pattern object or string) expected to be found in error message. - callable_obj: Function to be called. - args: Extra args. + args: Function to be called and extra positional args. kwargs: Extra kwargs. """ - context = _AssertRaisesContext(expected_exception, self, callable_obj, - expected_regex) - return context.handle('assertRaisesRegex', callable_obj, args, kwargs) + context = _AssertRaisesContext(expected_exception, self, expected_regex) + return context.handle('assertRaisesRegex', args, kwargs) def assertWarnsRegex(self, expected_warning, expected_regex, - callable_obj=None, *args, **kwargs): + *args, **kwargs): """Asserts that the message in a triggered warning matches a regex. Basic functioning is similar to assertWarns() with the addition that only warnings whose messages also match the regular expression @@ -1287,14 +1288,11 @@ expected_warning: Warning class expected to be triggered. expected_regex: Regex (re pattern object or string) expected to be found in error message. - callable_obj: Function to be called. - args: Extra args. + args: Function to be called and extra positional args. kwargs: Extra kwargs. """ - context = _AssertWarnsContext(expected_warning, self, callable_obj, - expected_regex) - return context.handle('assertWarnsRegex', callable_obj, args, kwargs) - + context = _AssertWarnsContext(expected_warning, self, expected_regex) + return context.handle('assertWarnsRegex', args, kwargs) def assertRegex(self, text, expected_regex, msg=None): """Fail the test unless the text matches the regular expression.""" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unittest2-0.8.0/unittest2/loader.py new/unittest2-1.1.0/unittest2/loader.py --- old/unittest2-0.8.0/unittest2/loader.py 2014-11-04 15:32:19.000000000 +0100 +++ new/unittest2-1.1.0/unittest2/loader.py 2015-06-29 12:04:21.000000000 +0200 @@ -31,29 +31,40 @@ return K -# what about .pyc or .pyo (etc) +# what about .pyc (etc) # we would need to avoid loading the same tests multiple times -# from '.py', '.pyc' *and* '.pyo' +# from '.py', *and* '.pyc' VALID_MODULE_NAME = re.compile(r'[_a-z]\w*\.py$', re.IGNORECASE) +class _FailedTest(case.TestCase): + _testMethodName = None + + def __init__(self, method_name, exception): + self._exception = exception + super(_FailedTest, self).__init__(method_name) + + def __getattr__(self, name): + if name != self._testMethodName: + return super(_FailedTest, self).__getattr__(name) + def testFailure(): + raise self._exception + return testFailure + + def _make_failed_import_test(name, suiteClass): message = 'Failed to import test module: %s\n%s' % ( name, traceback.format_exc()) - return _make_failed_test('ModuleImportFailure', name, ImportError(message), - suiteClass, message) + return _make_failed_test(name, ImportError(message), suiteClass, message) def _make_failed_load_tests(name, exception, suiteClass): message = 'Failed to call load_tests:\n%s' % (traceback.format_exc(),) return _make_failed_test( - 'LoadTestsFailure', name, exception, suiteClass, message) + name, exception, suiteClass, message) -def _make_failed_test(classname, methodname, exception, suiteClass, message): - def testFailure(self): - raise exception - attrs = {methodname: testFailure} - TestClass = type(classname, (case.TestCase,), attrs) - return suiteClass((TestClass(methodname),)), message +def _make_failed_test(methodname, exception, suiteClass, message): + test = _FailedTest(methodname, exception) + return suiteClass((test,)), message def _make_skipped_test(methodname, exception, suiteClass): @@ -188,7 +199,7 @@ else: # Otherwise, we signal that an AttributeError has occurred. error_case, error_message = _make_failed_test( - 'AttributeError', part, e, self.suiteClass, + part, e, self.suiteClass, 'Failed to access attribute:\n%s' % ( traceback.format_exc(),)) self.errors.append(error_message) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unittest2-0.8.0/unittest2/main.py new/unittest2-1.1.0/unittest2/main.py --- old/unittest2-0.8.0/unittest2/main.py 2014-10-31 07:25:15.000000000 +0100 +++ new/unittest2-1.1.0/unittest2/main.py 2015-03-06 05:59:33.000000000 +0100 @@ -65,7 +65,8 @@ def __init__(self, module='__main__', defaultTest=None, argv=None, testRunner=None, testLoader=loader.defaultTestLoader, exit=True, - verbosity=1, failfast=None, catchbreak=None, buffer=None): + verbosity=1, failfast=None, catchbreak=None, buffer=None, + tb_locals=False): if isinstance(module, six.string_types): self.module = __import__(module) for part in module.split('.')[1:]: @@ -80,6 +81,7 @@ self.failfast = failfast self.catchbreak = catchbreak self.buffer = buffer + self.tb_locals = tb_locals self.defaultTest = defaultTest self.testRunner = testRunner self.testLoader = testLoader @@ -153,7 +155,9 @@ parser.add_argument('-q', '--quiet', dest='verbosity', action='store_const', const=0, help='Quiet output') - + parser.add_argument('--locals', dest='tb_locals', + action='store_true', + help='Show local variables in tracebacks') if self.failfast is None: parser.add_argument('-f', '--failfast', dest='failfast', action='store_true', @@ -225,9 +229,16 @@ self.testRunner = runner.TextTestRunner if isinstance(self.testRunner, six.class_types): try: - testRunner = self.testRunner(verbosity=self.verbosity, - failfast=self.failfast, - buffer=self.buffer) + try: + testRunner = self.testRunner(verbosity=self.verbosity, + failfast=self.failfast, + buffer=self.buffer, + tb_locals=self.tb_locals) + except TypeError: + # didn't accept the tb_locals argument + testRunner = self.testRunner(verbosity=self.verbosity, + failfast=self.failfast, + buffer=self.buffer) except TypeError: # didn't accept the verbosity, buffer or failfast arguments testRunner = self.testRunner() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unittest2-0.8.0/unittest2/result.py new/unittest2-1.1.0/unittest2/result.py --- old/unittest2-0.8.0/unittest2/result.py 2014-10-29 02:38:35.000000000 +0100 +++ new/unittest2-1.1.0/unittest2/result.py 2015-03-06 06:17:01.000000000 +0100 @@ -1,10 +1,10 @@ """Test result object""" import sys -import traceback import unittest from six.moves import StringIO +import traceback2 as traceback from unittest2 import util from unittest2.compatibility import wraps @@ -47,6 +47,7 @@ self.unexpectedSuccesses = [] self.shouldStop = False self.buffer = False + self.tb_locals = False self._stdout_buffer = None self._stderr_buffer = None self._original_stdout = sys.stdout @@ -115,7 +116,6 @@ self.failures.append((test, self._exc_info_to_string(err, test))) self._mirrorOutput = True - @failfast def addSubTest(self, test, subtest, err): """Called at the end of a subtest. 'err' is None if the subtest ended successfully, otherwise it's a @@ -124,6 +124,8 @@ # By default, we don't do anything with successful subtests, but # more sophisticated test results might want to record them. if err is not None: + if getattr(self, 'failfast', False): + self.stop() if issubclass(err[0], test.failureException): errors = self.failures else: @@ -171,9 +173,11 @@ if exctype is test.failureException: # Skip assert*() traceback levels length = self._count_relevant_tb_levels(tb) - msgLines = traceback.format_exception(exctype, value, tb, length) else: - msgLines = traceback.format_exception(exctype, value, tb) + length = None + tb_e = traceback.TracebackException( + exctype, value, tb, limit=length, capture_locals=self.tb_locals) + msgLines = list(tb_e.format()) if self.buffer: output = sys.stdout.getvalue() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unittest2-0.8.0/unittest2/runner.py new/unittest2-1.1.0/unittest2/runner.py --- old/unittest2-0.8.0/unittest2/runner.py 2014-10-28 08:43:01.000000000 +0100 +++ new/unittest2-1.1.0/unittest2/runner.py 2015-03-06 06:22:55.000000000 +0100 @@ -4,6 +4,8 @@ import time import unittest +from six import u + from unittest2 import result try: @@ -28,7 +30,7 @@ def writeln(self, arg=None): if arg: self.write(arg) - self.write('\n') # text-mode streams translate to \r\n if needed + self.write(u('\n')) # text-mode streams translate to \r\n if needed class TextTestResult(result.TestResult): @@ -36,8 +38,8 @@ Used by TextTestRunner. """ - separator1 = '=' * 70 - separator2 = '-' * 70 + separator1 = u('=' * 70) + separator2 = u('-' * 70) def __init__(self, stream, descriptions, verbosity): super(TextTestResult, self).__init__(stream, descriptions, verbosity) @@ -135,12 +137,19 @@ resultclass = TextTestResult def __init__(self, stream=sys.stderr, descriptions=True, verbosity=1, - failfast=False, buffer=False, resultclass=None): + failfast=False, buffer=False, resultclass=None, + tb_locals=False): + """Construct a TextTestRunner. + + Subclasses should accept **kwargs to ensure compatibility as the + interface changes. + """ self.stream = _WritelnDecorator(stream) self.descriptions = descriptions self.verbosity = verbosity self.failfast = failfast self.buffer = buffer + self.tb_locals = tb_locals if resultclass is not None: self.resultclass = resultclass @@ -152,6 +161,7 @@ result = self._makeResult() result.failfast = self.failfast result.buffer = self.buffer + result.tb_locals = self.tb_locals registerResult(result) startTime = time.time() @@ -171,7 +181,7 @@ if hasattr(result, 'separator2'): self.stream.writeln(result.separator2) run = result.testsRun - self.stream.writeln("Ran %d test%s in %.3fs" % + self.stream.writeln(u("Ran %d test%s in %.3fs") % (run, run != 1 and "s" or "", timeTaken)) self.stream.writeln() @@ -186,22 +196,22 @@ expectedFails, unexpectedSuccesses, skipped = results infos = [] if not result.wasSuccessful(): - self.stream.write("FAILED") + self.stream.write(u("FAILED")) failed, errored = map(len, (result.failures, result.errors)) if failed: - infos.append("failures=%d" % failed) + infos.append(u("failures=%d") % failed) if errored: - infos.append("errors=%d" % errored) + infos.append(u("errors=%d") % errored) else: - self.stream.write("OK") + self.stream.write(u("OK")) if skipped: - infos.append("skipped=%d" % skipped) + infos.append(u("skipped=%d") % skipped) if expectedFails: - infos.append("expected failures=%d" % expectedFails) + infos.append(u("expected failures=%d") % expectedFails) if unexpectedSuccesses: - infos.append("unexpected successes=%d" % unexpectedSuccesses) + infos.append(u("unexpected successes=%d") % unexpectedSuccesses) if infos: - self.stream.writeln(" (%s)" % (", ".join(infos),)) + self.stream.writeln(u(" (%s)") % (u(", ").join(infos),)) else: - self.stream.write("\n") + self.stream.write(u("\n")) return result diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unittest2-0.8.0/unittest2/test/_test_unittest2_with.py new/unittest2-1.1.0/unittest2/test/_test_unittest2_with.py --- old/unittest2-0.8.0/unittest2/test/_test_unittest2_with.py 2014-10-22 00:51:22.000000000 +0200 +++ new/unittest2-1.1.0/unittest2/test/_test_unittest2_with.py 2015-06-29 12:23:32.000000000 +0200 @@ -45,7 +45,7 @@ self.assertRaises(KeyError, lambda: None) except self.failureException: e = sys.exc_info()[1] - self.assertIn("KeyError not raised", e.args) + self.assertIn("KeyError not raised by <lambda>", e.args) else: self.fail("assertRaises() didn't fail") try: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unittest2-0.8.0/unittest2/test/support.py new/unittest2-1.1.0/unittest2/test/support.py --- old/unittest2-0.8.0/unittest2/test/support.py 2014-10-29 11:38:26.000000000 +0100 +++ new/unittest2-1.1.0/unittest2/test/support.py 2015-06-29 12:24:31.000000000 +0200 @@ -135,8 +135,6 @@ try: if not hash(obj_1) == hash(obj_2): self.fail("%r and %r do not hash equal" % (obj_1, obj_2)) - except KeyboardInterrupt: - raise except Exception: e = sys.exc_info()[1] self.fail("Problem hashing %r and %r: %s" % (obj_1, obj_2, e)) @@ -146,8 +144,6 @@ if hash(obj_1) == hash(obj_2): self.fail("%s and %s hash equal, but shouldn't" % (obj_1, obj_2)) - except KeyboardInterrupt: - raise except Exception: e = sys.exc_info()[1] self.fail("Problem hashing %s and %s: %s" % (obj_1, obj_2, e)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unittest2-0.8.0/unittest2/test/test_assertions.py new/unittest2-1.1.0/unittest2/test/test_assertions.py --- old/unittest2-0.8.0/unittest2/test/test_assertions.py 2014-10-31 00:48:15.000000000 +0100 +++ new/unittest2-1.1.0/unittest2/test/test_assertions.py 2015-06-30 08:19:24.000000000 +0200 @@ -75,6 +75,10 @@ getattr(sys, 'pypy_version_info', None), "pypy doesn't use refcounting." ) + @unittest.skipIf( + sys.version_info[:2] in ((3, 2), (3, 3)), + "python 3.2 and 3.3 always leak." + ) def test_assertRaises_frames_survival(self): # Issue #9815: assertRaises should avoid keeping local variables # in a traceback alive. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unittest2-0.8.0/unittest2/test/test_break.py new/unittest2-1.1.0/unittest2/test/test_break.py --- old/unittest2-0.8.0/unittest2/test/test_break.py 2014-10-28 23:54:40.000000000 +0100 +++ new/unittest2-1.1.0/unittest2/test/test_break.py 2015-03-06 06:01:36.000000000 +0100 @@ -213,6 +213,7 @@ self.verbosity = verbosity self.failfast = failfast self.catchbreak = catchbreak + self.tb_locals = False self.testRunner = FakeRunner self.test = test self.result = None @@ -221,8 +222,9 @@ p.runTests() self.assertEqual(FakeRunner.initArgs, [((), {'verbosity': verbosity, - 'failfast': failfast, - 'buffer': None})]) + 'failfast': failfast, + 'tb_locals': False, + 'buffer': None})]) self.assertEqual(FakeRunner.runArgs, [test]) self.assertEqual(p.result, result) @@ -234,8 +236,9 @@ p.runTests() self.assertEqual(FakeRunner.initArgs, [((), {'verbosity': verbosity, - 'failfast': failfast, - 'buffer': None})]) + 'failfast': failfast, + 'tb_locals': False, + 'buffer': None})]) self.assertEqual(FakeRunner.runArgs, [test]) self.assertEqual(p.result, result) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unittest2-0.8.0/unittest2/test/test_case.py new/unittest2-1.1.0/unittest2/test/test_case.py --- old/unittest2-0.8.0/unittest2/test/test_case.py 2014-10-30 10:54:05.000000000 +0100 +++ new/unittest2-1.1.0/unittest2/test/test_case.py 2015-06-29 12:29:49.000000000 +0200 @@ -391,6 +391,34 @@ Foo(events).run(result) self.assertEqual(events, expected) + def test_subtests_failfast(self): + # Ensure proper test flow with subtests and failfast (issue #22894) + events = [] + + class Foo(unittest.TestCase): + def test_a(self): + with self.subTest(): + events.append('a1') + events.append('a2') + + def test_b(self): + with self.subTest(): + events.append('b1') + with self.subTest(): + self.fail('failure') + events.append('b2') + + def test_c(self): + events.append('c') + + result = unittest.TestResult() + result.failfast = True + suite = unittest.makeSuite(Foo) + suite.run(result) + + expected = ['a1', 'a2', 'b1'] + self.assertEqual(events, expected) + # "This class attribute gives the exception raised by the test() method. # If a test framework needs to use a specialized exception, possibly to # carry additional information, it must subclass this exception in @@ -1024,6 +1052,71 @@ self.assertRaises(self.failureException, self.assertRegex, 'saaas', r'aaaa') + def testAssertRaisesCallable(self): + class ExceptionMock(Exception): + pass + def Stub(): + raise ExceptionMock('We expect') + self.assertRaises(ExceptionMock, Stub) + # A tuple of exception classes is accepted + self.assertRaises((ValueError, ExceptionMock), Stub) + # *args and **kwargs also work + self.assertRaises(ValueError, int, '19', base=8) + # Failure when no exception is raised + with self.assertRaises(self.failureException): + self.assertRaises(ExceptionMock, lambda: 0) + # Failure when the function is None + with self.assertWarns(DeprecationWarning): + self.assertRaises(ExceptionMock, None) + # Failure when another exception is raised + with self.assertRaises(ExceptionMock): + self.assertRaises(ValueError, Stub) + + def testAssertRaisesContext(self): + class ExceptionMock(Exception): + pass + def Stub(): + raise ExceptionMock('We expect') + with self.assertRaises(ExceptionMock): + Stub() + # A tuple of exception classes is accepted + with self.assertRaises((ValueError, ExceptionMock)) as cm: + Stub() + # The context manager exposes caught exception + self.assertIsInstance(cm.exception, ExceptionMock) + self.assertEqual(cm.exception.args[0], 'We expect') + # *args and **kwargs also work + with self.assertRaises(ValueError): + int('19', base=8) + # Failure when no exception is raised + with self.assertRaises(self.failureException): + with self.assertRaises(ExceptionMock): + pass + # Custom message + with self.assertRaisesRegex(self.failureException, 'foobar'): + with self.assertRaises(ExceptionMock, msg='foobar'): + pass + # Invalid keyword argument + with self.assertWarnsRegex(DeprecationWarning, 'foobar'): + with self.assertRaises(AssertionError): + with self.assertRaises(ExceptionMock, foobar=42): + pass + # Failure when another exception is raised + with self.assertRaises(ExceptionMock): + self.assertRaises(ValueError, Stub) + + def testAssertRaisesNoExceptionType(self): + with self.assertRaises(TypeError): + self.assertRaises() + with self.assertRaises(TypeError): + self.assertRaises(1) + with self.assertRaises(TypeError): + self.assertRaises(object) + with self.assertRaises(TypeError): + self.assertRaises((ValueError, 1)) + with self.assertRaises(TypeError): + self.assertRaises((ValueError, object)) + def testAssertRaisesRegex(self): class ExceptionMock(Exception): pass @@ -1034,20 +1127,27 @@ self.assertRaisesRegex(ExceptionMock, re.compile('expect$'), Stub) self.assertRaisesRegex(ExceptionMock, 'expect$', Stub) self.assertRaisesRegex(ExceptionMock, u('expect$'), Stub) + with self.assertWarns(DeprecationWarning): + self.assertRaisesRegex(ExceptionMock, 'expect$', None) def testAssertNotRaisesRegex(self): self.assertRaisesRegex( - self.failureException, '^Exception not raised$', + self.failureException, '^Exception not raised by <lambda>$', self.assertRaisesRegex, Exception, re.compile('x'), lambda: None) self.assertRaisesRegex( - self.failureException, '^Exception not raised$', + self.failureException, '^Exception not raised by <lambda>$', self.assertRaisesRegex, Exception, 'x', lambda: None) - self.assertRaisesRegex( - self.failureException, '^Exception not raised$', - self.assertRaisesRegex, Exception, u('x'), - lambda: None) + # Custom message + with self.assertRaisesRegex(self.failureException, 'foobar'): + with self.assertRaisesRegex(Exception, 'expect', msg='foobar'): + pass + # Invalid keyword argument + with self.assertWarnsRegex(DeprecationWarning, 'foobar'): + with self.assertRaises(AssertionError): + with self.assertRaisesRegex(Exception, 'expect', foobar=42): + pass def testAssertRaisesRegexInvalidRegex(self): # Issue 20145. @@ -1093,6 +1193,50 @@ self.assertRaisesRegex, Exception, re.compile('^Expected$'), Stub) + def testAssertRaisesRegexNoExceptionType(self): + with self.assertRaises(TypeError): + self.assertRaisesRegex() + with self.assertRaises(TypeError): + self.assertRaisesRegex(ValueError) + with self.assertRaises(TypeError): + self.assertRaisesRegex(1, 'expect') + with self.assertRaises(TypeError): + self.assertRaisesRegex(object, 'expect') + with self.assertRaises(TypeError): + self.assertRaisesRegex((ValueError, 1), 'expect') + with self.assertRaises(TypeError): + self.assertRaisesRegex((ValueError, object), 'expect') + + def testAssertWarnsNoExceptionType(self): + with self.assertRaises(TypeError): + self.assertWarns() + with self.assertRaises(TypeError): + self.assertWarns(1) + with self.assertRaises(TypeError): + self.assertWarns(object) + with self.assertRaises(TypeError): + self.assertWarns((UserWarning, 1)) + with self.assertRaises(TypeError): + self.assertWarns((UserWarning, object)) + with self.assertRaises(TypeError): + self.assertWarns((UserWarning, Exception)) + + def testAssertWarnsRegexNoExceptionType(self): + with self.assertRaises(TypeError): + self.assertWarnsRegex() + with self.assertRaises(TypeError): + self.assertWarnsRegex(UserWarning) + with self.assertRaises(TypeError): + self.assertWarnsRegex(1, 'expect') + with self.assertRaises(TypeError): + self.assertWarnsRegex(object, 'expect') + with self.assertRaises(TypeError): + self.assertWarnsRegex((UserWarning, 1), 'expect') + with self.assertRaises(TypeError): + self.assertWarnsRegex((UserWarning, object), 'expect') + with self.assertRaises(TypeError): + self.assertWarnsRegex((UserWarning, Exception), 'expect') + @contextlib.contextmanager def assertNoStderr(self): with captured_stderr() as buf: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unittest2-0.8.0/unittest2/test/test_discovery.py new/unittest2-1.1.0/unittest2/test/test_discovery.py --- old/unittest2-0.8.0/unittest2/test/test_discovery.py 2014-11-04 15:11:54.000000000 +0100 +++ new/unittest2-1.1.0/unittest2/test/test_discovery.py 2015-06-29 06:17:45.000000000 +0200 @@ -3,6 +3,7 @@ import re import sys import types +import pickle try: import builtins except ImportError: @@ -491,6 +492,10 @@ test.my_package() self.assertEqual(import_calls, ['my_package']) + # Check picklability + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + pickle.loads(pickle.dumps(test, proto)) + def test_discover_with_module_that_raises_SkipTest_on_import(self): loader = unittest.TestLoader() @@ -527,6 +532,10 @@ self.assertEqual(result.testsRun, 1) self.assertEqual(import_calls, ['my_package']) + # Check picklability + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + pickle.loads(pickle.dumps(suite, proto)) + def test_command_line_handling_parseArgs(self): # Haha - take that uninstantiable class program = TestableTestProgram() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unittest2-0.8.0/unittest2/test/test_program.py new/unittest2-1.1.0/unittest2/test/test_program.py --- old/unittest2-0.8.0/unittest2/test/test_program.py 2014-10-29 11:50:49.000000000 +0100 +++ new/unittest2-1.1.0/unittest2/test/test_program.py 2015-03-06 06:13:56.000000000 +0100 @@ -118,6 +118,7 @@ result = None verbosity = 1 defaultTest = None + tb_locals = False testRunner = None testLoader = unittest2.defaultTestLoader progName = 'test' @@ -130,18 +131,19 @@ class FakeRunner(object): initArgs = None test = None - raiseError = False + raiseError = 0 def __init__(self, **kwargs): FakeRunner.initArgs = kwargs if FakeRunner.raiseError: - FakeRunner.raiseError = False + FakeRunner.raiseError -= 1 raise TypeError def run(self, test): FakeRunner.test = test return RESULT + class TestCommandLineArgs(unittest2.TestCase): def setUp(self): @@ -149,7 +151,7 @@ self.program.createTests = lambda: None FakeRunner.initArgs = None FakeRunner.test = None - FakeRunner.raiseError = False + FakeRunner.raiseError = 0 def testVerbosity(self): program = self.program @@ -225,6 +227,7 @@ self.assertEqual(FakeRunner.initArgs, {'verbosity': 'verbosity', 'failfast': 'failfast', + 'tb_locals': False, 'buffer': 'buffer'}) self.assertEqual(FakeRunner.test, 'test') self.assertIs(program.result, RESULT) @@ -243,10 +246,24 @@ self.assertEqual(FakeRunner.test, 'test') self.assertIs(program.result, RESULT) + def test_locals(self): + program = self.program + + program.testRunner = FakeRunner + program.parseArgs([None, '--locals']) + self.assertEqual(True, program.tb_locals) + program.runTests() + self.assertEqual(FakeRunner.initArgs, {'buffer': False, + 'failfast': False, + 'tb_locals': True, + 'verbosity': 1}) + def testRunTestsOldRunnerClass(self): program = self.program - FakeRunner.raiseError = True + # Two TypeErrors are needed to fall all the way back to old-style + # runners - one to fail tb_locals, one to fail buffer etc. + FakeRunner.raiseError = 2 program.testRunner = FakeRunner program.verbosity = 'verbosity' program.failfast = 'failfast' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unittest2-0.8.0/unittest2/test/test_result.py new/unittest2-1.1.0/unittest2/test/test_result.py --- old/unittest2-0.8.0/unittest2/test/test_result.py 2014-10-29 11:05:10.000000000 +0100 +++ new/unittest2-1.1.0/unittest2/test/test_result.py 2015-03-06 06:20:12.000000000 +0100 @@ -1,13 +1,28 @@ import sys import textwrap -import traceback +import traceback2 as traceback +import six from six.moves import StringIO import unittest2 import unittest2 as unittest +class MockTraceback(object): + class TracebackException: + def __init__(self, *args, **kwargs): + self.capture_locals = kwargs.get('capture_locals', False) + def format(self): + result = ['A traceback'] + if self.capture_locals: + result.append('locals') + return result + +def restore_traceback(): + unittest.result.traceback = traceback + + class Test_TestResult(unittest2.TestCase): # Note: there are not separate tests for TestResult.wasSuccessful(), # TestResult.errors, TestResult.failures, TestResult.testsRun or @@ -177,7 +192,7 @@ test_case, formatted_exc = result.failures[0] self.assertIs(test_case, test) - self.assertIsInstance(formatted_exc, str) + self.assertIsInstance(formatted_exc, six.string_types) # "addError(test, err)" # ... @@ -225,7 +240,26 @@ test_case, formatted_exc = result.errors[0] self.assertIs(test_case, test) - self.assertIsInstance(formatted_exc, str) + self.assertIsInstance(formatted_exc, six.string_types) + + def test_addError_locals(self): + class Foo(unittest.TestCase): + def test_1(self): + 1/0 + + test = Foo('test_1') + result = unittest.TestResult() + result.tb_locals = True + + unittest.result.traceback = MockTraceback + self.addCleanup(restore_traceback) + result.startTestRun() + test.run(result) + result.stopTestRun() + + self.assertEqual(len(result.errors), 1) + test_case, formatted_exc = result.errors[0] + self.assertEqual('A tracebacklocals', formatted_exc) def test_addSubTest(self): log = [] @@ -391,16 +425,6 @@ self.assertTrue(self.testRan) -class MockTraceback(object): - @staticmethod - def format_exception(*_): - return ['A traceback'] - - -def restore_traceback(): - unittest2.result.traceback = traceback - - class TestOutputBuffering(unittest2.TestCase): def setUp(self): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unittest2-0.8.0/unittest2/test/test_runner.py new/unittest2-1.1.0/unittest2/test/test_runner.py --- old/unittest2-0.8.0/unittest2/test/test_runner.py 2014-10-28 23:46:13.000000000 +0100 +++ new/unittest2-1.1.0/unittest2/test/test_runner.py 2015-03-06 06:05:12.000000000 +0100 @@ -160,7 +160,7 @@ self.assertEqual(runner.verbosity, 1) self.assertTrue(runner.descriptions) self.assertEqual(runner.resultclass, unittest2.TextTestResult) - + self.assertFalse(runner.tb_locals) def test_multiple_inheritance(self): class AResult(unittest.TestResult): @@ -181,7 +181,7 @@ pass result = unittest2.TestResult() runner = unittest2.TextTestRunner(stream=StringIO(), failfast=True, - buffer=True) + buffer=True) # Use our result object runner._makeResult = lambda: result runner.run(Test('testFoo')) @@ -189,6 +189,11 @@ self.assertTrue(result.failfast) self.assertTrue(result.buffer) + def test_locals(self): + runner = unittest.TextTestRunner(stream=io.StringIO(), tb_locals=True) + result = runner.run(unittest.TestSuite()) + self.assertEqual(True, result.tb_locals) + def testRunnerRegistersResult(self): class Test(unittest2.TestCase): def testFoo(self): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unittest2-0.8.0/unittest2/util.py new/unittest2-1.1.0/unittest2/util.py --- old/unittest2-0.8.0/unittest2/util.py 2014-10-29 04:25:24.000000000 +0100 +++ new/unittest2-1.1.0/unittest2/util.py 2014-11-05 10:17:14.000000000 +0100 @@ -60,45 +60,6 @@ def strclass(cls): return "%s.%s" % (cls.__module__, getattr(cls, '__qualname__', cls.__name__)) -def sorted_list_difference(expected, actual): - """Finds elements in only one or the other of two, sorted input lists. - - Returns a two-element tuple of lists. The first list contains those - elements in the "expected" list but not in the "actual" list, and the - second contains those elements in the "actual" list but not in the - "expected" list. Duplicate elements in either input list are ignored. - """ - i = j = 0 - missing = [] - unexpected = [] - while True: - try: - e = expected[i] - a = actual[j] - if e < a: - missing.append(e) - i += 1 - while expected[i] == e: - i += 1 - elif e > a: - unexpected.append(a) - j += 1 - while actual[j] == a: - j += 1 - else: - i += 1 - try: - while expected[i] == e: - i += 1 - finally: - j += 1 - while actual[j] == a: - j += 1 - except IndexError: - missing.extend(expected[i:]) - unexpected.extend(actual[j:]) - break - return missing, unexpected def unorderable_list_difference(expected, actual, ignore_duplicate=False): """Same behavior as sorted_list_difference but diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unittest2-0.8.0/unittest2.egg-info/PKG-INFO new/unittest2-1.1.0/unittest2.egg-info/PKG-INFO --- old/unittest2-0.8.0/unittest2.egg-info/PKG-INFO 2014-11-04 16:26:25.000000000 +0100 +++ new/unittest2-1.1.0/unittest2.egg-info/PKG-INFO 2015-06-30 08:48:20.000000000 +0200 @@ -1,10 +1,10 @@ Metadata-Version: 1.1 Name: unittest2 -Version: 0.8.0 +Version: 1.1.0 Summary: The new features in unittest backported to Python 2.4+. Home-page: http://pypi.python.org/pypi/unittest2 -Author: Michael Foord -Author-email: [email protected] +Author: Robert Collins +Author-email: [email protected] License: UNKNOWN Description: unittest2 is a backport of the new features added to the unittest testing framework in Python 2.7 and onwards. It is tested to run on Python 2.6, 2.7, @@ -30,8 +30,9 @@ * `Download unittest2 0.5.1 for Python 2.3 <http://voidspace.org.uk/downloads/unittest2-0.5.1-python2.3.zip>`_ - There is also a version of unittest2 for Python 3. This has the project name - "unittest2py3k" but uses the same package name ("unittest2"): + There was a separate version of unittest2 for Python 3. This is no longer + needed, but still exists on PyPI. This had the project name "unittest2py3k" but + uses the same package name ("unittest2"): * `unittest2 for Python 3 <http://pypi.python.org/pypi/unittest2py3k>`_ @@ -43,6 +44,11 @@ will work with the standard unittest test loaders, runners result objects however. + In general for documentation on unittest2 see the current latest documented of + CPython: + + * `CPython unittest documentation <https://docs.python.org/dev/library/unittest.html>`_ + New features include: * ``addCleanups`` - better resource management @@ -169,11 +175,39 @@ CHANGELOG ========= + 2015-06-20 - 1.1.0 + ------------------ + + - Issue #15836: assertRaises(), assertRaisesRegex(), assertWarns() and + assertWarnsRegex() assertments now check the type of the first argument + to prevent possible user error. Based on patch by Daniel Wagner-Hall. + + - Issue #24134: assertRaises(), assertRaisesRegex(), assertWarns() and + assertWarnsRegex() checks now emits a deprecation warning when callable is + None or keyword arguments except msg is passed in the context manager mode. + + - Issue #22903: The fake test case created by unittest.loader when it fails + importing a test module is now picklable. + + + 2015-03-12 - 1.0.1 + ------------------ + + - Unittest2 issue #94: Need at least 1.4 of six. + + 2015-03-06 - 1.0.0 + ------------------ + + - Issue #22936: Permit showing local variables in tracebacks. + 2014/11/05 - 0.8 ---------------- - Issue #22457: Honour load_tests in the start_dir of discovery. + - Issue #22894: TestCase.subTest() would cause the test suite to be stopped + when in failfast mode, even in the absence of failures. + 2014/10/31 - 0.7.1 ------------------ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unittest2-0.8.0/unittest2.egg-info/requires.txt new/unittest2-1.1.0/unittest2.egg-info/requires.txt --- old/unittest2-0.8.0/unittest2.egg-info/requires.txt 2014-11-04 16:26:25.000000000 +0100 +++ new/unittest2-1.1.0/unittest2.egg-info/requires.txt 2015-06-30 08:48:20.000000000 +0200 @@ -1,2 +1,3 @@ argparse -six +six>=1.4 +traceback2
