Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TDirectoryPyz.cxx
Go to the documentation of this file.
1// Author: Danilo Piparo, Stefan Wunsch, Massimiliano Galli CERN 08/2018
2// Original PyROOT code by Wim Lavrijsen, LBL
3
4/*************************************************************************
5 * Copyright (C) 1995-2018, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12#include "CPyCppyy.h"
13#include "CPPInstance.h"
14#include "PyROOTPythonize.h"
15#include "ProxyWrappers.h"
16#include "Utility.h"
17#include "PyzCppHelpers.hxx"
18#include "TClass.h"
19#include "TDirectory.h"
20#include "TKey.h"
21#include "TObject.h"
22#include "Python.h"
23
24using namespace CPyCppyy;
25
26////////////////////////////////////////////////////////////////////////////////
27/// \brief Implements the WriteObject method of TDirectory
28/// This method allows to write objects into TDirectory instances with this
29/// syntax:
30/// ~~~{.py}
31/// myDir.WriteObject(myObj, "myKeyName")
32/// ~~~
34{
35 CPPInstance *wrt = nullptr;
36 PyObject *name = nullptr;
37 PyObject *option = nullptr;
38 Int_t bufsize = 0;
39 if (!PyArg_ParseTuple(args, const_cast<char *>("O!O!|O!i:TDirectory::WriteObject"),
40 &CPPInstance_Type, &wrt,
42 &CPyCppyy_PyText_Type, &option,
43 &bufsize))
44 return nullptr;
45 auto dir = (TDirectory *)GetTClass(self)->DynamicCast(TDirectory::Class(), self->GetObject());
46 if (!dir) {
47 PyErr_SetString(PyExc_TypeError,
48 "TDirectory::WriteObject must be called with a TDirectory instance as first argument");
49 return nullptr;
50 }
51
52 // Implement a check on whether the object is derived from TObject or not. Similarly to what is done in
53 // TDirectory::WriteObject with SFINAE. Unfortunately, 'wrt' is a void* in this scope and can't be casted to its
54 // concrete type.
55 auto *wrtclass = GetTClass(wrt);
56 void *wrtobj = wrt->GetObject();
57 Int_t result = 0;
58
59 if (wrtclass->IsTObject()) {
60 // If the found TClass is derived from TObject, cast the object to a TObject since we are just interested in the
61 // object title for the purposes of the WriteTObject function.
62 auto objtowrite = static_cast<TObject *>(wrtclass->DynamicCast(TObject::Class(), wrtobj));
63
64 if (option != nullptr) {
65 result =
66 dir->WriteTObject(objtowrite, CPyCppyy_PyText_AsString(name), CPyCppyy_PyText_AsString(option), bufsize);
67 } else {
68 result = dir->WriteTObject(objtowrite, CPyCppyy_PyText_AsString(name));
69 }
70 } else {
71 if (option != nullptr) {
72 result = dir->WriteObjectAny(wrtobj, wrtclass, CPyCppyy_PyText_AsString(name),
73 CPyCppyy_PyText_AsString(option), bufsize);
74 } else {
75 result = dir->WriteObjectAny(wrtobj, wrtclass, CPyCppyy_PyText_AsString(name));
76 }
77 }
78
79 return PyInt_FromLong((Long_t)result);
80}
81
82////////////////////////////////////////////////////////////////////////////////
83/// \brief Implements a getter to assign to TDirectory.__getattr__
84/// Method that is assigned to TDirectory.__getattr__. It relies on Get to
85/// obtain the object from the TDirectory and adds on top:
86/// - Raising an AttributeError if the object does not exist
87/// - Caching the result of a successful get for future re-attempts.
88/// Once cached, the same object is retrieved every time.
89/// This pythonisation is inherited by TDirectoryFile and TFile.
91{
92 // Injection of TDirectory.__getattr__ that raises AttributeError on failure.
93 PyObject *result = CallPyObjMethod(self, "Get", attr);
94 if (!result)
95 return result;
96
97 if (!PyObject_IsTrue(result)) {
98 PyObject *astr = PyObject_Str(attr);
99 PyObject *stypestr = PyObject_Str(PyObject_Type(self));
100 PyErr_Format(PyExc_AttributeError, "%s object has no attribute \'%s\'", CPyCppyy_PyText_AsString(stypestr),
102 Py_DECREF(astr);
103 Py_DECREF(result);
104 return nullptr;
105 }
106
107 // Caching behavior seems to be more clear to the user; can always override said
108 // behavior (i.e. re-read from file) with an explicit Get() call
109 PyObject_SetAttr(self, attr, result);
110 return result;
111}
112
113////////////////////////////////////////////////////////////////////////////
114/// \brief Add attr syntax to TDirectory
115/// \param[in] self Always null, since this is a module function.
116/// \param[in] args Pointer to a Python tuple object containing the arguments
117/// This allows to use TDirectory and daughters (such as TDirectoryFile and TFile)
118/// as follows
119/// ~~~{.py}
120/// myfile.mydir.mysubdir.myHist.Draw()
121/// ~~~
123{
124 PyObject *pyclass = PyTuple_GetItem(args, 0);
125 Utility::AddToClass(pyclass, "__getattr__", (PyCFunction)TDirectoryGetAttr, METH_O);
127}
128
129////////////////////////////////////////////////////////////////////////////
130/// \brief Add pythonisation of TDirectory::WriteObject
131/// \param[in] self Always null, since this is a module function.
132/// \param[in] args Pointer to a Python tuple object containing the arguments
134{
135 PyObject *pyclass = PyTuple_GetItem(args, 0);
136 Utility::AddToClass(pyclass, "WriteObject", (PyCFunction)TDirectoryWriteObject);
138}
#define CPyCppyy_PyText_AsString
Definition CPyCppyy.h:97
#define Py_RETURN_NONE
Definition CPyCppyy.h:289
#define CPyCppyy_PyText_Type
Definition CPyCppyy.h:115
PyInt_FromLong
_object PyObject
TClass * GetTClass(const CPyCppyy::CPPInstance *pyobj)
PyObject * CallPyObjMethod(PyObject *obj, const char *meth)
Set of helper functions that are invoked from the C++ implementation of pythonizations.
long Long_t
Definition RtypesCore.h:54
PyObject * TDirectoryWriteObject(CPPInstance *self, PyObject *args)
Implements the WriteObject method of TDirectory This method allows to write objects into TDirectory i...
PyObject * TDirectoryGetAttr(PyObject *self, PyObject *attr)
Implements a getter to assign to TDirectory.__getattr__ Method that is assigned to TDirectory....
char name[80]
Definition TGX11.cxx:110
void * DynamicCast(const TClass *base, void *obj, Bool_t up=kTRUE)
Cast obj of this class type up to baseclass cl if up is true.
Definition TClass.cxx:4901
Describe directory structure in memory.
Definition TDirectory.h:45
Mother of all ROOT objects.
Definition TObject.h:41
bool AddToClass(PyObject *pyclass, const char *label, PyCFunction cfunc, int flags=METH_VARARGS)
Definition Utility.cxx:169
Set of helper functions that are invoked from the pythonizors, on the Python side.
PyTypeObject CPPInstance_Type
PyObject * AddDirectoryWritePyz(PyObject *self, PyObject *args)
Add pythonisation of TDirectory::WriteObject.
PyObject * AddDirectoryGetAttrPyz(PyObject *self, PyObject *args)
Add attr syntax to TDirectory.