##// END OF EJS Templates
Merge pull request #5762 from minrk/better_closure_check...
Thomas Kluyver -
r16518:161841f4 merge
parent child Browse files
Show More
@@ -0,0 +1,62 b''
1
2 import pickle
3
4 import nose.tools as nt
5 from IPython.utils import codeutil
6 from IPython.utils.pickleutil import can, uncan
7
8 def interactive(f):
9 f.__module__ = '__main__'
10 return f
11
12 def dumps(obj):
13 return pickle.dumps(can(obj))
14
15 def loads(obj):
16 return uncan(pickle.loads(obj))
17
18 def test_no_closure():
19 @interactive
20 def foo():
21 a = 5
22 return a
23
24 pfoo = dumps(foo)
25 bar = loads(pfoo)
26 nt.assert_equal(foo(), bar())
27
28 def test_generator_closure():
29 # this only creates a closure on Python 3
30 @interactive
31 def foo():
32 i = 'i'
33 r = [ i for j in (1,2) ]
34 return r
35
36 pfoo = dumps(foo)
37 bar = loads(pfoo)
38 nt.assert_equal(foo(), bar())
39
40 def test_nested_closure():
41 @interactive
42 def foo():
43 i = 'i'
44 def g():
45 return i
46 return g()
47
48 pfoo = dumps(foo)
49 bar = loads(pfoo)
50 nt.assert_equal(foo(), bar())
51
52 def test_closure():
53 i = 'i'
54 @interactive
55 def foo():
56 return i
57
58 # true closures are not supported
59 with nt.assert_raises(ValueError):
60 pfoo = dumps(foo)
61
62 No newline at end of file
@@ -10,19 +10,6 b' we need to automate all of this so that functions themselves can be pickled.'
10 10 Reference: A. Tremols, P Cogolo, "Python Cookbook," p 302-305
11 11 """
12 12
13 __docformat__ = "restructuredtext en"
14
15 #-------------------------------------------------------------------------------
16 # Copyright (C) 2008-2011 The IPython Development Team
17 #
18 # Distributed under the terms of the BSD License. The full license is in
19 # the file COPYING, distributed as part of this software.
20 #-------------------------------------------------------------------------------
21
22 #-------------------------------------------------------------------------------
23 # Imports
24 #-------------------------------------------------------------------------------
25
26 13 import sys
27 14 import types
28 15 try:
@@ -34,12 +21,10 b' def code_ctor(*args):'
34 21 return types.CodeType(*args)
35 22
36 23 def reduce_code(co):
37 if co.co_freevars or co.co_cellvars:
38 raise ValueError("Sorry, cannot pickle code objects with closures")
39 24 args = [co.co_argcount, co.co_nlocals, co.co_stacksize,
40 25 co.co_flags, co.co_code, co.co_consts, co.co_names,
41 26 co.co_varnames, co.co_filename, co.co_name, co.co_firstlineno,
42 co.co_lnotab]
27 co.co_lnotab, co.co_freevars, co.co_cellvars]
43 28 if sys.version_info[0] >= 3:
44 29 args.insert(1, co.co_kwonlyargcount)
45 30 return code_ctor, tuple(args)
@@ -2,18 +2,8 b''
2 2
3 3 """Pickle related utilities. Perhaps this should be called 'can'."""
4 4
5 __docformat__ = "restructuredtext en"
6
7 #-------------------------------------------------------------------------------
8 # Copyright (C) 2008-2011 The IPython Development Team
9 #
10 # Distributed under the terms of the BSD License. The full license is in
11 # the file COPYING, distributed as part of this software.
12 #-------------------------------------------------------------------------------
13
14 #-------------------------------------------------------------------------------
15 # Imports
16 #-------------------------------------------------------------------------------
5 # Copyright (c) IPython Development Team.
6 # Distributed under the terms of the Modified BSD License.
17 7
18 8 import copy
19 9 import logging
@@ -35,9 +25,11 b' from IPython.config import Application'
35 25 if py3compat.PY3:
36 26 buffer = memoryview
37 27 class_type = type
28 closure_attr = '__closure__'
38 29 else:
39 30 from types import ClassType
40 31 class_type = (type, ClassType)
32 closure_attr = 'func_closure'
41 33
42 34 #-------------------------------------------------------------------------------
43 35 # Functions
@@ -140,6 +132,9 b' class CannedFunction(CannedObject):'
140 132 self.defaults = [ can(fd) for fd in f.__defaults__ ]
141 133 else:
142 134 self.defaults = None
135
136 if getattr(f, closure_attr, None):
137 raise ValueError("Sorry, cannot pickle functions with closures.")
143 138 self.module = f.__module__ or '__main__'
144 139 self.__name__ = f.__name__
145 140 self.buffers = []
General Comments 0
You need to be logged in to leave comments. Login now