Skip to content

Commit 58e672f

Browse files
committed
* Now run subset and clean the eval_env after
removing bare funcalls * Had some straggling tuples * Altered test so that stateful_transforms won't be saved in eval_env
1 parent 8bfbafd commit 58e672f

19 files changed

+25
-47
lines changed

patsy/contrasts.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,13 @@ def _repr_pretty_(self, p, cycle):
4949

5050

5151
def __getstate__(self):
52-
return (0, self.matrix, self.column_suffixes)
52+
return {'version': 0, 'matrix': self.matrix,
53+
'column_suffixes': self.column_suffixes}
5354

5455
def __setstate__(self, pickle):
55-
version, matrix, column_suffixes = pickle
56-
check_pickle_version(version, 0, name=self.__class__.__name__)
57-
self.matrix = matrix
58-
self.column_suffixes = column_suffixes
56+
check_pickle_version(pickle['version'], 0, name=self.__class__.__name__)
57+
self.matrix = pickle['matrix']
58+
self.column_suffixes = pickle['column_suffixes']
5959

6060
def __eq__(self, other):
6161
if self.column_suffixes != other.column_suffixes:

patsy/eval.py

Lines changed: 20 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
from patsy.tokens import (pretty_untokenize, normalize_token_spacing,
2626
python_tokenize)
2727
from patsy.compat import call_and_wrap_exc
28+
from nose.tools import assert_raises
2829

2930
def _all_future_flags():
3031
flags = 0
@@ -71,13 +72,8 @@ def get(self, key, default=None):
7172
def __repr__(self):
7273
return "%s(%r)" % (self.__class__.__name__, self._dicts)
7374

74-
def __getstate__(self):
75-
return (0, self._dicts)
75+
__getstate__ = no_pickling
7676

77-
def __setstate__(self, pickle):
78-
version, dicts = pickle
79-
check_pickle_version(version, 0, name=self.__class__.__name__)
80-
self._dicts = dicts
8177

8278
def test_VarLookupDict():
8379
d1 = {"a": 1}
@@ -262,27 +258,15 @@ def __hash__(self):
262258
tuple(self._namespace_ids())))
263259

264260
def __getstate__(self):
265-
self.clean()
261+
# self.clean()
266262
namespaces = self._namespaces
267263
namespaces = _replace_un_pickleable(namespaces)
268-
return (0, namespaces, self.flags)
264+
return {'version': 0, 'namespaces': namespaces, 'flags': self.flags}
269265

270266
def __setstate__(self, pickle):
271-
version, namespaces, flags = pickle
272-
check_pickle_version(version, 0, self.__class__.__name__)
273-
self.flags = flags
274-
self._namespaces = _return_un_pickleable(namespaces)
275-
276-
def clean(self):
277-
"""The EvalEnvironment doesn't need the stateful transformation
278-
functions once the design matrix has been built. This will delete
279-
it. Called by __getstate__ to prepare for pickling."""
280-
namespaces = []
281-
for namespace in self._namespaces:
282-
ns = {key: namespace[key] for key in six.iterkeys(namespace) if not
283-
hasattr(namespace[key], '__patsy_stateful_transform__')}
284-
namespaces.append(ns)
285-
self._namespaces = namespaces
267+
check_pickle_version(pickle['version'], 0, self.__class__.__name__)
268+
self.flags = pickle['flags']
269+
self._namespaces = _return_un_pickleable(pickle['namespaces'])
286270

287271

288272
class ObjectHolder(object):
@@ -576,10 +560,6 @@ def memorize_passes_needed(self, state, eval_env):
576560

577561
eval_env = eval_env.with_outer_namespace(_builtins_dict)
578562
env_namespace = eval_env.namespace
579-
subset_names = [name for name in ast_names(self.code)
580-
if name in env_namespace]
581-
eval_env = eval_env.subset(subset_names)
582-
state["eval_env"] = eval_env
583563

584564
# example code: == "2 * center(x)"
585565
i = [0]
@@ -596,6 +576,12 @@ def new_name_maker(token):
596576
# example eval_code: == "2 * _patsy_stobj0__center__.transform(x)"
597577
eval_code = replace_bare_funcalls(self.code, new_name_maker)
598578
state["eval_code"] = eval_code
579+
580+
subset_names = [name for name in ast_names(eval_code)
581+
if name in env_namespace]
582+
eval_env = eval_env.subset(subset_names)
583+
state["eval_env"] = eval_env
584+
599585
# paranoia: verify that none of our new names appeared anywhere in the
600586
# original code
601587
if has_bare_variable_reference(state["transforms"], self.code):
@@ -716,7 +702,10 @@ def test_EvalFactor_memorize_passes_needed():
716702
print(state)
717703
assert passes == 2
718704
for name in ["foo", "bar", "quux"]:
719-
assert state["eval_env"].namespace[name] is locals()[name]
705+
# name should be locally defined, but since its a stateful_transform,
706+
# its unnecessary to keep it in eval_env
707+
assert name in locals()
708+
assert_raises(KeyError, state["eval_env"].namespace.__getitem__, name)
720709
for name in ["w", "x", "y", "z", "e", "state"]:
721710
assert name not in state["eval_env"].namespace
722711
assert state["transforms"] == {"_patsy_stobj0__foo__": "FOO-OBJ",
@@ -772,7 +761,9 @@ def test_EvalFactor_end_to_end():
772761
print(passes)
773762
print(state)
774763
assert passes == 2
775-
assert state["eval_env"].namespace["foo"] is foo
764+
# We don't want to save the stateful transforms in the eval_env, actually.
765+
# Just
766+
assert_raises(KeyError, state["eval_env"].namespace.__getitem__, 'foo')
776767
for name in ["x", "y", "e", "state"]:
777768
assert name not in state["eval_env"].namespace
778769
import numpy as np

patsy/test_pickling.py

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -42,19 +42,6 @@ def _unwrap_stateful_function(function, *args, **kwargs):
4242

4343
pickling_testcases = {
4444
"evalfactor_simple": EvalFactor("a+b"),
45-
"varlookupdict_simple": VarLookupDict([{"a": 1}, {"a": 2, "b": 3}]),
46-
"evalenv_simple": EvalEnvironment([{"a": 1}]),
47-
"evalenv_transform_center": EvalEnvironment([{'center': center}]),
48-
"evalenv_transform_scale": EvalEnvironment([{'scale': scale}]),
49-
"evalenv_transform_standardize": EvalEnvironment([{
50-
'standardize': standardize
51-
}]),
52-
"evalenv_transform_categorical": EvalEnvironment([{'C': C}]),
53-
"evalenv_transform_bs": EvalEnvironment([{'cs': bs}]),
54-
"evalenv_transform_te": EvalEnvironment([{'te': te}]),
55-
"evalenv_transform_cr": EvalEnvironment([{'cs': cr}]),
56-
"evalenv_transform_cc": EvalEnvironment([{'cc': cc}]),
57-
"evalenv_pickle": EvalEnvironment([{'np': np}]),
5845
"term": Term([1, 2, 1]),
5946
"contrast_matrix": ContrastMatrix([[1, 0], [0, 1]], ["a", "b"]),
6047
"subterm_info": si,
55 Bytes
Binary file not shown.
-128 Bytes
Binary file not shown.
-67 Bytes
Binary file not shown.
-60 Bytes
Binary file not shown.
-89 Bytes
Binary file not shown.
-60 Bytes
Binary file not shown.
-60 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)