Skip to content

Commit 9758f5f

Browse files
committed
Explicitly mark everything as being non-pickleable, to reduce accidents. We'll re-enable them one-by-one as we add pickle tests.
1 parent b420d7f commit 9758f5f

15 files changed

Lines changed: 137 additions & 11 deletions

patsy/categorical.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@
4545
pandas_Categorical_from_codes,
4646
pandas_Categorical_categories,
4747
pandas_Categorical_codes,
48-
safe_issubdtype)
48+
safe_issubdtype,
49+
no_pickling, assert_no_pickling)
4950

5051
if have_pandas:
5152
import pandas
@@ -58,6 +59,8 @@ def __init__(self, data, contrast, levels):
5859
self.contrast = contrast
5960
self.levels = levels
6061

62+
__getstate__ = no_pickling
63+
6164
def C(data, contrast=None, levels=None):
6265
"""
6366
Marks some `data` as being categorical, and specifies how to interpret
@@ -117,6 +120,8 @@ def test_C():
117120
assert c4.contrast == "NEW CONTRAST"
118121
assert c4.levels == "LEVELS"
119122

123+
assert_no_pickling(c4)
124+
120125
def guess_categorical(data):
121126
if safe_is_pandas_categorical(data):
122127
return True
@@ -212,6 +217,8 @@ def sniff(self, data):
212217
# would be too. Otherwise we need to keep looking.
213218
return self._level_set == set([True, False])
214219

220+
__getstate__ = no_pickling
221+
215222
def test_CategoricalSniffer():
216223
from patsy.missing import NAAction
217224
def t(NA_types, datas, exp_finish_fast, exp_levels, exp_contrast=None):

patsy/constraint.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@
1515
from patsy import PatsyError
1616
from patsy.origin import Origin
1717
from patsy.util import (atleast_2d_column_default,
18-
repr_pretty_delegate, repr_pretty_impl,
19-
SortAnythingKey)
18+
repr_pretty_delegate, repr_pretty_impl,
19+
SortAnythingKey,
20+
no_pickling, assert_no_pickling)
2021
from patsy.infix_parser import Token, Operator, ParseNode, infix_parse
2122
from patsy.compat import Scanner, Mapping
2223

@@ -66,6 +67,8 @@ def _repr_pretty_(self, p, cycle):
6667
return repr_pretty_impl(p, self,
6768
[self.variable_names, self.coefs, self.constants])
6869

70+
__getstate__ = no_pickling
71+
6972
@classmethod
7073
def combine(cls, constraints):
7174
"""Create a new LinearConstraint by ANDing together several existing
@@ -110,6 +113,8 @@ def test_LinearConstraint():
110113
assert_raises(ValueError, LinearConstraint, ["a", "b"],
111114
np.zeros((0, 2)))
112115

116+
assert_no_pickling(lc)
117+
113118
def test_LinearConstraint_combine():
114119
comb = LinearConstraint.combine([LinearConstraint(["a", "b"], [1, 0]),
115120
LinearConstraint(["a", "b"], [0, 1], [1])])

patsy/contrasts.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
import numpy as np
1616
from patsy import PatsyError
1717
from patsy.compat import triu_indices, tril_indices, diag_indices
18-
from patsy.util import repr_pretty_delegate, repr_pretty_impl, safe_issubdtype
18+
from patsy.util import (repr_pretty_delegate, repr_pretty_impl,
19+
safe_issubdtype,
20+
no_pickling, assert_no_pickling)
1921

