26 \ingroup Pythonizations
27 Decorator that allows to pythonize C++ classes. To pythonize means to add
28 some extra behaviour to a C++ class that is used from Python via PyROOT,
29 so that such a class can be used in an easier / more "pythonic" way.
30 When a pythonization is registered with this decorator, the injection of
31 the new behaviour in the C++ class is done immediately, if the class has
32 already been used from the application, or lazily, i.e. only when the class
33 is first accessed from the application.
36 class_name (string/iterable[string]): specifies either a single string or
37 multiple strings, where each string can be either (i) the name of a
38 C++ class to be pythonized, or (ii) a prefix to match all classes
39 whose name starts with that prefix.
40 ns (string): namespace of the classes to be pythonized. Default is the
41 global namespace (`::`).
42 is_prefix (boolean): if True, `class_name` contains one or multiple
43 prefixes, each prefix potentially matching multiple classes.
45 These are examples of prefixes and namespace and what they match:
46 - class_name="", ns="::" : all classes in the global namespace.
47 - class_name="C", ns="::" : all classes in the global namespace
48 whose name starts with "C"
49 - class_name="", ns="NS1::NS2" : all classes in namespace "NS1::NS2"
50 - class_name="C", ns="NS1::NS2" : all classes in namespace
51 "NS1::NS2" whose name starts with "C"
54 function: function that receives the user-defined function and
76 return class_name
in target
80 The real decorator. Accepts a user-provided function and decorates it.
81 An inner function - a wrapper of the user function - is registered in
82 cppyy as a pythonizor.
85 user_pythonizor (function): user-provided function to be decorated.
86 It implements some pythonization. It can accept two parameters:
87 the class to be pythonized, i.e. the Python proxy of the class
88 in which new behaviour can be injected, and optionally the name
89 of that class (can be used e.g. to do some more complex
93 function: the user function, after being registered as a
106 Wrapper function with the parameters that cppyy requires for a
107 pythonizor function (class proxy and class name). It invokes the
108 user function only if the current class - a candidate for being
109 pythonized - matches the `target` argument of the decorator.
112 klass (class type): cppyy proxy of the class that is the
113 current candidate to be pythonized.
114 name (string): name of the class that is the current candidate
121 pythonize_generic(klass, fqn)
124 _invoke(user_pythonizor, npars, klass, fqn)
134 return user_pythonizor
136 return pythonization_impl
144 Helper function to check the type of the `class name` argument specified by
145 the user in a @pythonization decorator.
148 target (string/iterable[string]): class name(s)/prefix(es).
151 list[string]: class name(s)/prefix(es) in `target`, with no repetitions.
163 'Invalid type of "target" argument in @pythonization: must be string or iterable of strings'
166 target = list(set(target))
173 Checks that a given target of a pythonizor does not specify a namespace
174 (only the class name / prefix of a class name should be present).
177 target (string): class name/prefix.
182 'Invalid value of "class_name" argument in '
183 '@pythonization: namespace definition found ("{}"). '
184 'Please use the "ns" parameter to specify the '
185 "namespace".
format(target)
191 Checks the number of parameters of the `f` function.
194 f (function): user pythonizor function.
197 int: number of positional parameters of `f`.
200 if npars == 0
or npars > 2:
202 "Pythonizor function {} has a wrong number of "
203 "parameters ({}). Allowed parameters are the class to "
210def _invoke(user_pythonizor, npars, klass, fqn):
212 Invokes the given user pythonizor function with the right arguments.
215 user_pythonizor (function): user pythonizor function.
216 npars (int): number of parameters of the user pythonizor function.
217 klass (class type): cppyy proxy of the class to be pythonized.
218 fqn (string): fully-qualified name of the class to be pythonized.
227 print(
"Error pythonizing class {}:".
format(fqn))
236 Finds already instantiated classes in namespace `ns` that pass the filter
237 of `passes_filter`. Every matching class is pythonized with the
238 `user_pythonizor` function.
239 This makes sure a pythonizor is also applied to classes that have already
240 been used at the time the pythonizor is registered.
243 ns (string): namespace of the class names of prefixes in `targets`.
244 passes_filter (function): function that determines if a given class
245 is the target of `user_pythonizor`.
246 user_pythonizor (function): user pythonizor function.
247 npars (int): number of parameters of the user pythonizor function.
270 if hasattr(instantiation,
"__cpp_name__"):
273 if hasattr(instantiation,
"__name__"):
277 f
"The template instantiation '{instantiation}' cannot be properly pythonized. Please report this as a bug."
280 ns_vars = vars(ns_obj)
282 if str(var_value).
startswith(
"<class cppyy.gbl."):
286 if str(var_value).
startswith(
"<cppyy.Template"):
291 instantiations =
getattr(var_value,
"_instantiations", {})
296 if instance
not in ns_vars:
297 instance_name = var_name +
"<" +
",".join(map(get_class_name, args)) +
">"
303 Finds and returns the proxy object of the `ns` namespace, if it has already
307 ns (string): a namespace.
310 namespace proxy object, if the namespace has already been accessed,
317 ns_obj = gbl_namespace
321 ns_vars = vars(ns_obj)
322 if ns
not in ns_vars:
331 Registers the ROOT pythonizations with cppyy for lazy injection.
334 exclude = [
"_rdf_utils",
"_rdf_pyz",
"_rdf_conversion_maps"]
336 if module_name
not in exclude: