Skip to content

Commit

Permalink
context.Context allows pickling.
Browse files Browse the repository at this point in the history
  • Loading branch information
ynikitenko committed Apr 22, 2022
1 parent 71d169a commit a0129d2
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 19 deletions.
30 changes: 15 additions & 15 deletions lena/context/context.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
""":class:`Context` provides a better representation for context."""
from __future__ import print_function

import functools
import json

import lena.core
Expand All @@ -27,20 +26,19 @@ def __init__(self, d=None, formatter=None):
"""Initialize from a dictionary *d* (empty by default).
Representation is defined by the *formatter*.
That must be a callable,
which should accept a dictionary and return a string.
The default is ``json.dumps``.
That must be a callable accepting a dictionary
and returning a string. The default is ``json.dumps``.
All public attributes of a :class:`Context`
can be got or set using dot notation
(for example, *context["data_path"]*
is equal to *context.data_path*).
Only one level of nesting is accessible
using dot notation.
Only one level of nesting is accessible using dot notation.
Tip
---
JSON and Python representations are different.
`JSON <https://docs.python.org/3/library/json.html>`_
and Python representations are different.
In particular, JSON *True* is written as lowercase *true*.
To convert JSON back to Python, use ``json.loads(string)``.
Expand All @@ -51,7 +49,6 @@ def __init__(self, d=None, formatter=None):
An attempt to get a private attribute raises
:exc:`AttributeError`.
"""
# todo: maybe add intersphinx reference to json
if d is None:
d = {}
super(Context, self).__init__(d)
Expand All @@ -63,10 +60,13 @@ def __init__(self, d=None, formatter=None):
)
self._formatter = formatter
else:
self._formatter = lambda s: json.dumps(s, sort_keys=True, indent=4)
# formatter should better be private,
self._formatter = functools.partial(json.dumps,
sort_keys=True, indent=4)
# same, but doesn't allow pickling
# lambda s: json.dumps(s, sort_keys=True, indent=4)
# formatter should be private,
# otherwise it'll mess with other attributes
# self.formatter = pprint.PrettyPrinter(indent=1)
# self._formatter = pprint.PrettyPrinter(indent=1)

def __call__(self, value):
"""Convert *value*'s context to :class:`Context` on the fly.
Expand All @@ -86,12 +86,12 @@ def __call__(self, value):
def __getattr__(self, name):
# we don't implement getting nested attributes,
# because that would require creating proxy objects
# - maybe in the future if needed.
# -- maybe in the future if needed.
if name.startswith('_'):
# this is not LenaAttributeError,
# as it wouldn't be so for other Lena classes
# that don't implement __getattr__
# see comment for Variable
# that don't implement __getattr__ .
# See comment for Variable.
raise AttributeError(name)
try:
return self[name]
Expand Down
2 changes: 0 additions & 2 deletions lena/flow/cache.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
"""Cache (pickle) flow."""
from __future__ import print_function

import sys
import os
import pickle
Expand Down
10 changes: 8 additions & 2 deletions tests/context/test_context.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from __future__ import print_function

import copy
import json
import pickle

import pytest

import lena.core
Expand Down Expand Up @@ -45,3 +45,9 @@ def test_context():
c._aaa = 3
with pytest.raises(AttributeError):
c._aaa

## Context can be pickled
d2 = {"a": "b"}
c2 = Context(d2)
picklestring = pickle.dumps(c2)
assert pickle.loads(picklestring) == c2

0 comments on commit a0129d2

Please sign in to comment.