1edb35d95SEugene Zelenko //===-- PythonDataObjects.h--------------------------------------*- C++ -*-===// 22c1f46dcSZachary Turner // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 62c1f46dcSZachary Turner // 72c1f46dcSZachary Turner //===----------------------------------------------------------------------===// 82c1f46dcSZachary Turner 9085328eeSLawrence D'Anna // 10085328eeSLawrence D'Anna // !! FIXME FIXME FIXME !! 11085328eeSLawrence D'Anna // 12085328eeSLawrence D'Anna // Python APIs nearly all can return an exception. They do this 13085328eeSLawrence D'Anna // by returning NULL, or -1, or some such value and setting 14085328eeSLawrence D'Anna // the exception state with PyErr_Set*(). Exceptions must be 15085328eeSLawrence D'Anna // handled before further python API functions are called. Failure 16085328eeSLawrence D'Anna // to do so will result in asserts on debug builds of python. 17085328eeSLawrence D'Anna // It will also sometimes, but not usually result in crashes of 18085328eeSLawrence D'Anna // release builds. 19085328eeSLawrence D'Anna // 20085328eeSLawrence D'Anna // Nearly all the code in this header does not handle python exceptions 21085328eeSLawrence D'Anna // correctly. It should all be converted to return Expected<> or 22085328eeSLawrence D'Anna // Error types to capture the exception. 23085328eeSLawrence D'Anna // 24085328eeSLawrence D'Anna // Everything in this file except functions that return Error or 25085328eeSLawrence D'Anna // Expected<> is considered deprecated and should not be 26085328eeSLawrence D'Anna // used in new code. If you need to use it, fix it first. 27085328eeSLawrence D'Anna // 28*d3bd5b3dSLawrence D'Anna // 29*d3bd5b3dSLawrence D'Anna // TODOs for this file 30*d3bd5b3dSLawrence D'Anna // 31*d3bd5b3dSLawrence D'Anna // * Make all methods safe for exceptions. 32*d3bd5b3dSLawrence D'Anna // 33*d3bd5b3dSLawrence D'Anna // * Eliminate method signatures that must translate exceptions into 34*d3bd5b3dSLawrence D'Anna // empty objects or NULLs. Almost everything here should return 35*d3bd5b3dSLawrence D'Anna // Expected<>. It should be acceptable for certain operations that 36*d3bd5b3dSLawrence D'Anna // can never fail to assert instead, such as the creation of 37*d3bd5b3dSLawrence D'Anna // PythonString from a string literal. 38*d3bd5b3dSLawrence D'Anna // 39*d3bd5b3dSLawrence D'Anna // * Elimintate Reset(), and make all non-default constructors private. 40*d3bd5b3dSLawrence D'Anna // Python objects should be created with Retain<> or Take<>, and they 41*d3bd5b3dSLawrence D'Anna // should be assigned with operator= 42*d3bd5b3dSLawrence D'Anna // 43*d3bd5b3dSLawrence D'Anna // * Eliminate default constructors, make python objects always 44*d3bd5b3dSLawrence D'Anna // nonnull, and use optionals where necessary. 45*d3bd5b3dSLawrence D'Anna // 46*d3bd5b3dSLawrence D'Anna 47085328eeSLawrence D'Anna 482c1f46dcSZachary Turner #ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H 492c1f46dcSZachary Turner #define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H 502c1f46dcSZachary Turner 51d68983e3SPavel Labath #ifndef LLDB_DISABLE_PYTHON 52d68983e3SPavel Labath 5341de9a97SKate Stone // LLDB Python header must be included first 5441de9a97SKate Stone #include "lldb-python.h" 5541de9a97SKate Stone 569c40264fSZachary Turner #include "lldb/Host/File.h" 57f2a8bccfSPavel Labath #include "lldb/Utility/StructuredData.h" 582c1f46dcSZachary Turner 595a72c02bSZachary Turner #include "llvm/ADT/ArrayRef.h" 605a72c02bSZachary Turner 612c1f46dcSZachary Turner namespace lldb_private { 62edb35d95SEugene Zelenko 63085328eeSLawrence D'Anna class PythonObject; 645a72c02bSZachary Turner class PythonBytes; 652c1f46dcSZachary Turner class PythonString; 662c1f46dcSZachary Turner class PythonList; 672c1f46dcSZachary Turner class PythonDictionary; 682c1f46dcSZachary Turner class PythonInteger; 69085328eeSLawrence D'Anna class PythonException; 702c1f46dcSZachary Turner 71b9c1b51eSKate Stone class StructuredPythonObject : public StructuredData::Generic { 722c1f46dcSZachary Turner public: 73b9c1b51eSKate Stone StructuredPythonObject() : StructuredData::Generic() {} 742c1f46dcSZachary Turner 75b9c1b51eSKate Stone StructuredPythonObject(void *obj) : StructuredData::Generic(obj) { 762c1f46dcSZachary Turner Py_XINCREF(GetValue()); 772c1f46dcSZachary Turner } 782c1f46dcSZachary Turner 79b9c1b51eSKate Stone ~StructuredPythonObject() override { 802c1f46dcSZachary Turner if (Py_IsInitialized()) 812c1f46dcSZachary Turner Py_XDECREF(GetValue()); 822c1f46dcSZachary Turner SetValue(nullptr); 832c1f46dcSZachary Turner } 842c1f46dcSZachary Turner 85b9c1b51eSKate Stone bool IsValid() const override { return GetValue() && GetValue() != Py_None; } 862c1f46dcSZachary Turner 872783d817SJonas Devlieghere void Serialize(llvm::json::OStream &s) const override; 882c1f46dcSZachary Turner 892c1f46dcSZachary Turner private: 902c1f46dcSZachary Turner DISALLOW_COPY_AND_ASSIGN(StructuredPythonObject); 912c1f46dcSZachary Turner }; 922c1f46dcSZachary Turner 93b9c1b51eSKate Stone enum class PyObjectType { 942c1f46dcSZachary Turner Unknown, 952c1f46dcSZachary Turner None, 96b81d715cSTatyana Krasnukha Boolean, 972c1f46dcSZachary Turner Integer, 982c1f46dcSZachary Turner Dictionary, 992c1f46dcSZachary Turner List, 1009c40264fSZachary Turner String, 1015a72c02bSZachary Turner Bytes, 102f9d6d204SZachary Turner ByteArray, 1037841efbbSZachary Turner Module, 104a1405147SZachary Turner Callable, 105a1405147SZachary Turner Tuple, 1069c40264fSZachary Turner File 1072c1f46dcSZachary Turner }; 1082c1f46dcSZachary Turner 109b9c1b51eSKate Stone enum class PyRefType { 110f8b22f8fSZachary Turner Borrowed, // We are not given ownership of the incoming PyObject. 111f8b22f8fSZachary Turner // We cannot safely hold it without calling Py_INCREF. 112f8b22f8fSZachary Turner Owned // We have ownership of the incoming PyObject. We should 113f8b22f8fSZachary Turner // not call Py_INCREF. 114f8b22f8fSZachary Turner }; 115f8b22f8fSZachary Turner 116085328eeSLawrence D'Anna namespace python { 117085328eeSLawrence D'Anna 118085328eeSLawrence D'Anna // Take a reference that you already own, and turn it into 119085328eeSLawrence D'Anna // a PythonObject. 120085328eeSLawrence D'Anna // 121085328eeSLawrence D'Anna // Most python API methods will return a +1 reference 122085328eeSLawrence D'Anna // if they succeed or NULL if and only if 123085328eeSLawrence D'Anna // they set an exception. Use this to collect such return 124085328eeSLawrence D'Anna // values, after checking for NULL. 125085328eeSLawrence D'Anna // 126085328eeSLawrence D'Anna // If T is not just PythonObject, then obj must be already be 127085328eeSLawrence D'Anna // checked to be of the correct type. 128085328eeSLawrence D'Anna template <typename T> T Take(PyObject *obj) { 129085328eeSLawrence D'Anna assert(obj); 130085328eeSLawrence D'Anna assert(!PyErr_Occurred()); 131085328eeSLawrence D'Anna T thing(PyRefType::Owned, obj); 132085328eeSLawrence D'Anna assert(thing.IsValid()); 133085328eeSLawrence D'Anna return std::move(thing); 134085328eeSLawrence D'Anna } 135085328eeSLawrence D'Anna 136085328eeSLawrence D'Anna // Retain a reference you have borrowed, and turn it into 137085328eeSLawrence D'Anna // a PythonObject. 138085328eeSLawrence D'Anna // 139085328eeSLawrence D'Anna // A minority of python APIs return a borrowed reference 140085328eeSLawrence D'Anna // instead of a +1. They will also return NULL if and only 141085328eeSLawrence D'Anna // if they set an exception. Use this to collect such return 142085328eeSLawrence D'Anna // values, after checking for NULL. 143085328eeSLawrence D'Anna // 144085328eeSLawrence D'Anna // If T is not just PythonObject, then obj must be already be 145085328eeSLawrence D'Anna // checked to be of the correct type. 146085328eeSLawrence D'Anna template <typename T> T Retain(PyObject *obj) { 147085328eeSLawrence D'Anna assert(obj); 148085328eeSLawrence D'Anna assert(!PyErr_Occurred()); 149085328eeSLawrence D'Anna T thing(PyRefType::Borrowed, obj); 150085328eeSLawrence D'Anna assert(thing.IsValid()); 151085328eeSLawrence D'Anna return std::move(thing); 152085328eeSLawrence D'Anna } 153085328eeSLawrence D'Anna 154085328eeSLawrence D'Anna } // namespace python 155085328eeSLawrence D'Anna 156b9c1b51eSKate Stone enum class PyInitialValue { Invalid, Empty }; 157f8b22f8fSZachary Turner 158085328eeSLawrence D'Anna template <typename T, typename Enable = void> struct PythonFormat; 159085328eeSLawrence D'Anna 160085328eeSLawrence D'Anna template <> struct PythonFormat<unsigned long long> { 161085328eeSLawrence D'Anna static constexpr char format = 'K'; 162085328eeSLawrence D'Anna static auto get(unsigned long long value) { return value; } 163085328eeSLawrence D'Anna }; 164085328eeSLawrence D'Anna 165085328eeSLawrence D'Anna template <> struct PythonFormat<long long> { 166085328eeSLawrence D'Anna static constexpr char format = 'L'; 167085328eeSLawrence D'Anna static auto get(long long value) { return value; } 168085328eeSLawrence D'Anna }; 169085328eeSLawrence D'Anna 170085328eeSLawrence D'Anna template <typename T> 171085328eeSLawrence D'Anna struct PythonFormat< 172085328eeSLawrence D'Anna T, typename std::enable_if<std::is_base_of<PythonObject, T>::value>::type> { 173085328eeSLawrence D'Anna static constexpr char format = 'O'; 174085328eeSLawrence D'Anna static auto get(const T &value) { return value.get(); } 175085328eeSLawrence D'Anna }; 176085328eeSLawrence D'Anna 177b9c1b51eSKate Stone class PythonObject { 1782c1f46dcSZachary Turner public: 179b9c1b51eSKate Stone PythonObject() : m_py_obj(nullptr) {} 1802c1f46dcSZachary Turner 181b9c1b51eSKate Stone PythonObject(PyRefType type, PyObject *py_obj) : m_py_obj(nullptr) { 182f8b22f8fSZachary Turner Reset(type, py_obj); 1832c1f46dcSZachary Turner } 1842c1f46dcSZachary Turner 185b9c1b51eSKate Stone PythonObject(const PythonObject &rhs) : m_py_obj(nullptr) { Reset(rhs); } 1862c1f46dcSZachary Turner 187085328eeSLawrence D'Anna PythonObject(PythonObject &&rhs) { 188085328eeSLawrence D'Anna m_py_obj = rhs.m_py_obj; 189085328eeSLawrence D'Anna rhs.m_py_obj = nullptr; 190085328eeSLawrence D'Anna } 191085328eeSLawrence D'Anna 192*d3bd5b3dSLawrence D'Anna ~PythonObject() { Reset(); } 1932c1f46dcSZachary Turner 194b9c1b51eSKate Stone void Reset() { 195085328eeSLawrence D'Anna if (m_py_obj && Py_IsInitialized()) 196085328eeSLawrence D'Anna Py_DECREF(m_py_obj); 197f8b22f8fSZachary Turner m_py_obj = nullptr; 1982c1f46dcSZachary Turner } 199f8b22f8fSZachary Turner 200b9c1b51eSKate Stone void Reset(const PythonObject &rhs) { 20160c24f70SZachary Turner if (!rhs.IsValid()) 202f8b22f8fSZachary Turner Reset(); 203f8b22f8fSZachary Turner else 204f8b22f8fSZachary Turner Reset(PyRefType::Borrowed, rhs.m_py_obj); 205f8b22f8fSZachary Turner } 206f8b22f8fSZachary Turner 207f8b22f8fSZachary Turner // PythonObject is implicitly convertible to PyObject *, which will call the 208f8b22f8fSZachary Turner // wrong overload. We want to explicitly disallow this, since a PyObject 209f8b22f8fSZachary Turner // *always* owns its reference. Therefore the overload which takes a 210f8b22f8fSZachary Turner // PyRefType doesn't make sense, and the copy constructor should be used. 211b9c1b51eSKate Stone void Reset(PyRefType type, const PythonObject &ref) = delete; 212f8b22f8fSZachary Turner 213*d3bd5b3dSLawrence D'Anna void Reset(PyRefType type, PyObject *py_obj) { 214f8b22f8fSZachary Turner if (py_obj == m_py_obj) 215f8b22f8fSZachary Turner return; 216f8b22f8fSZachary Turner 217f8b22f8fSZachary Turner if (Py_IsInitialized()) 218f8b22f8fSZachary Turner Py_XDECREF(m_py_obj); 219f8b22f8fSZachary Turner 220f8b22f8fSZachary Turner m_py_obj = py_obj; 221f8b22f8fSZachary Turner 222f8b22f8fSZachary Turner // If this is a borrowed reference, we need to convert it to 223f8b22f8fSZachary Turner // an owned reference by incrementing it. If it is an owned 224f8b22f8fSZachary Turner // reference (for example the caller allocated it with PyDict_New() 225f8b22f8fSZachary Turner // then we must *not* increment it. 226085328eeSLawrence D'Anna if (m_py_obj && Py_IsInitialized() && type == PyRefType::Borrowed) 227f8b22f8fSZachary Turner Py_XINCREF(m_py_obj); 2282c1f46dcSZachary Turner } 2292c1f46dcSZachary Turner 230b9c1b51eSKate Stone void Dump() const { 2312c1f46dcSZachary Turner if (m_py_obj) 2322c1f46dcSZachary Turner _PyObject_Dump(m_py_obj); 2332c1f46dcSZachary Turner else 2342c1f46dcSZachary Turner puts("NULL"); 2352c1f46dcSZachary Turner } 2362c1f46dcSZachary Turner 237b9c1b51eSKate Stone void Dump(Stream &strm) const; 2382c1f46dcSZachary Turner 239b9c1b51eSKate Stone PyObject *get() const { return m_py_obj; } 2402c1f46dcSZachary Turner 241b9c1b51eSKate Stone PyObject *release() { 24260c24f70SZachary Turner PyObject *result = m_py_obj; 24360c24f70SZachary Turner m_py_obj = nullptr; 24460c24f70SZachary Turner return result; 24560c24f70SZachary Turner } 24660c24f70SZachary Turner 247b9c1b51eSKate Stone PythonObject &operator=(const PythonObject &other) { 248f8b22f8fSZachary Turner Reset(PyRefType::Borrowed, other.get()); 249f8b22f8fSZachary Turner return *this; 2502c1f46dcSZachary Turner } 2512c1f46dcSZachary Turner 252085328eeSLawrence D'Anna void Reset(PythonObject &&other) { 253085328eeSLawrence D'Anna Reset(); 254085328eeSLawrence D'Anna m_py_obj = other.m_py_obj; 255085328eeSLawrence D'Anna other.m_py_obj = nullptr; 256085328eeSLawrence D'Anna } 257085328eeSLawrence D'Anna 258085328eeSLawrence D'Anna PythonObject &operator=(PythonObject &&other) { 259085328eeSLawrence D'Anna Reset(std::move(other)); 260085328eeSLawrence D'Anna return *this; 261085328eeSLawrence D'Anna } 262085328eeSLawrence D'Anna 263b9c1b51eSKate Stone PyObjectType GetObjectType() const; 2647841efbbSZachary Turner 265b9c1b51eSKate Stone PythonString Repr() const; 2667841efbbSZachary Turner 267b9c1b51eSKate Stone PythonString Str() const; 2687841efbbSZachary Turner 269b9c1b51eSKate Stone static PythonObject ResolveNameWithDictionary(llvm::StringRef name, 270b9c1b51eSKate Stone const PythonDictionary &dict); 2717841efbbSZachary Turner 272b58fb2f4SZachary Turner template <typename T> 273b9c1b51eSKate Stone static T ResolveNameWithDictionary(llvm::StringRef name, 274b9c1b51eSKate Stone const PythonDictionary &dict) { 275b58fb2f4SZachary Turner return ResolveNameWithDictionary(name, dict).AsType<T>(); 276b58fb2f4SZachary Turner } 277b58fb2f4SZachary Turner 278b9c1b51eSKate Stone PythonObject ResolveName(llvm::StringRef name) const; 2797841efbbSZachary Turner 280b9c1b51eSKate Stone template <typename T> T ResolveName(llvm::StringRef name) const { 281b58fb2f4SZachary Turner return ResolveName(name).AsType<T>(); 282b58fb2f4SZachary Turner } 283b58fb2f4SZachary Turner 284b9c1b51eSKate Stone bool HasAttribute(llvm::StringRef attribute) const; 2859c40264fSZachary Turner 286b9c1b51eSKate Stone PythonObject GetAttributeValue(llvm::StringRef attribute) const; 2877d6d218eSZachary Turner 288085328eeSLawrence D'Anna bool IsNone() const { return m_py_obj == Py_None; } 289f8b22f8fSZachary Turner 290085328eeSLawrence D'Anna bool IsValid() const { return m_py_obj != nullptr; } 291f8b22f8fSZachary Turner 292085328eeSLawrence D'Anna bool IsAllocated() const { return IsValid() && !IsNone(); } 293085328eeSLawrence D'Anna 294085328eeSLawrence D'Anna explicit operator bool() const { return IsValid() && !IsNone(); } 2952c1f46dcSZachary Turner 296b9c1b51eSKate Stone template <typename T> T AsType() const { 2977d6d218eSZachary Turner if (!T::Check(m_py_obj)) 2987d6d218eSZachary Turner return T(); 2997d6d218eSZachary Turner return T(PyRefType::Borrowed, m_py_obj); 3007d6d218eSZachary Turner } 3017d6d218eSZachary Turner 302b9c1b51eSKate Stone StructuredData::ObjectSP CreateStructuredObject() const; 3032c1f46dcSZachary Turner 3042c1f46dcSZachary Turner protected: 305085328eeSLawrence D'Anna static llvm::Error nullDeref() { 306085328eeSLawrence D'Anna return llvm::createStringError(llvm::inconvertibleErrorCode(), 307085328eeSLawrence D'Anna "A NULL PyObject* was dereferenced"); 308085328eeSLawrence D'Anna } 309085328eeSLawrence D'Anna static llvm::Error exception(const char *s = nullptr) { 310085328eeSLawrence D'Anna return llvm::make_error<PythonException>(s); 311085328eeSLawrence D'Anna } 312085328eeSLawrence D'Anna 313085328eeSLawrence D'Anna public: 314085328eeSLawrence D'Anna template <typename... T> 315085328eeSLawrence D'Anna llvm::Expected<PythonObject> CallMethod(const char *name, 316085328eeSLawrence D'Anna const T &... t) const { 317085328eeSLawrence D'Anna const char format[] = {'(', PythonFormat<T>::format..., ')', 0}; 318085328eeSLawrence D'Anna #if PY_MAJOR_VERSION < 3 319085328eeSLawrence D'Anna PyObject *obj = PyObject_CallMethod(m_py_obj, const_cast<char *>(name), 320085328eeSLawrence D'Anna const_cast<char *>(format), 321085328eeSLawrence D'Anna PythonFormat<T>::get(t)...); 322085328eeSLawrence D'Anna #else 323085328eeSLawrence D'Anna PyObject *obj = 324085328eeSLawrence D'Anna PyObject_CallMethod(m_py_obj, name, format, PythonFormat<T>::get(t)...); 325085328eeSLawrence D'Anna #endif 326085328eeSLawrence D'Anna if (!obj) 327085328eeSLawrence D'Anna return exception(); 328085328eeSLawrence D'Anna return python::Take<PythonObject>(obj); 329085328eeSLawrence D'Anna } 330085328eeSLawrence D'Anna 331085328eeSLawrence D'Anna llvm::Expected<PythonObject> GetAttribute(const char *name) const { 332085328eeSLawrence D'Anna if (!m_py_obj) 333085328eeSLawrence D'Anna return nullDeref(); 334085328eeSLawrence D'Anna PyObject *obj = PyObject_GetAttrString(m_py_obj, name); 335085328eeSLawrence D'Anna if (!obj) 336085328eeSLawrence D'Anna return exception(); 337085328eeSLawrence D'Anna return python::Take<PythonObject>(obj); 338085328eeSLawrence D'Anna } 339085328eeSLawrence D'Anna 340085328eeSLawrence D'Anna llvm::Expected<bool> IsTrue() { 341085328eeSLawrence D'Anna if (!m_py_obj) 342085328eeSLawrence D'Anna return nullDeref(); 343085328eeSLawrence D'Anna int r = PyObject_IsTrue(m_py_obj); 344085328eeSLawrence D'Anna if (r < 0) 345085328eeSLawrence D'Anna return exception(); 346085328eeSLawrence D'Anna return !!r; 347085328eeSLawrence D'Anna } 348085328eeSLawrence D'Anna 349085328eeSLawrence D'Anna llvm::Expected<long long> AsLongLong() { 350085328eeSLawrence D'Anna if (!m_py_obj) 351085328eeSLawrence D'Anna return nullDeref(); 352085328eeSLawrence D'Anna assert(!PyErr_Occurred()); 353085328eeSLawrence D'Anna long long r = PyLong_AsLongLong(m_py_obj); 354085328eeSLawrence D'Anna if (PyErr_Occurred()) 355085328eeSLawrence D'Anna return exception(); 356085328eeSLawrence D'Anna return r; 357085328eeSLawrence D'Anna } 358085328eeSLawrence D'Anna 359085328eeSLawrence D'Anna llvm::Expected<bool> IsInstance(const PythonObject &cls) { 360085328eeSLawrence D'Anna if (!m_py_obj || !cls.IsValid()) 361085328eeSLawrence D'Anna return nullDeref(); 362085328eeSLawrence D'Anna int r = PyObject_IsInstance(m_py_obj, cls.get()); 363085328eeSLawrence D'Anna if (r < 0) 364085328eeSLawrence D'Anna return exception(); 365085328eeSLawrence D'Anna return !!r; 366085328eeSLawrence D'Anna } 367085328eeSLawrence D'Anna 368085328eeSLawrence D'Anna protected: 3692c1f46dcSZachary Turner PyObject *m_py_obj; 3702c1f46dcSZachary Turner }; 3712c1f46dcSZachary Turner 372085328eeSLawrence D'Anna namespace python { 373085328eeSLawrence D'Anna 374085328eeSLawrence D'Anna // This is why C++ needs monads. 375085328eeSLawrence D'Anna template <typename T> llvm::Expected<T> As(llvm::Expected<PythonObject> &&obj) { 376085328eeSLawrence D'Anna if (!obj) 377085328eeSLawrence D'Anna return obj.takeError(); 378085328eeSLawrence D'Anna if (!T::Check(obj.get().get())) 379085328eeSLawrence D'Anna return llvm::createStringError(llvm::inconvertibleErrorCode(), 380085328eeSLawrence D'Anna "type error"); 381085328eeSLawrence D'Anna return T(PyRefType::Borrowed, std::move(obj.get().get())); 382085328eeSLawrence D'Anna } 383085328eeSLawrence D'Anna 384085328eeSLawrence D'Anna template <> llvm::Expected<bool> As<bool>(llvm::Expected<PythonObject> &&obj); 385085328eeSLawrence D'Anna 386085328eeSLawrence D'Anna template <> 387085328eeSLawrence D'Anna llvm::Expected<long long> As<long long>(llvm::Expected<PythonObject> &&obj); 388085328eeSLawrence D'Anna 389085328eeSLawrence D'Anna } // namespace python 390085328eeSLawrence D'Anna 391*d3bd5b3dSLawrence D'Anna template <class T> class TypedPythonObject : public PythonObject { 3925a72c02bSZachary Turner public: 393*d3bd5b3dSLawrence D'Anna // override to perform implicit type conversions on Reset 394*d3bd5b3dSLawrence D'Anna // This can be eliminated once we drop python 2 support. 395*d3bd5b3dSLawrence D'Anna static void Convert(PyRefType &type, PyObject *&py_obj) {} 396*d3bd5b3dSLawrence D'Anna 397*d3bd5b3dSLawrence D'Anna using PythonObject::Reset; 398*d3bd5b3dSLawrence D'Anna 399*d3bd5b3dSLawrence D'Anna void Reset(PyRefType type, PyObject *py_obj) { 400*d3bd5b3dSLawrence D'Anna Reset(); 401*d3bd5b3dSLawrence D'Anna if (!py_obj) 402*d3bd5b3dSLawrence D'Anna return; 403*d3bd5b3dSLawrence D'Anna T::Convert(type, py_obj); 404*d3bd5b3dSLawrence D'Anna if (T::Check(py_obj)) 405*d3bd5b3dSLawrence D'Anna PythonObject::Reset(type, py_obj); 406*d3bd5b3dSLawrence D'Anna else if (type == PyRefType::Owned) 407*d3bd5b3dSLawrence D'Anna Py_DECREF(py_obj); 408*d3bd5b3dSLawrence D'Anna } 409*d3bd5b3dSLawrence D'Anna 410*d3bd5b3dSLawrence D'Anna TypedPythonObject(PyRefType type, PyObject *py_obj) { Reset(type, py_obj); } 411*d3bd5b3dSLawrence D'Anna 412*d3bd5b3dSLawrence D'Anna TypedPythonObject() {} 413*d3bd5b3dSLawrence D'Anna }; 414*d3bd5b3dSLawrence D'Anna 415*d3bd5b3dSLawrence D'Anna class PythonBytes : public TypedPythonObject<PythonBytes> { 416*d3bd5b3dSLawrence D'Anna public: 417*d3bd5b3dSLawrence D'Anna using TypedPythonObject::TypedPythonObject; 4185a72c02bSZachary Turner explicit PythonBytes(llvm::ArrayRef<uint8_t> bytes); 4195a72c02bSZachary Turner PythonBytes(const uint8_t *bytes, size_t length); 4205a72c02bSZachary Turner 421b9c1b51eSKate Stone static bool Check(PyObject *py_obj); 4225a72c02bSZachary Turner 423b9c1b51eSKate Stone llvm::ArrayRef<uint8_t> GetBytes() const; 4245a72c02bSZachary Turner 425b9c1b51eSKate Stone size_t GetSize() const; 4265a72c02bSZachary Turner 427b9c1b51eSKate Stone void SetBytes(llvm::ArrayRef<uint8_t> stringbytes); 4285a72c02bSZachary Turner 429b9c1b51eSKate Stone StructuredData::StringSP CreateStructuredString() const; 4305a72c02bSZachary Turner }; 4315a72c02bSZachary Turner 432*d3bd5b3dSLawrence D'Anna class PythonByteArray : public TypedPythonObject<PythonByteArray> { 433f9d6d204SZachary Turner public: 434*d3bd5b3dSLawrence D'Anna using TypedPythonObject::TypedPythonObject; 435f9d6d204SZachary Turner explicit PythonByteArray(llvm::ArrayRef<uint8_t> bytes); 436f9d6d204SZachary Turner PythonByteArray(const uint8_t *bytes, size_t length); 437f9d6d204SZachary Turner PythonByteArray(const PythonBytes &object); 438f9d6d204SZachary Turner 439b9c1b51eSKate Stone static bool Check(PyObject *py_obj); 440f9d6d204SZachary Turner 441b9c1b51eSKate Stone llvm::ArrayRef<uint8_t> GetBytes() const; 442f9d6d204SZachary Turner 443b9c1b51eSKate Stone size_t GetSize() const; 444f9d6d204SZachary Turner 445b9c1b51eSKate Stone void SetBytes(llvm::ArrayRef<uint8_t> stringbytes); 446f9d6d204SZachary Turner 447b9c1b51eSKate Stone StructuredData::StringSP CreateStructuredString() const; 448f9d6d204SZachary Turner }; 449f9d6d204SZachary Turner 450*d3bd5b3dSLawrence D'Anna class PythonString : public TypedPythonObject<PythonString> { 4512c1f46dcSZachary Turner public: 452*d3bd5b3dSLawrence D'Anna using TypedPythonObject::TypedPythonObject; 453085328eeSLawrence D'Anna static llvm::Expected<PythonString> FromUTF8(llvm::StringRef string); 454085328eeSLawrence D'Anna 455*d3bd5b3dSLawrence D'Anna PythonString() : TypedPythonObject() {} // MSVC requires this for some reason 456edb35d95SEugene Zelenko 457*d3bd5b3dSLawrence D'Anna explicit PythonString(llvm::StringRef string); // safe, null on error 4582c1f46dcSZachary Turner 45922c8efcdSZachary Turner static bool Check(PyObject *py_obj); 460*d3bd5b3dSLawrence D'Anna static void Convert(PyRefType &type, PyObject *&py_obj); 4612c1f46dcSZachary Turner 462085328eeSLawrence D'Anna llvm::StringRef GetString() const; // safe, empty string on error 463085328eeSLawrence D'Anna 464085328eeSLawrence D'Anna llvm::Expected<llvm::StringRef> AsUTF8() const; 4652c1f46dcSZachary Turner 466b9c1b51eSKate Stone size_t GetSize() const; 4672c1f46dcSZachary Turner 468085328eeSLawrence D'Anna void SetString(llvm::StringRef string); // safe, null on error 4692c1f46dcSZachary Turner 4702c1f46dcSZachary Turner StructuredData::StringSP CreateStructuredString() const; 4712c1f46dcSZachary Turner }; 4722c1f46dcSZachary Turner 473*d3bd5b3dSLawrence D'Anna class PythonInteger : public TypedPythonObject<PythonInteger> { 4742c1f46dcSZachary Turner public: 475*d3bd5b3dSLawrence D'Anna using TypedPythonObject::TypedPythonObject; 476edb35d95SEugene Zelenko 477*d3bd5b3dSLawrence D'Anna PythonInteger() : TypedPythonObject() {} // MSVC requires this for some reason 478*d3bd5b3dSLawrence D'Anna 479*d3bd5b3dSLawrence D'Anna explicit PythonInteger(int64_t value); 4802c1f46dcSZachary Turner 48122c8efcdSZachary Turner static bool Check(PyObject *py_obj); 482*d3bd5b3dSLawrence D'Anna static void Convert(PyRefType &type, PyObject *&py_obj); 4832c1f46dcSZachary Turner 4842c1f46dcSZachary Turner int64_t GetInteger() const; 4852c1f46dcSZachary Turner 486b9c1b51eSKate Stone void SetInteger(int64_t value); 4872c1f46dcSZachary Turner 4882c1f46dcSZachary Turner StructuredData::IntegerSP CreateStructuredInteger() const; 4892c1f46dcSZachary Turner }; 4902c1f46dcSZachary Turner 491*d3bd5b3dSLawrence D'Anna class PythonBoolean : public TypedPythonObject<PythonBoolean> { 492b81d715cSTatyana Krasnukha public: 493*d3bd5b3dSLawrence D'Anna using TypedPythonObject::TypedPythonObject; 494b81d715cSTatyana Krasnukha 495*d3bd5b3dSLawrence D'Anna explicit PythonBoolean(bool value); 496b81d715cSTatyana Krasnukha 497b81d715cSTatyana Krasnukha static bool Check(PyObject *py_obj); 498b81d715cSTatyana Krasnukha 499b81d715cSTatyana Krasnukha bool GetValue() const; 500b81d715cSTatyana Krasnukha 501b81d715cSTatyana Krasnukha void SetValue(bool value); 502b81d715cSTatyana Krasnukha 503b81d715cSTatyana Krasnukha StructuredData::BooleanSP CreateStructuredBoolean() const; 504b81d715cSTatyana Krasnukha }; 505b81d715cSTatyana Krasnukha 506*d3bd5b3dSLawrence D'Anna class PythonList : public TypedPythonObject<PythonList> { 5072c1f46dcSZachary Turner public: 508*d3bd5b3dSLawrence D'Anna using TypedPythonObject::TypedPythonObject; 509*d3bd5b3dSLawrence D'Anna 510*d3bd5b3dSLawrence D'Anna PythonList() : TypedPythonObject() {} // MSVC requires this for some reason 511*d3bd5b3dSLawrence D'Anna 51287f47729SZachary Turner explicit PythonList(PyInitialValue value); 51387f47729SZachary Turner explicit PythonList(int list_size); 5142c1f46dcSZachary Turner 51522c8efcdSZachary Turner static bool Check(PyObject *py_obj); 51622c8efcdSZachary Turner 5172c1f46dcSZachary Turner uint32_t GetSize() const; 5182c1f46dcSZachary Turner 5192c1f46dcSZachary Turner PythonObject GetItemAtIndex(uint32_t index) const; 5202c1f46dcSZachary Turner 521f8b22f8fSZachary Turner void SetItemAtIndex(uint32_t index, const PythonObject &object); 5222c1f46dcSZachary Turner 523f8b22f8fSZachary Turner void AppendItem(const PythonObject &object); 5242c1f46dcSZachary Turner 5252c1f46dcSZachary Turner StructuredData::ArraySP CreateStructuredArray() const; 5262c1f46dcSZachary Turner }; 5272c1f46dcSZachary Turner 528*d3bd5b3dSLawrence D'Anna class PythonTuple : public TypedPythonObject<PythonTuple> { 529a1405147SZachary Turner public: 530*d3bd5b3dSLawrence D'Anna using TypedPythonObject::TypedPythonObject; 531*d3bd5b3dSLawrence D'Anna 532a1405147SZachary Turner explicit PythonTuple(PyInitialValue value); 533a1405147SZachary Turner explicit PythonTuple(int tuple_size); 534a1405147SZachary Turner PythonTuple(std::initializer_list<PythonObject> objects); 535a1405147SZachary Turner PythonTuple(std::initializer_list<PyObject *> objects); 536a1405147SZachary Turner 537a1405147SZachary Turner static bool Check(PyObject *py_obj); 538a1405147SZachary Turner 539a1405147SZachary Turner uint32_t GetSize() const; 540a1405147SZachary Turner 541a1405147SZachary Turner PythonObject GetItemAtIndex(uint32_t index) const; 542a1405147SZachary Turner 543a1405147SZachary Turner void SetItemAtIndex(uint32_t index, const PythonObject &object); 544a1405147SZachary Turner 545a1405147SZachary Turner StructuredData::ArraySP CreateStructuredArray() const; 546a1405147SZachary Turner }; 547a1405147SZachary Turner 548*d3bd5b3dSLawrence D'Anna class PythonDictionary : public TypedPythonObject<PythonDictionary> { 5492c1f46dcSZachary Turner public: 550*d3bd5b3dSLawrence D'Anna using TypedPythonObject::TypedPythonObject; 551edb35d95SEugene Zelenko 552*d3bd5b3dSLawrence D'Anna PythonDictionary() : TypedPythonObject() {} // MSVC requires this for some reason 553*d3bd5b3dSLawrence D'Anna 554*d3bd5b3dSLawrence D'Anna explicit PythonDictionary(PyInitialValue value); 5552c1f46dcSZachary Turner 55622c8efcdSZachary Turner static bool Check(PyObject *py_obj); 55722c8efcdSZachary Turner 5582c1f46dcSZachary Turner uint32_t GetSize() const; 5592c1f46dcSZachary Turner 560f8b22f8fSZachary Turner PythonList GetKeys() const; 5612c1f46dcSZachary Turner 562f8b22f8fSZachary Turner PythonObject GetItemForKey(const PythonObject &key) const; 563f8b22f8fSZachary Turner void SetItemForKey(const PythonObject &key, const PythonObject &value); 5642c1f46dcSZachary Turner 5652c1f46dcSZachary Turner StructuredData::DictionarySP CreateStructuredDictionary() const; 5662c1f46dcSZachary Turner }; 56787f47729SZachary Turner 568*d3bd5b3dSLawrence D'Anna class PythonModule : public TypedPythonObject<PythonModule> { 5697841efbbSZachary Turner public: 570*d3bd5b3dSLawrence D'Anna using TypedPythonObject::TypedPythonObject; 5717841efbbSZachary Turner 5727841efbbSZachary Turner static bool Check(PyObject *py_obj); 5737841efbbSZachary Turner 574b9c1b51eSKate Stone static PythonModule BuiltinsModule(); 575a1405147SZachary Turner 576b9c1b51eSKate Stone static PythonModule MainModule(); 577a1405147SZachary Turner 578b9c1b51eSKate Stone static PythonModule AddModule(llvm::StringRef module); 5797841efbbSZachary Turner 580085328eeSLawrence D'Anna // safe, returns invalid on error; 581085328eeSLawrence D'Anna static PythonModule ImportModule(llvm::StringRef name) { 582085328eeSLawrence D'Anna std::string s = name; 583085328eeSLawrence D'Anna auto mod = Import(s.c_str()); 584085328eeSLawrence D'Anna if (!mod) { 585085328eeSLawrence D'Anna llvm::consumeError(mod.takeError()); 586085328eeSLawrence D'Anna return PythonModule(); 587085328eeSLawrence D'Anna } 588085328eeSLawrence D'Anna return std::move(mod.get()); 589085328eeSLawrence D'Anna } 590085328eeSLawrence D'Anna 591085328eeSLawrence D'Anna static llvm::Expected<PythonModule> Import(const char *name); 592085328eeSLawrence D'Anna 593085328eeSLawrence D'Anna llvm::Expected<PythonObject> Get(const char *name); 5942419f1d5SZachary Turner 5957841efbbSZachary Turner PythonDictionary GetDictionary() const; 5967841efbbSZachary Turner }; 5977841efbbSZachary Turner 598*d3bd5b3dSLawrence D'Anna class PythonCallable : public TypedPythonObject<PythonCallable> { 599a1405147SZachary Turner public: 600*d3bd5b3dSLawrence D'Anna using TypedPythonObject::TypedPythonObject; 601*d3bd5b3dSLawrence D'Anna 602b58fb2f4SZachary Turner struct ArgInfo { 603b58fb2f4SZachary Turner size_t count; 604a5d6765cSEnrico Granata bool is_bound_method : 1; 605b58fb2f4SZachary Turner bool has_varargs : 1; 606b58fb2f4SZachary Turner bool has_kwargs : 1; 607b58fb2f4SZachary Turner }; 608b58fb2f4SZachary Turner 609b9c1b51eSKate Stone static bool Check(PyObject *py_obj); 610a1405147SZachary Turner 611b9c1b51eSKate Stone ArgInfo GetNumArguments() const; 61227a14f19SJim Ingham 61327a14f19SJim Ingham // If the callable is a Py_Class, then find the number of arguments 61427a14f19SJim Ingham // of the __init__ method. 61527a14f19SJim Ingham ArgInfo GetNumInitArguments() const; 616b58fb2f4SZachary Turner 617b9c1b51eSKate Stone PythonObject operator()(); 618a1405147SZachary Turner 619b9c1b51eSKate Stone PythonObject operator()(std::initializer_list<PyObject *> args); 620a1405147SZachary Turner 621b9c1b51eSKate Stone PythonObject operator()(std::initializer_list<PythonObject> args); 622b58fb2f4SZachary Turner 623b58fb2f4SZachary Turner template <typename Arg, typename... Args> 624b9c1b51eSKate Stone PythonObject operator()(const Arg &arg, Args... args) { 625b58fb2f4SZachary Turner return operator()({arg, args...}); 626b58fb2f4SZachary Turner } 627a1405147SZachary Turner }; 628a1405147SZachary Turner 629*d3bd5b3dSLawrence D'Anna class PythonFile : public TypedPythonObject<PythonFile> { 6309c40264fSZachary Turner public: 631*d3bd5b3dSLawrence D'Anna using TypedPythonObject::TypedPythonObject; 632edb35d95SEugene Zelenko 633*d3bd5b3dSLawrence D'Anna PythonFile() : TypedPythonObject() {} // MSVC requires this for some reason 6349c40264fSZachary Turner 6359c40264fSZachary Turner static bool Check(PyObject *py_obj); 6369c40264fSZachary Turner 637d9b553ecSLawrence D'Anna static llvm::Expected<PythonFile> FromFile(File &file, 638d9b553ecSLawrence D'Anna const char *mode = nullptr); 639d9b553ecSLawrence D'Anna 640d9b553ecSLawrence D'Anna // FIXME delete this after FILE* typemaps are deleted 641d9b553ecSLawrence D'Anna // and ScriptInterpreterPython is fixed 642d9b553ecSLawrence D'Anna PythonFile(File &file, const char *mode = nullptr) { 643d9b553ecSLawrence D'Anna auto f = FromFile(file, mode); 644d9b553ecSLawrence D'Anna if (f) 645d9b553ecSLawrence D'Anna *this = std::move(f.get()); 646d9b553ecSLawrence D'Anna else { 647d9b553ecSLawrence D'Anna Reset(); 648d9b553ecSLawrence D'Anna llvm::consumeError(f.takeError()); 649d9b553ecSLawrence D'Anna } 650d9b553ecSLawrence D'Anna } 651eda01c31SZachary Turner 6522fce1137SLawrence D'Anna lldb::FileUP GetUnderlyingFile() const; 653085328eeSLawrence D'Anna 654085328eeSLawrence D'Anna llvm::Expected<lldb::FileSP> ConvertToFile(bool borrowed = false); 655085328eeSLawrence D'Anna llvm::Expected<lldb::FileSP> 656085328eeSLawrence D'Anna ConvertToFileForcingUseOfScriptingIOMethods(bool borrowed = false); 6579c40264fSZachary Turner }; 6589c40264fSZachary Turner 659085328eeSLawrence D'Anna class PythonException : public llvm::ErrorInfo<PythonException> { 660085328eeSLawrence D'Anna private: 661085328eeSLawrence D'Anna PyObject *m_exception_type, *m_exception, *m_traceback; 662085328eeSLawrence D'Anna PyObject *m_repr_bytes; 663085328eeSLawrence D'Anna 664085328eeSLawrence D'Anna public: 665085328eeSLawrence D'Anna static char ID; 666085328eeSLawrence D'Anna const char *toCString() const; 667085328eeSLawrence D'Anna PythonException(const char *caller = nullptr); 668085328eeSLawrence D'Anna void Restore(); 669085328eeSLawrence D'Anna ~PythonException(); 670085328eeSLawrence D'Anna void log(llvm::raw_ostream &OS) const override; 671085328eeSLawrence D'Anna std::error_code convertToErrorCode() const override; 672085328eeSLawrence D'Anna }; 673085328eeSLawrence D'Anna 674085328eeSLawrence D'Anna // This extracts the underlying T out of an Expected<T> and returns it. 675085328eeSLawrence D'Anna // If the Expected is an Error instead of a T, that error will be converted 676085328eeSLawrence D'Anna // into a python exception, and this will return a default-constructed T. 677085328eeSLawrence D'Anna // 678085328eeSLawrence D'Anna // This is appropriate for use right at the boundary of python calling into 679085328eeSLawrence D'Anna // C++, such as in a SWIG typemap. In such a context you should simply 680085328eeSLawrence D'Anna // check if the returned T is valid, and if it is, return a NULL back 681085328eeSLawrence D'Anna // to python. This will result in the Error being raised as an exception 682085328eeSLawrence D'Anna // from python code's point of view. 683085328eeSLawrence D'Anna // 684085328eeSLawrence D'Anna // For example: 685085328eeSLawrence D'Anna // ``` 686085328eeSLawrence D'Anna // Expected<Foo *> efoop = some_cpp_function(); 687085328eeSLawrence D'Anna // Foo *foop = unwrapOrSetPythonException(efoop); 688085328eeSLawrence D'Anna // if (!foop) 689085328eeSLawrence D'Anna // return NULL; 690085328eeSLawrence D'Anna // do_something(*foop); 691085328eeSLawrence D'Anna // 692085328eeSLawrence D'Anna // If the Error returned was itself created because a python exception was 693085328eeSLawrence D'Anna // raised when C++ code called into python, then the original exception 694085328eeSLawrence D'Anna // will be restored. Otherwise a simple string exception will be raised. 695085328eeSLawrence D'Anna template <typename T> T unwrapOrSetPythonException(llvm::Expected<T> expected) { 696085328eeSLawrence D'Anna if (expected) 697085328eeSLawrence D'Anna return expected.get(); 698085328eeSLawrence D'Anna llvm::handleAllErrors( 699085328eeSLawrence D'Anna expected.takeError(), [](PythonException &E) { E.Restore(); }, 700085328eeSLawrence D'Anna [](const llvm::ErrorInfoBase &E) { 701085328eeSLawrence D'Anna PyErr_SetString(PyExc_Exception, E.message().c_str()); 702085328eeSLawrence D'Anna }); 703085328eeSLawrence D'Anna return T(); 704085328eeSLawrence D'Anna } 705085328eeSLawrence D'Anna 7062c1f46dcSZachary Turner } // namespace lldb_private 7072c1f46dcSZachary Turner 708a281b42bSZachary Turner #endif 709d68983e3SPavel Labath 710d68983e3SPavel Labath #endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H 711