18 \ingroup Pythonizations
19 Decorator that allows to pythonize C++ classes. To pythonize means to add
20 some extra behaviour to a C++ class that is used from Python via PyROOT,
21 so that such a class can be used in an easier / more "pythonic" way.
22 When a pythonization is registered with this decorator, the injection of
23 the new behaviour in the C++ class is done immediately, if the class has
24 already been used from the application, or lazily, i.e. only when the class
25 is first accessed from the application.
28 class_name (string/iterable[string]): specifies either a single string or
29 multiple strings, where each string can be either (i) the name of a
30 C++ class to be pythonized, or (ii) a prefix to match all classes
31 whose name starts with that prefix.
32 ns (string): namespace of the classes to be pythonized. Default is the
33 global namespace (`::`).
34 is_prefix (boolean): if True, `class_name` contains one or multiple
35 prefixes, each prefix potentially matching multiple classes.
37 These are examples of prefixes and namespace and what they match:
38 - class_name="", ns="::" : all classes in the global namespace.
39 - class_name="C", ns="::" : all classes in the global namespace
40 whose name starts with "C"
41 - class_name="", ns="NS1::NS2" : all classes in namespace "NS1::NS2"
42 - class_name="C", ns="NS1::NS2" : all classes in namespace
43 "NS1::NS2" whose name starts with "C"
46 function: function that receives the user-defined function and
69 return class_name
in target
73 The real decorator. Accepts a user-provided function and decorates it.
74 An inner function - a wrapper of the user function - is registered in
75 cppyy as a pythonizor.
78 user_pythonizor (function): user-provided function to be decorated.
79 It implements some pythonization. It can accept two parameters:
80 the class to be pythonized, i.e. the Python proxy of the class
81 in which new behaviour can be injected, and optionally the name
82 of that class (can be used e.g. to do some more complex
86 function: the user function, after being registered as a
100 Wrapper function with the parameters that cppyy requires for a
101 pythonizor function (class proxy and class name). It invokes the
102 user function only if the current class - a candidate for being
103 pythonized - matches the `target` argument of the decorator.
106 klass (class type): cppyy proxy of the class that is the
107 current candidate to be pythonized.
108 name (string): name of the class that is the current candidate
111 from ._generic
import pythonize_generic
119 _invoke(user_pythonizor, npars, klass, fqn)
129 return user_pythonizor
131 return pythonization_impl
139 Helper function to check the type of the `class name` argument specified by
140 the user in a @pythonization decorator.
143 target (string/iterable[string]): class name(s)/prefix(es).
146 list[string]: class name(s)/prefix(es) in `target`, with no repetitions.
158 'Invalid type of "target" argument in @pythonization: must be string or iterable of strings'
161 target = list(set(target))
168 Checks that a given target of a pythonizor does not specify a namespace
169 (only the class name / prefix of a class name should be present).
172 target (string): class name/prefix.
177 'Invalid value of "class_name" argument in '
178 '@pythonization: namespace definition found ("{}"). '
179 'Please use the "ns" parameter to specify the '
180 "namespace".
format(target)
186 Checks the number of parameters of the `f` function.
189 f (function): user pythonizor function.
192 int: number of positional parameters of `f`.
195 if npars == 0
or npars > 2:
197 "Pythonizor function {} has a wrong number of "
198 "parameters ({}). Allowed parameters are the class to "
205def _invoke(user_pythonizor, npars, klass, fqn):
207 Invokes the given user pythonizor function with the right arguments.
210 user_pythonizor (function): user pythonizor function.
211 npars (int): number of parameters of the user pythonizor function.
212 klass (class type): cppyy proxy of the class to be pythonized.
213 fqn (string): fully-qualified name of the class to be pythonized.
222 print(
"Error pythonizing class {}:".
format(fqn))
231 Finds already instantiated classes in namespace `ns` that pass the filter
232 of `passes_filter`. Every matching class is pythonized with the
233 `user_pythonizor` function.
234 This makes sure a pythonizor is also applied to classes that have already
235 been used at the time the pythonizor is registered.
238 ns (string): namespace of the class names of prefixes in `targets`.
239 passes_filter (function): function that determines if a given class
240 is the target of `user_pythonizor`.
241 user_pythonizor (function): user pythonizor function.
242 npars (int): number of parameters of the user pythonizor function.
265 if hasattr(instantiation,
"__cpp_name__"):
268 if hasattr(instantiation,
"__name__"):
272 f
"The template instantiation '{instantiation}' cannot be properly pythonized. Please report this as a bug."
275 ns_vars = vars(ns_obj)
277 if str(var_value).
startswith(
"<class cppyy.gbl."):
281 if str(var_value).
startswith(
"<cppyy.Template"):
286 instantiations =
getattr(var_value,
"_instantiations", {})
291 if instance
not in ns_vars:
292 instance_name = var_name +
"<" +
",".join(map(get_class_name, args)) +
">"
298 Finds and returns the proxy object of the `ns` namespace, if it has already
302 ns (string): a namespace.
305 namespace proxy object, if the namespace has already been accessed,
317 ns_vars = vars(ns_obj)
318 if ns
not in ns_vars:
327 Registers the ROOT pythonizations with cppyy for lazy injection.
330 exclude = [
"_rdf_utils",
"_rdf_pyz",
"_rdf_conversion_maps"]
332 if module_name
not in exclude:
340 from ROOT
import gSystem
358 from ROOT
import gSystem
382 from ROOT
import gROOT
392 print(
"Press <space> key to continue")