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 // 28d3bd5b3dSLawrence D'Anna // 29d3bd5b3dSLawrence D'Anna // TODOs for this file 30d3bd5b3dSLawrence D'Anna // 31d3bd5b3dSLawrence D'Anna // * Make all methods safe for exceptions. 32d3bd5b3dSLawrence D'Anna // 33d3bd5b3dSLawrence D'Anna // * Eliminate method signatures that must translate exceptions into 34d3bd5b3dSLawrence D'Anna // empty objects or NULLs. Almost everything here should return 35d3bd5b3dSLawrence D'Anna // Expected<>. It should be acceptable for certain operations that 36d3bd5b3dSLawrence D'Anna // can never fail to assert instead, such as the creation of 37d3bd5b3dSLawrence D'Anna // PythonString from a string literal. 38d3bd5b3dSLawrence D'Anna // 39e9264b74SKazuaki Ishizaki // * Eliminate Reset(), and make all non-default constructors private. 40d3bd5b3dSLawrence D'Anna // Python objects should be created with Retain<> or Take<>, and they 41d3bd5b3dSLawrence D'Anna // should be assigned with operator= 42d3bd5b3dSLawrence D'Anna // 43d3bd5b3dSLawrence D'Anna // * Eliminate default constructors, make python objects always 44d3bd5b3dSLawrence D'Anna // nonnull, and use optionals where necessary. 45d3bd5b3dSLawrence D'Anna // 46d3bd5b3dSLawrence 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 5159998b7bSJonas Devlieghere #include "lldb/Host/Config.h" 5259998b7bSJonas Devlieghere 534e26cf2cSJonas Devlieghere #if LLDB_ENABLE_PYTHON 54d68983e3SPavel Labath 5541de9a97SKate Stone // LLDB Python header must be included first 5641de9a97SKate Stone #include "lldb-python.h" 5741de9a97SKate Stone 589c40264fSZachary Turner #include "lldb/Host/File.h" 59f2a8bccfSPavel Labath #include "lldb/Utility/StructuredData.h" 602c1f46dcSZachary Turner 615a72c02bSZachary Turner #include "llvm/ADT/ArrayRef.h" 625a72c02bSZachary Turner 632c1f46dcSZachary Turner namespace lldb_private { 6404edd189SLawrence D'Anna namespace python { 65edb35d95SEugene Zelenko 66085328eeSLawrence D'Anna class PythonObject; 675a72c02bSZachary Turner class PythonBytes; 682c1f46dcSZachary Turner class PythonString; 692c1f46dcSZachary Turner class PythonList; 702c1f46dcSZachary Turner class PythonDictionary; 712c1f46dcSZachary Turner class PythonInteger; 72085328eeSLawrence D'Anna class PythonException; 732c1f46dcSZachary Turner 74bbef51ebSLawrence D'Anna class GIL { 75bbef51ebSLawrence D'Anna public: 76bbef51ebSLawrence D'Anna GIL() { 77bbef51ebSLawrence D'Anna m_state = PyGILState_Ensure(); 78bbef51ebSLawrence D'Anna assert(!PyErr_Occurred()); 79bbef51ebSLawrence D'Anna } 80bbef51ebSLawrence D'Anna ~GIL() { PyGILState_Release(m_state); } 81bbef51ebSLawrence D'Anna 82bbef51ebSLawrence D'Anna protected: 83bbef51ebSLawrence D'Anna PyGILState_STATE m_state; 84bbef51ebSLawrence D'Anna }; 85bbef51ebSLawrence D'Anna 86b9c1b51eSKate Stone class StructuredPythonObject : public StructuredData::Generic { 872c1f46dcSZachary Turner public: 88b9c1b51eSKate Stone StructuredPythonObject() : StructuredData::Generic() {} 892c1f46dcSZachary Turner 90b9c1b51eSKate Stone StructuredPythonObject(void *obj) : StructuredData::Generic(obj) { 91*a6598575SRalf Grosse-Kunstleve assert(PyGILState_Check()); 922c1f46dcSZachary Turner Py_XINCREF(GetValue()); 932c1f46dcSZachary Turner } 942c1f46dcSZachary Turner 95b9c1b51eSKate Stone ~StructuredPythonObject() override { 96*a6598575SRalf Grosse-Kunstleve if (Py_IsInitialized()) { 97*a6598575SRalf Grosse-Kunstleve if (_Py_IsFinalizing()) { 98*a6598575SRalf Grosse-Kunstleve // Leak GetValue() rather than crashing the process. 99*a6598575SRalf Grosse-Kunstleve // https://docs.python.org/3/c-api/init.html#c.PyGILState_Ensure 100*a6598575SRalf Grosse-Kunstleve } else { 101*a6598575SRalf Grosse-Kunstleve PyGILState_STATE state = PyGILState_Ensure(); 1022c1f46dcSZachary Turner Py_XDECREF(GetValue()); 103*a6598575SRalf Grosse-Kunstleve PyGILState_Release(state); 104*a6598575SRalf Grosse-Kunstleve } 105*a6598575SRalf Grosse-Kunstleve } 1062c1f46dcSZachary Turner SetValue(nullptr); 1072c1f46dcSZachary Turner } 1082c1f46dcSZachary Turner 109b9c1b51eSKate Stone bool IsValid() const override { return GetValue() && GetValue() != Py_None; } 1102c1f46dcSZachary Turner 1112783d817SJonas Devlieghere void Serialize(llvm::json::OStream &s) const override; 1122c1f46dcSZachary Turner 1132c1f46dcSZachary Turner private: 114eaebcbc6SKonrad Kleine StructuredPythonObject(const StructuredPythonObject &) = delete; 115eaebcbc6SKonrad Kleine const StructuredPythonObject & 116eaebcbc6SKonrad Kleine operator=(const StructuredPythonObject &) = delete; 1172c1f46dcSZachary Turner }; 1182c1f46dcSZachary Turner 119b9c1b51eSKate Stone enum class PyObjectType { 1202c1f46dcSZachary Turner Unknown, 1212c1f46dcSZachary Turner None, 122b81d715cSTatyana Krasnukha Boolean, 1232c1f46dcSZachary Turner Integer, 1242c1f46dcSZachary Turner Dictionary, 1252c1f46dcSZachary Turner List, 1269c40264fSZachary Turner String, 1275a72c02bSZachary Turner Bytes, 128f9d6d204SZachary Turner ByteArray, 1297841efbbSZachary Turner Module, 130a1405147SZachary Turner Callable, 131a1405147SZachary Turner Tuple, 1329c40264fSZachary Turner File 1332c1f46dcSZachary Turner }; 1342c1f46dcSZachary Turner 135b9c1b51eSKate Stone enum class PyRefType { 136f8b22f8fSZachary Turner Borrowed, // We are not given ownership of the incoming PyObject. 137f8b22f8fSZachary Turner // We cannot safely hold it without calling Py_INCREF. 138f8b22f8fSZachary Turner Owned // We have ownership of the incoming PyObject. We should 139f8b22f8fSZachary Turner // not call Py_INCREF. 140f8b22f8fSZachary Turner }; 141f8b22f8fSZachary Turner 142085328eeSLawrence D'Anna 143085328eeSLawrence D'Anna // Take a reference that you already own, and turn it into 144085328eeSLawrence D'Anna // a PythonObject. 145085328eeSLawrence D'Anna // 146085328eeSLawrence D'Anna // Most python API methods will return a +1 reference 147085328eeSLawrence D'Anna // if they succeed or NULL if and only if 148085328eeSLawrence D'Anna // they set an exception. Use this to collect such return 149085328eeSLawrence D'Anna // values, after checking for NULL. 150085328eeSLawrence D'Anna // 151085328eeSLawrence D'Anna // If T is not just PythonObject, then obj must be already be 152085328eeSLawrence D'Anna // checked to be of the correct type. 153085328eeSLawrence D'Anna template <typename T> T Take(PyObject *obj) { 154085328eeSLawrence D'Anna assert(obj); 155085328eeSLawrence D'Anna assert(!PyErr_Occurred()); 156085328eeSLawrence D'Anna T thing(PyRefType::Owned, obj); 157085328eeSLawrence D'Anna assert(thing.IsValid()); 1581dfb1a85SPavel Labath return thing; 159085328eeSLawrence D'Anna } 160085328eeSLawrence D'Anna 161085328eeSLawrence D'Anna // Retain a reference you have borrowed, and turn it into 162085328eeSLawrence D'Anna // a PythonObject. 163085328eeSLawrence D'Anna // 164085328eeSLawrence D'Anna // A minority of python APIs return a borrowed reference 165085328eeSLawrence D'Anna // instead of a +1. They will also return NULL if and only 166085328eeSLawrence D'Anna // if they set an exception. Use this to collect such return 167085328eeSLawrence D'Anna // values, after checking for NULL. 168085328eeSLawrence D'Anna // 169085328eeSLawrence D'Anna // If T is not just PythonObject, then obj must be already be 170085328eeSLawrence D'Anna // checked to be of the correct type. 171085328eeSLawrence D'Anna template <typename T> T Retain(PyObject *obj) { 172085328eeSLawrence D'Anna assert(obj); 173085328eeSLawrence D'Anna assert(!PyErr_Occurred()); 174085328eeSLawrence D'Anna T thing(PyRefType::Borrowed, obj); 175085328eeSLawrence D'Anna assert(thing.IsValid()); 1761dfb1a85SPavel Labath return thing; 177085328eeSLawrence D'Anna } 178085328eeSLawrence D'Anna 179722b6189SLawrence D'Anna // This class can be used like a utility function to convert from 180722b6189SLawrence D'Anna // a llvm-friendly Twine into a null-terminated const char *, 181722b6189SLawrence D'Anna // which is the form python C APIs want their strings in. 182722b6189SLawrence D'Anna // 183722b6189SLawrence D'Anna // Example: 184722b6189SLawrence D'Anna // const llvm::Twine &some_twine; 185722b6189SLawrence D'Anna // PyFoo_Bar(x, y, z, NullTerminated(some_twine)); 186722b6189SLawrence D'Anna // 187722b6189SLawrence D'Anna // Why a class instead of a function? If the twine isn't already null 188722b6189SLawrence D'Anna // terminated, it will need a temporary buffer to copy the string 189722b6189SLawrence D'Anna // into. We need that buffer to stick around for the lifetime of the 190722b6189SLawrence D'Anna // statement. 191722b6189SLawrence D'Anna class NullTerminated { 192722b6189SLawrence D'Anna const char *str; 193722b6189SLawrence D'Anna llvm::SmallString<32> storage; 194722b6189SLawrence D'Anna 195722b6189SLawrence D'Anna public: 196722b6189SLawrence D'Anna NullTerminated(const llvm::Twine &twine) { 197722b6189SLawrence D'Anna llvm::StringRef ref = twine.toNullTerminatedStringRef(storage); 198722b6189SLawrence D'Anna str = ref.begin(); 199722b6189SLawrence D'Anna } 200722b6189SLawrence D'Anna operator const char *() { return str; } 201722b6189SLawrence D'Anna }; 202722b6189SLawrence D'Anna 20304edd189SLawrence D'Anna inline llvm::Error nullDeref() { 20404edd189SLawrence D'Anna return llvm::createStringError(llvm::inconvertibleErrorCode(), 20504edd189SLawrence D'Anna "A NULL PyObject* was dereferenced"); 20604edd189SLawrence D'Anna } 20704edd189SLawrence D'Anna 20804edd189SLawrence D'Anna inline llvm::Error exception(const char *s = nullptr) { 20904edd189SLawrence D'Anna return llvm::make_error<PythonException>(s); 21004edd189SLawrence D'Anna } 21104edd189SLawrence D'Anna 21204edd189SLawrence D'Anna inline llvm::Error keyError() { 21304edd189SLawrence D'Anna return llvm::createStringError(llvm::inconvertibleErrorCode(), 21404edd189SLawrence D'Anna "key not in dict"); 21504edd189SLawrence D'Anna } 216085328eeSLawrence D'Anna 2176a93a12aSLawrence D'Anna #if PY_MAJOR_VERSION < 3 2186a93a12aSLawrence D'Anna // The python 2 API declares some arguments as char* that should 2196a93a12aSLawrence D'Anna // be const char *, but it doesn't actually modify them. 2206a93a12aSLawrence D'Anna inline char *py2_const_cast(const char *s) { return const_cast<char *>(s); } 2216a93a12aSLawrence D'Anna #else 2226a93a12aSLawrence D'Anna inline const char *py2_const_cast(const char *s) { return s; } 2236a93a12aSLawrence D'Anna #endif 2246a93a12aSLawrence D'Anna 225b9c1b51eSKate Stone enum class PyInitialValue { Invalid, Empty }; 226f8b22f8fSZachary Turner 227085328eeSLawrence D'Anna template <typename T, typename Enable = void> struct PythonFormat; 228085328eeSLawrence D'Anna 229085328eeSLawrence D'Anna template <> struct PythonFormat<unsigned long long> { 230085328eeSLawrence D'Anna static constexpr char format = 'K'; 231085328eeSLawrence D'Anna static auto get(unsigned long long value) { return value; } 232085328eeSLawrence D'Anna }; 233085328eeSLawrence D'Anna 234085328eeSLawrence D'Anna template <> struct PythonFormat<long long> { 235085328eeSLawrence D'Anna static constexpr char format = 'L'; 236085328eeSLawrence D'Anna static auto get(long long value) { return value; } 237085328eeSLawrence D'Anna }; 238085328eeSLawrence D'Anna 23904edd189SLawrence D'Anna template <> struct PythonFormat<PyObject *> { 24004edd189SLawrence D'Anna static constexpr char format = 'O'; 24104edd189SLawrence D'Anna static auto get(PyObject *value) { return value; } 24204edd189SLawrence D'Anna }; 24304edd189SLawrence D'Anna 244085328eeSLawrence D'Anna template <typename T> 245085328eeSLawrence D'Anna struct PythonFormat< 246085328eeSLawrence D'Anna T, typename std::enable_if<std::is_base_of<PythonObject, T>::value>::type> { 247085328eeSLawrence D'Anna static constexpr char format = 'O'; 248085328eeSLawrence D'Anna static auto get(const T &value) { return value.get(); } 249085328eeSLawrence D'Anna }; 250085328eeSLawrence D'Anna 251b9c1b51eSKate Stone class PythonObject { 2522c1f46dcSZachary Turner public: 253fd2433e1SJonas Devlieghere PythonObject() = default; 2542c1f46dcSZachary Turner 25504edd189SLawrence D'Anna PythonObject(PyRefType type, PyObject *py_obj) { 25604edd189SLawrence D'Anna m_py_obj = py_obj; 25704edd189SLawrence D'Anna // If this is a borrowed reference, we need to convert it to 25804edd189SLawrence D'Anna // an owned reference by incrementing it. If it is an owned 25904edd189SLawrence D'Anna // reference (for example the caller allocated it with PyDict_New() 26004edd189SLawrence D'Anna // then we must *not* increment it. 26104edd189SLawrence D'Anna if (m_py_obj && Py_IsInitialized() && type == PyRefType::Borrowed) 26204edd189SLawrence D'Anna Py_XINCREF(m_py_obj); 2632c1f46dcSZachary Turner } 2642c1f46dcSZachary Turner 26503819d1cSLawrence D'Anna PythonObject(const PythonObject &rhs) 26603819d1cSLawrence D'Anna : PythonObject(PyRefType::Borrowed, rhs.m_py_obj) {} 2672c1f46dcSZachary Turner 268085328eeSLawrence D'Anna PythonObject(PythonObject &&rhs) { 269085328eeSLawrence D'Anna m_py_obj = rhs.m_py_obj; 270085328eeSLawrence D'Anna rhs.m_py_obj = nullptr; 271085328eeSLawrence D'Anna } 272085328eeSLawrence D'Anna 273d3bd5b3dSLawrence D'Anna ~PythonObject() { Reset(); } 2742c1f46dcSZachary Turner 275b9c1b51eSKate Stone void Reset() { 276*a6598575SRalf Grosse-Kunstleve if (m_py_obj && Py_IsInitialized()) { 277*a6598575SRalf Grosse-Kunstleve if (_Py_IsFinalizing()) { 278*a6598575SRalf Grosse-Kunstleve // Leak m_py_obj rather than crashing the process. 279*a6598575SRalf Grosse-Kunstleve // https://docs.python.org/3/c-api/init.html#c.PyGILState_Ensure 280*a6598575SRalf Grosse-Kunstleve } else { 281*a6598575SRalf Grosse-Kunstleve PyGILState_STATE state = PyGILState_Ensure(); 282085328eeSLawrence D'Anna Py_DECREF(m_py_obj); 283*a6598575SRalf Grosse-Kunstleve PyGILState_Release(state); 284*a6598575SRalf Grosse-Kunstleve } 285*a6598575SRalf Grosse-Kunstleve } 286f8b22f8fSZachary Turner m_py_obj = nullptr; 2872c1f46dcSZachary Turner } 288f8b22f8fSZachary Turner 289b9c1b51eSKate Stone void Dump() const { 2902c1f46dcSZachary Turner if (m_py_obj) 2912c1f46dcSZachary Turner _PyObject_Dump(m_py_obj); 2922c1f46dcSZachary Turner else 2932c1f46dcSZachary Turner puts("NULL"); 2942c1f46dcSZachary Turner } 2952c1f46dcSZachary Turner 296b9c1b51eSKate Stone void Dump(Stream &strm) const; 2972c1f46dcSZachary Turner 298b9c1b51eSKate Stone PyObject *get() const { return m_py_obj; } 2992c1f46dcSZachary Turner 300b9c1b51eSKate Stone PyObject *release() { 30160c24f70SZachary Turner PyObject *result = m_py_obj; 30260c24f70SZachary Turner m_py_obj = nullptr; 30360c24f70SZachary Turner return result; 30460c24f70SZachary Turner } 30560c24f70SZachary Turner 30603819d1cSLawrence D'Anna PythonObject &operator=(PythonObject other) { 307085328eeSLawrence D'Anna Reset(); 30803819d1cSLawrence D'Anna m_py_obj = std::exchange(other.m_py_obj, nullptr); 309085328eeSLawrence D'Anna return *this; 310085328eeSLawrence D'Anna } 311085328eeSLawrence D'Anna 312b9c1b51eSKate Stone PyObjectType GetObjectType() const; 3137841efbbSZachary Turner 314b9c1b51eSKate Stone PythonString Repr() const; 3157841efbbSZachary Turner 316b9c1b51eSKate Stone PythonString Str() const; 3177841efbbSZachary Turner 318b9c1b51eSKate Stone static PythonObject ResolveNameWithDictionary(llvm::StringRef name, 319b9c1b51eSKate Stone const PythonDictionary &dict); 3207841efbbSZachary Turner 321b58fb2f4SZachary Turner template <typename T> 322b9c1b51eSKate Stone static T ResolveNameWithDictionary(llvm::StringRef name, 323b9c1b51eSKate Stone const PythonDictionary &dict) { 324b58fb2f4SZachary Turner return ResolveNameWithDictionary(name, dict).AsType<T>(); 325b58fb2f4SZachary Turner } 326b58fb2f4SZachary Turner 327b9c1b51eSKate Stone PythonObject ResolveName(llvm::StringRef name) const; 3287841efbbSZachary Turner 329b9c1b51eSKate Stone template <typename T> T ResolveName(llvm::StringRef name) const { 330b58fb2f4SZachary Turner return ResolveName(name).AsType<T>(); 331b58fb2f4SZachary Turner } 332b58fb2f4SZachary Turner 333b9c1b51eSKate Stone bool HasAttribute(llvm::StringRef attribute) const; 3349c40264fSZachary Turner 335b9c1b51eSKate Stone PythonObject GetAttributeValue(llvm::StringRef attribute) const; 3367d6d218eSZachary Turner 337085328eeSLawrence D'Anna bool IsNone() const { return m_py_obj == Py_None; } 338f8b22f8fSZachary Turner 339085328eeSLawrence D'Anna bool IsValid() const { return m_py_obj != nullptr; } 340f8b22f8fSZachary Turner 341085328eeSLawrence D'Anna bool IsAllocated() const { return IsValid() && !IsNone(); } 342085328eeSLawrence D'Anna 343085328eeSLawrence D'Anna explicit operator bool() const { return IsValid() && !IsNone(); } 3442c1f46dcSZachary Turner 345b9c1b51eSKate Stone template <typename T> T AsType() const { 3467d6d218eSZachary Turner if (!T::Check(m_py_obj)) 3477d6d218eSZachary Turner return T(); 3487d6d218eSZachary Turner return T(PyRefType::Borrowed, m_py_obj); 3497d6d218eSZachary Turner } 3507d6d218eSZachary Turner 351b9c1b51eSKate Stone StructuredData::ObjectSP CreateStructuredObject() const; 3522c1f46dcSZachary Turner 353085328eeSLawrence D'Anna template <typename... T> 354085328eeSLawrence D'Anna llvm::Expected<PythonObject> CallMethod(const char *name, 355085328eeSLawrence D'Anna const T &... t) const { 356085328eeSLawrence D'Anna const char format[] = {'(', PythonFormat<T>::format..., ')', 0}; 357085328eeSLawrence D'Anna PyObject *obj = 358c86a6acaSLawrence D'Anna PyObject_CallMethod(m_py_obj, py2_const_cast(name), 359c86a6acaSLawrence D'Anna py2_const_cast(format), PythonFormat<T>::get(t)...); 360c86a6acaSLawrence D'Anna if (!obj) 361c86a6acaSLawrence D'Anna return exception(); 362c86a6acaSLawrence D'Anna return python::Take<PythonObject>(obj); 363c86a6acaSLawrence D'Anna } 364c86a6acaSLawrence D'Anna 365c86a6acaSLawrence D'Anna template <typename... T> 366c86a6acaSLawrence D'Anna llvm::Expected<PythonObject> Call(const T &... t) const { 367c86a6acaSLawrence D'Anna const char format[] = {'(', PythonFormat<T>::format..., ')', 0}; 368c86a6acaSLawrence D'Anna PyObject *obj = PyObject_CallFunction(m_py_obj, py2_const_cast(format), 369c86a6acaSLawrence D'Anna PythonFormat<T>::get(t)...); 370085328eeSLawrence D'Anna if (!obj) 371085328eeSLawrence D'Anna return exception(); 372085328eeSLawrence D'Anna return python::Take<PythonObject>(obj); 373085328eeSLawrence D'Anna } 374085328eeSLawrence D'Anna 375722b6189SLawrence D'Anna llvm::Expected<PythonObject> GetAttribute(const llvm::Twine &name) const { 376085328eeSLawrence D'Anna if (!m_py_obj) 377085328eeSLawrence D'Anna return nullDeref(); 378722b6189SLawrence D'Anna PyObject *obj = PyObject_GetAttrString(m_py_obj, NullTerminated(name)); 379085328eeSLawrence D'Anna if (!obj) 380085328eeSLawrence D'Anna return exception(); 381085328eeSLawrence D'Anna return python::Take<PythonObject>(obj); 382085328eeSLawrence D'Anna } 383085328eeSLawrence D'Anna 384085328eeSLawrence D'Anna llvm::Expected<bool> IsTrue() { 385085328eeSLawrence D'Anna if (!m_py_obj) 386085328eeSLawrence D'Anna return nullDeref(); 387085328eeSLawrence D'Anna int r = PyObject_IsTrue(m_py_obj); 388085328eeSLawrence D'Anna if (r < 0) 389085328eeSLawrence D'Anna return exception(); 390085328eeSLawrence D'Anna return !!r; 391085328eeSLawrence D'Anna } 392085328eeSLawrence D'Anna 39352712d3fSLawrence D'Anna llvm::Expected<long long> AsLongLong() const; 39452712d3fSLawrence D'Anna 39552712d3fSLawrence D'Anna llvm::Expected<long long> AsUnsignedLongLong() const; 39652712d3fSLawrence D'Anna 39752712d3fSLawrence D'Anna // wraps on overflow, instead of raising an error. 39852712d3fSLawrence D'Anna llvm::Expected<unsigned long long> AsModuloUnsignedLongLong() const; 399085328eeSLawrence D'Anna 400085328eeSLawrence D'Anna llvm::Expected<bool> IsInstance(const PythonObject &cls) { 401085328eeSLawrence D'Anna if (!m_py_obj || !cls.IsValid()) 402085328eeSLawrence D'Anna return nullDeref(); 403085328eeSLawrence D'Anna int r = PyObject_IsInstance(m_py_obj, cls.get()); 404085328eeSLawrence D'Anna if (r < 0) 405085328eeSLawrence D'Anna return exception(); 406085328eeSLawrence D'Anna return !!r; 407085328eeSLawrence D'Anna } 408085328eeSLawrence D'Anna 409085328eeSLawrence D'Anna protected: 4109494c510SJonas Devlieghere PyObject *m_py_obj = nullptr; 4112c1f46dcSZachary Turner }; 4122c1f46dcSZachary Turner 413085328eeSLawrence D'Anna 414085328eeSLawrence D'Anna // This is why C++ needs monads. 415085328eeSLawrence D'Anna template <typename T> llvm::Expected<T> As(llvm::Expected<PythonObject> &&obj) { 416085328eeSLawrence D'Anna if (!obj) 417085328eeSLawrence D'Anna return obj.takeError(); 418085328eeSLawrence D'Anna if (!T::Check(obj.get().get())) 419085328eeSLawrence D'Anna return llvm::createStringError(llvm::inconvertibleErrorCode(), 420085328eeSLawrence D'Anna "type error"); 421085328eeSLawrence D'Anna return T(PyRefType::Borrowed, std::move(obj.get().get())); 422085328eeSLawrence D'Anna } 423085328eeSLawrence D'Anna 424085328eeSLawrence D'Anna template <> llvm::Expected<bool> As<bool>(llvm::Expected<PythonObject> &&obj); 425085328eeSLawrence D'Anna 426085328eeSLawrence D'Anna template <> 427085328eeSLawrence D'Anna llvm::Expected<long long> As<long long>(llvm::Expected<PythonObject> &&obj); 428085328eeSLawrence D'Anna 429c86a6acaSLawrence D'Anna template <> 43052712d3fSLawrence D'Anna llvm::Expected<unsigned long long> 43152712d3fSLawrence D'Anna As<unsigned long long>(llvm::Expected<PythonObject> &&obj); 43252712d3fSLawrence D'Anna 43352712d3fSLawrence D'Anna template <> 434c86a6acaSLawrence D'Anna llvm::Expected<std::string> As<std::string>(llvm::Expected<PythonObject> &&obj); 435c86a6acaSLawrence D'Anna 436085328eeSLawrence D'Anna 437d3bd5b3dSLawrence D'Anna template <class T> class TypedPythonObject : public PythonObject { 4385a72c02bSZachary Turner public: 439d3bd5b3dSLawrence D'Anna // override to perform implicit type conversions on Reset 440d3bd5b3dSLawrence D'Anna // This can be eliminated once we drop python 2 support. 441d3bd5b3dSLawrence D'Anna static void Convert(PyRefType &type, PyObject *&py_obj) {} 442d3bd5b3dSLawrence D'Anna 443722b6189SLawrence D'Anna TypedPythonObject(PyRefType type, PyObject *py_obj) { 444d3bd5b3dSLawrence D'Anna if (!py_obj) 445d3bd5b3dSLawrence D'Anna return; 446d3bd5b3dSLawrence D'Anna T::Convert(type, py_obj); 447d3bd5b3dSLawrence D'Anna if (T::Check(py_obj)) 44804edd189SLawrence D'Anna PythonObject::operator=(PythonObject(type, py_obj)); 449d3bd5b3dSLawrence D'Anna else if (type == PyRefType::Owned) 450d3bd5b3dSLawrence D'Anna Py_DECREF(py_obj); 451d3bd5b3dSLawrence D'Anna } 452d3bd5b3dSLawrence D'Anna 453fd2433e1SJonas Devlieghere TypedPythonObject() = default; 454d3bd5b3dSLawrence D'Anna }; 455d3bd5b3dSLawrence D'Anna 456d3bd5b3dSLawrence D'Anna class PythonBytes : public TypedPythonObject<PythonBytes> { 457d3bd5b3dSLawrence D'Anna public: 458d3bd5b3dSLawrence D'Anna using TypedPythonObject::TypedPythonObject; 4595a72c02bSZachary Turner explicit PythonBytes(llvm::ArrayRef<uint8_t> bytes); 4605a72c02bSZachary Turner PythonBytes(const uint8_t *bytes, size_t length); 4615a72c02bSZachary Turner 462b9c1b51eSKate Stone static bool Check(PyObject *py_obj); 4635a72c02bSZachary Turner 464b9c1b51eSKate Stone llvm::ArrayRef<uint8_t> GetBytes() const; 4655a72c02bSZachary Turner 466b9c1b51eSKate Stone size_t GetSize() const; 4675a72c02bSZachary Turner 468b9c1b51eSKate Stone void SetBytes(llvm::ArrayRef<uint8_t> stringbytes); 4695a72c02bSZachary Turner 470b9c1b51eSKate Stone StructuredData::StringSP CreateStructuredString() const; 4715a72c02bSZachary Turner }; 4725a72c02bSZachary Turner 473d3bd5b3dSLawrence D'Anna class PythonByteArray : public TypedPythonObject<PythonByteArray> { 474f9d6d204SZachary Turner public: 475d3bd5b3dSLawrence D'Anna using TypedPythonObject::TypedPythonObject; 476f9d6d204SZachary Turner explicit PythonByteArray(llvm::ArrayRef<uint8_t> bytes); 477f9d6d204SZachary Turner PythonByteArray(const uint8_t *bytes, size_t length); 478f9d6d204SZachary Turner PythonByteArray(const PythonBytes &object); 479f9d6d204SZachary Turner 480b9c1b51eSKate Stone static bool Check(PyObject *py_obj); 481f9d6d204SZachary Turner 482b9c1b51eSKate Stone llvm::ArrayRef<uint8_t> GetBytes() const; 483f9d6d204SZachary Turner 484b9c1b51eSKate Stone size_t GetSize() const; 485f9d6d204SZachary Turner 486b9c1b51eSKate Stone void SetBytes(llvm::ArrayRef<uint8_t> stringbytes); 487f9d6d204SZachary Turner 488b9c1b51eSKate Stone StructuredData::StringSP CreateStructuredString() const; 489f9d6d204SZachary Turner }; 490f9d6d204SZachary Turner 491d3bd5b3dSLawrence D'Anna class PythonString : public TypedPythonObject<PythonString> { 4922c1f46dcSZachary Turner public: 493d3bd5b3dSLawrence D'Anna using TypedPythonObject::TypedPythonObject; 494085328eeSLawrence D'Anna static llvm::Expected<PythonString> FromUTF8(llvm::StringRef string); 495085328eeSLawrence D'Anna 496d3bd5b3dSLawrence D'Anna PythonString() : TypedPythonObject() {} // MSVC requires this for some reason 497edb35d95SEugene Zelenko 498d3bd5b3dSLawrence D'Anna explicit PythonString(llvm::StringRef string); // safe, null on error 4992c1f46dcSZachary Turner 50022c8efcdSZachary Turner static bool Check(PyObject *py_obj); 501d3bd5b3dSLawrence D'Anna static void Convert(PyRefType &type, PyObject *&py_obj); 5022c1f46dcSZachary Turner 503085328eeSLawrence D'Anna llvm::StringRef GetString() const; // safe, empty string on error 504085328eeSLawrence D'Anna 505085328eeSLawrence D'Anna llvm::Expected<llvm::StringRef> AsUTF8() const; 5062c1f46dcSZachary Turner 507b9c1b51eSKate Stone size_t GetSize() const; 5082c1f46dcSZachary Turner 509085328eeSLawrence D'Anna void SetString(llvm::StringRef string); // safe, null on error 5102c1f46dcSZachary Turner 5112c1f46dcSZachary Turner StructuredData::StringSP CreateStructuredString() const; 5122c1f46dcSZachary Turner }; 5132c1f46dcSZachary Turner 514d3bd5b3dSLawrence D'Anna class PythonInteger : public TypedPythonObject<PythonInteger> { 5152c1f46dcSZachary Turner public: 516d3bd5b3dSLawrence D'Anna using TypedPythonObject::TypedPythonObject; 517edb35d95SEugene Zelenko 518d3bd5b3dSLawrence D'Anna PythonInteger() : TypedPythonObject() {} // MSVC requires this for some reason 519d3bd5b3dSLawrence D'Anna 520d3bd5b3dSLawrence D'Anna explicit PythonInteger(int64_t value); 5212c1f46dcSZachary Turner 52222c8efcdSZachary Turner static bool Check(PyObject *py_obj); 523d3bd5b3dSLawrence D'Anna static void Convert(PyRefType &type, PyObject *&py_obj); 5242c1f46dcSZachary Turner 525b9c1b51eSKate Stone void SetInteger(int64_t value); 5262c1f46dcSZachary Turner 5272c1f46dcSZachary Turner StructuredData::IntegerSP CreateStructuredInteger() const; 5282c1f46dcSZachary Turner }; 5292c1f46dcSZachary Turner 530d3bd5b3dSLawrence D'Anna class PythonBoolean : public TypedPythonObject<PythonBoolean> { 531b81d715cSTatyana Krasnukha public: 532d3bd5b3dSLawrence D'Anna using TypedPythonObject::TypedPythonObject; 533b81d715cSTatyana Krasnukha 534d3bd5b3dSLawrence D'Anna explicit PythonBoolean(bool value); 535b81d715cSTatyana Krasnukha 536b81d715cSTatyana Krasnukha static bool Check(PyObject *py_obj); 537b81d715cSTatyana Krasnukha 538b81d715cSTatyana Krasnukha bool GetValue() const; 539b81d715cSTatyana Krasnukha 540b81d715cSTatyana Krasnukha void SetValue(bool value); 541b81d715cSTatyana Krasnukha 542b81d715cSTatyana Krasnukha StructuredData::BooleanSP CreateStructuredBoolean() const; 543b81d715cSTatyana Krasnukha }; 544b81d715cSTatyana Krasnukha 545d3bd5b3dSLawrence D'Anna class PythonList : public TypedPythonObject<PythonList> { 5462c1f46dcSZachary Turner public: 547d3bd5b3dSLawrence D'Anna using TypedPythonObject::TypedPythonObject; 548d3bd5b3dSLawrence D'Anna 549d3bd5b3dSLawrence D'Anna PythonList() : TypedPythonObject() {} // MSVC requires this for some reason 550d3bd5b3dSLawrence D'Anna 55187f47729SZachary Turner explicit PythonList(PyInitialValue value); 55287f47729SZachary Turner explicit PythonList(int list_size); 5532c1f46dcSZachary Turner 55422c8efcdSZachary Turner static bool Check(PyObject *py_obj); 55522c8efcdSZachary Turner 5562c1f46dcSZachary Turner uint32_t GetSize() const; 5572c1f46dcSZachary Turner 5582c1f46dcSZachary Turner PythonObject GetItemAtIndex(uint32_t index) const; 5592c1f46dcSZachary Turner 560f8b22f8fSZachary Turner void SetItemAtIndex(uint32_t index, const PythonObject &object); 5612c1f46dcSZachary Turner 562f8b22f8fSZachary Turner void AppendItem(const PythonObject &object); 5632c1f46dcSZachary Turner 5642c1f46dcSZachary Turner StructuredData::ArraySP CreateStructuredArray() const; 5652c1f46dcSZachary Turner }; 5662c1f46dcSZachary Turner 567d3bd5b3dSLawrence D'Anna class PythonTuple : public TypedPythonObject<PythonTuple> { 568a1405147SZachary Turner public: 569d3bd5b3dSLawrence D'Anna using TypedPythonObject::TypedPythonObject; 570d3bd5b3dSLawrence D'Anna 571a1405147SZachary Turner explicit PythonTuple(PyInitialValue value); 572a1405147SZachary Turner explicit PythonTuple(int tuple_size); 573a1405147SZachary Turner PythonTuple(std::initializer_list<PythonObject> objects); 574a1405147SZachary Turner PythonTuple(std::initializer_list<PyObject *> objects); 575a1405147SZachary Turner 576a1405147SZachary Turner static bool Check(PyObject *py_obj); 577a1405147SZachary Turner 578a1405147SZachary Turner uint32_t GetSize() const; 579a1405147SZachary Turner 580a1405147SZachary Turner PythonObject GetItemAtIndex(uint32_t index) const; 581a1405147SZachary Turner 582a1405147SZachary Turner void SetItemAtIndex(uint32_t index, const PythonObject &object); 583a1405147SZachary Turner 584a1405147SZachary Turner StructuredData::ArraySP CreateStructuredArray() const; 585a1405147SZachary Turner }; 586a1405147SZachary Turner 587d3bd5b3dSLawrence D'Anna class PythonDictionary : public TypedPythonObject<PythonDictionary> { 5882c1f46dcSZachary Turner public: 589d3bd5b3dSLawrence D'Anna using TypedPythonObject::TypedPythonObject; 590edb35d95SEugene Zelenko 591d3bd5b3dSLawrence D'Anna PythonDictionary() : TypedPythonObject() {} // MSVC requires this for some reason 592d3bd5b3dSLawrence D'Anna 593d3bd5b3dSLawrence D'Anna explicit PythonDictionary(PyInitialValue value); 5942c1f46dcSZachary Turner 59522c8efcdSZachary Turner static bool Check(PyObject *py_obj); 59622c8efcdSZachary Turner 5972c1f46dcSZachary Turner uint32_t GetSize() const; 5982c1f46dcSZachary Turner 599f8b22f8fSZachary Turner PythonList GetKeys() const; 6002c1f46dcSZachary Turner 601c86a6acaSLawrence D'Anna PythonObject GetItemForKey(const PythonObject &key) const; // DEPRECATED 602c86a6acaSLawrence D'Anna void SetItemForKey(const PythonObject &key, 603c86a6acaSLawrence D'Anna const PythonObject &value); // DEPRECATED 604c86a6acaSLawrence D'Anna 605c86a6acaSLawrence D'Anna llvm::Expected<PythonObject> GetItem(const PythonObject &key) const; 606722b6189SLawrence D'Anna llvm::Expected<PythonObject> GetItem(const llvm::Twine &key) const; 607c86a6acaSLawrence D'Anna llvm::Error SetItem(const PythonObject &key, const PythonObject &value) const; 608722b6189SLawrence D'Anna llvm::Error SetItem(const llvm::Twine &key, const PythonObject &value) const; 6092c1f46dcSZachary Turner 6102c1f46dcSZachary Turner StructuredData::DictionarySP CreateStructuredDictionary() const; 6112c1f46dcSZachary Turner }; 61287f47729SZachary Turner 613d3bd5b3dSLawrence D'Anna class PythonModule : public TypedPythonObject<PythonModule> { 6147841efbbSZachary Turner public: 615d3bd5b3dSLawrence D'Anna using TypedPythonObject::TypedPythonObject; 6167841efbbSZachary Turner 6177841efbbSZachary Turner static bool Check(PyObject *py_obj); 6187841efbbSZachary Turner 619b9c1b51eSKate Stone static PythonModule BuiltinsModule(); 620a1405147SZachary Turner 621b9c1b51eSKate Stone static PythonModule MainModule(); 622a1405147SZachary Turner 623b9c1b51eSKate Stone static PythonModule AddModule(llvm::StringRef module); 6247841efbbSZachary Turner 625085328eeSLawrence D'Anna // safe, returns invalid on error; 626085328eeSLawrence D'Anna static PythonModule ImportModule(llvm::StringRef name) { 627adcd0268SBenjamin Kramer std::string s = std::string(name); 628085328eeSLawrence D'Anna auto mod = Import(s.c_str()); 629085328eeSLawrence D'Anna if (!mod) { 630085328eeSLawrence D'Anna llvm::consumeError(mod.takeError()); 631085328eeSLawrence D'Anna return PythonModule(); 632085328eeSLawrence D'Anna } 633085328eeSLawrence D'Anna return std::move(mod.get()); 634085328eeSLawrence D'Anna } 635085328eeSLawrence D'Anna 636722b6189SLawrence D'Anna static llvm::Expected<PythonModule> Import(const llvm::Twine &name); 637085328eeSLawrence D'Anna 638722b6189SLawrence D'Anna llvm::Expected<PythonObject> Get(const llvm::Twine &name); 6392419f1d5SZachary Turner 6407841efbbSZachary Turner PythonDictionary GetDictionary() const; 6417841efbbSZachary Turner }; 6427841efbbSZachary Turner 643d3bd5b3dSLawrence D'Anna class PythonCallable : public TypedPythonObject<PythonCallable> { 644a1405147SZachary Turner public: 645d3bd5b3dSLawrence D'Anna using TypedPythonObject::TypedPythonObject; 646d3bd5b3dSLawrence D'Anna 647b58fb2f4SZachary Turner struct ArgInfo { 6482386537cSLawrence D'Anna /* the largest number of positional arguments this callable 6492386537cSLawrence D'Anna * can accept, or UNBOUNDED, ie UINT_MAX if it's a varargs 6502386537cSLawrence D'Anna * function and can accept an arbitrary number */ 6512386537cSLawrence D'Anna unsigned max_positional_args; 6522386537cSLawrence D'Anna static constexpr unsigned UNBOUNDED = UINT_MAX; // FIXME c++17 inline 653b58fb2f4SZachary Turner }; 654b58fb2f4SZachary Turner 655b9c1b51eSKate Stone static bool Check(PyObject *py_obj); 656a1405147SZachary Turner 657c86a6acaSLawrence D'Anna llvm::Expected<ArgInfo> GetArgInfo() const; 658c86a6acaSLawrence D'Anna 659b9c1b51eSKate Stone PythonObject operator()(); 660a1405147SZachary Turner 661b9c1b51eSKate Stone PythonObject operator()(std::initializer_list<PyObject *> args); 662a1405147SZachary Turner 663b9c1b51eSKate Stone PythonObject operator()(std::initializer_list<PythonObject> args); 664b58fb2f4SZachary Turner 665b58fb2f4SZachary Turner template <typename Arg, typename... Args> 666b9c1b51eSKate Stone PythonObject operator()(const Arg &arg, Args... args) { 667b58fb2f4SZachary Turner return operator()({arg, args...}); 668b58fb2f4SZachary Turner } 669a1405147SZachary Turner }; 670a1405147SZachary Turner 671d3bd5b3dSLawrence D'Anna class PythonFile : public TypedPythonObject<PythonFile> { 6729c40264fSZachary Turner public: 673d3bd5b3dSLawrence D'Anna using TypedPythonObject::TypedPythonObject; 674edb35d95SEugene Zelenko 675d3bd5b3dSLawrence D'Anna PythonFile() : TypedPythonObject() {} // MSVC requires this for some reason 6769c40264fSZachary Turner 6779c40264fSZachary Turner static bool Check(PyObject *py_obj); 6789c40264fSZachary Turner 679d9b553ecSLawrence D'Anna static llvm::Expected<PythonFile> FromFile(File &file, 680d9b553ecSLawrence D'Anna const char *mode = nullptr); 681d9b553ecSLawrence D'Anna 682085328eeSLawrence D'Anna llvm::Expected<lldb::FileSP> ConvertToFile(bool borrowed = false); 683085328eeSLawrence D'Anna llvm::Expected<lldb::FileSP> 684085328eeSLawrence D'Anna ConvertToFileForcingUseOfScriptingIOMethods(bool borrowed = false); 6859c40264fSZachary Turner }; 6869c40264fSZachary Turner 687085328eeSLawrence D'Anna class PythonException : public llvm::ErrorInfo<PythonException> { 688085328eeSLawrence D'Anna private: 689085328eeSLawrence D'Anna PyObject *m_exception_type, *m_exception, *m_traceback; 690085328eeSLawrence D'Anna PyObject *m_repr_bytes; 691085328eeSLawrence D'Anna 692085328eeSLawrence D'Anna public: 693085328eeSLawrence D'Anna static char ID; 694085328eeSLawrence D'Anna const char *toCString() const; 695085328eeSLawrence D'Anna PythonException(const char *caller = nullptr); 696085328eeSLawrence D'Anna void Restore(); 697085328eeSLawrence D'Anna ~PythonException(); 698085328eeSLawrence D'Anna void log(llvm::raw_ostream &OS) const override; 699085328eeSLawrence D'Anna std::error_code convertToErrorCode() const override; 70004edd189SLawrence D'Anna bool Matches(PyObject *exc) const; 70104edd189SLawrence D'Anna std::string ReadBacktrace() const; 702085328eeSLawrence D'Anna }; 703085328eeSLawrence D'Anna 704085328eeSLawrence D'Anna // This extracts the underlying T out of an Expected<T> and returns it. 705085328eeSLawrence D'Anna // If the Expected is an Error instead of a T, that error will be converted 706085328eeSLawrence D'Anna // into a python exception, and this will return a default-constructed T. 707085328eeSLawrence D'Anna // 708085328eeSLawrence D'Anna // This is appropriate for use right at the boundary of python calling into 709085328eeSLawrence D'Anna // C++, such as in a SWIG typemap. In such a context you should simply 710085328eeSLawrence D'Anna // check if the returned T is valid, and if it is, return a NULL back 711085328eeSLawrence D'Anna // to python. This will result in the Error being raised as an exception 712085328eeSLawrence D'Anna // from python code's point of view. 713085328eeSLawrence D'Anna // 714085328eeSLawrence D'Anna // For example: 715085328eeSLawrence D'Anna // ``` 716085328eeSLawrence D'Anna // Expected<Foo *> efoop = some_cpp_function(); 717085328eeSLawrence D'Anna // Foo *foop = unwrapOrSetPythonException(efoop); 718085328eeSLawrence D'Anna // if (!foop) 719085328eeSLawrence D'Anna // return NULL; 720085328eeSLawrence D'Anna // do_something(*foop); 721085328eeSLawrence D'Anna // 722085328eeSLawrence D'Anna // If the Error returned was itself created because a python exception was 723085328eeSLawrence D'Anna // raised when C++ code called into python, then the original exception 724085328eeSLawrence D'Anna // will be restored. Otherwise a simple string exception will be raised. 725085328eeSLawrence D'Anna template <typename T> T unwrapOrSetPythonException(llvm::Expected<T> expected) { 726085328eeSLawrence D'Anna if (expected) 727085328eeSLawrence D'Anna return expected.get(); 728085328eeSLawrence D'Anna llvm::handleAllErrors( 729085328eeSLawrence D'Anna expected.takeError(), [](PythonException &E) { E.Restore(); }, 730085328eeSLawrence D'Anna [](const llvm::ErrorInfoBase &E) { 731085328eeSLawrence D'Anna PyErr_SetString(PyExc_Exception, E.message().c_str()); 732085328eeSLawrence D'Anna }); 733085328eeSLawrence D'Anna return T(); 734085328eeSLawrence D'Anna } 735085328eeSLawrence D'Anna 736722b6189SLawrence D'Anna // This is only here to help incrementally migrate old, exception-unsafe 737722b6189SLawrence D'Anna // code. 738722b6189SLawrence D'Anna template <typename T> T unwrapIgnoringErrors(llvm::Expected<T> expected) { 739722b6189SLawrence D'Anna if (expected) 740722b6189SLawrence D'Anna return std::move(expected.get()); 741722b6189SLawrence D'Anna llvm::consumeError(expected.takeError()); 742722b6189SLawrence D'Anna return T(); 743722b6189SLawrence D'Anna } 744722b6189SLawrence D'Anna 74504edd189SLawrence D'Anna llvm::Expected<PythonObject> runStringOneLine(const llvm::Twine &string, 74604edd189SLawrence D'Anna const PythonDictionary &globals, 74704edd189SLawrence D'Anna const PythonDictionary &locals); 74804edd189SLawrence D'Anna 74904edd189SLawrence D'Anna llvm::Expected<PythonObject> runStringMultiLine(const llvm::Twine &string, 75004edd189SLawrence D'Anna const PythonDictionary &globals, 75104edd189SLawrence D'Anna const PythonDictionary &locals); 75204edd189SLawrence D'Anna 75304edd189SLawrence D'Anna // Sometimes the best way to interact with a python interpreter is 75404edd189SLawrence D'Anna // to run some python code. You construct a PythonScript with 75504edd189SLawrence D'Anna // script string. The script assigns some function to `_function_` 75604edd189SLawrence D'Anna // and you get a C++ callable object that calls the python function. 75704edd189SLawrence D'Anna // 75804edd189SLawrence D'Anna // Example: 75904edd189SLawrence D'Anna // 76004edd189SLawrence D'Anna // const char script[] = R"( 76104edd189SLawrence D'Anna // def main(x, y): 76204edd189SLawrence D'Anna // .... 76304edd189SLawrence D'Anna // )"; 76404edd189SLawrence D'Anna // 76504edd189SLawrence D'Anna // Expected<PythonObject> cpp_foo_wrapper(PythonObject x, PythonObject y) { 76604edd189SLawrence D'Anna // // no need to synchronize access to this global, we already have the GIL 76704edd189SLawrence D'Anna // static PythonScript foo(script) 76804edd189SLawrence D'Anna // return foo(x, y); 76904edd189SLawrence D'Anna // } 77004edd189SLawrence D'Anna class PythonScript { 77104edd189SLawrence D'Anna const char *script; 77204edd189SLawrence D'Anna PythonCallable function; 77304edd189SLawrence D'Anna 77404edd189SLawrence D'Anna llvm::Error Init(); 77504edd189SLawrence D'Anna 77604edd189SLawrence D'Anna public: 77704edd189SLawrence D'Anna PythonScript(const char *script) : script(script), function() {} 77804edd189SLawrence D'Anna 77904edd189SLawrence D'Anna template <typename... Args> 78004edd189SLawrence D'Anna llvm::Expected<PythonObject> operator()(Args &&... args) { 78104edd189SLawrence D'Anna if (llvm::Error error = Init()) 78204edd189SLawrence D'Anna return std::move(error); 78304edd189SLawrence D'Anna return function.Call(std::forward<Args>(args)...); 78404edd189SLawrence D'Anna } 78504edd189SLawrence D'Anna }; 78604edd189SLawrence D'Anna 78704edd189SLawrence D'Anna } // namespace python 7882c1f46dcSZachary Turner } // namespace lldb_private 7892c1f46dcSZachary Turner 790a281b42bSZachary Turner #endif 791d68983e3SPavel Labath 792d68983e3SPavel Labath #endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H 793