From 019094db05bbf124010f2c3346978a666ff4349e Mon Sep 17 00:00:00 2001 From: thequackdaddy Date: Thu, 6 Apr 2017 20:15:02 -0500 Subject: [PATCH] Clean the EvalEnvironment before pickling to removing patsy's stateful transforms which have different names/qualnames from expected. --- patsy/eval.py | 31 +++++++++++++++++- patsy/mgcv_cubic_splines.py | 6 ---- patsy/splines.py | 2 -- patsy/state.py | 6 ---- .../0.5/evalenv_transform_bs.pickle | Bin 89 -> 60 bytes .../0.5/evalenv_transform_cc.pickle | Bin 97 -> 60 bytes .../0.5/evalenv_transform_center.pickle | Bin 88 -> 60 bytes .../0.5/evalenv_transform_cr.pickle | Bin 100 -> 60 bytes .../0.5/evalenv_transform_scale.pickle | Bin 87 -> 60 bytes .../0.5/evalenv_transform_standardize.pickle | Bin 99 -> 60 bytes .../0.5/evalenv_transform_te.pickle | Bin 97 -> 60 bytes 11 files changed, 30 insertions(+), 15 deletions(-) diff --git a/patsy/eval.py b/patsy/eval.py index a0d5913..c853988 100644 --- a/patsy/eval.py +++ b/patsy/eval.py @@ -262,6 +262,7 @@ def __hash__(self): tuple(self._namespace_ids()))) def __getstate__(self): + self.clean() namespaces = self._namespaces namespaces = _replace_un_pickleable(namespaces) return (0, namespaces, self.flags) @@ -272,6 +273,17 @@ def __setstate__(self, pickle): self.flags = flags self._namespaces = _return_un_pickleable(namespaces) + def clean(self): + """The EvalEnvironment doesn't need the stateful transformation + functions once the design matrix has been built. This will delete + it. Called by __getstate__ to prepare for pickling.""" + namespaces = [] + for namespace in self._namespaces: + ns = {key: namespace[key] for key in six.iterkeys(namespace) if not + hasattr(namespace[key], '__patsy_stateful_transform__')} + namespaces.append(ns) + self._namespaces = namespaces + class ObjectHolder(object): def __init__(self, kind, module, name): @@ -489,7 +501,23 @@ def test_EvalEnvironment_eq(): capture_local_env = lambda: EvalEnvironment.capture(0) env3 = capture_local_env() env4 = capture_local_env() - assert env3 != env4 # This fails... + assert env3 != env4 + + +def test_EvalEnvironment_clean(): + from patsy.state import center, standardize + from patsy.splines import bs + + env1 = EvalEnvironment([{'center': center}]) + env2 = EvalEnvironment([{'standardize': standardize}]) + env3 = EvalEnvironment([{'bs': bs}]) + env1.clean() + env2.clean() + env3.clean() + + env1._namespaces == [{}] + env2._namespaces == [{}] + env3._namespaces == [{}] _builtins_dict = {} six.exec_("from patsy.builtins import *", {}, _builtins_dict) @@ -650,6 +678,7 @@ def __setstate__(self, pickle): self.code = pickle['code'] self.origin = pickle['origin'] + def test_EvalFactor_pickle_saves_origin(): from patsy.util import assert_pickled_equals # The pickling tests use object equality before and after pickling diff --git a/patsy/mgcv_cubic_splines.py b/patsy/mgcv_cubic_splines.py index 11ec055..f1f53b2 100644 --- a/patsy/mgcv_cubic_splines.py +++ b/patsy/mgcv_cubic_splines.py @@ -730,8 +730,6 @@ def __setstate__(self, pickle): cr = stateful_transform(CR) -cr.__qualname__ = 'cr' -cr.__name__ = 'cr' class CC(CubicRegressionSpline): @@ -774,8 +772,6 @@ def __setstate__(self, pickle): cc = stateful_transform(CC) -cc.__qualname__ = 'cc' -cc.__name__ = 'cc' def test_crs_errors(): @@ -978,8 +974,6 @@ def __setstate__(self, pickle): te = stateful_transform(TE) -te.__qualname__ = 'te' -te.__name__ = 'te' def test_te_errors(): diff --git a/patsy/splines.py b/patsy/splines.py index 96668fc..0cba98c 100644 --- a/patsy/splines.py +++ b/patsy/splines.py @@ -257,8 +257,6 @@ def __setstate__(self, pickle): bs = stateful_transform(BS) -bs.__qualname__ = 'bs' -bs.__name__ = 'bs' def test_bs_compat(): diff --git a/patsy/state.py b/patsy/state.py index a45ed72..1d59d5b 100644 --- a/patsy/state.py +++ b/patsy/state.py @@ -126,8 +126,6 @@ def __setstate__(self, pickle): center = stateful_transform(Center) -center.__qualname__ = 'center' -center.__name__ = 'center' # See: # http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#On-line_algorithm @@ -196,9 +194,5 @@ def __setstate__(self, pickle): standardize = stateful_transform(Standardize) -standardize.__qualname__ = 'standardize' -standardize.__name__ = 'standardize' # R compatibility: scale = standardize -scale.__qualname__ = 'scale' -scale.__name__ = 'scale' diff --git a/pickle_testcases/0.5/evalenv_transform_bs.pickle b/pickle_testcases/0.5/evalenv_transform_bs.pickle index 547608f749616cdabd5aadff158b9a814410eee1..1d48cbd684bd13abf9c9d4aa0e85da001e5316b3 100644 GIT binary patch delta 18 Zcma#FVQFBQYB-U_kUi0xp?yk{9sn(@1qc8D delta 47 zcmcDCWNBcT>NkN}CeP`QUKIW?~&wP;EYcR^xFaiv~yNn%Orlnl1XQ;HM48QP~L=>Y(7 C0uY%1 diff --git a/pickle_testcases/0.5/evalenv_transform_cr.pickle b/pickle_testcases/0.5/evalenv_transform_cr.pickle index 550190cec70165730a8f02759ff092ac53d91249..1d48cbd684bd13abf9c9d4aa0e85da001e5316b3 100644 GIT binary patch delta 18 ZcmYeXVQFBQYB-U_kUi0xp?yk{9sn+K1rq=O delta 58 zcmcCXVQFBQ8aa{0P``&Mxp+#CL_uOnaiv~vdU9EOa%oa#a(rLzJXv*X% M#fjbw?NgHU0A-&Q@&Et; diff --git a/pickle_testcases/0.5/evalenv_transform_scale.pickle b/pickle_testcases/0.5/evalenv_transform_scale.pickle index bd2ea177a20ad1aaa82fd26528e4bc1e69e71008..1d48cbd684bd13abf9c9d4aa0e85da001e5316b3 100644 GIT binary patch delta 18 ZcmWHyVQFBQYB-U_kUi0xp?yk{9sn(f1qJ{B delta 45 zcmcBsXK7%W>NAnWP^pKtI5{yVbxIF+L1Ia9rCxDKVoB