5
5
* Min RK
6
6
"""
7
7
#-----------------------------------------------------------------------------
8
- # Copyright (C) 2010-2011 The IPython Development Team
8
+ # Copyright (C) 2013 The IPython Development Team
9
9
#
10
10
# Distributed under the terms of the BSD License. The full license is in
11
11
# the file COPYING, distributed as part of this software.
17
17
from IPython .parallel .error import UnmetDependency
18
18
from IPython .parallel .util import interactive
19
19
from IPython .utils import py3compat
20
+ from IPython .utils .pickleutil import can , uncan
20
21
21
22
class depend (object ):
22
23
"""Dependency decorator, for use with tasks.
@@ -58,12 +59,12 @@ def __init__(self, f, df, *dargs, **dkwargs):
58
59
self .df = df
59
60
self .dargs = dargs
60
61
self .dkwargs = dkwargs
61
-
62
- def __call__ (self , * args , ** kwargs ):
63
- # if hasattr(self.f, 'func_globals') and hasattr(self.df, 'func_globals'):
64
- # self.df.func_globals = self.f.func_globals
62
+
63
+ def check_dependency (self ):
65
64
if self .df (* self .dargs , ** self .dkwargs ) is False :
66
65
raise UnmetDependency ()
66
+
67
+ def __call__ (self , * args , ** kwargs ):
67
68
return self .f (* args , ** kwargs )
68
69
69
70
if not py3compat .PY3 :
@@ -72,41 +73,62 @@ def __name__(self):
72
73
return self .func_name
73
74
74
75
@interactive
75
- def _require (* names ):
76
+ def _require (* modules , ** mapping ):
76
77
"""Helper for @require decorator."""
77
78
from IPython .parallel .error import UnmetDependency
79
+ from IPython .utils .pickleutil import uncan
78
80
user_ns = globals ()
79
- for name in names :
80
- if name in user_ns :
81
- continue
81
+ for name in modules :
82
82
try :
83
- exec 'import %s' % name in user_ns
83
+ exec 'import %s' % name in user_ns
84
84
except ImportError :
85
85
raise UnmetDependency (name )
86
+
87
+ for name , cobj in mapping .items ():
88
+ user_ns [name ] = uncan (cobj , user_ns )
86
89
return True
87
90
88
- def require (* mods ):
89
- """Simple decorator for requiring names to be importable.
91
+ def require (* objects , ** mapping ):
92
+ """Simple decorator for requiring local objects and modules to be available
93
+ when the decorated function is called on the engine.
94
+
95
+ Modules specified by name or passed directly will be imported
96
+ prior to calling the decorated function.
97
+
98
+ Objects other than modules will be pushed as a part of the task.
99
+ Functions can be passed positionally,
100
+ and will be pushed to the engine with their __name__.
101
+ Other objects can be passed by keyword arg.
90
102
91
103
Examples
92
104
--------
93
105
94
106
In [1]: @require('numpy')
95
107
...: def norm(a):
96
- ...: import numpy
97
108
...: return numpy.linalg.norm(a,2)
109
+
110
+ In [2]: foo = lambda x: x*x
111
+ In [3]: @require(foo)
112
+ ...: def bar(a):
113
+ ...: return foo(1-a)
98
114
"""
99
115
names = []
100
- for mod in mods :
101
- if isinstance (mod , ModuleType ):
102
- mod = mod .__name__
116
+ for obj in objects :
117
+ if isinstance (obj , ModuleType ):
118
+ obj = obj .__name__
103
119
104
- if isinstance (mod , basestring ):
105
- names .append (mod )
120
+ if isinstance (obj , basestring ):
121
+ names .append (obj )
122
+ elif hasattr (obj , '__name__' ):
123
+ mapping [obj .__name__ ] = obj
106
124
else :
107
- raise TypeError ("names must be modules or module names, not %s" % type (mod ))
125
+ raise TypeError ("Objects other than modules and functions "
126
+ "must be passed by kwarg, but got: %s" % type (obj )
127
+ )
108
128
109
- return depend (_require , * names )
129
+ for name , obj in mapping .items ():
130
+ mapping [name ] = can (obj )
131
+ return depend (_require , * names , ** mapping )
110
132
111
133
class Dependency (set ):
112
134
"""An object for representing a set of msg_id dependencies.
0 commit comments