24 \ingroup Pythonizations
25 Decorator that allows to pythonize C++ classes. To pythonize means to add
26 some extra behaviour to a C++ class that is used from Python via PyROOT,
27 so that such a class can be used in an easier / more "pythonic" way.
28 When a pythonization is registered with this decorator, the injection of
29 the new behaviour in the C++ class is done immediately, if the class has
30 already been used from the application, or lazily, i.e. only when the class
31 is first accessed from the application.
34 class_name (string/iterable[string]): specifies either a single string or
35 multiple strings, where each string can be either (i) the name of a
36 C++ class to be pythonized, or (ii) a prefix to match all classes
37 whose name starts with that prefix.
38 ns (string): namespace of the classes to be pythonized. Default is the
39 global namespace (`::`).
40 is_prefix (boolean): if True, `class_name` contains one or multiple
41 prefixes, each prefix potentially matching multiple classes.
43 These are examples of prefixes and namespace and what they match:
44 - class_name="", ns="::" : all classes in the global namespace.
45 - class_name="C", ns="::" : all classes in the global namespace
46 whose name starts with "C"
47 - class_name="", ns="NS1::NS2" : all classes in namespace "NS1::NS2"
48 - class_name="C", ns="NS1::NS2" : all classes in namespace
49 "NS1::NS2" whose name starts with "C"
52 function: function that receives the user-defined function and
75 return class_name
in target
79 The real decorator. Accepts a user-provided function and decorates it.
80 An inner function - a wrapper of the user function - is registered in
81 cppyy as a pythonizor.
84 user_pythonizor (function): user-provided function to be decorated.
85 It implements some pythonization. It can accept two parameters:
86 the class to be pythonized, i.e. the Python proxy of the class
87 in which new behaviour can be injected, and optionally the name
88 of that class (can be used e.g. to do some more complex
92 function: the user function, after being registered as a
105 Wrapper function with the parameters that cppyy requires for a
106 pythonizor function (class proxy and class name). It invokes the
107 user function only if the current class - a candidate for being
108 pythonized - matches the `target` argument of the decorator.
111 klass (class type): cppyy proxy of the class that is the
112 current candidate to be pythonized.
113 name (string): name of the class that is the current candidate
116 from ._generic
import pythonize_generic
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: