Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-structlog for
openSUSE:Factory checked in at 2021-02-19 23:45:01
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-structlog (Old)
and /work/SRC/openSUSE:Factory/.python-structlog.new.28504 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-structlog"
Fri Feb 19 23:45:01 2021 rev:5 rq:873660 version:21.1.0
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-structlog/python-structlog.changes
2021-01-04 19:09:09.435376244 +0100
+++
/work/SRC/openSUSE:Factory/.python-structlog.new.28504/python-structlog.changes
2021-02-19 23:45:42.607389557 +0100
@@ -1,0 +2,11 @@
+Fri Feb 19 08:07:55 UTC 2021 - Michael Vetter <[email protected]>
+
+- Update to 21.1.0:
+ * structlog.threadlocal.wrap_dict() now has a correct type
+ annotation. #290
+ * Fix isolation in structlog.contextvars. #302
+ * The default configuration and loggers are pickleable again. #301
+ * structlog.dev.ConsoleRenderer will now look for a logger_name
+ key if no logger key is set. #295
+
+-------------------------------------------------------------------
Old:
----
20.2.0.tar.gz
New:
----
21.1.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-structlog.spec ++++++
--- /var/tmp/diff_new_pack.jfIIC9/_old 2021-02-19 23:45:43.187390126 +0100
+++ /var/tmp/diff_new_pack.jfIIC9/_new 2021-02-19 23:45:43.191390130 +0100
@@ -20,7 +20,7 @@
# because of acyncio for tests
%define skip_python2 1
Name: python-structlog
-Version: 20.2.0
+Version: 21.1.0
Release: 0
Summary: Structured Logging for Python
License: Apache-2.0 OR MIT
++++++ 20.2.0.tar.gz -> 21.1.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/structlog-20.2.0/.github/CONTRIBUTING.rst
new/structlog-21.1.0/.github/CONTRIBUTING.rst
--- old/structlog-20.2.0/.github/CONTRIBUTING.rst 2020-12-31
12:22:45.000000000 +0100
+++ new/structlog-21.1.0/.github/CONTRIBUTING.rst 2021-02-18
17:02:08.000000000 +0100
@@ -23,6 +23,8 @@
- No contribution is too small!
Please submit as many fixes for typos and grammar bloopers as you can!
- Try to limit each pull request to *one* change only.
+- Since we squash on merge, it's up to you how you handle updates to the main
branch.
+ Whether you prefer to rebase on main or merge main into your branch, do
whatever is more comfortable for you.
- *Always* add tests and docs for your code.
This is a hard rule; patches with missing tests or documentation can't be
merged.
- Make sure your changes pass our CI_.
@@ -67,7 +69,7 @@
- To run the test suite, all you need is a recent tox_.
It will ensure the test suite runs with all dependencies against all Python
versions just as it will in our CI.
- If you lack some Python versions, you can can make it a non-failure using
``tox --skip-missing-interpreters`` (in that case you may want to look into
pyenv_ that makes it very easy to install many different Python versions in
parallel).
+ If you lack some Python versions, you can can make it a non-failure using
``tox --skip-missing-interpreters`` (in that case you may want to look into
asdf_ or pyenv_ that make it very easy to install many different Python
versions in parallel).
- Write `good test docstrings`_.
@@ -182,14 +184,15 @@
.. _`PEP 8`: https://www.python.org/dev/peps/pep-0008/
.. _`PEP 257`: https://www.python.org/dev/peps/pep-0257/
.. _`good test docstrings`: https://jml.io/pages/test-docstrings.html
-.. _`Code of Conduct`:
https://github.com/hynek/structlog/blob/master/.github/CODE_OF_CONDUCT.rst
-.. _changelog: https://github.com/hynek/structlog/blob/master/CHANGELOG.rst
+.. _`Code of Conduct`:
https://github.com/hynek/structlog/blob/main/.github/CODE_OF_CONDUCT.rst
+.. _changelog: https://github.com/hynek/structlog/blob/main/CHANGELOG.rst
.. _`backward compatibility`:
https://www.structlog.org/en/latest/backward-compatibility.html
.. _tox: https://tox.readthedocs.io/
.. _pyenv: https://github.com/pyenv/pyenv
+.. _asdf: https://asdf-vm.com/
.. _reStructuredText:
https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html
.. _semantic newlines:
https://rhodesmill.org/brandon/2012/one-sentence-per-line/
.. _CI: https://github.com/hynek/structlog/actions?query=workflow%3ACI
.. _black: https://github.com/psf/black
.. _pre-commit: https://pre-commit.com/
-.. _isort: https://github.com/timothycrosley/isort
+.. _isort: https://github.com/PyCQA/isort
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/structlog-20.2.0/.github/PULL_REQUEST_TEMPLATE.md
new/structlog-21.1.0/.github/PULL_REQUEST_TEMPLATE.md
--- old/structlog-20.2.0/.github/PULL_REQUEST_TEMPLATE.md 2020-12-31
12:22:45.000000000 +0100
+++ new/structlog-21.1.0/.github/PULL_REQUEST_TEMPLATE.md 2021-02-18
17:02:08.000000000 +0100
@@ -7,8 +7,8 @@
- [ ] Added **tests** for changed code.
- [ ] Updated **documentation** for changed code.
- [ ] New functions/classes have to be added to `docs/api.rst` by hand.
- - [ ] Changed/added classes/methods/functions have appropriate
`versionadded`, `versionchanged`, or `deprecated`
[directives](http://www.sphinx-doc.org/en/stable/markup/para.html#directive-versionadded).
Find the appropriate next version in our
[``__init__.py``](https://github.com/hynek/structlog/blob/master/src/structlog/__init__.py)
file.
+ - [ ] Changed/added classes/methods/functions have appropriate
`versionadded`, `versionchanged`, or `deprecated`
[directives](http://www.sphinx-doc.org/en/stable/markup/para.html#directive-versionadded).
Find the appropriate next version in our
[``__init__.py``](https://github.com/hynek/structlog/blob/main/src/structlog/__init__.py)
file.
- [ ] Documentation in `.rst` files is written using [semantic
newlines](https://rhodesmill.org/brandon/2012/one-sentence-per-line/).
-- [ ] Changes (and possible deprecations) are documented in the
[changelog](https://github.com/hynek/structlog/blob/master/CHANGELOG.rst).
+- [ ] Changes (and possible deprecations) are documented in the
[changelog](https://github.com/hynek/structlog/blob/main/CHANGELOG.rst).
If you have *any* questions to *any* of the points above, just **submit and
ask**! This checklist is here to *help* you, not to deter you from
contributing!
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/structlog-20.2.0/.github/workflows/main.yml
new/structlog-21.1.0/.github/workflows/main.yml
--- old/structlog-20.2.0/.github/workflows/main.yml 2020-12-31
12:22:45.000000000 +0100
+++ new/structlog-21.1.0/.github/workflows/main.yml 2021-02-18
17:02:08.000000000 +0100
@@ -3,9 +3,9 @@
on:
push:
- branches: ["master"]
+ branches: ["main"]
pull_request:
- branches: ["master"]
+ branches: ["main"]
workflow_dispatch:
jobs:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/structlog-20.2.0/.pre-commit-config.yaml
new/structlog-21.1.0/.pre-commit-config.yaml
--- old/structlog-20.2.0/.pre-commit-config.yaml 2020-12-31
12:22:45.000000000 +0100
+++ new/structlog-21.1.0/.pre-commit-config.yaml 2021-02-18
17:02:08.000000000 +0100
@@ -7,7 +7,7 @@
language_version: python3.8
- repo: https://github.com/PyCQA/isort
- rev: 5.6.4
+ rev: 5.7.0
hooks:
- id: isort
additional_dependencies: [toml]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/structlog-20.2.0/CHANGELOG.rst
new/structlog-21.1.0/CHANGELOG.rst
--- old/structlog-20.2.0/CHANGELOG.rst 2020-12-31 12:22:45.000000000 +0100
+++ new/structlog-21.1.0/CHANGELOG.rst 2021-02-18 17:02:08.000000000 +0100
@@ -5,6 +5,39 @@
The third digit is only for regressions.
+21.1.0 (2021-02-18)
+-------------------
+
+
+Backward-incompatible changes:
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+*none*
+
+
+Deprecations:
+^^^^^^^^^^^^^
+
+*none*
+
+
+Changes:
+^^^^^^^^
+
+- ``structlog.threadlocal.wrap_dict()`` now has a correct type annotation.
+ `#290 <https://github.com/hynek/structlog/pull/290>`_
+- Fix isolation in ``structlog.contextvars``.
+ `#302 <https://github.com/hynek/structlog/pull/302>`_
+- The default configuration and loggers are pickleable again.
+ `#301 <https://github.com/hynek/structlog/pull/301>`_
+- ``structlog.dev.ConsoleRenderer`` will now look for a ``logger_name`` key if
no
+ ``logger`` key is set.
+ `#295 <https://github.com/hynek/structlog/pull/295>`_
+
+
+----
+
+
20.2.0 (2020-12-31)
-------------------
@@ -21,6 +54,14 @@
Check out the new chapter on typing for details.
+- The default bound logger (``wrapper_class``) if you don't configure
``structlog`` has changed.
+ It's mostly compatible with the old one but a few uncommon methods like
``log``, ``failure``, or ``err`` don't exist anymore.
+
+ You can regain the old behavior by using
``structlog.configure(wrapper_class=structlog.BoundLogger)``.
+
+ Please note that due to the various interactions between settings, it's
possible that you encounter even more errors.
+ We **strongly** urge you to always configure all possible settings since the
default configuration is *not* covered by our `backward compatibility policy
<https://www.structlog.org/en/stable/backward-compatibility.html>`_.
+
Deprecations:
^^^^^^^^^^^^^
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/structlog-20.2.0/docs/api.rst
new/structlog-21.1.0/docs/api.rst
--- old/structlog-20.2.0/docs/api.rst 2020-12-31 12:22:45.000000000 +0100
+++ new/structlog-21.1.0/docs/api.rst 2021-02-18 17:02:08.000000000 +0100
@@ -71,7 +71,7 @@
.. automodule:: structlog.dev
.. autoclass:: ConsoleRenderer
- :members: get_default_level_styles
+ :members: get_default_level_styles
.. autofunction:: set_exc_info
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/structlog-20.2.0/docs/code_examples/flask_/webapp.py
new/structlog-21.1.0/docs/code_examples/flask_/webapp.py
--- old/structlog-20.2.0/docs/code_examples/flask_/webapp.py 2020-12-31
12:22:45.000000000 +0100
+++ new/structlog-21.1.0/docs/code_examples/flask_/webapp.py 2021-02-18
17:02:08.000000000 +0100
@@ -46,7 +46,6 @@
key_order=["event", "view", "peer"]
),
],
- context_class=structlog.threadlocal.wrap_dict(dict),
logger_factory=structlog.stdlib.LoggerFactory(),
)
app.run()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/structlog-20.2.0/docs/contextvars.rst
new/structlog-21.1.0/docs/contextvars.rst
--- old/structlog-20.2.0/docs/contextvars.rst 2020-12-31 12:22:45.000000000
+0100
+++ new/structlog-21.1.0/docs/contextvars.rst 2021-02-18 17:02:08.000000000
+0100
@@ -38,7 +38,7 @@
>>> configure(
... processors=[
... merge_contextvars,
- ... structlog.processors.KeyValueRenderer(),
+ ... structlog.processors.KeyValueRenderer(key_order=["event", "a"]),
... ]
... )
>>> log = structlog.get_logger()
@@ -50,12 +50,14 @@
>>> # Then use loggers as per normal
>>> # (perhaps by using structlog.get_logger() to create them).
>>> log.msg("hello")
- a=1 b=2 event='hello'
+ event='hello' a=1 b=2
>>> # Use unbind_contextvars to remove a variable from the context
>>> unbind_contextvars("b")
>>> log.msg("world")
- a=1 event='world'
+ event='world' a=1
>>> # And when we clear the threadlocal state again, it goes away.
+ >>> # a=None is printed due to the key_order argument passed to
+ >>> # KeyValueRenderer, but it is NOT present anymore.
>>> clear_contextvars()
>>> log.msg("hi there")
- event='hi there'
+ event='hi there' a=None
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/structlog-20.2.0/docs/getting-started.rst
new/structlog-21.1.0/docs/getting-started.rst
--- old/structlog-20.2.0/docs/getting-started.rst 2020-12-31
12:22:45.000000000 +0100
+++ new/structlog-21.1.0/docs/getting-started.rst 2021-02-18
17:02:08.000000000 +0100
@@ -39,7 +39,7 @@
It should be noted that even in most complex logging setups the example would
still look just like that thanks to `configuration`.
Using the defaults, as above, is equivalent to::
- import loggging
+ import logging
import structlog
structlog.configure(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/structlog-20.2.0/docs/license.rst
new/structlog-21.1.0/docs/license.rst
--- old/structlog-20.2.0/docs/license.rst 2020-12-31 12:22:45.000000000
+0100
+++ new/structlog-21.1.0/docs/license.rst 2021-02-18 17:02:08.000000000
+0100
@@ -8,8 +8,8 @@
The full license texts can be also found in the source code repository:
-- `Apache License 2.0
<https://github.com/hynek/structlog/blob/master/LICENSE.apache2>`_
-- `MIT <https://github.com/hynek/structlog/blob/master/LICENSE.mit>`_
+- `Apache License 2.0
<https://github.com/hynek/structlog/blob/main/LICENSE.apache2>`_
+- `MIT <https://github.com/hynek/structlog/blob/main/LICENSE.mit>`_
.. _authors:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/structlog-20.2.0/pyproject.toml
new/structlog-21.1.0/pyproject.toml
--- old/structlog-20.2.0/pyproject.toml 2020-12-31 12:22:45.000000000 +0100
+++ new/structlog-21.1.0/pyproject.toml 2021-02-18 17:02:08.000000000 +0100
@@ -27,7 +27,7 @@
"pragma: no cover",
"if TYPE_CHECKING:",
"raise NotImplementedError",
- # typing-related code
+ # typing-related code
"^if (False|TYPE_CHECKING):",
": \\.\\.\\.$",
"^ +\\.\\.\\.$",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/structlog-20.2.0/src/structlog/__init__.py
new/structlog-21.1.0/src/structlog/__init__.py
--- old/structlog-20.2.0/src/structlog/__init__.py 2020-12-31
12:22:45.000000000 +0100
+++ new/structlog-21.1.0/src/structlog/__init__.py 2021-02-18
17:02:08.000000000 +0100
@@ -42,7 +42,7 @@
contextvars = None # type: ignore
-__version__ = "20.2.0"
+__version__ = "21.1.0"
__title__ = "structlog"
__description__ = "Structured Logging for Python"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/structlog-20.2.0/src/structlog/_log_levels.py
new/structlog-21.1.0/src/structlog/_log_levels.py
--- old/structlog-20.2.0/src/structlog/_log_levels.py 2020-12-31
12:22:45.000000000 +0100
+++ new/structlog-21.1.0/src/structlog/_log_levels.py 2021-02-18
17:02:08.000000000 +0100
@@ -94,6 +94,18 @@
values.
.. versionadded:: 20.2.0
+ .. versionchanged:: 21.1.0 The returned loggers are now pickleable.
+ """
+
+ return _LEVEL_TO_FILTERING_LOGGER[min_level]
+
+
+def _make_filtering_bound_logger(min_level: int) -> Type[FilteringBoundLogger]:
+ """
+ Create a new `FilteringBoundLogger` that only logs *min_level* or higher.
+
+ The logger is optimized such that log levels below *min_level* only consist
+ of a ``return None``.
"""
def make_method(level: int) -> Callable[..., Any]:
@@ -124,3 +136,21 @@
(BoundLoggerBase,),
meths,
)
+
+
+# Pre-create all possible filters to make them pickleable.
+BoundLoggerFilteringAtNotset = _make_filtering_bound_logger(NOTSET)
+BoundLoggerFilteringAtDebug = _make_filtering_bound_logger(DEBUG)
+BoundLoggerFilteringAtInfo = _make_filtering_bound_logger(INFO)
+BoundLoggerFilteringAtWarning = _make_filtering_bound_logger(WARNING)
+BoundLoggerFilteringAtError = _make_filtering_bound_logger(ERROR)
+BoundLoggerFilteringAtCritical = _make_filtering_bound_logger(CRITICAL)
+
+_LEVEL_TO_FILTERING_LOGGER = {
+ CRITICAL: BoundLoggerFilteringAtCritical,
+ ERROR: BoundLoggerFilteringAtError,
+ WARNING: BoundLoggerFilteringAtWarning,
+ INFO: BoundLoggerFilteringAtInfo,
+ DEBUG: BoundLoggerFilteringAtDebug,
+ NOTSET: BoundLoggerFilteringAtNotset,
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/structlog-20.2.0/src/structlog/contextvars.py
new/structlog-21.1.0/src/structlog/contextvars.py
--- old/structlog-20.2.0/src/structlog/contextvars.py 2020-12-31
12:22:45.000000000 +0100
+++ new/structlog-21.1.0/src/structlog/contextvars.py 2021-02-18
17:02:08.000000000 +0100
@@ -7,6 +7,9 @@
Python 3.7 as :mod:`contextvars`.
.. versionadded:: 20.1.0
+.. versionchanged:: 21.1.0
+ Reimplemented without using a single dict as context carrier for improved
+ isolation. Every key-value pair is a separate `contextvars.ContextVar` now.
See :doc:`contextvars`.
"""
@@ -15,17 +18,16 @@
from typing import Any, Dict
-from .types import Context, WrappedLogger
+from .types import EventDict, WrappedLogger
-_CONTEXT: contextvars.ContextVar[Dict[str, Any]] = contextvars.ContextVar(
- "structlog_context"
-)
+STRUCTLOG_KEY_PREFIX = "structlog_"
+_CONTEXT_VARS: Dict[str, contextvars.ContextVar[Any]] = {}
def merge_contextvars(
- logger: WrappedLogger, method_name: str, event_dict: Dict[str, Any]
-) -> Context:
+ logger: WrappedLogger, method_name: str, event_dict: EventDict
+) -> EventDict:
"""
A processor that merges in a global (context-local) context.
@@ -33,11 +35,15 @@
context-local context is included in all log calls.
.. versionadded:: 20.1.0
+ .. versionchanged:: 21.1.0 See toplevel note.
"""
- ctx = _get_context().copy()
- ctx.update(event_dict)
+ ctx = contextvars.copy_context()
- return ctx
+ for k in ctx:
+ if k.name.startswith(STRUCTLOG_KEY_PREFIX) and ctx[k] is not Ellipsis:
+ event_dict.setdefault(k.name[len(STRUCTLOG_KEY_PREFIX) :], ctx[k])
+
+ return event_dict
def clear_contextvars() -> None:
@@ -48,9 +54,12 @@
handling code.
.. versionadded:: 20.1.0
+ .. versionchanged:: 21.1.0 See toplevel note.
"""
- ctx = _get_context()
- ctx.clear()
+ ctx = contextvars.copy_context()
+ for k in ctx:
+ if k.name.startswith(STRUCTLOG_KEY_PREFIX):
+ k.set(Ellipsis)
def bind_contextvars(**kw: Any) -> None:
@@ -61,8 +70,17 @@
context to be global (context-local).
.. versionadded:: 20.1.0
+ .. versionchanged:: 21.1.0 See toplevel note.
"""
- _get_context().update(kw)
+ for k, v in kw.items():
+ structlog_k = f"{STRUCTLOG_KEY_PREFIX}{k}"
+ try:
+ var = _CONTEXT_VARS[structlog_k]
+ except KeyError:
+ var = contextvars.ContextVar(structlog_k, default=Ellipsis)
+ _CONTEXT_VARS[structlog_k] = var
+
+ var.set(v)
def unbind_contextvars(*keys: str) -> None:
@@ -73,15 +91,9 @@
remove keys from a global (context-local) context.
.. versionadded:: 20.1.0
+ .. versionchanged:: 21.1.0 See toplevel note.
"""
- ctx = _get_context()
- for key in keys:
- ctx.pop(key, None)
-
-
-def _get_context() -> Context:
- try:
- return _CONTEXT.get()
- except LookupError:
- _CONTEXT.set({})
- return _CONTEXT.get()
+ for k in keys:
+ structlog_k = f"{STRUCTLOG_KEY_PREFIX}{k}"
+ if structlog_k in _CONTEXT_VARS:
+ _CONTEXT_VARS[structlog_k].set(Ellipsis)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/structlog-20.2.0/src/structlog/dev.py
new/structlog-21.1.0/src/structlog/dev.py
--- old/structlog-20.2.0/src/structlog/dev.py 2020-12-31 12:22:45.000000000
+0100
+++ new/structlog-21.1.0/src/structlog/dev.py 2021-02-18 17:02:08.000000000
+0100
@@ -123,7 +123,8 @@
the log line.
:param pad_event: Pad the event to this many characters.
- :param colors: Use colors for a nicer output.
+ :param colors: Use colors for a nicer output. The default is True if
+ colorama is present, otherwise False.
:param force_colors: Force colors even for non-tty destinations.
Use this option if your logs are stored in a file that is meant
to be streamed to the console.
@@ -152,6 +153,8 @@
.. versionchanged:: 19.2 Can be pickled now.
.. versionchanged:: 20.1 ``colorama`` does not initialize lazily on Windows
anymore because it breaks rendering.
+ .. versionchanged: 21.1 It is additionally possible to set the logger name
+ using the ``logger_name`` key in the ``event_dict``.
"""
def __init__(
@@ -254,6 +257,9 @@
sio.write(self._styles.bright + event)
logger_name = event_dict.pop("logger", None)
+ if logger_name is None:
+ logger_name = event_dict.pop("logger_name", None)
+
if logger_name is not None:
sio.write(
"["
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/structlog-20.2.0/src/structlog/stdlib.py
new/structlog-21.1.0/src/structlog/stdlib.py
--- old/structlog-20.2.0/src/structlog/stdlib.py 2020-12-31
12:22:45.000000000 +0100
+++ new/structlog-21.1.0/src/structlog/stdlib.py 2021-02-18
17:02:08.000000000 +0100
@@ -34,7 +34,7 @@
try:
- from . import contextvars
+ import contextvars
except ImportError:
contextvars = None # type: ignore
@@ -380,6 +380,7 @@
It is useful to be able to log synchronously occasionally.
.. versionadded:: 20.2.0
+ .. versionchanged:: 20.2.0 fix _dispatch_to_sync contextvars usage
"""
__slots__ = ["sync_bl", "_loop"]
@@ -474,11 +475,10 @@
"""
Merge contextvars and log using the sync logger in a thread pool.
"""
- ctx = contextvars._get_context().copy()
- ctx.update(kw)
+ ctx = contextvars.copy_context()
await self._loop.run_in_executor(
- self._executor, partial(meth, event, *args, **ctx)
+ self._executor, partial(ctx.run, partial(meth, event, *args, **kw))
)
async def debug(self, event: str, *args: Any, **kw: Any) -> None:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/structlog-20.2.0/src/structlog/threadlocal.py
new/structlog-21.1.0/src/structlog/threadlocal.py
--- old/structlog-20.2.0/src/structlog/threadlocal.py 2020-12-31
12:22:45.000000000 +0100
+++ new/structlog-21.1.0/src/structlog/threadlocal.py 2021-02-18
17:02:08.000000000 +0100
@@ -35,7 +35,7 @@
ThreadLocal = _determine_threadlocal()
-def wrap_dict(dict_class: Type[EventDict]) -> Type[EventDict]:
+def wrap_dict(dict_class: Type[Context]) -> Type[Context]:
"""
Wrap a dict-like class and return the resulting class.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/structlog-20.2.0/src/structlog/twisted.py
new/structlog-21.1.0/src/structlog/twisted.py
--- old/structlog-20.2.0/src/structlog/twisted.py 2020-12-31
12:22:45.000000000 +0100
+++ new/structlog-21.1.0/src/structlog/twisted.py 2021-02-18
17:02:08.000000000 +0100
@@ -89,9 +89,7 @@
_why = eventDict.pop("_why", None)
event = eventDict.pop("event", None)
- if isinstance(_stuff, _FAIL_TYPES) and isinstance( # type: ignore
- event, _FAIL_TYPES
- ):
+ if isinstance(_stuff, _FAIL_TYPES) and isinstance(event, _FAIL_TYPES):
raise ValueError("Both _stuff and event contain an Exception/Failure.")
# `log.err('event', _why='alsoEvent')` is ambiguous.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/structlog-20.2.0/tests/test_config.py
new/structlog-21.1.0/tests/test_config.py
--- old/structlog-20.2.0/tests/test_config.py 2020-12-31 12:22:45.000000000
+0100
+++ new/structlog-21.1.0/tests/test_config.py 2021-02-18 17:02:08.000000000
+0100
@@ -28,8 +28,8 @@
)
[email protected]
-def proxy():
[email protected](name="proxy")
+def _proxy():
"""
Returns a BoundLoggerLazyProxy constructed w/o parameters & None as logger.
"""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/structlog-20.2.0/tests/test_contextvars.py
new/structlog-21.1.0/tests/test_contextvars.py
--- old/structlog-20.2.0/tests/test_contextvars.py 2020-12-31
12:22:45.000000000 +0100
+++ new/structlog-21.1.0/tests/test_contextvars.py 2021-02-18
17:02:08.000000000 +0100
@@ -2,6 +2,9 @@
# 2.0, and the MIT License. See the LICENSE file in the root of this
# repository for complete details.
+import asyncio
+import secrets
+
import pytest
from structlog.contextvars import (
@@ -54,11 +57,11 @@
async def coro():
bind_contextvars(a=1)
- await event_loop.create_task(nested_coro())
- return merge_contextvars(None, None, {"b": 2})
+ return await event_loop.create_task(nested_coro())
async def nested_coro():
bind_contextvars(c=3)
+ return merge_contextvars(None, None, {"b": 2})
assert {"a": 1, "b": 2, "c": 3} == await event_loop.create_task(coro())
@@ -110,7 +113,7 @@
assert {} == await event_loop.create_task(coro())
- async def test_undbind(self, event_loop):
+ async def test_unbind(self, event_loop):
"""
Unbinding a previously bound variable causes it to be removed from the
result of merge_contextvars.
@@ -123,13 +126,49 @@
assert {"b": 2} == await event_loop.create_task(coro())
- async def test_undbind_not_bound(self, event_loop):
+ async def test_unbind_not_bound(self, event_loop):
"""
Unbinding a not bound variable causes doesn't raise an exception.
"""
async def coro():
- unbind_contextvars("a")
+ # Since unbinding means "setting to Ellipsis", we have to make
+ # some effort to ensure that the ContextVar never existed.
+ unbind_contextvars("a" + secrets.token_hex())
+
return merge_contextvars(None, None, {"b": 2})
assert {"b": 2} == await event_loop.create_task(coro())
+
+ async def test_parallel_binds(self, event_loop):
+ """
+ Binding a variable causes it to be included in the result of
+ merge_contextvars.
+ """
+
+ coro1_bind = asyncio.Event()
+ coro2_bind = asyncio.Event()
+
+ bind_contextvars(c=3)
+
+ async def coro1():
+ bind_contextvars(a=1)
+
+ coro1_bind.set()
+ await coro2_bind.wait()
+
+ return merge_contextvars(None, None, {"b": 2})
+
+ async def coro2():
+ bind_contextvars(a=2)
+
+ await coro1_bind.wait()
+ coro2_bind.set()
+
+ return merge_contextvars(None, None, {"b": 2})
+
+ coro1_task = event_loop.create_task(coro1())
+ coro2_task = event_loop.create_task(coro2())
+
+ assert {"a": 1, "b": 2, "c": 3} == await coro1_task
+ assert {"a": 2, "b": 2, "c": 3} == await coro2_task
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/structlog-20.2.0/tests/test_dev.py
new/structlog-21.1.0/tests/test_dev.py
--- old/structlog-20.2.0/tests/test_dev.py 2020-12-31 12:22:45.000000000
+0100
+++ new/structlog-21.1.0/tests/test_dev.py 2021-02-18 17:02:08.000000000
+0100
@@ -23,25 +23,25 @@
assert len("test") == len(dev._pad("test", 2))
[email protected]
-def cr():
[email protected](name="cr")
+def _cr():
return dev.ConsoleRenderer(colors=dev._has_colorama)
[email protected]
-def styles(cr):
[email protected](name="styles")
+def _styles(cr):
return cr._styles
[email protected]
-def padded(styles):
[email protected](name="padded")
+def _padded(styles):
return (
styles.bright + dev._pad("test", dev._EVENT_WIDTH) + styles.reset + " "
)
[email protected]
-def unpadded(styles):
[email protected](name="unpadded")
+def _unpadded(styles):
return styles.bright + "test" + styles.reset
@@ -94,16 +94,22 @@
None, None, {"event": "test", "level": "critical", "foo": "bar"}
)
- # fmt: off
assert (
- "[" + dev.RED + styles.bright +
- dev._pad("critical", cr._longest_level) +
- styles.reset + "] " +
- padded +
- styles.kv_key + "foo" + styles.reset + "=" +
- styles.kv_value + "bar" + styles.reset
+ "["
+ + dev.RED
+ + styles.bright
+ + dev._pad("critical", cr._longest_level)
+ + styles.reset
+ + "] "
+ + padded
+ + styles.kv_key
+ + "foo"
+ + styles.reset
+ + "="
+ + styles.kv_value
+ + "bar"
+ + styles.reset
) == rv
- # fmt: on
def test_init_accepts_overriding_levels(self, styles, padded):
"""
@@ -122,16 +128,22 @@
None, None, {"event": "test", "level": "MY_OH_MY", "foo": "bar"}
)
- # fmt: off
assert (
- "[" + dev.RED + styles.bright +
- dev._pad("MY_OH_MY", cr._longest_level) +
- styles.reset + "] " +
- padded +
- styles.kv_key + "foo" + styles.reset + "=" +
- styles.kv_value + "bar" + styles.reset
+ "["
+ + dev.RED
+ + styles.bright
+ + dev._pad("MY_OH_MY", cr._longest_level)
+ + styles.reset
+ + "] "
+ + padded
+ + styles.kv_key
+ + "foo"
+ + styles.reset
+ + "="
+ + styles.kv_value
+ + "bar"
+ + styles.reset
) == rv
- # fmt: on
def test_logger_name(self, cr, styles, padded):
"""
@@ -139,14 +151,29 @@
"""
rv = cr(None, None, {"event": "test", "logger": "some_module"})
- # fmt: off
assert (
- padded +
- "[" + dev.BLUE + styles.bright +
- "some_module" +
- styles.reset + "] "
+ padded
+ + "["
+ + dev.BLUE
+ + styles.bright
+ + "some_module"
+ + styles.reset
+ + "] "
) == rv
- # fmt: on
+
+ def test_logger_name_name(self, cr, padded, styles):
+ """
+ It's possible to set the logger name using a "logger_name" key.
+ """
+ assert (
+ padded
+ + "["
+ + dev.BLUE
+ + styles.bright
+ + "yolo"
+ + styles.reset
+ + "] "
+ ) == cr(None, None, {"event": "test", "logger_name": "yolo"})
def test_key_values(self, cr, styles, padded):
"""
@@ -154,17 +181,24 @@
"""
rv = cr(None, None, {"event": "test", "key": "value", "foo": "bar"})
- # fmt: off
assert (
- padded +
- styles.kv_key + "foo" + styles.reset + "=" +
- styles.kv_value + "bar" +
- styles.reset + " " +
- styles.kv_key + "key" + styles.reset + "=" +
- styles.kv_value + "value" +
- styles.reset
+ padded
+ + styles.kv_key
+ + "foo"
+ + styles.reset
+ + "="
+ + styles.kv_value
+ + "bar"
+ + styles.reset
+ + " "
+ + styles.kv_key
+ + "key"
+ + styles.reset
+ + "="
+ + styles.kv_value
+ + "value"
+ + styles.reset
) == rv
- # fmt: on
def test_exception(self, cr, padded):
"""
@@ -193,15 +227,19 @@
None, None, {"event": "test", "foo": "bar"}
)
- # fmt: off
assert (
- styles.bright +
- dev._pad("test", 42) +
- styles.reset + " " +
- styles.kv_key + "foo" + styles.reset + "=" +
- styles.kv_value + "bar" + styles.reset
+ styles.bright
+ + dev._pad("test", 42)
+ + styles.reset
+ + " "
+ + styles.kv_key
+ + "foo"
+ + styles.reset
+ + "="
+ + styles.kv_value
+ + "bar"
+ + styles.reset
) == rv
- # fmt: on
def test_everything(self, cr, styles, padded):
"""
@@ -225,26 +263,46 @@
},
)
- # fmt: off
assert (
- styles.timestamp + "13:13" + styles.reset +
- " [" + styles.level_error + styles.bright +
- dev._pad("error", cr._longest_level) +
- styles.reset + "] " +
- padded +
- "[" + dev.BLUE + styles.bright +
- "some_module" +
- styles.reset + "] " +
- styles.kv_key + "foo" + styles.reset + "=" +
- styles.kv_value + "bar" +
- styles.reset + " " +
- styles.kv_key + "key" + styles.reset + "=" +
- styles.kv_value + "value" +
- styles.reset +
- "\n" + stack + "\n\n" + "=" * 79 + "\n" +
- "\n" + exc
+ styles.timestamp
+ + "13:13"
+ + styles.reset
+ + " ["
+ + styles.level_error
+ + styles.bright
+ + dev._pad("error", cr._longest_level)
+ + styles.reset
+ + "] "
+ + padded
+ + "["
+ + dev.BLUE
+ + styles.bright
+ + "some_module"
+ + styles.reset
+ + "] "
+ + styles.kv_key
+ + "foo"
+ + styles.reset
+ + "="
+ + styles.kv_value
+ + "bar"
+ + styles.reset
+ + " "
+ + styles.kv_key
+ + "key"
+ + styles.reset
+ + "="
+ + styles.kv_value
+ + "value"
+ + styles.reset
+ + "\n"
+ + stack
+ + "\n\n"
+ + "=" * 79
+ + "\n"
+ + "\n"
+ + exc
) == rv
- # fmt: on
def test_colorama_colors_false(self):
"""
@@ -271,16 +329,22 @@
None, None, {"event": "test", "level": "critical", "foo": "bar"}
)
- # fmt: off
assert (
- "[" + dev.RED + styles.bright +
- dev._pad("critical", cr._longest_level) +
- styles.reset + "] " +
- padded +
- styles.kv_key + "foo" + styles.reset + "=" +
- styles.kv_value + "bar" + styles.reset
+ "["
+ + dev.RED
+ + styles.bright
+ + dev._pad("critical", cr._longest_level)
+ + styles.reset
+ + "] "
+ + padded
+ + styles.kv_key
+ + "foo"
+ + styles.reset
+ + "="
+ + styles.kv_value
+ + "bar"
+ + styles.reset
) == rv
- # fmt: on
assert not dev._has_colorama or dev._ColorfulStyles is cr._styles
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/structlog-20.2.0/tests/test_log_levels.py
new/structlog-21.1.0/tests/test_log_levels.py
--- old/structlog-20.2.0/tests/test_log_levels.py 2020-12-31
12:22:45.000000000 +0100
+++ new/structlog-21.1.0/tests/test_log_levels.py 2021-02-18
17:02:08.000000000 +0100
@@ -3,10 +3,12 @@
# repository for complete details.
import logging
+import pickle
import pytest
from structlog import make_filtering_bound_logger
+from structlog._log_levels import _LEVEL_TO_NAME
from structlog.testing import CapturingLogger
@@ -53,3 +55,12 @@
bl.exception("boom", exc_info=42)
assert [("error", (), {"event": "boom", "exc_info": 42})]
+
+ @pytest.mark.parametrize("level", tuple(_LEVEL_TO_NAME.keys()))
+ def test_pickle(self, level):
+ """
+ FilteringBoundLogger are pickleable.
+ """
+ bl = make_filtering_bound_logger(level)
+
+ assert bl == pickle.loads(pickle.dumps(bl))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/structlog-20.2.0/tox.ini new/structlog-21.1.0/tox.ini
--- old/structlog-20.2.0/tox.ini 2020-12-31 12:22:45.000000000 +0100
+++ new/structlog-21.1.0/tox.ini 2021-02-18 17:02:08.000000000 +0100
@@ -1,3 +1,6 @@
+[flake8]
+ignore = E203,W503,W504
+
# Keep docs in sync with docs env and .readthedocs.yml.
[gh-actions]
python =
@@ -9,7 +12,8 @@
[tox]
-envlist =
lint,mypy,{py36,py37,py38,py39,pypy3}-threads,{py38,py39,pypy3}-greenlets,py38-colorama,docs,pypi-description,manifest,coverage-report
+# Currently, pypy3 is broken on macOS. Since we don't need it for coverage, we
only test it in CI.
+envlist =
lint,mypy,{py36,py37,py38,py39}-threads,{py38,py39}-greenlets,py38-colorama,docs,pypi-description,manifest,coverage-report
isolated_build = True
@@ -97,6 +101,8 @@
basepython = python3.8
deps = coverage[toml]
skip_install = true
+parallel_show_output = true
+depends = {py36,py37,py38,py39}-threads,{py38,py39}-greenlets,py38-colorama
commands =
coverage combine
coverage report
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/structlog-20.2.0/typing_examples.py
new/structlog-21.1.0/typing_examples.py
--- old/structlog-20.2.0/typing_examples.py 2020-12-31 12:22:45.000000000
+0100
+++ new/structlog-21.1.0/typing_examples.py 2021-02-18 17:02:08.000000000
+0100
@@ -187,3 +187,24 @@
wrapper_class=structlog.stdlib.AsyncBoundLogger,
cache_logger_on_first_use=True,
)
+
+# Regression test for
+# https://github.com/wemake-services/wemake-django-template/
+structlog.configure(
+ processors=[
+ structlog.stdlib.filter_by_level,
+ structlog.processors.TimeStamper(fmt="iso"),
+ structlog.stdlib.add_logger_name,
+ structlog.stdlib.add_log_level,
+ structlog.stdlib.PositionalArgumentsFormatter(),
+ structlog.processors.StackInfoRenderer(),
+ structlog.processors.format_exc_info,
+ structlog.processors.UnicodeDecoder(),
+ structlog.processors.ExceptionPrettyPrinter(),
+ structlog.stdlib.ProcessorFormatter.wrap_for_formatter,
+ ],
+ context_class=structlog.threadlocal.wrap_dict(dict),
+ logger_factory=structlog.stdlib.LoggerFactory(),
+ wrapper_class=structlog.stdlib.BoundLogger,
+ cache_logger_on_first_use=True,
+)