10b57cec5SDimitry Andric //===-- PythonDataObjects.h--------------------------------------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 99dba64beSDimitry Andric // 109dba64beSDimitry Andric // !! FIXME FIXME FIXME !! 119dba64beSDimitry Andric // 129dba64beSDimitry Andric // Python APIs nearly all can return an exception. They do this 139dba64beSDimitry Andric // by returning NULL, or -1, or some such value and setting 149dba64beSDimitry Andric // the exception state with PyErr_Set*(). Exceptions must be 159dba64beSDimitry Andric // handled before further python API functions are called. Failure 169dba64beSDimitry Andric // to do so will result in asserts on debug builds of python. 179dba64beSDimitry Andric // It will also sometimes, but not usually result in crashes of 189dba64beSDimitry Andric // release builds. 199dba64beSDimitry Andric // 209dba64beSDimitry Andric // Nearly all the code in this header does not handle python exceptions 219dba64beSDimitry Andric // correctly. It should all be converted to return Expected<> or 229dba64beSDimitry Andric // Error types to capture the exception. 239dba64beSDimitry Andric // 249dba64beSDimitry Andric // Everything in this file except functions that return Error or 259dba64beSDimitry Andric // Expected<> is considered deprecated and should not be 269dba64beSDimitry Andric // used in new code. If you need to use it, fix it first. 279dba64beSDimitry Andric // 289dba64beSDimitry Andric // 299dba64beSDimitry Andric // TODOs for this file 309dba64beSDimitry Andric // 319dba64beSDimitry Andric // * Make all methods safe for exceptions. 329dba64beSDimitry Andric // 339dba64beSDimitry Andric // * Eliminate method signatures that must translate exceptions into 349dba64beSDimitry Andric // empty objects or NULLs. Almost everything here should return 359dba64beSDimitry Andric // Expected<>. It should be acceptable for certain operations that 369dba64beSDimitry Andric // can never fail to assert instead, such as the creation of 379dba64beSDimitry Andric // PythonString from a string literal. 389dba64beSDimitry Andric // 399dba64beSDimitry Andric // * Elimintate Reset(), and make all non-default constructors private. 409dba64beSDimitry Andric // Python objects should be created with Retain<> or Take<>, and they 419dba64beSDimitry Andric // should be assigned with operator= 429dba64beSDimitry Andric // 439dba64beSDimitry Andric // * Eliminate default constructors, make python objects always 449dba64beSDimitry Andric // nonnull, and use optionals where necessary. 459dba64beSDimitry Andric // 469dba64beSDimitry Andric 479dba64beSDimitry Andric 480b57cec5SDimitry Andric #ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H 490b57cec5SDimitry Andric #define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H 500b57cec5SDimitry Andric 51*480093f4SDimitry Andric #include "lldb/Host/Config.h" 52*480093f4SDimitry Andric 53*480093f4SDimitry Andric #if LLDB_ENABLE_PYTHON 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric // LLDB Python header must be included first 560b57cec5SDimitry Andric #include "lldb-python.h" 570b57cec5SDimitry Andric 580b57cec5SDimitry Andric #include "lldb/Host/File.h" 590b57cec5SDimitry Andric #include "lldb/Utility/StructuredData.h" 600b57cec5SDimitry Andric 610b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h" 620b57cec5SDimitry Andric 630b57cec5SDimitry Andric namespace lldb_private { 649dba64beSDimitry Andric namespace python { 650b57cec5SDimitry Andric 669dba64beSDimitry Andric class PythonObject; 670b57cec5SDimitry Andric class PythonBytes; 680b57cec5SDimitry Andric class PythonString; 690b57cec5SDimitry Andric class PythonList; 700b57cec5SDimitry Andric class PythonDictionary; 710b57cec5SDimitry Andric class PythonInteger; 729dba64beSDimitry Andric class PythonException; 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric class StructuredPythonObject : public StructuredData::Generic { 750b57cec5SDimitry Andric public: 760b57cec5SDimitry Andric StructuredPythonObject() : StructuredData::Generic() {} 770b57cec5SDimitry Andric 780b57cec5SDimitry Andric StructuredPythonObject(void *obj) : StructuredData::Generic(obj) { 790b57cec5SDimitry Andric Py_XINCREF(GetValue()); 800b57cec5SDimitry Andric } 810b57cec5SDimitry Andric 820b57cec5SDimitry Andric ~StructuredPythonObject() override { 830b57cec5SDimitry Andric if (Py_IsInitialized()) 840b57cec5SDimitry Andric Py_XDECREF(GetValue()); 850b57cec5SDimitry Andric SetValue(nullptr); 860b57cec5SDimitry Andric } 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric bool IsValid() const override { return GetValue() && GetValue() != Py_None; } 890b57cec5SDimitry Andric 909dba64beSDimitry Andric void Serialize(llvm::json::OStream &s) const override; 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric private: 930b57cec5SDimitry Andric DISALLOW_COPY_AND_ASSIGN(StructuredPythonObject); 940b57cec5SDimitry Andric }; 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric enum class PyObjectType { 970b57cec5SDimitry Andric Unknown, 980b57cec5SDimitry Andric None, 990b57cec5SDimitry Andric Boolean, 1000b57cec5SDimitry Andric Integer, 1010b57cec5SDimitry Andric Dictionary, 1020b57cec5SDimitry Andric List, 1030b57cec5SDimitry Andric String, 1040b57cec5SDimitry Andric Bytes, 1050b57cec5SDimitry Andric ByteArray, 1060b57cec5SDimitry Andric Module, 1070b57cec5SDimitry Andric Callable, 1080b57cec5SDimitry Andric Tuple, 1090b57cec5SDimitry Andric File 1100b57cec5SDimitry Andric }; 1110b57cec5SDimitry Andric 1120b57cec5SDimitry Andric enum class PyRefType { 1130b57cec5SDimitry Andric Borrowed, // We are not given ownership of the incoming PyObject. 1140b57cec5SDimitry Andric // We cannot safely hold it without calling Py_INCREF. 1150b57cec5SDimitry Andric Owned // We have ownership of the incoming PyObject. We should 1160b57cec5SDimitry Andric // not call Py_INCREF. 1170b57cec5SDimitry Andric }; 1180b57cec5SDimitry Andric 1199dba64beSDimitry Andric 1209dba64beSDimitry Andric // Take a reference that you already own, and turn it into 1219dba64beSDimitry Andric // a PythonObject. 1229dba64beSDimitry Andric // 1239dba64beSDimitry Andric // Most python API methods will return a +1 reference 1249dba64beSDimitry Andric // if they succeed or NULL if and only if 1259dba64beSDimitry Andric // they set an exception. Use this to collect such return 1269dba64beSDimitry Andric // values, after checking for NULL. 1279dba64beSDimitry Andric // 1289dba64beSDimitry Andric // If T is not just PythonObject, then obj must be already be 1299dba64beSDimitry Andric // checked to be of the correct type. 1309dba64beSDimitry Andric template <typename T> T Take(PyObject *obj) { 1319dba64beSDimitry Andric assert(obj); 1329dba64beSDimitry Andric assert(!PyErr_Occurred()); 1339dba64beSDimitry Andric T thing(PyRefType::Owned, obj); 1349dba64beSDimitry Andric assert(thing.IsValid()); 135*480093f4SDimitry Andric return thing; 1369dba64beSDimitry Andric } 1379dba64beSDimitry Andric 1389dba64beSDimitry Andric // Retain a reference you have borrowed, and turn it into 1399dba64beSDimitry Andric // a PythonObject. 1409dba64beSDimitry Andric // 1419dba64beSDimitry Andric // A minority of python APIs return a borrowed reference 1429dba64beSDimitry Andric // instead of a +1. They will also return NULL if and only 1439dba64beSDimitry Andric // if they set an exception. Use this to collect such return 1449dba64beSDimitry Andric // values, after checking for NULL. 1459dba64beSDimitry Andric // 1469dba64beSDimitry Andric // If T is not just PythonObject, then obj must be already be 1479dba64beSDimitry Andric // checked to be of the correct type. 1489dba64beSDimitry Andric template <typename T> T Retain(PyObject *obj) { 1499dba64beSDimitry Andric assert(obj); 1509dba64beSDimitry Andric assert(!PyErr_Occurred()); 1519dba64beSDimitry Andric T thing(PyRefType::Borrowed, obj); 1529dba64beSDimitry Andric assert(thing.IsValid()); 153*480093f4SDimitry Andric return thing; 1549dba64beSDimitry Andric } 1559dba64beSDimitry Andric 1569dba64beSDimitry Andric // This class can be used like a utility function to convert from 1579dba64beSDimitry Andric // a llvm-friendly Twine into a null-terminated const char *, 1589dba64beSDimitry Andric // which is the form python C APIs want their strings in. 1599dba64beSDimitry Andric // 1609dba64beSDimitry Andric // Example: 1619dba64beSDimitry Andric // const llvm::Twine &some_twine; 1629dba64beSDimitry Andric // PyFoo_Bar(x, y, z, NullTerminated(some_twine)); 1639dba64beSDimitry Andric // 1649dba64beSDimitry Andric // Why a class instead of a function? If the twine isn't already null 1659dba64beSDimitry Andric // terminated, it will need a temporary buffer to copy the string 1669dba64beSDimitry Andric // into. We need that buffer to stick around for the lifetime of the 1679dba64beSDimitry Andric // statement. 1689dba64beSDimitry Andric class NullTerminated { 1699dba64beSDimitry Andric const char *str; 1709dba64beSDimitry Andric llvm::SmallString<32> storage; 1719dba64beSDimitry Andric 1729dba64beSDimitry Andric public: 1739dba64beSDimitry Andric NullTerminated(const llvm::Twine &twine) { 1749dba64beSDimitry Andric llvm::StringRef ref = twine.toNullTerminatedStringRef(storage); 1759dba64beSDimitry Andric str = ref.begin(); 1769dba64beSDimitry Andric } 1779dba64beSDimitry Andric operator const char *() { return str; } 1789dba64beSDimitry Andric }; 1799dba64beSDimitry Andric 1809dba64beSDimitry Andric inline llvm::Error nullDeref() { 1819dba64beSDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(), 1829dba64beSDimitry Andric "A NULL PyObject* was dereferenced"); 1839dba64beSDimitry Andric } 1849dba64beSDimitry Andric 1859dba64beSDimitry Andric inline llvm::Error exception(const char *s = nullptr) { 1869dba64beSDimitry Andric return llvm::make_error<PythonException>(s); 1879dba64beSDimitry Andric } 1889dba64beSDimitry Andric 1899dba64beSDimitry Andric inline llvm::Error keyError() { 1909dba64beSDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(), 1919dba64beSDimitry Andric "key not in dict"); 1929dba64beSDimitry Andric } 1939dba64beSDimitry Andric 194*480093f4SDimitry Andric #if PY_MAJOR_VERSION < 3 195*480093f4SDimitry Andric // The python 2 API declares some arguments as char* that should 196*480093f4SDimitry Andric // be const char *, but it doesn't actually modify them. 197*480093f4SDimitry Andric inline char *py2_const_cast(const char *s) { return const_cast<char *>(s); } 198*480093f4SDimitry Andric #else 199*480093f4SDimitry Andric inline const char *py2_const_cast(const char *s) { return s; } 200*480093f4SDimitry Andric #endif 201*480093f4SDimitry Andric 2020b57cec5SDimitry Andric enum class PyInitialValue { Invalid, Empty }; 2030b57cec5SDimitry Andric 2049dba64beSDimitry Andric template <typename T, typename Enable = void> struct PythonFormat; 2059dba64beSDimitry Andric 2069dba64beSDimitry Andric template <> struct PythonFormat<unsigned long long> { 2079dba64beSDimitry Andric static constexpr char format = 'K'; 2089dba64beSDimitry Andric static auto get(unsigned long long value) { return value; } 2099dba64beSDimitry Andric }; 2109dba64beSDimitry Andric 2119dba64beSDimitry Andric template <> struct PythonFormat<long long> { 2129dba64beSDimitry Andric static constexpr char format = 'L'; 2139dba64beSDimitry Andric static auto get(long long value) { return value; } 2149dba64beSDimitry Andric }; 2159dba64beSDimitry Andric 2169dba64beSDimitry Andric template <> struct PythonFormat<PyObject *> { 2179dba64beSDimitry Andric static constexpr char format = 'O'; 2189dba64beSDimitry Andric static auto get(PyObject *value) { return value; } 2199dba64beSDimitry Andric }; 2209dba64beSDimitry Andric 2219dba64beSDimitry Andric template <typename T> 2229dba64beSDimitry Andric struct PythonFormat< 2239dba64beSDimitry Andric T, typename std::enable_if<std::is_base_of<PythonObject, T>::value>::type> { 2249dba64beSDimitry Andric static constexpr char format = 'O'; 2259dba64beSDimitry Andric static auto get(const T &value) { return value.get(); } 2269dba64beSDimitry Andric }; 2279dba64beSDimitry Andric 2280b57cec5SDimitry Andric class PythonObject { 2290b57cec5SDimitry Andric public: 2300b57cec5SDimitry Andric PythonObject() : m_py_obj(nullptr) {} 2310b57cec5SDimitry Andric 2329dba64beSDimitry Andric PythonObject(PyRefType type, PyObject *py_obj) { 2330b57cec5SDimitry Andric m_py_obj = py_obj; 2340b57cec5SDimitry Andric // If this is a borrowed reference, we need to convert it to 2350b57cec5SDimitry Andric // an owned reference by incrementing it. If it is an owned 2360b57cec5SDimitry Andric // reference (for example the caller allocated it with PyDict_New() 2370b57cec5SDimitry Andric // then we must *not* increment it. 2389dba64beSDimitry Andric if (m_py_obj && Py_IsInitialized() && type == PyRefType::Borrowed) 2390b57cec5SDimitry Andric Py_XINCREF(m_py_obj); 2400b57cec5SDimitry Andric } 2410b57cec5SDimitry Andric 2429dba64beSDimitry Andric PythonObject(const PythonObject &rhs) 2439dba64beSDimitry Andric : PythonObject(PyRefType::Borrowed, rhs.m_py_obj) {} 2449dba64beSDimitry Andric 2459dba64beSDimitry Andric PythonObject(PythonObject &&rhs) { 2469dba64beSDimitry Andric m_py_obj = rhs.m_py_obj; 2479dba64beSDimitry Andric rhs.m_py_obj = nullptr; 2489dba64beSDimitry Andric } 2499dba64beSDimitry Andric 2509dba64beSDimitry Andric ~PythonObject() { Reset(); } 2519dba64beSDimitry Andric 2529dba64beSDimitry Andric void Reset() { 2539dba64beSDimitry Andric if (m_py_obj && Py_IsInitialized()) 2549dba64beSDimitry Andric Py_DECREF(m_py_obj); 2559dba64beSDimitry Andric m_py_obj = nullptr; 2569dba64beSDimitry Andric } 2579dba64beSDimitry Andric 2580b57cec5SDimitry Andric void Dump() const { 2590b57cec5SDimitry Andric if (m_py_obj) 2600b57cec5SDimitry Andric _PyObject_Dump(m_py_obj); 2610b57cec5SDimitry Andric else 2620b57cec5SDimitry Andric puts("NULL"); 2630b57cec5SDimitry Andric } 2640b57cec5SDimitry Andric 2650b57cec5SDimitry Andric void Dump(Stream &strm) const; 2660b57cec5SDimitry Andric 2670b57cec5SDimitry Andric PyObject *get() const { return m_py_obj; } 2680b57cec5SDimitry Andric 2690b57cec5SDimitry Andric PyObject *release() { 2700b57cec5SDimitry Andric PyObject *result = m_py_obj; 2710b57cec5SDimitry Andric m_py_obj = nullptr; 2720b57cec5SDimitry Andric return result; 2730b57cec5SDimitry Andric } 2740b57cec5SDimitry Andric 2759dba64beSDimitry Andric PythonObject &operator=(PythonObject other) { 2769dba64beSDimitry Andric Reset(); 2779dba64beSDimitry Andric m_py_obj = std::exchange(other.m_py_obj, nullptr); 2780b57cec5SDimitry Andric return *this; 2790b57cec5SDimitry Andric } 2800b57cec5SDimitry Andric 2810b57cec5SDimitry Andric PyObjectType GetObjectType() const; 2820b57cec5SDimitry Andric 2830b57cec5SDimitry Andric PythonString Repr() const; 2840b57cec5SDimitry Andric 2850b57cec5SDimitry Andric PythonString Str() const; 2860b57cec5SDimitry Andric 2870b57cec5SDimitry Andric static PythonObject ResolveNameWithDictionary(llvm::StringRef name, 2880b57cec5SDimitry Andric const PythonDictionary &dict); 2890b57cec5SDimitry Andric 2900b57cec5SDimitry Andric template <typename T> 2910b57cec5SDimitry Andric static T ResolveNameWithDictionary(llvm::StringRef name, 2920b57cec5SDimitry Andric const PythonDictionary &dict) { 2930b57cec5SDimitry Andric return ResolveNameWithDictionary(name, dict).AsType<T>(); 2940b57cec5SDimitry Andric } 2950b57cec5SDimitry Andric 2960b57cec5SDimitry Andric PythonObject ResolveName(llvm::StringRef name) const; 2970b57cec5SDimitry Andric 2980b57cec5SDimitry Andric template <typename T> T ResolveName(llvm::StringRef name) const { 2990b57cec5SDimitry Andric return ResolveName(name).AsType<T>(); 3000b57cec5SDimitry Andric } 3010b57cec5SDimitry Andric 3020b57cec5SDimitry Andric bool HasAttribute(llvm::StringRef attribute) const; 3030b57cec5SDimitry Andric 3040b57cec5SDimitry Andric PythonObject GetAttributeValue(llvm::StringRef attribute) const; 3050b57cec5SDimitry Andric 3069dba64beSDimitry Andric bool IsNone() const { return m_py_obj == Py_None; } 3070b57cec5SDimitry Andric 3089dba64beSDimitry Andric bool IsValid() const { return m_py_obj != nullptr; } 3090b57cec5SDimitry Andric 3109dba64beSDimitry Andric bool IsAllocated() const { return IsValid() && !IsNone(); } 3119dba64beSDimitry Andric 3129dba64beSDimitry Andric explicit operator bool() const { return IsValid() && !IsNone(); } 3130b57cec5SDimitry Andric 3140b57cec5SDimitry Andric template <typename T> T AsType() const { 3150b57cec5SDimitry Andric if (!T::Check(m_py_obj)) 3160b57cec5SDimitry Andric return T(); 3170b57cec5SDimitry Andric return T(PyRefType::Borrowed, m_py_obj); 3180b57cec5SDimitry Andric } 3190b57cec5SDimitry Andric 3200b57cec5SDimitry Andric StructuredData::ObjectSP CreateStructuredObject() const; 3210b57cec5SDimitry Andric 3229dba64beSDimitry Andric public: 3239dba64beSDimitry Andric template <typename... T> 3249dba64beSDimitry Andric llvm::Expected<PythonObject> CallMethod(const char *name, 3259dba64beSDimitry Andric const T &... t) const { 3269dba64beSDimitry Andric const char format[] = {'(', PythonFormat<T>::format..., ')', 0}; 3279dba64beSDimitry Andric PyObject *obj = 3289dba64beSDimitry Andric PyObject_CallMethod(m_py_obj, py2_const_cast(name), 3299dba64beSDimitry Andric py2_const_cast(format), PythonFormat<T>::get(t)...); 3309dba64beSDimitry Andric if (!obj) 3319dba64beSDimitry Andric return exception(); 3329dba64beSDimitry Andric return python::Take<PythonObject>(obj); 3339dba64beSDimitry Andric } 3349dba64beSDimitry Andric 3359dba64beSDimitry Andric template <typename... T> 3369dba64beSDimitry Andric llvm::Expected<PythonObject> Call(const T &... t) const { 3379dba64beSDimitry Andric const char format[] = {'(', PythonFormat<T>::format..., ')', 0}; 3389dba64beSDimitry Andric PyObject *obj = PyObject_CallFunction(m_py_obj, py2_const_cast(format), 3399dba64beSDimitry Andric PythonFormat<T>::get(t)...); 3409dba64beSDimitry Andric if (!obj) 3419dba64beSDimitry Andric return exception(); 3429dba64beSDimitry Andric return python::Take<PythonObject>(obj); 3439dba64beSDimitry Andric } 3449dba64beSDimitry Andric 3459dba64beSDimitry Andric llvm::Expected<PythonObject> GetAttribute(const llvm::Twine &name) const { 3469dba64beSDimitry Andric if (!m_py_obj) 3479dba64beSDimitry Andric return nullDeref(); 3489dba64beSDimitry Andric PyObject *obj = PyObject_GetAttrString(m_py_obj, NullTerminated(name)); 3499dba64beSDimitry Andric if (!obj) 3509dba64beSDimitry Andric return exception(); 3519dba64beSDimitry Andric return python::Take<PythonObject>(obj); 3529dba64beSDimitry Andric } 3539dba64beSDimitry Andric 3549dba64beSDimitry Andric llvm::Expected<bool> IsTrue() { 3559dba64beSDimitry Andric if (!m_py_obj) 3569dba64beSDimitry Andric return nullDeref(); 3579dba64beSDimitry Andric int r = PyObject_IsTrue(m_py_obj); 3589dba64beSDimitry Andric if (r < 0) 3599dba64beSDimitry Andric return exception(); 3609dba64beSDimitry Andric return !!r; 3619dba64beSDimitry Andric } 3629dba64beSDimitry Andric 3639dba64beSDimitry Andric llvm::Expected<long long> AsLongLong() { 3649dba64beSDimitry Andric if (!m_py_obj) 3659dba64beSDimitry Andric return nullDeref(); 3669dba64beSDimitry Andric assert(!PyErr_Occurred()); 3679dba64beSDimitry Andric long long r = PyLong_AsLongLong(m_py_obj); 3689dba64beSDimitry Andric if (PyErr_Occurred()) 3699dba64beSDimitry Andric return exception(); 3709dba64beSDimitry Andric return r; 3719dba64beSDimitry Andric } 3729dba64beSDimitry Andric 3739dba64beSDimitry Andric llvm::Expected<bool> IsInstance(const PythonObject &cls) { 3749dba64beSDimitry Andric if (!m_py_obj || !cls.IsValid()) 3759dba64beSDimitry Andric return nullDeref(); 3769dba64beSDimitry Andric int r = PyObject_IsInstance(m_py_obj, cls.get()); 3779dba64beSDimitry Andric if (r < 0) 3789dba64beSDimitry Andric return exception(); 3799dba64beSDimitry Andric return !!r; 3809dba64beSDimitry Andric } 3819dba64beSDimitry Andric 3829dba64beSDimitry Andric protected: 3830b57cec5SDimitry Andric PyObject *m_py_obj; 3840b57cec5SDimitry Andric }; 3850b57cec5SDimitry Andric 3869dba64beSDimitry Andric 3879dba64beSDimitry Andric // This is why C++ needs monads. 3889dba64beSDimitry Andric template <typename T> llvm::Expected<T> As(llvm::Expected<PythonObject> &&obj) { 3899dba64beSDimitry Andric if (!obj) 3909dba64beSDimitry Andric return obj.takeError(); 3919dba64beSDimitry Andric if (!T::Check(obj.get().get())) 3929dba64beSDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(), 3939dba64beSDimitry Andric "type error"); 3949dba64beSDimitry Andric return T(PyRefType::Borrowed, std::move(obj.get().get())); 3959dba64beSDimitry Andric } 3969dba64beSDimitry Andric 3979dba64beSDimitry Andric template <> llvm::Expected<bool> As<bool>(llvm::Expected<PythonObject> &&obj); 3989dba64beSDimitry Andric 3999dba64beSDimitry Andric template <> 4009dba64beSDimitry Andric llvm::Expected<long long> As<long long>(llvm::Expected<PythonObject> &&obj); 4019dba64beSDimitry Andric 4029dba64beSDimitry Andric template <> 4039dba64beSDimitry Andric llvm::Expected<std::string> As<std::string>(llvm::Expected<PythonObject> &&obj); 4049dba64beSDimitry Andric 4059dba64beSDimitry Andric 4069dba64beSDimitry Andric template <class T> class TypedPythonObject : public PythonObject { 4070b57cec5SDimitry Andric public: 4089dba64beSDimitry Andric // override to perform implicit type conversions on Reset 4099dba64beSDimitry Andric // This can be eliminated once we drop python 2 support. 4109dba64beSDimitry Andric static void Convert(PyRefType &type, PyObject *&py_obj) {} 4119dba64beSDimitry Andric 4129dba64beSDimitry Andric TypedPythonObject(PyRefType type, PyObject *py_obj) { 4139dba64beSDimitry Andric if (!py_obj) 4149dba64beSDimitry Andric return; 4159dba64beSDimitry Andric T::Convert(type, py_obj); 4169dba64beSDimitry Andric if (T::Check(py_obj)) 4179dba64beSDimitry Andric PythonObject::operator=(PythonObject(type, py_obj)); 4189dba64beSDimitry Andric else if (type == PyRefType::Owned) 4199dba64beSDimitry Andric Py_DECREF(py_obj); 4209dba64beSDimitry Andric } 4219dba64beSDimitry Andric 4229dba64beSDimitry Andric TypedPythonObject() {} 4239dba64beSDimitry Andric }; 4249dba64beSDimitry Andric 4259dba64beSDimitry Andric class PythonBytes : public TypedPythonObject<PythonBytes> { 4269dba64beSDimitry Andric public: 4279dba64beSDimitry Andric using TypedPythonObject::TypedPythonObject; 4280b57cec5SDimitry Andric explicit PythonBytes(llvm::ArrayRef<uint8_t> bytes); 4290b57cec5SDimitry Andric PythonBytes(const uint8_t *bytes, size_t length); 4300b57cec5SDimitry Andric 4310b57cec5SDimitry Andric static bool Check(PyObject *py_obj); 4320b57cec5SDimitry Andric 4330b57cec5SDimitry Andric llvm::ArrayRef<uint8_t> GetBytes() const; 4340b57cec5SDimitry Andric 4350b57cec5SDimitry Andric size_t GetSize() const; 4360b57cec5SDimitry Andric 4370b57cec5SDimitry Andric void SetBytes(llvm::ArrayRef<uint8_t> stringbytes); 4380b57cec5SDimitry Andric 4390b57cec5SDimitry Andric StructuredData::StringSP CreateStructuredString() const; 4400b57cec5SDimitry Andric }; 4410b57cec5SDimitry Andric 4429dba64beSDimitry Andric class PythonByteArray : public TypedPythonObject<PythonByteArray> { 4430b57cec5SDimitry Andric public: 4449dba64beSDimitry Andric using TypedPythonObject::TypedPythonObject; 4450b57cec5SDimitry Andric explicit PythonByteArray(llvm::ArrayRef<uint8_t> bytes); 4460b57cec5SDimitry Andric PythonByteArray(const uint8_t *bytes, size_t length); 4470b57cec5SDimitry Andric PythonByteArray(const PythonBytes &object); 4480b57cec5SDimitry Andric 4490b57cec5SDimitry Andric static bool Check(PyObject *py_obj); 4500b57cec5SDimitry Andric 4510b57cec5SDimitry Andric llvm::ArrayRef<uint8_t> GetBytes() const; 4520b57cec5SDimitry Andric 4530b57cec5SDimitry Andric size_t GetSize() const; 4540b57cec5SDimitry Andric 4550b57cec5SDimitry Andric void SetBytes(llvm::ArrayRef<uint8_t> stringbytes); 4560b57cec5SDimitry Andric 4570b57cec5SDimitry Andric StructuredData::StringSP CreateStructuredString() const; 4580b57cec5SDimitry Andric }; 4590b57cec5SDimitry Andric 4609dba64beSDimitry Andric class PythonString : public TypedPythonObject<PythonString> { 4610b57cec5SDimitry Andric public: 4629dba64beSDimitry Andric using TypedPythonObject::TypedPythonObject; 4639dba64beSDimitry Andric static llvm::Expected<PythonString> FromUTF8(llvm::StringRef string); 4640b57cec5SDimitry Andric 4659dba64beSDimitry Andric PythonString() : TypedPythonObject() {} // MSVC requires this for some reason 4669dba64beSDimitry Andric 4679dba64beSDimitry Andric explicit PythonString(llvm::StringRef string); // safe, null on error 4680b57cec5SDimitry Andric 4690b57cec5SDimitry Andric static bool Check(PyObject *py_obj); 4709dba64beSDimitry Andric static void Convert(PyRefType &type, PyObject *&py_obj); 4710b57cec5SDimitry Andric 4729dba64beSDimitry Andric llvm::StringRef GetString() const; // safe, empty string on error 4730b57cec5SDimitry Andric 4749dba64beSDimitry Andric llvm::Expected<llvm::StringRef> AsUTF8() const; 4750b57cec5SDimitry Andric 4760b57cec5SDimitry Andric size_t GetSize() const; 4770b57cec5SDimitry Andric 4789dba64beSDimitry Andric void SetString(llvm::StringRef string); // safe, null on error 4790b57cec5SDimitry Andric 4800b57cec5SDimitry Andric StructuredData::StringSP CreateStructuredString() const; 4810b57cec5SDimitry Andric }; 4820b57cec5SDimitry Andric 4839dba64beSDimitry Andric class PythonInteger : public TypedPythonObject<PythonInteger> { 4840b57cec5SDimitry Andric public: 4859dba64beSDimitry Andric using TypedPythonObject::TypedPythonObject; 4860b57cec5SDimitry Andric 4879dba64beSDimitry Andric PythonInteger() : TypedPythonObject() {} // MSVC requires this for some reason 4889dba64beSDimitry Andric 4899dba64beSDimitry Andric explicit PythonInteger(int64_t value); 4900b57cec5SDimitry Andric 4910b57cec5SDimitry Andric static bool Check(PyObject *py_obj); 4929dba64beSDimitry Andric static void Convert(PyRefType &type, PyObject *&py_obj); 4930b57cec5SDimitry Andric 4940b57cec5SDimitry Andric int64_t GetInteger() const; 4950b57cec5SDimitry Andric 4960b57cec5SDimitry Andric void SetInteger(int64_t value); 4970b57cec5SDimitry Andric 4980b57cec5SDimitry Andric StructuredData::IntegerSP CreateStructuredInteger() const; 4990b57cec5SDimitry Andric }; 5000b57cec5SDimitry Andric 5019dba64beSDimitry Andric class PythonBoolean : public TypedPythonObject<PythonBoolean> { 5020b57cec5SDimitry Andric public: 5039dba64beSDimitry Andric using TypedPythonObject::TypedPythonObject; 5040b57cec5SDimitry Andric 5059dba64beSDimitry Andric explicit PythonBoolean(bool value); 5060b57cec5SDimitry Andric 5070b57cec5SDimitry Andric static bool Check(PyObject *py_obj); 5080b57cec5SDimitry Andric 5090b57cec5SDimitry Andric bool GetValue() const; 5100b57cec5SDimitry Andric 5110b57cec5SDimitry Andric void SetValue(bool value); 5120b57cec5SDimitry Andric 5130b57cec5SDimitry Andric StructuredData::BooleanSP CreateStructuredBoolean() const; 5140b57cec5SDimitry Andric }; 5150b57cec5SDimitry Andric 5169dba64beSDimitry Andric class PythonList : public TypedPythonObject<PythonList> { 5170b57cec5SDimitry Andric public: 5189dba64beSDimitry Andric using TypedPythonObject::TypedPythonObject; 5199dba64beSDimitry Andric 5209dba64beSDimitry Andric PythonList() : TypedPythonObject() {} // MSVC requires this for some reason 5219dba64beSDimitry Andric 5220b57cec5SDimitry Andric explicit PythonList(PyInitialValue value); 5230b57cec5SDimitry Andric explicit PythonList(int list_size); 5240b57cec5SDimitry Andric 5250b57cec5SDimitry Andric static bool Check(PyObject *py_obj); 5260b57cec5SDimitry Andric 5270b57cec5SDimitry Andric uint32_t GetSize() const; 5280b57cec5SDimitry Andric 5290b57cec5SDimitry Andric PythonObject GetItemAtIndex(uint32_t index) const; 5300b57cec5SDimitry Andric 5310b57cec5SDimitry Andric void SetItemAtIndex(uint32_t index, const PythonObject &object); 5320b57cec5SDimitry Andric 5330b57cec5SDimitry Andric void AppendItem(const PythonObject &object); 5340b57cec5SDimitry Andric 5350b57cec5SDimitry Andric StructuredData::ArraySP CreateStructuredArray() const; 5360b57cec5SDimitry Andric }; 5370b57cec5SDimitry Andric 5389dba64beSDimitry Andric class PythonTuple : public TypedPythonObject<PythonTuple> { 5390b57cec5SDimitry Andric public: 5409dba64beSDimitry Andric using TypedPythonObject::TypedPythonObject; 5419dba64beSDimitry Andric 5420b57cec5SDimitry Andric explicit PythonTuple(PyInitialValue value); 5430b57cec5SDimitry Andric explicit PythonTuple(int tuple_size); 5440b57cec5SDimitry Andric PythonTuple(std::initializer_list<PythonObject> objects); 5450b57cec5SDimitry Andric PythonTuple(std::initializer_list<PyObject *> objects); 5460b57cec5SDimitry Andric 5470b57cec5SDimitry Andric static bool Check(PyObject *py_obj); 5480b57cec5SDimitry Andric 5490b57cec5SDimitry Andric uint32_t GetSize() const; 5500b57cec5SDimitry Andric 5510b57cec5SDimitry Andric PythonObject GetItemAtIndex(uint32_t index) const; 5520b57cec5SDimitry Andric 5530b57cec5SDimitry Andric void SetItemAtIndex(uint32_t index, const PythonObject &object); 5540b57cec5SDimitry Andric 5550b57cec5SDimitry Andric StructuredData::ArraySP CreateStructuredArray() const; 5560b57cec5SDimitry Andric }; 5570b57cec5SDimitry Andric 5589dba64beSDimitry Andric class PythonDictionary : public TypedPythonObject<PythonDictionary> { 5590b57cec5SDimitry Andric public: 5609dba64beSDimitry Andric using TypedPythonObject::TypedPythonObject; 5610b57cec5SDimitry Andric 5629dba64beSDimitry Andric PythonDictionary() : TypedPythonObject() {} // MSVC requires this for some reason 5639dba64beSDimitry Andric 5649dba64beSDimitry Andric explicit PythonDictionary(PyInitialValue value); 5650b57cec5SDimitry Andric 5660b57cec5SDimitry Andric static bool Check(PyObject *py_obj); 5670b57cec5SDimitry Andric 5680b57cec5SDimitry Andric uint32_t GetSize() const; 5690b57cec5SDimitry Andric 5700b57cec5SDimitry Andric PythonList GetKeys() const; 5710b57cec5SDimitry Andric 5729dba64beSDimitry Andric PythonObject GetItemForKey(const PythonObject &key) const; // DEPRECATED 5739dba64beSDimitry Andric void SetItemForKey(const PythonObject &key, 5749dba64beSDimitry Andric const PythonObject &value); // DEPRECATED 5759dba64beSDimitry Andric 5769dba64beSDimitry Andric llvm::Expected<PythonObject> GetItem(const PythonObject &key) const; 5779dba64beSDimitry Andric llvm::Expected<PythonObject> GetItem(const llvm::Twine &key) const; 5789dba64beSDimitry Andric llvm::Error SetItem(const PythonObject &key, const PythonObject &value) const; 5799dba64beSDimitry Andric llvm::Error SetItem(const llvm::Twine &key, const PythonObject &value) const; 5800b57cec5SDimitry Andric 5810b57cec5SDimitry Andric StructuredData::DictionarySP CreateStructuredDictionary() const; 5820b57cec5SDimitry Andric }; 5830b57cec5SDimitry Andric 5849dba64beSDimitry Andric class PythonModule : public TypedPythonObject<PythonModule> { 5850b57cec5SDimitry Andric public: 5869dba64beSDimitry Andric using TypedPythonObject::TypedPythonObject; 5870b57cec5SDimitry Andric 5880b57cec5SDimitry Andric static bool Check(PyObject *py_obj); 5890b57cec5SDimitry Andric 5900b57cec5SDimitry Andric static PythonModule BuiltinsModule(); 5910b57cec5SDimitry Andric 5920b57cec5SDimitry Andric static PythonModule MainModule(); 5930b57cec5SDimitry Andric 5940b57cec5SDimitry Andric static PythonModule AddModule(llvm::StringRef module); 5950b57cec5SDimitry Andric 5969dba64beSDimitry Andric // safe, returns invalid on error; 5979dba64beSDimitry Andric static PythonModule ImportModule(llvm::StringRef name) { 5989dba64beSDimitry Andric std::string s = name; 5999dba64beSDimitry Andric auto mod = Import(s.c_str()); 6009dba64beSDimitry Andric if (!mod) { 6019dba64beSDimitry Andric llvm::consumeError(mod.takeError()); 6029dba64beSDimitry Andric return PythonModule(); 6039dba64beSDimitry Andric } 6049dba64beSDimitry Andric return std::move(mod.get()); 6059dba64beSDimitry Andric } 6060b57cec5SDimitry Andric 6079dba64beSDimitry Andric static llvm::Expected<PythonModule> Import(const llvm::Twine &name); 6080b57cec5SDimitry Andric 6099dba64beSDimitry Andric llvm::Expected<PythonObject> Get(const llvm::Twine &name); 6100b57cec5SDimitry Andric 6110b57cec5SDimitry Andric PythonDictionary GetDictionary() const; 6120b57cec5SDimitry Andric }; 6130b57cec5SDimitry Andric 6149dba64beSDimitry Andric class PythonCallable : public TypedPythonObject<PythonCallable> { 6150b57cec5SDimitry Andric public: 6169dba64beSDimitry Andric using TypedPythonObject::TypedPythonObject; 6179dba64beSDimitry Andric 6180b57cec5SDimitry Andric struct ArgInfo { 6199dba64beSDimitry Andric /* the largest number of positional arguments this callable 6209dba64beSDimitry Andric * can accept, or UNBOUNDED, ie UINT_MAX if it's a varargs 6219dba64beSDimitry Andric * function and can accept an arbitrary number */ 6229dba64beSDimitry Andric unsigned max_positional_args; 6239dba64beSDimitry Andric static constexpr unsigned UNBOUNDED = UINT_MAX; // FIXME c++17 inline 6240b57cec5SDimitry Andric }; 6250b57cec5SDimitry Andric 6260b57cec5SDimitry Andric static bool Check(PyObject *py_obj); 6270b57cec5SDimitry Andric 6289dba64beSDimitry Andric llvm::Expected<ArgInfo> GetArgInfo() const; 6290b57cec5SDimitry Andric 6300b57cec5SDimitry Andric PythonObject operator()(); 6310b57cec5SDimitry Andric 6320b57cec5SDimitry Andric PythonObject operator()(std::initializer_list<PyObject *> args); 6330b57cec5SDimitry Andric 6340b57cec5SDimitry Andric PythonObject operator()(std::initializer_list<PythonObject> args); 6350b57cec5SDimitry Andric 6360b57cec5SDimitry Andric template <typename Arg, typename... Args> 6370b57cec5SDimitry Andric PythonObject operator()(const Arg &arg, Args... args) { 6380b57cec5SDimitry Andric return operator()({arg, args...}); 6390b57cec5SDimitry Andric } 6400b57cec5SDimitry Andric }; 6410b57cec5SDimitry Andric 6429dba64beSDimitry Andric class PythonFile : public TypedPythonObject<PythonFile> { 6430b57cec5SDimitry Andric public: 6449dba64beSDimitry Andric using TypedPythonObject::TypedPythonObject; 6450b57cec5SDimitry Andric 6469dba64beSDimitry Andric PythonFile() : TypedPythonObject() {} // MSVC requires this for some reason 6470b57cec5SDimitry Andric 6480b57cec5SDimitry Andric static bool Check(PyObject *py_obj); 6490b57cec5SDimitry Andric 6509dba64beSDimitry Andric static llvm::Expected<PythonFile> FromFile(File &file, 6519dba64beSDimitry Andric const char *mode = nullptr); 6520b57cec5SDimitry Andric 6539dba64beSDimitry Andric llvm::Expected<lldb::FileSP> ConvertToFile(bool borrowed = false); 6549dba64beSDimitry Andric llvm::Expected<lldb::FileSP> 6559dba64beSDimitry Andric ConvertToFileForcingUseOfScriptingIOMethods(bool borrowed = false); 6560b57cec5SDimitry Andric }; 6570b57cec5SDimitry Andric 6589dba64beSDimitry Andric class PythonException : public llvm::ErrorInfo<PythonException> { 6599dba64beSDimitry Andric private: 6609dba64beSDimitry Andric PyObject *m_exception_type, *m_exception, *m_traceback; 6619dba64beSDimitry Andric PyObject *m_repr_bytes; 6629dba64beSDimitry Andric 6639dba64beSDimitry Andric public: 6649dba64beSDimitry Andric static char ID; 6659dba64beSDimitry Andric const char *toCString() const; 6669dba64beSDimitry Andric PythonException(const char *caller = nullptr); 6679dba64beSDimitry Andric void Restore(); 6689dba64beSDimitry Andric ~PythonException(); 6699dba64beSDimitry Andric void log(llvm::raw_ostream &OS) const override; 6709dba64beSDimitry Andric std::error_code convertToErrorCode() const override; 6719dba64beSDimitry Andric bool Matches(PyObject *exc) const; 6729dba64beSDimitry Andric std::string ReadBacktrace() const; 6739dba64beSDimitry Andric }; 6749dba64beSDimitry Andric 6759dba64beSDimitry Andric // This extracts the underlying T out of an Expected<T> and returns it. 6769dba64beSDimitry Andric // If the Expected is an Error instead of a T, that error will be converted 6779dba64beSDimitry Andric // into a python exception, and this will return a default-constructed T. 6789dba64beSDimitry Andric // 6799dba64beSDimitry Andric // This is appropriate for use right at the boundary of python calling into 6809dba64beSDimitry Andric // C++, such as in a SWIG typemap. In such a context you should simply 6819dba64beSDimitry Andric // check if the returned T is valid, and if it is, return a NULL back 6829dba64beSDimitry Andric // to python. This will result in the Error being raised as an exception 6839dba64beSDimitry Andric // from python code's point of view. 6849dba64beSDimitry Andric // 6859dba64beSDimitry Andric // For example: 6869dba64beSDimitry Andric // ``` 6879dba64beSDimitry Andric // Expected<Foo *> efoop = some_cpp_function(); 6889dba64beSDimitry Andric // Foo *foop = unwrapOrSetPythonException(efoop); 6899dba64beSDimitry Andric // if (!foop) 6909dba64beSDimitry Andric // return NULL; 6919dba64beSDimitry Andric // do_something(*foop); 6929dba64beSDimitry Andric // 6939dba64beSDimitry Andric // If the Error returned was itself created because a python exception was 6949dba64beSDimitry Andric // raised when C++ code called into python, then the original exception 6959dba64beSDimitry Andric // will be restored. Otherwise a simple string exception will be raised. 6969dba64beSDimitry Andric template <typename T> T unwrapOrSetPythonException(llvm::Expected<T> expected) { 6979dba64beSDimitry Andric if (expected) 6989dba64beSDimitry Andric return expected.get(); 6999dba64beSDimitry Andric llvm::handleAllErrors( 7009dba64beSDimitry Andric expected.takeError(), [](PythonException &E) { E.Restore(); }, 7019dba64beSDimitry Andric [](const llvm::ErrorInfoBase &E) { 7029dba64beSDimitry Andric PyErr_SetString(PyExc_Exception, E.message().c_str()); 7039dba64beSDimitry Andric }); 7049dba64beSDimitry Andric return T(); 7059dba64beSDimitry Andric } 7069dba64beSDimitry Andric 7079dba64beSDimitry Andric // This is only here to help incrementally migrate old, exception-unsafe 7089dba64beSDimitry Andric // code. 7099dba64beSDimitry Andric template <typename T> T unwrapIgnoringErrors(llvm::Expected<T> expected) { 7109dba64beSDimitry Andric if (expected) 7119dba64beSDimitry Andric return std::move(expected.get()); 7129dba64beSDimitry Andric llvm::consumeError(expected.takeError()); 7139dba64beSDimitry Andric return T(); 7149dba64beSDimitry Andric } 7159dba64beSDimitry Andric 7169dba64beSDimitry Andric llvm::Expected<PythonObject> runStringOneLine(const llvm::Twine &string, 7179dba64beSDimitry Andric const PythonDictionary &globals, 7189dba64beSDimitry Andric const PythonDictionary &locals); 7199dba64beSDimitry Andric 7209dba64beSDimitry Andric llvm::Expected<PythonObject> runStringMultiLine(const llvm::Twine &string, 7219dba64beSDimitry Andric const PythonDictionary &globals, 7229dba64beSDimitry Andric const PythonDictionary &locals); 7239dba64beSDimitry Andric 7249dba64beSDimitry Andric // Sometimes the best way to interact with a python interpreter is 7259dba64beSDimitry Andric // to run some python code. You construct a PythonScript with 7269dba64beSDimitry Andric // script string. The script assigns some function to `_function_` 7279dba64beSDimitry Andric // and you get a C++ callable object that calls the python function. 7289dba64beSDimitry Andric // 7299dba64beSDimitry Andric // Example: 7309dba64beSDimitry Andric // 7319dba64beSDimitry Andric // const char script[] = R"( 7329dba64beSDimitry Andric // def main(x, y): 7339dba64beSDimitry Andric // .... 7349dba64beSDimitry Andric // )"; 7359dba64beSDimitry Andric // 7369dba64beSDimitry Andric // Expected<PythonObject> cpp_foo_wrapper(PythonObject x, PythonObject y) { 7379dba64beSDimitry Andric // // no need to synchronize access to this global, we already have the GIL 7389dba64beSDimitry Andric // static PythonScript foo(script) 7399dba64beSDimitry Andric // return foo(x, y); 7409dba64beSDimitry Andric // } 7419dba64beSDimitry Andric class PythonScript { 7429dba64beSDimitry Andric const char *script; 7439dba64beSDimitry Andric PythonCallable function; 7449dba64beSDimitry Andric 7459dba64beSDimitry Andric llvm::Error Init(); 7469dba64beSDimitry Andric 7479dba64beSDimitry Andric public: 7489dba64beSDimitry Andric PythonScript(const char *script) : script(script), function() {} 7499dba64beSDimitry Andric 7509dba64beSDimitry Andric template <typename... Args> 7519dba64beSDimitry Andric llvm::Expected<PythonObject> operator()(Args &&... args) { 7529dba64beSDimitry Andric if (llvm::Error error = Init()) 7539dba64beSDimitry Andric return std::move(error); 7549dba64beSDimitry Andric return function.Call(std::forward<Args>(args)...); 7559dba64beSDimitry Andric } 7569dba64beSDimitry Andric }; 7579dba64beSDimitry Andric 7589dba64beSDimitry Andric } // namespace python 7590b57cec5SDimitry Andric } // namespace lldb_private 7600b57cec5SDimitry Andric 7610b57cec5SDimitry Andric #endif 7620b57cec5SDimitry Andric 7630b57cec5SDimitry Andric #endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H 764