2022
class ContrastMatrix(object):
2123
"""A simple container for a matrix used for coding categorical factors.
@@ -46,6 +48,8 @@ def __init__(self, matrix, column_suffixes):
4648
def _repr_pretty_(self, p, cycle):
4749
repr_pretty_impl(p, self, [self.matrix, self.column_suffixes])
4850

51+
__getstate__ = no_pickling
52+
4953
def test_ContrastMatrix():
5054
cm = ContrastMatrix([[1, 0], [0, 1]], ["a", "b"])
5155
assert np.array_equal(cm.matrix, np.eye(2))
@@ -56,6 +60,8 @@ def test_ContrastMatrix():
5660
from nose.tools import assert_raises
5761
assert_raises(PatsyError, ContrastMatrix, [[1], [0]], ["a", "b"])
5862

63+
assert_no_pickling(cm)
64+
5965
# This always produces an object of the type that Python calls 'str' (whether
6066
# that be a Python 2 string-of-bytes or a Python 3 string-of-unicode). It does
6167
# *not* make any particular guarantees about being reversible or having other
@@ -176,6 +182,8 @@ def code_without_intercept(self, levels):
176182
names = _name_levels("T.", levels[:reference] + levels[reference + 1:])
177183
return ContrastMatrix(contrasts, names)
178184

185+
__getstate__ = no_pickling
186+
179187
def test_Treatment():
180188
t1 = Treatment()
181189
matrix = t1.code_with_intercept(["a", "b", "c"])
@@ -272,6 +280,8 @@ def code_with_intercept(self, levels):
272280
def code_without_intercept(self, levels):
273281
return self._code_either(False, levels)
274282

283+
__getstate__ = no_pickling
284+
275285
def test_Poly():
276286
t1 = Poly()
277287
matrix = t1.code_with_intercept(["a", "b", "c"])
@@ -378,6 +388,8 @@ def code_without_intercept(self, levels):
378388
included_levels = levels[:omit_i] + levels[omit_i + 1:]
379389
return ContrastMatrix(matrix, _name_levels("S.", included_levels))
380390

391+
__getstate__ = no_pickling
392+
381393
def test_Sum():
382394
t1 = Sum()
383395
matrix = t1.code_with_intercept(["a", "b", "c"])
@@ -471,6 +483,8 @@ def code_without_intercept(self, levels):
471483
return ContrastMatrix(contrast,
472484
_name_levels("H.", levels[1:]))
473485

486+
__getstate__ = no_pickling
487+
474488
def test_Helmert():
475489
t1 = Helmert()
476490
for levels in (["a", "b", "c", "d"], ("a", "b", "c", "d")):
@@ -536,6 +550,8 @@ def code_without_intercept(self, levels):
536550
contrast = self._diff_contrast(levels)
537551
return ContrastMatrix(contrast, _name_levels("D.", levels[:-1]))
538552

553+
__getstate__ = no_pickling
554+
539555
def test_diff():
540556
t1 = Diff()
541557
matrix = t1.code_with_intercept(["a", "b", "c", "d"])

patsy/desc.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from patsy.eval import EvalEnvironment, EvalFactor
1515
from patsy.util import uniqueify_list
1616
from patsy.util import repr_pretty_delegate, repr_pretty_impl
17+
from patsy.util import no_pickling, assert_no_pickling
1718

1819
# These are made available in the patsy.* namespace
1920
__all__ = ["Term", "ModelDesc", "INTERCEPT"]
@@ -64,6 +65,8 @@ def name(self):
6465
else:
6566
return "Intercept"
6667

68+
__getstate__ = no_pickling
69+
6770
INTERCEPT = Term([])
6871

6972
class _MockFactor(object):
@@ -83,6 +86,8 @@ def test_Term():
8386
assert Term([f2, f1]).name() == "b:a"
8487
assert Term([]).name() == "Intercept"
8588

89+
assert_no_pickling(Term([]))
90+
8691
class ModelDesc(object):
8792
"""A simple container representing the termlists parsed from a formula.
8893
@@ -161,6 +166,8 @@ def from_formula(cls, tree_or_string):
161166
assert isinstance(value, cls)
162167
return value
163168

169+
__getstate__ = no_pickling
170+
164171
def test_ModelDesc():
165172
f1 = _MockFactor("a")
166173
f2 = _MockFactor("b")
@@ -170,6 +177,8 @@ def test_ModelDesc():
170177
print(m.describe())
171178
assert m.describe() == "1 + a ~ 0 + a + a:b"
172179

