3 """Base class from which all cwrap plugins should inherit. 5 Override any of the following methods to implement the desired wrapping 10 """Initialize the Plugin class prior to calling any other functions. 12 It is used to give the Plugin access to the cwrap object's helper 16 cwrap: the cwrap object performing the wrapping. 22 """Used to generate code for runtime checks of object types. 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 30 Template('(PyObject*)Py_TYPE($arg) == THPTensorClass') 32 As a simpler example, if the type == 'bool' then we would return: 34 Template('PyBool_Check($arg)') 36 Note that the name of the identifier that will be substituted must be 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 46 A Template string as described above, or None if this Plugin does 47 not have a corresponding type check for the passed type. 53 """Used to generate code unpacking of Python objects into C types. 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 62 Template('((THPTensor*)$arg)->cdata') 64 For a simpler type, such as a long, we could do: 66 Template('PyLong_AsLong($arg)') 68 though in practice we will use our own custom unpacking code. Once 69 again, $arg must be used as the identifier. 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 78 A Template string as described above, or None if this Plugin does 79 not have a corresponding type unpack for the passed type. 85 """Used to generate code wrapping a function's return value. 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']. 94 Continuing on with our THTensor* example, we might do something like: 96 Template('return THPTensor_(New)($result);') 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 *. 102 For a bool, we could do Template('return PyBool_FromLong($result);'). 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. 109 option: dictionary containing the information for this specific 113 A Template string as described above, or None if this Plugin does 114 not have a corresponding return wrapper for the functions return 121 """Used to create a code template to wrap the options. 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. 130 Note that for any declaration only one Plugin can generate the wrapper 134 declaration: the declaration for the wrapped method. 137 A template string representing the entire function declaration, 138 with identifiers as necessary. 144 """Used to modify argument metadata prior to assignment. 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. 155 arguments: a list of argument metadata dictionaries. 158 The same list of arguments, with any modifications as you see fit. 164 """Used to generate a string for accessing the passed arg. 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 174 Its best to look at some of the existing Plugins to get a sense of what 178 arg: a dictionary specifying attributes of the arg to be accessed 179 option: dictionary containing the information for this specific 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. 190 """Used to modify the code for the entire output file. 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. 197 code: a string source code for the wrapped declarations. 200 The same code, modified as the plugin sees fit. 206 """Used to postprocess a type check. 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: 213 '(PyObject*)Py_TYPE(PyTuple_GET_ITEM(args, 1)) == THPTensorClass' 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. 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 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. 237 """Used to generate additional checks based on all the individual ones. 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: 244 CHECK_TYPE(GET_ARG(0)) && CHECK_TYPE(GET_ARG(1)) && .. 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. 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 256 The modified code string with any additional checks, or just the 257 existing code if no modifications are to be made. 263 """Used to postprocess a type unpack. 265 Same as process_single_check above, but for type unpacking. E.g. an 266 example code could be: 268 PyLong_FromLong(PyTuple_GET_ITEM(args, 0)) 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 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 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. 292 """Used to modify the arguments to the underlying C function call. 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. 301 code: A string as described above. 302 option: dictionary containing the information for this specific 306 The same code, modified as the plugin sees fit. 312 """Used to modify the entire code body for an option. 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. 320 code: string representing the generated code for the option 321 option: dictionary containing the information for this specific 325 The same code, modified as the plugin sees fit. 331 """Used to modify the entire code body for a declaration. 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. 339 code: string representing the generated code for the declaration 340 declaration: the declaration metadata. 343 The same code, modified as the plugin sees fit. 349 """Used to process/modify the function's declaration. 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. 359 Its best to look at some of the existing Plugins to get a sense of what 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. 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. 376 """Used to modify the code template for the option. 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. 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 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 397 The same "code template", possibly modified by this plugin. 403 """Used to include any code before argument assignment. 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. 410 template: String representing the code to be inserted. If other 411 plugins have included code for pre_arg_assign, it will be included 413 option: dictionary containing the information for this specific 417 template, with any additional code if needed. 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