Hello community, here is the log from the commit of package python-testfixtures for openSUSE:Factory checked in at 2020-12-03 18:40:45 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-testfixtures (Old) and /work/SRC/openSUSE:Factory/.python-testfixtures.new.5913 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-testfixtures" Thu Dec 3 18:40:45 2020 rev:15 rq:851911 version:6.15.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-testfixtures/python-testfixtures.changes 2020-10-29 09:45:33.968013322 +0100 +++ /work/SRC/openSUSE:Factory/.python-testfixtures.new.5913/python-testfixtures.changes 2020-12-03 18:41:54.794115098 +0100 @@ -1,0 +2,6 @@ +Sun Nov 29 18:59:58 UTC 2020 - ecsos <ec...@opensuse.org> + +- update to 6.15.0: + - Add support to :class:LogCapture for making sure log entries above a specified level have been checked. + +------------------------------------------------------------------- Old: ---- testfixtures-6.14.2.tar.gz New: ---- testfixtures-6.15.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-testfixtures.spec ++++++ --- /var/tmp/diff_new_pack.VFisEH/_old 2020-12-03 18:41:55.802115734 +0100 +++ /var/tmp/diff_new_pack.VFisEH/_new 2020-12-03 18:41:55.802115734 +0100 @@ -19,7 +19,7 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} %bcond_without python2 Name: python-testfixtures -Version: 6.14.2 +Version: 6.15.0 Release: 0 Summary: A collection of helpers and mock objects for unit tests and doc tests License: MIT ++++++ testfixtures-6.14.2.tar.gz -> testfixtures-6.15.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/testfixtures-6.14.2/CHANGELOG.rst new/testfixtures-6.15.0/CHANGELOG.rst --- old/testfixtures-6.14.2/CHANGELOG.rst 2020-09-04 19:48:19.000000000 +0200 +++ new/testfixtures-6.15.0/CHANGELOG.rst 2020-10-09 07:22:56.000000000 +0200 @@ -3,6 +3,14 @@ .. currentmodule:: testfixtures +6.15.0 (9 Oct 2020) +------------------- + +- Add support to :class:`LogCapture` for making sure log entries above a specified + level have been checked. + +Thanks to Zoltan Farkas for the implementation. + 6.14.2 (4 Sep 2020) ------------------- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/testfixtures-6.14.2/PKG-INFO new/testfixtures-6.15.0/PKG-INFO --- old/testfixtures-6.14.2/PKG-INFO 2020-09-04 19:48:23.000000000 +0200 +++ new/testfixtures-6.15.0/PKG-INFO 2020-10-09 07:22:59.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: testfixtures -Version: 6.14.2 +Version: 6.15.0 Summary: A collection of helpers and mock objects for unit tests and doc tests. Home-page: https://github.com/Simplistix/testfixtures Author: Chris Withers diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/testfixtures-6.14.2/testfixtures/comparison.py new/testfixtures-6.15.0/testfixtures/comparison.py --- old/testfixtures-6.14.2/testfixtures/comparison.py 2020-09-04 19:48:19.000000000 +0200 +++ new/testfixtures-6.15.0/testfixtures/comparison.py 2020-10-09 07:22:56.000000000 +0200 @@ -633,7 +633,7 @@ with this string in the message in the :class:`AssertionError`. - :param x_label: If provided, in the event of an :class:`AssertionError` + :param y_label: If provided, in the event of an :class:`AssertionError` being raised, the object passed as the second positional argument, or ``y`` keyword argument, will be labelled with this string in the message in the diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/testfixtures-6.14.2/testfixtures/logcapture.py new/testfixtures-6.15.0/testfixtures/logcapture.py --- old/testfixtures-6.14.2/testfixtures/logcapture.py 2020-09-04 19:48:19.000000000 +0200 +++ new/testfixtures-6.15.0/testfixtures/logcapture.py 2020-10-09 07:22:56.000000000 +0200 @@ -42,15 +42,21 @@ If ``True``, log messages will be compared recursively by :meth:`LogCapture.check`. + + :param ensure_checks_above: The log level above which checks must be made for logged events. + """ instances = set() atexit_setup = False installed = False + default_ensure_checks_above = logging.NOTSET def __init__(self, names=None, install=True, level=1, propagate=None, attributes=('name', 'levelname', 'getMessage'), - recursive_check=False): + recursive_check=False, + ensure_checks_above=None + ): logging.Handler.__init__(self) if not isinstance(names, tuple): names = (names, ) @@ -60,7 +66,12 @@ self.attributes = attributes self.recursive_check = recursive_check self.old = defaultdict(dict) - self.clear() + #: The log level above which checks must be made for logged events. + if ensure_checks_above is None: + self.ensure_checks_above = self.default_ensure_checks_above + else: + self.ensure_checks_above = ensure_checks_above + self.clear() # declares self.records: List[LogRecord] if install: self.install() @@ -73,11 +84,55 @@ '%s' % ('\n'.join((str(i.names) for i in cls.instances))) ) + def __len__(self): + return len(self.records) + + def __getitem__(self, index): + return self._actual_row(self.records[index]) + + def __contains__(self, what): + for i, item in enumerate(self): + if what == item: + self.records[i].checked = True + return True + def clear(self): - "Clear any entries that have been captured." + """Clear any entries that have been captured.""" self.records = [] + def mark_all_checked(self): + """ + Mark all captured events as checked. + This should be called if you have made assertions about logging + other than through :class:`LogCapture` methods. + """ + for record in self.records: + record.checked = True + + def ensure_checked(self, level=None): + """ + Ensure every entry logged above the specified `level` has been checked. + Raises an :class:`AssertionError` if this is not the case. + + :param level: the logging level, defaults to :attr:`ensure_checks_above`. + :type level: Optional[int] + """ + if level is None: + level = self.ensure_checks_above + if level == logging.NOTSET: + return + un_checked = [] + for record in self.records: + if record.levelno >= level and not record.checked: + un_checked.append(self._actual_row(record)) + if un_checked: + raise AssertionError(( + 'Not asserted ERROR log(s): %s' + ) % (pformat(un_checked))) + def emit(self, record): + # record: logging.LogRecord + record.checked = False self.records.append(record) def install(self): @@ -94,7 +149,7 @@ self.old['levels'][name] = logger.level self.old['handlers'][name] = logger.handlers self.old['disabled'][name] = logger.disabled - self.old['progagate'][name] = logger.propagate + self.old['propagate'][name] = logger.propagate logger.setLevel(self.level) logger.handlers = [self] logger.disabled = False @@ -120,7 +175,7 @@ logger.setLevel(self.old['levels'][name]) logger.handlers = self.old['handlers'][name] logger.disabled = self.old['disabled'][name] - logger.propagate = self.old['progagate'][name] + logger.propagate = self.old['propagate'][name] self.instances.remove(self) @classmethod @@ -130,11 +185,22 @@ i.uninstall() def _actual_row(self, record): - for a in self.attributes: - value = getattr(record, a, None) - if callable(value): - value = value() - yield value + # Convert a log record to a Tuple or attribute value according the attributes member. + # record: logging.LogRecord + + if callable(self.attributes): + return self.attributes(record) + else: + values = [] + for a in self.attributes: + value = getattr(record, a, None) + if callable(value): + value = value() + values.append(value) + if len(values) == 1: + return values[0] + else: + return tuple(values) def actual(self): """ @@ -145,17 +211,13 @@ This can be useful for making more complex assertions about logged records. The actual records logged can also be inspected by using the :attr:`records` attribute. + + :rtype: List + """ actual = [] for r in self.records: - if callable(self.attributes): - actual.append(self.attributes(r)) - else: - result = tuple(self._actual_row(r)) - if len(result) == 1: - actual.append(result[0]) - else: - actual.append(result) + actual.append(self._actual_row(r)) return actual def __str__(self): @@ -174,11 +236,13 @@ A sequence of entries of the structure specified by the ``attributes`` passed to the constructor. """ - return compare( + result = compare( expected, actual=self.actual(), recursive=self.recursive_check ) + self.mark_all_checked() + return result def check_present(self, *expected, **kw): """ @@ -213,6 +277,7 @@ matched.pop() break else: + self.records[index].checked = True matched_indices.append(index+1) matched.append(entry) else: @@ -225,12 +290,13 @@ expected = list(expected) matched = [] unmatched = [] - for entry in actual: + for i, entry in enumerate(actual): try: index = expected.index(entry) except ValueError: unmatched.append(entry) else: + self.records[i].checked = True matched.append(expected.pop(index)) if not expected: break @@ -247,6 +313,7 @@ def __exit__(self, type, value, traceback): self.uninstall() + self.ensure_checked() class LogCaptureForDecorator(LogCapture): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/testfixtures-6.14.2/testfixtures/tests/test_log_capture.py new/testfixtures-6.15.0/testfixtures/tests/test_log_capture.py --- old/testfixtures-6.14.2/testfixtures/tests/test_log_capture.py 2020-09-04 19:48:19.000000000 +0200 +++ new/testfixtures-6.15.0/testfixtures/tests/test_log_capture.py 2020-10-09 07:22:56.000000000 +0200 @@ -1,6 +1,6 @@ from __future__ import absolute_import -from logging import getLogger +from logging import getLogger, ERROR from unittest import TestCase from testfixtures.shouldraise import ShouldAssert @@ -49,6 +49,11 @@ C('logging.LogRecord'), ]) + @log_capture(ensure_checks_above=ERROR) + def test_simple_strict(self, l): + root.error('during') + l.check(("root", "ERROR", "during")) + def test_uninstall_properly(self): root = getLogger() child = getLogger('child') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/testfixtures-6.14.2/testfixtures/tests/test_logcapture.py new/testfixtures-6.15.0/testfixtures/tests/test_logcapture.py --- old/testfixtures-6.14.2/testfixtures/tests/test_logcapture.py 2020-09-04 19:48:19.000000000 +0200 +++ new/testfixtures-6.15.0/testfixtures/tests/test_logcapture.py 2020-10-09 07:22:56.000000000 +0200 @@ -1,5 +1,5 @@ from __future__ import print_function -from logging import getLogger +from logging import getLogger, ERROR from textwrap import dedent from unittest import TestCase from warnings import catch_warnings @@ -25,6 +25,57 @@ root.info('after') assert str(l) == "root INFO\n during" + def test_simple_strict(self): + log_capture = LogCapture(ensure_checks_above=ERROR) + root.error('during') + log_capture.uninstall() + with ShouldAssert("Not asserted ERROR log(s): [('root', 'ERROR', 'during')]"): + log_capture.ensure_checked() + + def test_simple_strict_re_defaulted(self): + old = LogCapture.default_ensure_checks_above + try: + LogCapture.default_ensure_checks_above = ERROR + log_capture = LogCapture() + root.error('during') + log_capture.uninstall() + with ShouldAssert("Not asserted ERROR log(s): [('root', 'ERROR', 'during')]"): + log_capture.ensure_checked() + finally: + LogCapture.default_ensure_checks_above = old + + def test_simple_strict_asserted(self): + log_capture = LogCapture(ensure_checks_above=ERROR) + root.error('during') + log_capture.uninstall() + log_capture.check(("root", "ERROR", "during")) + log_capture.ensure_checked() + + def test_simple_strict_asserted_2(self): + log_capture = LogCapture(ensure_checks_above=ERROR) + root.error('during') + log_capture.uninstall() + assert ("root", "ERROR", "during") in log_capture + assert ("root", "INFO", "during") not in log_capture + log_capture.ensure_checked() + + def test_simple_strict_asserted_3(self): + log_capture = LogCapture(ensure_checks_above=ERROR) + root.error('during') + log_capture.uninstall() + log_capture.mark_all_checked() + log_capture.ensure_checked() + + def test_simple_strict_ctx(self): + with ShouldAssert("Not asserted ERROR log(s): [('root', 'ERROR', 'during')]"): + with LogCapture(ensure_checks_above=ERROR) as log_capture: + root.error('during') + + def test_simple_strict_asserted_ctx(self): + with LogCapture(ensure_checks_above=ERROR) as log_capture: + root.error('during') + log_capture.check(("root", "ERROR", "during")) + def test_specific_logger(self): l = LogCapture('one') root.info('1') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/testfixtures-6.14.2/testfixtures/version.txt new/testfixtures-6.15.0/testfixtures/version.txt --- old/testfixtures-6.14.2/testfixtures/version.txt 2020-09-04 19:48:19.000000000 +0200 +++ new/testfixtures-6.15.0/testfixtures/version.txt 2020-10-09 07:22:56.000000000 +0200 @@ -1 +1 @@ -6.14.2 +6.15.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/testfixtures-6.14.2/testfixtures.egg-info/PKG-INFO new/testfixtures-6.15.0/testfixtures.egg-info/PKG-INFO --- old/testfixtures-6.14.2/testfixtures.egg-info/PKG-INFO 2020-09-04 19:48:23.000000000 +0200 +++ new/testfixtures-6.15.0/testfixtures.egg-info/PKG-INFO 2020-10-09 07:22:59.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: testfixtures -Version: 6.14.2 +Version: 6.15.0 Summary: A collection of helpers and mock objects for unit tests and doc tests. Home-page: https://github.com/Simplistix/testfixtures Author: Chris Withers _______________________________________________ openSUSE Commits mailing list -- commit@lists.opensuse.org To unsubscribe, email commit-le...@lists.opensuse.org List Netiquette: https://en.opensuse.org/openSUSE:Mailing_list_netiquette List Archives: https://lists.opensuse.org/archives/list/commit@lists.opensuse.org