180+
assert_no_pickling(m)
181+
173182
assert ModelDesc([], []).describe() == "~ 0"
174183
assert ModelDesc([INTERCEPT], []).describe() == "1 ~ 0"
175184
assert ModelDesc([INTERCEPT], [INTERCEPT]).describe() == "1 ~ 1"
@@ -200,6 +209,8 @@ def _pretty_repr_(self, p, cycle): # pragma: no cover
200209
[self.intercept, self.intercept_origin,
201210
self.intercept_removed, self.terms])
202211

212+
__getstate__ = no_pickling
213+
203214
def _maybe_add_intercept(doit, terms):
204215
if doit:
205216
return (INTERCEPT,) + terms

patsy/design_info.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@
3131
from patsy import PatsyError
3232
from patsy.util import atleast_2d_column_default
3333
from patsy.compat import OrderedDict
34-
from patsy.util import repr_pretty_delegate, repr_pretty_impl, safe_issubdtype
34+
from patsy.util import (repr_pretty_delegate, repr_pretty_impl,
35+
safe_issubdtype,
36+
no_pickling, assert_no_pickling)
3537
from patsy.constraint import linear_constraint
3638
from patsy.contrasts import ContrastMatrix
3739
from patsy.desc import ModelDesc, Term
@@ -119,6 +121,8 @@ def __repr__(self):
119121
kwlist.append(("categories", self.categories))
120122
repr_pretty_impl(p, self, [], kwlist)
121123

124+
__getstate__ = no_pickling
125+
122126
class SubtermInfo(object):
123127
"""A SubtermInfo object is a simple metadata container describing a single
124128
primitive interaction and how it is coded in our design matrix. Our final
@@ -188,6 +192,8 @@ def _repr_pretty_(self, p, cycle):
188192
("contrast_matrices", self.contrast_matrices),
189193
("num_columns", self.num_columns)])
190194

195+
__getstate__ = no_pickling
196+
191197
class DesignInfo(object):
192198
"""A DesignInfo object holds metadata about a design matrix.
193199
@@ -616,6 +622,8 @@ def from_array(cls, array_like, default_column_prefix="column"):
616622
for i in columns]
617623
return DesignInfo(column_names)
618624

625+
__getstate__ = no_pickling
626+
619627
def test_DesignInfo():
620628
from nose.tools import assert_raises
621629
class _MockFactor(object):
@@ -659,6 +667,8 @@ def name(self):
659667
# smoke test
660668
repr(di)
661669

670+
assert_no_pickling(di)
671+
662672
# One without term objects
663673
di = DesignInfo(["a1", "a2", "a3", "b"])
664674
assert di.column_names == ["a1", "a2", "a3", "b"]
@@ -915,6 +925,8 @@ def _repr_pretty_(self, p, cycle):
915925
# object to keep the design_info (they may have different columns!), or
916926
# anything fancy like that.
917927

928+
__reduce__ = no_pickling
929+
918930
def test_design_matrix():
919931
from nose.tools import assert_raises
920932

@@ -945,6 +957,8 @@ def test_design_matrix():
945957
mm6 = DesignMatrix([[12, 14, 16, 18]], default_column_prefix="x")
946958
assert mm6.design_info.column_names == ["x0", "x1", "x2", "x3"]
947959

960+
assert_no_pickling(mm6)
961+
948962
# Only real-valued matrices can be DesignMatrixs
949963
assert_raises(ValueError, DesignMatrix, [1, 2, 3j])
950964
assert_raises(ValueError, DesignMatrix, ["a", "b", "c"])

patsy/eval.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
import numbers
2121
import six
2222
from patsy import PatsyError
23-
from patsy.util import PushbackAdapter
23+
from patsy.util import PushbackAdapter, no_pickling, assert_no_pickling
2424
from patsy.tokens import (pretty_untokenize, normalize_token_spacing,
2525
python_tokenize)
2626
from patsy.compat import call_and_wrap_exc
@@ -70,6 +70,9 @@ def get(self, key, default=None):
7070
def __repr__(self):
7171
return "%s(%r)" % (self.__class__.__name__, self._dicts)
7272

73+
__getstate__ = no_pickling
74+
75+
7376
def test_VarLookupDict():
7477
d1 = {"a": 1}
7578
d2 = {"a": 2, "b": 3}
@@ -86,6 +89,8 @@ def test_VarLookupDict():
8689
assert ds.get("c") is None
8790
assert isinstance(repr(ds), six.string_types)
8891

