Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-eliot for openSUSE:Factory checked in at 2021-10-16 22:47:18 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-eliot (Old) and /work/SRC/openSUSE:Factory/.python-eliot.new.1890 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-eliot" Sat Oct 16 22:47:18 2021 rev:9 rq:925640 version:1.13.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-eliot/python-eliot.changes 2021-01-21 21:54:48.997780719 +0100 +++ /work/SRC/openSUSE:Factory/.python-eliot.new.1890/python-eliot.changes 2021-10-16 22:47:55.076705960 +0200 @@ -1,0 +2,7 @@ +Wed Sep 1 08:32:49 UTC 2021 - John Paul Adrian Glaubitz <adrian.glaub...@suse.com> + +- Update to 1.13.0 + * Custom JSON encoder support in tests +- Update BuildRequires from setup.py + +------------------------------------------------------------------- Old: ---- python-eliot-1.12.0.tar.gz New: ---- python-eliot-1.13.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-eliot.spec ++++++ --- /var/tmp/diff_new_pack.12d19O/_old 2021-10-16 22:47:55.448706273 +0200 +++ /var/tmp/diff_new_pack.12d19O/_new 2021-10-16 22:47:55.452706277 +0200 @@ -19,7 +19,7 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} %define skip_python2 1 Name: python-eliot -Version: 1.12.0 +Version: 1.13.0 Release: 0 Summary: A logging system that tells the user why something happened License: Apache-2.0 @@ -33,6 +33,7 @@ BuildRequires: %{python_module flake8} BuildRequires: %{python_module hypothesis >= 3.47.0} BuildRequires: %{python_module pyrsistent >= 0.11.8} +BuildRequires: %{python_module pytest-xdist} BuildRequires: %{python_module pytest} BuildRequires: %{python_module setuptools >= 40} BuildRequires: %{python_module six} @@ -52,7 +53,7 @@ %endif Requires: python-zope.interface Requires(post): update-alternatives -Requires(postun): update-alternatives +Requires(postun):update-alternatives BuildArch: noarch %python_subpackages ++++++ python-eliot-1.12.0.tar.gz -> python-eliot-1.13.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/eliot-1.12.0/.github/workflows/main.yml new/eliot-1.13.0/.github/workflows/main.yml --- old/eliot-1.12.0/.github/workflows/main.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/eliot-1.13.0/.github/workflows/main.yml 2020-12-15 20:09:24.000000000 +0100 @@ -0,0 +1,34 @@ +--- +name: CI + +on: + push: + branches: ["master"] + pull_request: + branches: ["master"] + workflow_dispatch: + +jobs: + tests: + name: "Python ${{ matrix.python-version }}" + runs-on: "ubuntu-latest" + + strategy: + matrix: + python-version: ["3.6", "3.7", "3.8", "3.9", "pypy3"] + + steps: + - uses: "actions/checkout@v2" + - uses: "actions/setup-python@v2" + with: + python-version: "${{ matrix.python-version }}" + - name: "Install dependencies" + run: | + set -xe + python -VV + python -m site + python -m pip install --upgrade pip setuptools wheel + python -m pip install --upgrade virtualenv tox tox-gh-actions + + - name: "Run tox targets for ${{ matrix.python-version }}" + run: "python -m tox" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/eliot-1.12.0/.travis.yml new/eliot-1.13.0/.travis.yml --- old/eliot-1.12.0/.travis.yml 2020-01-23 21:52:58.000000000 +0100 +++ new/eliot-1.13.0/.travis.yml 1970-01-01 01:00:00.000000000 +0100 @@ -1,15 +0,0 @@ -language: python -dist: xenial -python: - - "3.5" - - "3.6" - - "3.7" - - "3.8" - - "pypy3" - -install: pip install tox-travis - -script: tox - -notifications: - email: false diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/eliot-1.12.0/README.rst new/eliot-1.13.0/README.rst --- old/eliot-1.12.0/README.rst 2020-01-23 21:52:58.000000000 +0100 +++ new/eliot-1.13.0/README.rst 2020-12-15 20:09:24.000000000 +0100 @@ -29,7 +29,7 @@ Eliot is only used to generate your logs; you will might need tools like Logstash and ElasticSearch to aggregate and store logs if you are using multiple processes across multiple machines. -Eliot supports Python 3.5, 3.6, 3.7, and 3.8, as well as PyPy3. +Eliot supports Python 3.6, 3.7, 3.8, and 3.9, as well as PyPy3. It is maintained by Itamar Turner-Trauring, and released under the Apache 2.0 License. Python 2.7 is in legacy support mode, with the last release supported being 1.7; see `here <https://eliot.readthedocs.io/en/stable/python2.html>`_ for details. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/eliot-1.12.0/docs/source/generating/testing.rst new/eliot-1.13.0/docs/source/generating/testing.rst --- old/eliot-1.12.0/docs/source/generating/testing.rst 2020-01-23 21:52:58.000000000 +0100 +++ new/eliot-1.13.0/docs/source/generating/testing.rst 2020-12-15 20:09:24.000000000 +0100 @@ -233,6 +233,35 @@ self.assertEqual(servers, [msg.message["server"] for msg in messages]) +Custom JSON encoding +-------------------- + +Just like a ``FileDestination`` can have a custom JSON encoder, so can your tests, so you can validate your messages with that JSON encoder: + +.. code-block:: python + + from unittest import TestCase + from eliot.json import EliotJSONEncoder + from eliot.testing import capture_logging + + class MyClass: + def __init__(self, x): + self.x = x + + class MyEncoder(EliotJSONEncoder): + def default(self, obj): + if isinstance(obj, MyClass): + return {"x": obj.x} + return EliotJSONEncoder.default(self, obj) + + class LoggingTests(TestCase): + @capture_logging(None, encoder_=MyEncoder) + def test_logging(self, logger): + # Logged messages will be validated using MyEncoder.... + ... + +Notice that the hyphen after ``encoder_`` is deliberate: by default keyword arguments are passed to the assertion function (the first argument to ``@capture_logging``) so it's marked this way to indicate it's part of Eliot's API. + Custom testing setup -------------------- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/eliot-1.12.0/docs/source/index.rst new/eliot-1.13.0/docs/source/index.rst --- old/eliot-1.12.0/docs/source/index.rst 2020-01-23 21:52:58.000000000 +0100 +++ new/eliot-1.13.0/docs/source/index.rst 2020-12-15 20:09:24.000000000 +0100 @@ -28,7 +28,7 @@ * **Start here:** :doc:`Quickstart documentation <quickstart>` * Need help or have any questions? `File an issue <https://github.com/itamarst/eliot/issues/new>`_. * Eliot is licensed under the `Apache 2.0 license <https://github.com/itamarst/eliot/blob/master/LICENSE>`_, and the source code is `available on GitHub <https://github.com/itamarst/eliot>`_. -* Eliot supports Python 3.8, 3.7, 3.6, and 3.5, as well as PyPy3. +* Eliot supports Python 3.9, 3.8, 3.7, 3.6, and PyPy3. Python 2.7 is in legacy support mode (see :ref:`python2` for details). * **Commercial support** is available from `Python???Speed <https://pythonspeed.com/services/#eliot>`_. * Read on for the full documentation. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/eliot-1.12.0/docs/source/news.rst new/eliot-1.13.0/docs/source/news.rst --- old/eliot-1.12.0/docs/source/news.rst 2020-01-23 21:52:58.000000000 +0100 +++ new/eliot-1.13.0/docs/source/news.rst 2020-12-15 20:09:24.000000000 +0100 @@ -1,6 +1,18 @@ What's New ========== +1.13.0 +^^^^^^ + +Features: + +* ``@capture_logging`` and ``MemoryLogger`` now support specifying a custom JSON encoder. By default they now use Eliot's encoder. This means tests can now match the encoding used by a ``FileDestination``. +* Added support for Python 3.9. + +Deprecation: + +* Python 3.5 is no longer supported. + 1.12.0 ^^^^^^ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/eliot-1.12.0/eliot/_output.py new/eliot-1.13.0/eliot/_output.py --- old/eliot-1.12.0/eliot/_output.py 2020-01-23 21:52:58.000000000 +0100 +++ new/eliot-1.13.0/eliot/_output.py 2020-12-15 20:09:24.000000000 +0100 @@ -262,8 +262,12 @@ not mutate this list. """ - def __init__(self): + def __init__(self, encoder=EliotJSONEncoder): + """ + @param encoder: A JSONEncoder subclass to use when encoding JSON. + """ self._lock = Lock() + self._encoder = encoder self.reset() @exclusively @@ -344,8 +348,7 @@ serializer.serialize(dictionary) try: - bytesjson.dumps(dictionary) - pyjson.dumps(dictionary) + pyjson.dumps(dictionary, cls=self._encoder) except Exception as e: raise TypeError("Message %s doesn't encode to JSON: %s" % (dictionary, e)) @@ -462,6 +465,8 @@ Add a destination that writes a JSON message per line to the given file. @param output_file: A file-like object. + + @param encoder: A JSONEncoder subclass to use when encoding JSON. """ Logger._destinations.add(FileDestination(file=output_file, encoder=encoder)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/eliot-1.12.0/eliot/_version.py new/eliot-1.13.0/eliot/_version.py --- old/eliot-1.12.0/eliot/_version.py 2020-01-23 21:52:58.000000000 +0100 +++ new/eliot-1.13.0/eliot/_version.py 2020-12-15 20:09:24.000000000 +0100 @@ -22,9 +22,9 @@ # setup.py/versioneer.py will grep for the variable names, so they must # each be defined on a line of their own. _version.py will just call # get_keywords(). - git_refnames = " (HEAD -> master, tag: 1.12.0)" - git_full = "4470cc147cd29e59f12730ec3c811a89e61edc65" - git_date = "2020-01-23 15:52:58 -0500" + git_refnames = " (tag: 1.13.0)" + git_full = "e858c8ef7302e22ca05f37565d929db8e0fab153" + git_date = "2020-12-15 14:09:24 -0500" keywords = {"refnames": git_refnames, "full": git_full, "date": git_date} return keywords diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/eliot-1.12.0/eliot/testing.py new/eliot-1.13.0/eliot/testing.py --- old/eliot-1.12.0/eliot/testing.py 2020-01-23 21:52:58.000000000 +0100 +++ new/eliot-1.13.0/eliot/testing.py 2020-12-15 20:09:24.000000000 +0100 @@ -20,6 +20,7 @@ from ._message import MESSAGE_TYPE_FIELD, TASK_LEVEL_FIELD, TASK_UUID_FIELD from ._output import MemoryLogger from . import _output +from .json import EliotJSONEncoder COMPLETED_STATUSES = (FAILED_STATUS, SUCCEEDED_STATUS) @@ -298,7 +299,9 @@ return previous_logger -def validateLogging(assertion, *assertionArgs, **assertionKwargs): +def validateLogging( + assertion, *assertionArgs, encoder_=EliotJSONEncoder, **assertionKwargs +): """ Decorator factory for L{unittest.TestCase} methods to add logging validation. @@ -330,6 +333,8 @@ @param assertionKwargs: Additional keyword arguments to pass to C{assertion}. + + @param encoder_: C{json.JSONEncoder} subclass to use when validating JSON. """ def decorator(function): @@ -337,7 +342,7 @@ def wrapper(self, *args, **kwargs): skipped = False - kwargs["logger"] = logger = MemoryLogger() + kwargs["logger"] = logger = MemoryLogger(encoder=encoder_) self.addCleanup(check_for_errors, logger) # TestCase runs cleanups in reverse order, and we want this to # run *before* tracebacks are checked: @@ -361,7 +366,9 @@ validate_logging = validateLogging -def capture_logging(assertion, *assertionArgs, **assertionKwargs): +def capture_logging( + assertion, *assertionArgs, encoder_=EliotJSONEncoder, **assertionKwargs +): """ Capture and validate all logging that doesn't specify a L{Logger}. @@ -369,7 +376,9 @@ """ def decorator(function): - @validate_logging(assertion, *assertionArgs, **assertionKwargs) + @validate_logging( + assertion, *assertionArgs, encoder_=encoder_, **assertionKwargs + ) @wraps(function) def wrapper(self, *args, **kwargs): logger = kwargs["logger"] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/eliot-1.12.0/eliot/tests/common.py new/eliot-1.13.0/eliot/tests/common.py --- old/eliot-1.12.0/eliot/tests/common.py 2020-01-23 21:52:58.000000000 +0100 +++ new/eliot-1.13.0/eliot/tests/common.py 2020-12-15 20:09:24.000000000 +0100 @@ -3,6 +3,20 @@ """ from io import BytesIO +from json import JSONEncoder + + +class CustomObject(object): + """Gets encoded to JSON.""" + + +class CustomJSONEncoder(JSONEncoder): + """JSONEncoder that knows about L{CustomObject}.""" + + def default(self, o): + if isinstance(o, CustomObject): + return "CUSTOM!" + return JSONEncoder.default(self, o) class FakeSys(object): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/eliot-1.12.0/eliot/tests/test_dask.py new/eliot-1.13.0/eliot/tests/test_dask.py --- old/eliot-1.12.0/eliot/tests/test_dask.py 2020-01-23 21:52:58.000000000 +0100 +++ new/eliot-1.13.0/eliot/tests/test_dask.py 2020-12-15 20:09:24.000000000 +0100 @@ -106,6 +106,8 @@ top_action_name: [ {"eliot:remote_task": ["dask:task", "mult"]}, {"eliot:remote_task": ["dask:task", "mult"]}, + {"eliot:remote_task": ["dask:task"]}, + {"eliot:remote_task": ["dask:task"]}, {"eliot:remote_task": ["dask:task", "finally"]}, ] } @@ -114,20 +116,36 @@ ) # Make sure dependencies are tracked: - mult1_msg, mult2_msg, final_msg = LoggedMessage.ofType( - logger.messages, "dask:task" + ( + mult1_msg, + mult2_msg, + reduce1_msg, + reduce2_msg, + final_msg, + ) = LoggedMessage.ofType(logger.messages, "dask:task") + self.assertEqual( + reduce1_msg.message["dependencies"], [mult1_msg.message["key"]] + ) + self.assertEqual( + reduce2_msg.message["dependencies"], [mult2_msg.message["key"]] ) self.assertEqual( sorted(final_msg.message["dependencies"]), - sorted([mult1_msg.message["key"], mult2_msg.message["key"]]), + sorted([reduce1_msg.message["key"], reduce2_msg.message["key"]]), ) # Make sure dependencies are logically earlier in the logs: self.assertTrue( - mult1_msg.message["task_level"] < final_msg.message["task_level"] + mult1_msg.message["task_level"] < reduce1_msg.message["task_level"] + ) + self.assertTrue( + mult2_msg.message["task_level"] < reduce2_msg.message["task_level"] + ) + self.assertTrue( + reduce1_msg.message["task_level"] < final_msg.message["task_level"] ) self.assertTrue( - mult2_msg.message["task_level"] < final_msg.message["task_level"] + reduce2_msg.message["task_level"] < final_msg.message["task_level"] ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/eliot-1.12.0/eliot/tests/test_output.py new/eliot-1.13.0/eliot/tests/test_output.py --- old/eliot-1.12.0/eliot/tests/test_output.py 2020-01-23 21:52:58.000000000 +0100 +++ new/eliot-1.13.0/eliot/tests/test_output.py 2020-12-15 20:09:24.000000000 +0100 @@ -32,6 +32,7 @@ from .._validation import ValidationError, Field, _MessageSerializer from .._traceback import write_traceback from ..testing import assertContainsFields +from .common import CustomObject, CustomJSONEncoder class MemoryLoggerTests(TestCase): @@ -122,6 +123,27 @@ ) self.assertRaises(TypeError, logger.validate) + @skipUnless(np, "NumPy is not installed.") + def test_EliotJSONEncoder(self): + """ + L{MemoryLogger.validate} uses the EliotJSONEncoder by default to do + encoding testing. + """ + logger = MemoryLogger() + logger.write({"message_type": "type", "foo": np.uint64(12)}, None) + logger.validate() + + def test_JSON_custom_encoder(self): + """ + L{MemoryLogger.validate} will use a custom JSON encoder if one was given. + """ + logger = MemoryLogger(encoder=CustomJSONEncoder) + logger.write( + {"message_type": "type", "custom": CustomObject()}, + None, + ) + logger.validate() + def test_serialize(self): """ L{MemoryLogger.serialize} returns a list of serialized versions of the diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/eliot-1.12.0/eliot/tests/test_testing.py new/eliot-1.13.0/eliot/tests/test_testing.py --- old/eliot-1.12.0/eliot/tests/test_testing.py 2020-01-23 21:52:58.000000000 +0100 +++ new/eliot-1.13.0/eliot/tests/test_testing.py 2020-12-15 20:09:24.000000000 +0100 @@ -4,7 +4,12 @@ from __future__ import unicode_literals -from unittest import SkipTest, TestResult, TestCase +from unittest import SkipTest, TestResult, TestCase, skipUnless + +try: + import numpy as np +except ImportError: + np = None from ..testing import ( issuperset, @@ -25,7 +30,8 @@ from .._message import Message from .._validation import ActionType, MessageType, ValidationError, Field from .._traceback import write_traceback -from .. import add_destination, remove_destination, _output +from .. import add_destination, remove_destination, _output, log_message +from .common import CustomObject, CustomJSONEncoder class IsSuperSetTests(TestCase): @@ -740,6 +746,28 @@ ) +class JSONEncodingTests(TestCase): + """Tests for L{capture_logging} JSON encoder support.""" + + @skipUnless(np, "NumPy is not installed.") + @capture_logging(None) + def test_default_JSON_encoder(self, logger): + """ + L{capture_logging} validates using L{EliotJSONEncoder} by default. + """ + # Default JSON encoder can't handle NumPy: + log_message(message_type="hello", number=np.uint32(12)) + + @capture_logging(None, encoder_=CustomJSONEncoder) + def test_custom_JSON_encoder(self, logger): + """ + L{capture_logging} can be called with a custom JSON encoder, which is then + used for validation. + """ + # Default JSON encoder can't handle this custom object: + log_message(message_type="hello", object=CustomObject()) + + MESSAGE1 = MessageType( "message1", [Field.forTypes("x", [int], "A number")], "A message for testing." ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/eliot-1.12.0/setup.py new/eliot-1.13.0/setup.py --- old/eliot-1.12.0/setup.py 2020-01-23 21:52:58.000000000 +0100 +++ new/eliot-1.13.0/setup.py 2020-12-15 20:09:24.000000000 +0100 @@ -18,10 +18,10 @@ "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Topic :: System :: Logging", @@ -30,7 +30,7 @@ version=versioneer.get_version(), cmdclass=versioneer.get_cmdclass(), description="Logging library that tells you why it happened", - python_requires=">=3.5.3", + python_requires=">=3.6.0", install_requires=[ # Python 3 compatibility: "six", @@ -54,6 +54,7 @@ # Tasteful testing for Python: "testtools", "pytest", + "pytest-xdist", ], "dev": [ # Ensure we can do python_requires correctly: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/eliot-1.12.0/tox.ini new/eliot-1.13.0/tox.ini --- old/eliot-1.12.0/tox.ini 2020-01-23 21:52:58.000000000 +0100 +++ new/eliot-1.13.0/tox.ini 2020-12-15 20:09:24.000000000 +0100 @@ -1,32 +1,32 @@ [tox] -envlist = py35-numpy, py36, py37, pypy3, py38, - py35-twisted-latest, +envlist = py38-numpy, py36, py37, pypy3, py38, py39, + py38-twisted-latest, linters3, sphinx -[travis] +[gh-actions] python = - 3.5: py35-numpy, py35-twisted-latest 3.6: py36 3.7: py37, linters3, sphinx - 3.8: py38 + 3.8: py38, py38-numpy, py38-twisted-latest + 3.9: py39 pypy3: pypy3 [testenv] commands = {envpython} setup.py --version - pip install eliot[test] - {envpython} -m unittest {posargs:discover -v eliot.tests} + pip install .[test] + pip list + {envpython} -m pytest -n 2 ## No Twisted ## -[testenv:py35-numpy] -basepython = python3.5 +[testenv:py38-numpy] +basepython = python3.8 deps = numpy - dask[bag]==1.2.1 + dask[bag] [testenv:py36] basepython = python3.6 -deps = cffi - pyinstaller +deps = [testenv:py37] basepython = python3.7 @@ -38,10 +38,15 @@ [testenv:py38] basepython = python3.8 +deps = cffi + pyinstaller + +[testenv:py39] +basepython = python3.9 deps = -[testenv:py35-twisted-latest] -basepython = python3.5 +[testenv:py38-twisted-latest] +basepython = python3.8 deps = Twisted [testenv:pypy3] @@ -56,7 +61,7 @@ basepython = python3.7 commands = pyflakes eliot - black --check --target-version=py35 eliot + black --check --target-version=py36 eliot [testenv:sphinx] deps = sphinx