-
-
Notifications
You must be signed in to change notification settings - Fork 629
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2707 from marshmallow-code/context
Use a context variable to pass Schema context
- Loading branch information
Showing
17 changed files
with
480 additions
and
305 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
Context (experimental) | ||
====================== | ||
|
||
.. automodule:: marshmallow.experimental.context | ||
:members: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
"""Experimental features. | ||
The features in this subpackage are experimental. Breaking changes may be | ||
introduced in minor marshmallow versions. | ||
""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
"""Helper API for setting serialization/deserialization context. | ||
Example usage: | ||
.. code-block:: python | ||
import typing | ||
from marshmallow import Schema, fields | ||
from marshmallow.experimental.context import Context | ||
class UserContext(typing.TypedDict): | ||
suffix: str | ||
UserSchemaContext = Context[UserContext] | ||
class UserSchema(Schema): | ||
name_suffixed = fields.Function( | ||
lambda user: user["name"] + UserSchemaContext.get()["suffix"] | ||
) | ||
with UserSchemaContext({"suffix": "bar"}): | ||
print(UserSchema().dump({"name": "foo"})) | ||
# {'name_suffixed': 'foobar'} | ||
""" | ||
|
||
import contextlib | ||
import contextvars | ||
import typing | ||
|
||
_T = typing.TypeVar("_T") | ||
_CURRENT_CONTEXT: contextvars.ContextVar = contextvars.ContextVar("context") | ||
|
||
|
||
class Context(contextlib.AbstractContextManager, typing.Generic[_T]): | ||
"""Context manager for setting and retrieving context.""" | ||
|
||
def __init__(self, context: _T) -> None: | ||
self.context = context | ||
self.token: contextvars.Token | None = None | ||
|
||
def __enter__(self) -> None: | ||
self.token = _CURRENT_CONTEXT.set(self.context) | ||
|
||
def __exit__(self, *args, **kwargs) -> None: | ||
_CURRENT_CONTEXT.reset(typing.cast(contextvars.Token, self.token)) | ||
|
||
@classmethod | ||
def get(cls, default=...) -> _T: | ||
"""Get the current context. | ||
:param default: Default value to return if no context is set. | ||
If not provided and no context is set, a :exc:`LookupError` is raised. | ||
""" | ||
if default is not ...: | ||
return _CURRENT_CONTEXT.get(default) | ||
return _CURRENT_CONTEXT.get() |
Oops, something went wrong.