Caffe2 - Python API
A deep learning, cross platform ML framework
__init__.py
1 
2 class CWrapPlugin(object):
3  """Base class from which all cwrap plugins should inherit.
4 
5  Override any of the following methods to implement the desired wrapping
6  behavior.
7  """
8 
9  def initialize(self, cwrap):
10  """Initialize the Plugin class prior to calling any other functions.
11 
12  It is used to give the Plugin access to the cwrap object's helper
13  functions and state.
14 
15  Args:
16  cwrap: the cwrap object performing the wrapping.
17 
18  """
19  pass
20 
21  def get_type_check(self, arg, option):
22  """Used to generate code for runtime checks of object types.
23 
24  The type can be found in arg['type']. For example, it could be
25  THTensor*. If this Plugin recognizes the type in arg, it should
26  return a Template string containing code that checks whether a
27  Python object is of this type. For example, the return type in
28  this case would be:
29 
30  Template('(PyObject*)Py_TYPE($arg) == THPTensorClass')
31 
32  As a simpler example, if the type == 'bool' then we would return:
33 
34  Template('PyBool_Check($arg)')
35 
36  Note that the name of the identifier that will be substituted must be
37  $arg.
38 
39  Args:
40  arg: a Python object with a 'type' field representing the type
41  to generate a check string for.
42  option: a dictionary containing the information for this specific
43  option.
44 
45  Returns:
46  A Template string as described above, or None if this Plugin does
47  not have a corresponding type check for the passed type.
48 
49  """
50  pass
51 
52  def get_type_unpack(self, arg, option):
53  """Used to generate code unpacking of Python objects into C types.
54 
55  Similar to get_type_check, but for unpacking Python objects into their
56  corresponding C types. The type is once again accessible via
57  arg['type']. This time we return a Template string that unpacks an
58  object. For a THTensor*, we know that the corresponding PyTorch type is
59  a THPTensor*, so we need to get the cdata from the object. So we would
60  return:
61 
62  Template('((THPTensor*)$arg)->cdata')
63 
64  For a simpler type, such as a long, we could do:
65 
66  Template('PyLong_AsLong($arg)')
67 
68  though in practice we will use our own custom unpacking code. Once
69  again, $arg must be used as the identifier.
70 
71  Args:
72  arg: a Python object with a 'type' field representing the type
73  to generate a unpack string for.
74  option: dictionary containing the information for this specific
75  option.
76 
77  Returns:
78  A Template string as described above, or None if this Plugin does
79  not have a corresponding type unpack for the passed type.
80 
81  """
82  pass
83 
84  def get_return_wrapper(self, option):
85  """Used to generate code wrapping a function's return value.
86 
87  Wrapped functions should always return a PyObject *. However,
88  internally, the code will be working with C objects or primitives.
89  Therefore, if a function has a return value we need to convert it back
90  to a PyObject * before the function returns. Plugins can override this
91  function to generate wrapper code for returning specific C types. The
92  type is accessible via option['return'].
93 
94  Continuing on with our THTensor* example, we might do something like:
95 
96  Template('return THPTensor_(New)($result);')
97 
98  In general, you want to do return <statement>; In this case, we call
99  into THP's library routine that takes a THTensor* (the $result
100  identifier) and returns a PyObject *.
101 
102  For a bool, we could do Template('return PyBool_FromLong($result);').
103 
104  Note that in other cases, our logic might be more complicated. For
105  example, if our return value is also an argument to the function call,
106  we could need to increase the reference count prior to returning.
107 
108  Args:
109  option: dictionary containing the information for this specific
110  option.
111 
112  Returns:
113  A Template string as described above, or None if this Plugin does
114  not have a corresponding return wrapper for the functions return
115  type or specifier.
116 
117  """
118  pass
119 
120  def get_wrapper_template(self, declaration):
121  """Used to create a code template to wrap the options.
122 
123  This function returns a Template string that contains the function call
124  for the overall declaration, including the method definition, opening
125  and closing brackets, and any additional code within the method body.
126  Look through the examples to get a sense of what this might look like.
127  The only requirements are that it contains unsubstituted template
128  identifiers for anything the cwrap engine expects.
129 
130  Note that for any declaration only one Plugin can generate the wrapper
131  template.
132 
133  Args:
134  declaration: the declaration for the wrapped method.
135 
136  Returns:
137  A template string representing the entire function declaration,
138  with identifiers as necessary.
139 
140  """
141  pass
142 
143  def get_assign_args(self, arguments):
144  """Used to modify argument metadata prior to assignment.
145 
146  We have already setup argument checking, and how to unpack arguments.
147  This function allows you to modify the metadata of an argument prior to
148  actually performing the assignment. For example, you might want to
149  check that an argument is of a specific type, but when unpacking it you
150  might want to treat it as a different type. This function will allow
151  you to do stuff like that --> e.g. you could set the 'type' field for a
152  particular argument to be something else.
153 
154  Args:
155  arguments: a list of argument metadata dictionaries.
156 
157  Returns:
158  The same list of arguments, with any modifications as you see fit.
159 
160  """
161  pass
162 
163  def get_arg_accessor(self, arg, option):
164  """Used to generate a string for accessing the passed arg.
165 
166  One of the key components of the YAML definition for a method to be
167  wrapped are the arguments to that method. Override this function to
168  show how to access that specific arg in the code. For example, you
169  might do something different if the argument is a keyword argument, or
170  a constant, or self. The base cwrap plugin has a fallback arg accessor
171  for loading elements from the args PyObject * tuple passed to the
172  function.
173 
174  Its best to look at some of the existing Plugins to get a sense of what
175  one might do.
176 
177  Args:
178  arg: a dictionary specifying attributes of the arg to be accessed
179  option: dictionary containing the information for this specific
180  option.
181 
182  Returns:
183  A a string (note: not a Template string!) of code that can be used
184  to access the given arg. If the plugin does not know how to access
185  the arg, return None.
186  """
187  pass
188 
189  def process_full_file(self, code, template_path):
190  """Used to modify the code for the entire output file.
191 
192  The last thing any plugin can do. Code contains the results of wrapping
193  all the declarations. The plugin can do things like adding header
194  guards, include statements, etc.
195 
196  Args:
197  code: a string source code for the wrapped declarations.
198 
199  Returns:
200  The same code, modified as the plugin sees fit.
201 
202  """
203  return code
204 
205  def process_single_check(self, code, arg, arg_accessor):
206  """Used to postprocess a type check.
207 
208  Above we defined a function get_type_check that returns a Template
209  string that allows for type checking a PyObject * for a specific type.
210  In this function, the passed "code" is a combination of that type check
211  along with a specific arg_accessor pasted in. For example:
212 
213  '(PyObject*)Py_TYPE(PyTuple_GET_ITEM(args, 1)) == THPTensorClass'
214 
215  This function can be overridden to support modifying this check string.
216  For example, if an argument can be null, we might want to check and see
217  if the type is Py_None, as well.
218 
219  Args:
220  code: The string code representing a type check for a specific
221  argument being accessed.
222  arg: dictionary containing properties of that specific argument
223  arg_accessor: the arg_accessor string for that specific argument.
224  Note that this is likely also embedded in code, but if you want to
225  be able to access this arg and throw away the other code, you can
226  do so.
227 
228  Returns:
229  A string representing the processed check/access string for this
230  arg. If the plugin does not know how to modify a specific input, it
231  should return the original code.
232 
233  """
234  return code
235 
236  def process_all_checks(self, code, option):
237  """Used to generate additional checks based on all the individual ones.
238 
239  After individually processing each argument with get_type_check,
240  get_arg_accessor, process_single_check, this function allows you to
241  inspect the combined checks and do any additional checking/modify that
242  string as you see fit. In particular, given code is a string like:
243 
244  CHECK_TYPE(GET_ARG(0)) && CHECK_TYPE(GET_ARG(1)) && ..
245 
246  We can process it as we see fit. For example, we may want to add a
247  check at the beginning that we have the specified number of arguments.
248 
249  Args:
250  code: A string representing each argument check separated by an
251  '&&'. code can be None if there are no arguments to be checked.
252  option: dictionary containing the information for this specific
253  option.
254 
255  Returns:
256  The modified code string with any additional checks, or just the
257  existing code if no modifications are to be made.
258 
259  """
260  return code
261 
262  def process_single_unpack(self, code, arg, arg_accessor):
263  """Used to postprocess a type unpack.
264 
265  Same as process_single_check above, but for type unpacking. E.g. an
266  example code could be:
267 
268  PyLong_FromLong(PyTuple_GET_ITEM(args, 0))
269 
270  And this code could modify that as it sees fit. For example, if the
271  result of accessing the argument is None, we would not want to call the
272  unpacking code.
273 
274  Args:
275  code: The string code representing a type unpack for a specific
276  argument being accessed.
277  arg: dictionary containing properties of that specific argument
278  arg_accessor: the arg_accessor string for that specific argument.
279  Note that this is likely also embedded in code, but if you want to
280  be able to access this arg and throw away the other code, you can
281  do so.
282 
283  Returns:
284  A string representing the processed unpack/access string for this
285  arg. If the plugin does not know how to modify a specific input, it
286  should return the original code.
287 
288  """
289  return code
290 
291  def process_all_call_arg(self, code, option):
292  """Used to modify the arguments to the underlying C function call.
293 
294  Code is the string of comma-separated arguments that will be passed to
295  the wrapped C function. You can use this function to modify that string
296  as you see fit. For example, THP prepends the LIBRARY_STATE definition
297  so that the generated code will follow the conventions it uses for
298  writing one function for both TH/THC calls.
299 
300  Args:
301  code: A string as described above.
302  option: dictionary containing the information for this specific
303  option.
304 
305  Returns:
306  The same code, modified as the plugin sees fit.
307 
308  """
309  return code
310 
311  def process_option_code(self, code, option):
312  """Used to modify the entire code body for an option.
313 
314  Code in this case is a string containing the entire generated code for
315  a specific option. Note that this body includes the checks for each
316  option, i.e. if (type checks for one permutation) { ... } else if (type
317  checks for another permutation) { ... } etc.
318 
319  Args:
320  code: string representing the generated code for the option
321  option: dictionary containing the information for this specific
322  option.
323 
324  Returns:
325  The same code, modified as the plugin sees fit.
326 
327  """
328  return code
329 
330  def process_wrapper(self, code, declaration):
331  """Used to modify the entire code body for a declaration.
332 
333  Code in this case is a string containing the entire generated code for
334  a specific declaration. This code can be modified as the plugin sees
335  fit. For example, we might want to wrap the function in preprocessor
336  guards if it is only enabled for floats.
337 
338  Args:
339  code: string representing the generated code for the declaration
340  declaration: the declaration metadata.
341 
342  Returns:
343  The same code, modified as the plugin sees fit.
344 
345  """
346  return code
347 
348  def process_declarations(self, declarations):
349  """Used to process/modify the function's declaration.
350 
351  Cwrap loads the YAML of a function to be cwrap'd into a dictionary.
352  This is known as the declaration. The cwrap code sets some defaults as
353  necessary, and then passes this dictionary to process_declarations.
354  Overriding this code allows the plugin to modify this declaration as it
355  sees fit prior to any code generation. The plugin may add, remove or
356  modify the fields of the declaration dictionary. It can also save state
357  to the Plugin for use in subsequent function overrides.
358 
359  Its best to look at some of the existing Plugins to get a sense of what
360  one might do.
361 
362  Args:
363  declarations: a list of declarations, i.e. dictionaries that define
364  the function(s) being wrapped. Note that this can be plural, so the
365  function must take care to modify each input declaration.
366 
367  Returns:
368  Those same declarations, modified as the Plugin sees fit. Note that
369  you could insert a declaration, if you wanted to take an input
370  declaration and e.g. wrap it multiple times.
371 
372  """
373  return declarations
374 
375  def process_option_code_template(self, template, option):
376  """Used to modify the code template for the option.
377 
378  The "code template" can be thought of the actual body implementing the
379  wrapped function call --> i.e. it is not the argument check,
380  assignment, etc. but the actual logic of the function. The template is
381  a list containing two operations: the $call, and the $return_result.
382  These represent the "locations" where the function call will happen,
383  and the function will return.
384 
385  This function can modify the list to insert arbitrary code around the
386  $call and $return_result. For example, one might want to wrap the code
387  in a try/catch, or post-process the result in some way. This allows a
388  plugin to do that.
389 
390  Args:
391  template: a list containing $call and $return_result, in addition
392  to any arbitrary code inserted by other plugins.
393  option: dictionary containing the information for this specific
394  option.
395 
396  Returns:
397  The same "code template", possibly modified by this plugin.
398 
399  """
400  return template
401 
402  def process_pre_arg_assign(self, template, option):
403  """Used to include any code before argument assignment.
404 
405  This function can be used to insert any code that will be part of the
406  resulting function. The code is inserted after argument checks occur,
407  but before argument assignment.
408 
409  Args:
410  template: String representing the code to be inserted. If other
411  plugins have included code for pre_arg_assign, it will be included
412  here.
413  option: dictionary containing the information for this specific
414  option.
415 
416  Returns:
417  template, with any additional code if needed.
418 
419  """
420  return template
421 
422 
423 from .NNExtension import NNExtension
424 from .NullableArguments import NullableArguments
425 from .OptionalArguments import OptionalArguments
426 from .ArgcountChecker import ArgcountChecker
427 from .ArgumentReferences import ArgumentReferences
428 from .BeforeAfterCall import BeforeAfterCall
429 from .ConstantArguments import ConstantArguments
430 from .ReturnArguments import ReturnArguments
431 from .GILRelease import GILRelease
432 from .AutoGPU import AutoGPU
433 from .CuDNNPlugin import CuDNNPlugin
434 from .WrapDim import WrapDim
def process_option_code_template(self, template, option)
Definition: __init__.py:375
def process_all_call_arg(self, code, option)
Definition: __init__.py:291
def process_full_file(self, code, template_path)
Definition: __init__.py:189
def get_wrapper_template(self, declaration)
Definition: __init__.py:120
def process_wrapper(self, code, declaration)
Definition: __init__.py:330
def get_return_wrapper(self, option)
Definition: __init__.py:84
def process_declarations(self, declarations)
Definition: __init__.py:348
def process_single_unpack(self, code, arg, arg_accessor)
Definition: __init__.py:262
def get_arg_accessor(self, arg, option)
Definition: __init__.py:163
def process_pre_arg_assign(self, template, option)
Definition: __init__.py:402
def process_all_checks(self, code, option)
Definition: __init__.py:236
def get_assign_args(self, arguments)
Definition: __init__.py:143
def get_type_unpack(self, arg, option)
Definition: __init__.py:52
def process_single_check(self, code, arg, arg_accessor)
Definition: __init__.py:205
def initialize(self, cwrap)
Definition: __init__.py:9
def get_type_check(self, arg, option)
Definition: __init__.py:21
def process_option_code(self, code, option)
Definition: __init__.py:311