##// END OF EJS Templates
support non-modules in @require...
MinRK -
Show More
@@ -5,18 +5,21 b' Authors:'
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.
12 12 #-----------------------------------------------------------------------------
13 13
14 import sys
15
14 16 from types import ModuleType
15 17
16 18 from IPython.parallel.client.asyncresult import AsyncResult
17 19 from IPython.parallel.error import UnmetDependency
18 20 from IPython.parallel.util import interactive
19 21 from IPython.utils import py3compat
22 from IPython.utils.pickleutil import can, uncan
20 23
21 24 class depend(object):
22 25 """Dependency decorator, for use with tasks.
@@ -60,8 +63,9 b' class dependent(object):'
60 63 self.dkwargs = dkwargs
61 64
62 65 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
66 user_ns = sys.modules['__main__'].__dict__
67 for key, value in self.dkwargs.items():
68 self.dkwargs[key] = uncan(value, user_ns)
65 69 if self.df(*self.dargs, **self.dkwargs) is False:
66 70 raise UnmetDependency()
67 71 return self.f(*args, **kwargs)
@@ -72,41 +76,62 b' class dependent(object):'
72 76 return self.func_name
73 77
74 78 @interactive
75 def _require(*names):
79 def _require(*modules, **mapping):
76 80 """Helper for @require decorator."""
77 81 from IPython.parallel.error import UnmetDependency
82 from IPython.utils.pickleutil import uncan
78 83 user_ns = globals()
79 for name in names:
80 if name in user_ns:
81 continue
84 for name in modules:
82 85 try:
83 exec 'import %s'%name in user_ns
86 exec 'import %s' % name in user_ns
84 87 except ImportError:
85 88 raise UnmetDependency(name)
89
90 for name, cobj in mapping.items():
91 user_ns[name] = uncan(cobj, user_ns)
86 92 return True
87 93
88 def require(*mods):
89 """Simple decorator for requiring names to be importable.
94 def require(*objects, **mapping):
95 """Simple decorator for requiring local objects and modules to be available
96 when the decorated function is called on the engine.
97
98 Modules specified by name or passed directly will be imported
99 prior to calling the decorated function.
100
101 Objects other than modules will be pushed as a part of the task.
102 Functions can be passed positionally,
103 and will be pushed to the engine with their __name__.
104 Other objects can be passed by keyword arg.
90 105
91 106 Examples
92 107 --------
93 108
94 109 In [1]: @require('numpy')
95 110 ...: def norm(a):
96 ...: import numpy
97 111 ...: return numpy.linalg.norm(a,2)
112
113 In [2]: foo = lambda x: x*x
114 In [3]: @require(foo)
115 ...: def bar(a):
116 ...: return foo(1-a)
98 117 """
99 118 names = []
100 for mod in mods:
101 if isinstance(mod, ModuleType):
102 mod = mod.__name__
119 for obj in objects:
120 if isinstance(obj, ModuleType):
121 obj = obj.__name__
103 122
104 if isinstance(mod, basestring):
105 names.append(mod)
123 if isinstance(obj, basestring):
124 names.append(obj)
125 elif hasattr(obj, '__name__'):
126 mapping[obj.__name__] = obj
106 127 else:
107 raise TypeError("names must be modules or module names, not %s"%type(mod))
128 raise TypeError("Objects other than modules and functions "
129 "must be passed by kwarg, but got: %s" % type(obj)
130 )
108 131
109 return depend(_require, *names)
132 for name, obj in mapping.items():
133 mapping[name] = can(obj)
134 return depend(_require, *names, **mapping)
110 135
111 136 class Dependency(set):
112 137 """An object for representing a set of msg_id dependencies.
General Comments 0
You need to be logged in to leave comments. Login now