92+
assert_no_pickling(ds)
93+
8994
def ast_names(code):
9095
"""Iterator that yields all the (ast) names in a Python expression.
9196
@@ -251,6 +256,8 @@ def __hash__(self):
251256
self.flags,
252257
tuple(self._namespace_ids())))
253258

259+
__getstate__ = no_pickling
260+
254261
def _a(): # pragma: no cover
255262
_a = 1
256263
return _b()
@@ -292,6 +299,8 @@ def test_EvalEnvironment_capture_namespace():
292299

293300
assert_raises(TypeError, EvalEnvironment.capture, 1.2)
294301

302+
assert_no_pickling(EvalEnvironment.capture())
303+
295304
def test_EvalEnvironment_capture_flags():
296305
if sys.version_info >= (3,):
297306
# This is the only __future__ feature currently usable in Python
@@ -556,6 +565,8 @@ def eval(self, memorize_state, data):
556565
memorize_state,
557566
data)
558567

568+
__getstate__ = no_pickling
569+
559570
def test_EvalFactor_basics():
560571
e = EvalFactor("a+b")
561572
assert e.code == "a + b"
@@ -566,6 +577,8 @@ def test_EvalFactor_basics():
566577
assert e.origin is None
567578
assert e2.origin == "asdf"
568579

580+
assert_no_pickling(e)
581+
569582
def test_EvalFactor_memorize_passes_needed():
570583
from patsy.state import stateful_transform
571584
foo = stateful_transform(lambda: "FOO-OBJ")

patsy/infix_parser.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@
3434

3535
from patsy import PatsyError
3636
from patsy.origin import Origin
37-
from patsy.util import repr_pretty_delegate, repr_pretty_impl
37+
from patsy.util import (repr_pretty_delegate, repr_pretty_impl,
38+
no_pickling, assert_no_pickling)
3839

3940
class _UniqueValue(object):
4041
def __init__(self, print_as):
@@ -43,6 +44,7 @@ def __init__(self, print_as):
4344
def __repr__(self):
4445
return "%s(%r)" % (self.__class__.__name__, self._print_as)
4546

47+
__getstate__ = no_pickling
4648

4749
class Token(object):
4850
"""A token with possible payload.
@@ -68,6 +70,8 @@ def _repr_pretty_(self, p, cycle):
6870
kwargs = [("extra", self.extra)]
6971
return repr_pretty_impl(p, self, [self.type, self.origin], kwargs)
7072

73+
__getstate__ = no_pickling
74+
7175
class ParseNode(object):
7276
def __init__(self, type, token, args, origin):
7377
self.type = type
@@ -79,6 +83,8 @@ def __init__(self, type, token, args, origin):
7983
def _repr_pretty_(self, p, cycle):
8084
return repr_pretty_impl(p, self, [self.type, self.token, self.args])
8185

86+
__getstate__ = no_pickling
87+
8288
class Operator(object):
8389
def __init__(self, token_type, arity, precedence):
8490
self.token_type = token_type
@@ -89,11 +95,15 @@ def __repr__(self):
8995
return "%s(%r, %r, %r)" % (self.__class__.__name__,
9096
self.token_type, self.arity, self.precedence)
9197

98+
__getstate__ = no_pickling
99+
92100
class _StackOperator(object):
93101
def __init__(self, op, token):
94102
self.op = op
95103
self.token = token
96104

105+
__getstate__ = no_pickling
106+
97107
_open_paren = Operator(Token.LPAREN, -1, -9999999)
98108

99109
class _ParseContext(object):
@@ -105,6 +115,8 @@ def __init__(self, unary_ops, binary_ops, atomic_types, trace):
105115
self.atomic_types = atomic_types
106116
self.trace = trace
107117

118+
__getstate__ = no_pickling
119+
108120
def _read_noun_context(token, c):
109121
if token.type == Token.LPAREN:
110122
if c.trace:

0 commit comments

Comments
 (0)