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,
+)

Reply via email to