1292932Sdim//===-- PythonDataObjects.h--------------------------------------*- C++ -*-===// 2292932Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6292932Sdim// 7292932Sdim//===----------------------------------------------------------------------===// 8292932Sdim 9360784Sdim// 10360784Sdim// !! FIXME FIXME FIXME !! 11360784Sdim// 12360784Sdim// Python APIs nearly all can return an exception. They do this 13360784Sdim// by returning NULL, or -1, or some such value and setting 14360784Sdim// the exception state with PyErr_Set*(). Exceptions must be 15360784Sdim// handled before further python API functions are called. Failure 16360784Sdim// to do so will result in asserts on debug builds of python. 17360784Sdim// It will also sometimes, but not usually result in crashes of 18360784Sdim// release builds. 19360784Sdim// 20360784Sdim// Nearly all the code in this header does not handle python exceptions 21360784Sdim// correctly. It should all be converted to return Expected<> or 22360784Sdim// Error types to capture the exception. 23360784Sdim// 24360784Sdim// Everything in this file except functions that return Error or 25360784Sdim// Expected<> is considered deprecated and should not be 26360784Sdim// used in new code. If you need to use it, fix it first. 27360784Sdim// 28360784Sdim// 29360784Sdim// TODOs for this file 30360784Sdim// 31360784Sdim// * Make all methods safe for exceptions. 32360784Sdim// 33360784Sdim// * Eliminate method signatures that must translate exceptions into 34360784Sdim// empty objects or NULLs. Almost everything here should return 35360784Sdim// Expected<>. It should be acceptable for certain operations that 36360784Sdim// can never fail to assert instead, such as the creation of 37360784Sdim// PythonString from a string literal. 38360784Sdim// 39360784Sdim// * Elimintate Reset(), and make all non-default constructors private. 40360784Sdim// Python objects should be created with Retain<> or Take<>, and they 41360784Sdim// should be assigned with operator= 42360784Sdim// 43360784Sdim// * Eliminate default constructors, make python objects always 44360784Sdim// nonnull, and use optionals where necessary. 45360784Sdim// 46360784Sdim 47360784Sdim 48292932Sdim#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H 49292932Sdim#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H 50292932Sdim 51360784Sdim#include "lldb/Host/Config.h" 52292932Sdim 53360784Sdim#if LLDB_ENABLE_PYTHON 54360784Sdim 55314564Sdim// LLDB Python header must be included first 56314564Sdim#include "lldb-python.h" 57314564Sdim 58292932Sdim#include "lldb/Host/File.h" 59321369Sdim#include "lldb/Utility/StructuredData.h" 60292932Sdim 61294024Sdim#include "llvm/ADT/ArrayRef.h" 62294024Sdim 63292932Sdimnamespace lldb_private { 64360784Sdimnamespace python { 65292932Sdim 66360784Sdimclass PythonObject; 67294024Sdimclass PythonBytes; 68292932Sdimclass PythonString; 69292932Sdimclass PythonList; 70292932Sdimclass PythonDictionary; 71292932Sdimclass PythonInteger; 72360784Sdimclass PythonException; 73292932Sdim 74314564Sdimclass StructuredPythonObject : public StructuredData::Generic { 75292932Sdimpublic: 76314564Sdim StructuredPythonObject() : StructuredData::Generic() {} 77292932Sdim 78314564Sdim StructuredPythonObject(void *obj) : StructuredData::Generic(obj) { 79314564Sdim Py_XINCREF(GetValue()); 80314564Sdim } 81292932Sdim 82314564Sdim ~StructuredPythonObject() override { 83314564Sdim if (Py_IsInitialized()) 84314564Sdim Py_XDECREF(GetValue()); 85314564Sdim SetValue(nullptr); 86314564Sdim } 87292932Sdim 88314564Sdim bool IsValid() const override { return GetValue() && GetValue() != Py_None; } 89292932Sdim 90360784Sdim void Serialize(llvm::json::OStream &s) const override; 91292932Sdim 92292932Sdimprivate: 93314564Sdim DISALLOW_COPY_AND_ASSIGN(StructuredPythonObject); 94292932Sdim}; 95292932Sdim 96314564Sdimenum class PyObjectType { 97314564Sdim Unknown, 98314564Sdim None, 99353358Sdim Boolean, 100314564Sdim Integer, 101314564Sdim Dictionary, 102314564Sdim List, 103314564Sdim String, 104314564Sdim Bytes, 105314564Sdim ByteArray, 106314564Sdim Module, 107314564Sdim Callable, 108314564Sdim Tuple, 109314564Sdim File 110292932Sdim}; 111292932Sdim 112314564Sdimenum class PyRefType { 113314564Sdim Borrowed, // We are not given ownership of the incoming PyObject. 114314564Sdim // We cannot safely hold it without calling Py_INCREF. 115314564Sdim Owned // We have ownership of the incoming PyObject. We should 116314564Sdim // not call Py_INCREF. 117292932Sdim}; 118292932Sdim 119292932Sdim 120360784Sdim// Take a reference that you already own, and turn it into 121360784Sdim// a PythonObject. 122360784Sdim// 123360784Sdim// Most python API methods will return a +1 reference 124360784Sdim// if they succeed or NULL if and only if 125360784Sdim// they set an exception. Use this to collect such return 126360784Sdim// values, after checking for NULL. 127360784Sdim// 128360784Sdim// If T is not just PythonObject, then obj must be already be 129360784Sdim// checked to be of the correct type. 130360784Sdimtemplate <typename T> T Take(PyObject *obj) { 131360784Sdim assert(obj); 132360784Sdim assert(!PyErr_Occurred()); 133360784Sdim T thing(PyRefType::Owned, obj); 134360784Sdim assert(thing.IsValid()); 135360784Sdim return thing; 136360784Sdim} 137360784Sdim 138360784Sdim// Retain a reference you have borrowed, and turn it into 139360784Sdim// a PythonObject. 140360784Sdim// 141360784Sdim// A minority of python APIs return a borrowed reference 142360784Sdim// instead of a +1. They will also return NULL if and only 143360784Sdim// if they set an exception. Use this to collect such return 144360784Sdim// values, after checking for NULL. 145360784Sdim// 146360784Sdim// If T is not just PythonObject, then obj must be already be 147360784Sdim// checked to be of the correct type. 148360784Sdimtemplate <typename T> T Retain(PyObject *obj) { 149360784Sdim assert(obj); 150360784Sdim assert(!PyErr_Occurred()); 151360784Sdim T thing(PyRefType::Borrowed, obj); 152360784Sdim assert(thing.IsValid()); 153360784Sdim return thing; 154360784Sdim} 155360784Sdim 156360784Sdim// This class can be used like a utility function to convert from 157360784Sdim// a llvm-friendly Twine into a null-terminated const char *, 158360784Sdim// which is the form python C APIs want their strings in. 159360784Sdim// 160360784Sdim// Example: 161360784Sdim// const llvm::Twine &some_twine; 162360784Sdim// PyFoo_Bar(x, y, z, NullTerminated(some_twine)); 163360784Sdim// 164360784Sdim// Why a class instead of a function? If the twine isn't already null 165360784Sdim// terminated, it will need a temporary buffer to copy the string 166360784Sdim// into. We need that buffer to stick around for the lifetime of the 167360784Sdim// statement. 168360784Sdimclass NullTerminated { 169360784Sdim const char *str; 170360784Sdim llvm::SmallString<32> storage; 171360784Sdim 172292932Sdimpublic: 173360784Sdim NullTerminated(const llvm::Twine &twine) { 174360784Sdim llvm::StringRef ref = twine.toNullTerminatedStringRef(storage); 175360784Sdim str = ref.begin(); 176314564Sdim } 177360784Sdim operator const char *() { return str; } 178360784Sdim}; 179292932Sdim 180360784Sdiminline llvm::Error nullDeref() { 181360784Sdim return llvm::createStringError(llvm::inconvertibleErrorCode(), 182360784Sdim "A NULL PyObject* was dereferenced"); 183360784Sdim} 184292932Sdim 185360784Sdiminline llvm::Error exception(const char *s = nullptr) { 186360784Sdim return llvm::make_error<PythonException>(s); 187360784Sdim} 188292932Sdim 189360784Sdiminline llvm::Error keyError() { 190360784Sdim return llvm::createStringError(llvm::inconvertibleErrorCode(), 191360784Sdim "key not in dict"); 192360784Sdim} 193292932Sdim 194360784Sdim#if PY_MAJOR_VERSION < 3 195360784Sdim// The python 2 API declares some arguments as char* that should 196360784Sdim// be const char *, but it doesn't actually modify them. 197360784Sdiminline char *py2_const_cast(const char *s) { return const_cast<char *>(s); } 198360784Sdim#else 199360784Sdiminline const char *py2_const_cast(const char *s) { return s; } 200360784Sdim#endif 201292932Sdim 202360784Sdimenum class PyInitialValue { Invalid, Empty }; 203292932Sdim 204360784Sdimtemplate <typename T, typename Enable = void> struct PythonFormat; 205292932Sdim 206360784Sdimtemplate <> struct PythonFormat<unsigned long long> { 207360784Sdim static constexpr char format = 'K'; 208360784Sdim static auto get(unsigned long long value) { return value; } 209360784Sdim}; 210292932Sdim 211360784Sdimtemplate <> struct PythonFormat<long long> { 212360784Sdim static constexpr char format = 'L'; 213360784Sdim static auto get(long long value) { return value; } 214360784Sdim}; 215360784Sdim 216360784Sdimtemplate <> struct PythonFormat<PyObject *> { 217360784Sdim static constexpr char format = 'O'; 218360784Sdim static auto get(PyObject *value) { return value; } 219360784Sdim}; 220360784Sdim 221360784Sdimtemplate <typename T> 222360784Sdimstruct PythonFormat< 223360784Sdim T, typename std::enable_if<std::is_base_of<PythonObject, T>::value>::type> { 224360784Sdim static constexpr char format = 'O'; 225360784Sdim static auto get(const T &value) { return value.get(); } 226360784Sdim}; 227360784Sdim 228360784Sdimclass PythonObject { 229360784Sdimpublic: 230360784Sdim PythonObject() : m_py_obj(nullptr) {} 231360784Sdim 232360784Sdim PythonObject(PyRefType type, PyObject *py_obj) { 233314564Sdim m_py_obj = py_obj; 234314564Sdim // If this is a borrowed reference, we need to convert it to 235314564Sdim // an owned reference by incrementing it. If it is an owned 236314564Sdim // reference (for example the caller allocated it with PyDict_New() 237314564Sdim // then we must *not* increment it. 238360784Sdim if (m_py_obj && Py_IsInitialized() && type == PyRefType::Borrowed) 239314564Sdim Py_XINCREF(m_py_obj); 240314564Sdim } 241292932Sdim 242360784Sdim PythonObject(const PythonObject &rhs) 243360784Sdim : PythonObject(PyRefType::Borrowed, rhs.m_py_obj) {} 244360784Sdim 245360784Sdim PythonObject(PythonObject &&rhs) { 246360784Sdim m_py_obj = rhs.m_py_obj; 247360784Sdim rhs.m_py_obj = nullptr; 248360784Sdim } 249360784Sdim 250360784Sdim ~PythonObject() { Reset(); } 251360784Sdim 252360784Sdim void Reset() { 253360784Sdim if (m_py_obj && Py_IsInitialized()) 254360784Sdim Py_DECREF(m_py_obj); 255360784Sdim m_py_obj = nullptr; 256360784Sdim } 257360784Sdim 258314564Sdim void Dump() const { 259314564Sdim if (m_py_obj) 260314564Sdim _PyObject_Dump(m_py_obj); 261314564Sdim else 262314564Sdim puts("NULL"); 263314564Sdim } 264292932Sdim 265314564Sdim void Dump(Stream &strm) const; 266292932Sdim 267314564Sdim PyObject *get() const { return m_py_obj; } 268292932Sdim 269314564Sdim PyObject *release() { 270314564Sdim PyObject *result = m_py_obj; 271314564Sdim m_py_obj = nullptr; 272314564Sdim return result; 273314564Sdim } 274292932Sdim 275360784Sdim PythonObject &operator=(PythonObject other) { 276360784Sdim Reset(); 277360784Sdim m_py_obj = std::exchange(other.m_py_obj, nullptr); 278314564Sdim return *this; 279314564Sdim } 280292932Sdim 281314564Sdim PyObjectType GetObjectType() const; 282292932Sdim 283314564Sdim PythonString Repr() const; 284292932Sdim 285314564Sdim PythonString Str() const; 286292932Sdim 287314564Sdim static PythonObject ResolveNameWithDictionary(llvm::StringRef name, 288314564Sdim const PythonDictionary &dict); 289292932Sdim 290314564Sdim template <typename T> 291314564Sdim static T ResolveNameWithDictionary(llvm::StringRef name, 292314564Sdim const PythonDictionary &dict) { 293314564Sdim return ResolveNameWithDictionary(name, dict).AsType<T>(); 294314564Sdim } 295292932Sdim 296314564Sdim PythonObject ResolveName(llvm::StringRef name) const; 297292932Sdim 298314564Sdim template <typename T> T ResolveName(llvm::StringRef name) const { 299314564Sdim return ResolveName(name).AsType<T>(); 300314564Sdim } 301292932Sdim 302314564Sdim bool HasAttribute(llvm::StringRef attribute) const; 303292932Sdim 304314564Sdim PythonObject GetAttributeValue(llvm::StringRef attribute) const; 305292932Sdim 306360784Sdim bool IsNone() const { return m_py_obj == Py_None; } 307292932Sdim 308360784Sdim bool IsValid() const { return m_py_obj != nullptr; } 309292932Sdim 310360784Sdim bool IsAllocated() const { return IsValid() && !IsNone(); } 311292932Sdim 312360784Sdim explicit operator bool() const { return IsValid() && !IsNone(); } 313360784Sdim 314314564Sdim template <typename T> T AsType() const { 315314564Sdim if (!T::Check(m_py_obj)) 316314564Sdim return T(); 317314564Sdim return T(PyRefType::Borrowed, m_py_obj); 318314564Sdim } 319314564Sdim 320314564Sdim StructuredData::ObjectSP CreateStructuredObject() const; 321314564Sdim 322360784Sdimpublic: 323360784Sdim template <typename... T> 324360784Sdim llvm::Expected<PythonObject> CallMethod(const char *name, 325360784Sdim const T &... t) const { 326360784Sdim const char format[] = {'(', PythonFormat<T>::format..., ')', 0}; 327360784Sdim PyObject *obj = 328360784Sdim PyObject_CallMethod(m_py_obj, py2_const_cast(name), 329360784Sdim py2_const_cast(format), PythonFormat<T>::get(t)...); 330360784Sdim if (!obj) 331360784Sdim return exception(); 332360784Sdim return python::Take<PythonObject>(obj); 333360784Sdim } 334360784Sdim 335360784Sdim template <typename... T> 336360784Sdim llvm::Expected<PythonObject> Call(const T &... t) const { 337360784Sdim const char format[] = {'(', PythonFormat<T>::format..., ')', 0}; 338360784Sdim PyObject *obj = PyObject_CallFunction(m_py_obj, py2_const_cast(format), 339360784Sdim PythonFormat<T>::get(t)...); 340360784Sdim if (!obj) 341360784Sdim return exception(); 342360784Sdim return python::Take<PythonObject>(obj); 343360784Sdim } 344360784Sdim 345360784Sdim llvm::Expected<PythonObject> GetAttribute(const llvm::Twine &name) const { 346360784Sdim if (!m_py_obj) 347360784Sdim return nullDeref(); 348360784Sdim PyObject *obj = PyObject_GetAttrString(m_py_obj, NullTerminated(name)); 349360784Sdim if (!obj) 350360784Sdim return exception(); 351360784Sdim return python::Take<PythonObject>(obj); 352360784Sdim } 353360784Sdim 354360784Sdim llvm::Expected<bool> IsTrue() { 355360784Sdim if (!m_py_obj) 356360784Sdim return nullDeref(); 357360784Sdim int r = PyObject_IsTrue(m_py_obj); 358360784Sdim if (r < 0) 359360784Sdim return exception(); 360360784Sdim return !!r; 361360784Sdim } 362360784Sdim 363360784Sdim llvm::Expected<long long> AsLongLong() { 364360784Sdim if (!m_py_obj) 365360784Sdim return nullDeref(); 366360784Sdim assert(!PyErr_Occurred()); 367360784Sdim long long r = PyLong_AsLongLong(m_py_obj); 368360784Sdim if (PyErr_Occurred()) 369360784Sdim return exception(); 370360784Sdim return r; 371360784Sdim } 372360784Sdim 373360784Sdim llvm::Expected<bool> IsInstance(const PythonObject &cls) { 374360784Sdim if (!m_py_obj || !cls.IsValid()) 375360784Sdim return nullDeref(); 376360784Sdim int r = PyObject_IsInstance(m_py_obj, cls.get()); 377360784Sdim if (r < 0) 378360784Sdim return exception(); 379360784Sdim return !!r; 380360784Sdim } 381360784Sdim 382292932Sdimprotected: 383314564Sdim PyObject *m_py_obj; 384292932Sdim}; 385292932Sdim 386360784Sdim 387360784Sdim// This is why C++ needs monads. 388360784Sdimtemplate <typename T> llvm::Expected<T> As(llvm::Expected<PythonObject> &&obj) { 389360784Sdim if (!obj) 390360784Sdim return obj.takeError(); 391360784Sdim if (!T::Check(obj.get().get())) 392360784Sdim return llvm::createStringError(llvm::inconvertibleErrorCode(), 393360784Sdim "type error"); 394360784Sdim return T(PyRefType::Borrowed, std::move(obj.get().get())); 395360784Sdim} 396360784Sdim 397360784Sdimtemplate <> llvm::Expected<bool> As<bool>(llvm::Expected<PythonObject> &&obj); 398360784Sdim 399360784Sdimtemplate <> 400360784Sdimllvm::Expected<long long> As<long long>(llvm::Expected<PythonObject> &&obj); 401360784Sdim 402360784Sdimtemplate <> 403360784Sdimllvm::Expected<std::string> As<std::string>(llvm::Expected<PythonObject> &&obj); 404360784Sdim 405360784Sdim 406360784Sdimtemplate <class T> class TypedPythonObject : public PythonObject { 407294024Sdimpublic: 408360784Sdim // override to perform implicit type conversions on Reset 409360784Sdim // This can be eliminated once we drop python 2 support. 410360784Sdim static void Convert(PyRefType &type, PyObject *&py_obj) {} 411360784Sdim 412360784Sdim TypedPythonObject(PyRefType type, PyObject *py_obj) { 413360784Sdim if (!py_obj) 414360784Sdim return; 415360784Sdim T::Convert(type, py_obj); 416360784Sdim if (T::Check(py_obj)) 417360784Sdim PythonObject::operator=(PythonObject(type, py_obj)); 418360784Sdim else if (type == PyRefType::Owned) 419360784Sdim Py_DECREF(py_obj); 420360784Sdim } 421360784Sdim 422360784Sdim TypedPythonObject() {} 423360784Sdim}; 424360784Sdim 425360784Sdimclass PythonBytes : public TypedPythonObject<PythonBytes> { 426360784Sdimpublic: 427360784Sdim using TypedPythonObject::TypedPythonObject; 428314564Sdim explicit PythonBytes(llvm::ArrayRef<uint8_t> bytes); 429314564Sdim PythonBytes(const uint8_t *bytes, size_t length); 430294024Sdim 431314564Sdim static bool Check(PyObject *py_obj); 432294024Sdim 433314564Sdim llvm::ArrayRef<uint8_t> GetBytes() const; 434294024Sdim 435314564Sdim size_t GetSize() const; 436294024Sdim 437314564Sdim void SetBytes(llvm::ArrayRef<uint8_t> stringbytes); 438294024Sdim 439314564Sdim StructuredData::StringSP CreateStructuredString() const; 440294024Sdim}; 441294024Sdim 442360784Sdimclass PythonByteArray : public TypedPythonObject<PythonByteArray> { 443309124Sdimpublic: 444360784Sdim using TypedPythonObject::TypedPythonObject; 445314564Sdim explicit PythonByteArray(llvm::ArrayRef<uint8_t> bytes); 446314564Sdim PythonByteArray(const uint8_t *bytes, size_t length); 447314564Sdim PythonByteArray(const PythonBytes &object); 448309124Sdim 449314564Sdim static bool Check(PyObject *py_obj); 450309124Sdim 451314564Sdim llvm::ArrayRef<uint8_t> GetBytes() const; 452309124Sdim 453314564Sdim size_t GetSize() const; 454309124Sdim 455314564Sdim void SetBytes(llvm::ArrayRef<uint8_t> stringbytes); 456309124Sdim 457314564Sdim StructuredData::StringSP CreateStructuredString() const; 458309124Sdim}; 459309124Sdim 460360784Sdimclass PythonString : public TypedPythonObject<PythonString> { 461292932Sdimpublic: 462360784Sdim using TypedPythonObject::TypedPythonObject; 463360784Sdim static llvm::Expected<PythonString> FromUTF8(llvm::StringRef string); 464292932Sdim 465360784Sdim PythonString() : TypedPythonObject() {} // MSVC requires this for some reason 466292932Sdim 467360784Sdim explicit PythonString(llvm::StringRef string); // safe, null on error 468360784Sdim 469314564Sdim static bool Check(PyObject *py_obj); 470360784Sdim static void Convert(PyRefType &type, PyObject *&py_obj); 471292932Sdim 472360784Sdim llvm::StringRef GetString() const; // safe, empty string on error 473292932Sdim 474360784Sdim llvm::Expected<llvm::StringRef> AsUTF8() const; 475292932Sdim 476314564Sdim size_t GetSize() const; 477292932Sdim 478360784Sdim void SetString(llvm::StringRef string); // safe, null on error 479292932Sdim 480314564Sdim StructuredData::StringSP CreateStructuredString() const; 481292932Sdim}; 482292932Sdim 483360784Sdimclass PythonInteger : public TypedPythonObject<PythonInteger> { 484292932Sdimpublic: 485360784Sdim using TypedPythonObject::TypedPythonObject; 486360784Sdim 487360784Sdim PythonInteger() : TypedPythonObject() {} // MSVC requires this for some reason 488360784Sdim 489314564Sdim explicit PythonInteger(int64_t value); 490292932Sdim 491314564Sdim static bool Check(PyObject *py_obj); 492360784Sdim static void Convert(PyRefType &type, PyObject *&py_obj); 493292932Sdim 494314564Sdim int64_t GetInteger() const; 495292932Sdim 496314564Sdim void SetInteger(int64_t value); 497292932Sdim 498314564Sdim StructuredData::IntegerSP CreateStructuredInteger() const; 499292932Sdim}; 500292932Sdim 501360784Sdimclass PythonBoolean : public TypedPythonObject<PythonBoolean> { 502353358Sdimpublic: 503360784Sdim using TypedPythonObject::TypedPythonObject; 504360784Sdim 505353358Sdim explicit PythonBoolean(bool value); 506353358Sdim 507353358Sdim static bool Check(PyObject *py_obj); 508353358Sdim 509353358Sdim bool GetValue() const; 510353358Sdim 511353358Sdim void SetValue(bool value); 512353358Sdim 513353358Sdim StructuredData::BooleanSP CreateStructuredBoolean() const; 514353358Sdim}; 515353358Sdim 516360784Sdimclass PythonList : public TypedPythonObject<PythonList> { 517292932Sdimpublic: 518360784Sdim using TypedPythonObject::TypedPythonObject; 519360784Sdim 520360784Sdim PythonList() : TypedPythonObject() {} // MSVC requires this for some reason 521360784Sdim 522314564Sdim explicit PythonList(PyInitialValue value); 523314564Sdim explicit PythonList(int list_size); 524292932Sdim 525314564Sdim static bool Check(PyObject *py_obj); 526292932Sdim 527314564Sdim uint32_t GetSize() const; 528292932Sdim 529314564Sdim PythonObject GetItemAtIndex(uint32_t index) const; 530292932Sdim 531314564Sdim void SetItemAtIndex(uint32_t index, const PythonObject &object); 532292932Sdim 533314564Sdim void AppendItem(const PythonObject &object); 534292932Sdim 535314564Sdim StructuredData::ArraySP CreateStructuredArray() const; 536292932Sdim}; 537292932Sdim 538360784Sdimclass PythonTuple : public TypedPythonObject<PythonTuple> { 539292932Sdimpublic: 540360784Sdim using TypedPythonObject::TypedPythonObject; 541360784Sdim 542314564Sdim explicit PythonTuple(PyInitialValue value); 543314564Sdim explicit PythonTuple(int tuple_size); 544314564Sdim PythonTuple(std::initializer_list<PythonObject> objects); 545314564Sdim PythonTuple(std::initializer_list<PyObject *> objects); 546292932Sdim 547314564Sdim static bool Check(PyObject *py_obj); 548292932Sdim 549314564Sdim uint32_t GetSize() const; 550292932Sdim 551314564Sdim PythonObject GetItemAtIndex(uint32_t index) const; 552292932Sdim 553314564Sdim void SetItemAtIndex(uint32_t index, const PythonObject &object); 554292932Sdim 555314564Sdim StructuredData::ArraySP CreateStructuredArray() const; 556292932Sdim}; 557292932Sdim 558360784Sdimclass PythonDictionary : public TypedPythonObject<PythonDictionary> { 559292932Sdimpublic: 560360784Sdim using TypedPythonObject::TypedPythonObject; 561360784Sdim 562360784Sdim PythonDictionary() : TypedPythonObject() {} // MSVC requires this for some reason 563360784Sdim 564314564Sdim explicit PythonDictionary(PyInitialValue value); 565292932Sdim 566314564Sdim static bool Check(PyObject *py_obj); 567292932Sdim 568314564Sdim uint32_t GetSize() const; 569292932Sdim 570314564Sdim PythonList GetKeys() const; 571292932Sdim 572360784Sdim PythonObject GetItemForKey(const PythonObject &key) const; // DEPRECATED 573360784Sdim void SetItemForKey(const PythonObject &key, 574360784Sdim const PythonObject &value); // DEPRECATED 575292932Sdim 576360784Sdim llvm::Expected<PythonObject> GetItem(const PythonObject &key) const; 577360784Sdim llvm::Expected<PythonObject> GetItem(const llvm::Twine &key) const; 578360784Sdim llvm::Error SetItem(const PythonObject &key, const PythonObject &value) const; 579360784Sdim llvm::Error SetItem(const llvm::Twine &key, const PythonObject &value) const; 580360784Sdim 581314564Sdim StructuredData::DictionarySP CreateStructuredDictionary() const; 582292932Sdim}; 583292932Sdim 584360784Sdimclass PythonModule : public TypedPythonObject<PythonModule> { 585314564Sdimpublic: 586360784Sdim using TypedPythonObject::TypedPythonObject; 587292932Sdim 588314564Sdim static bool Check(PyObject *py_obj); 589292932Sdim 590314564Sdim static PythonModule BuiltinsModule(); 591292932Sdim 592314564Sdim static PythonModule MainModule(); 593292932Sdim 594314564Sdim static PythonModule AddModule(llvm::StringRef module); 595292932Sdim 596360784Sdim // safe, returns invalid on error; 597360784Sdim static PythonModule ImportModule(llvm::StringRef name) { 598360784Sdim std::string s = name; 599360784Sdim auto mod = Import(s.c_str()); 600360784Sdim if (!mod) { 601360784Sdim llvm::consumeError(mod.takeError()); 602360784Sdim return PythonModule(); 603360784Sdim } 604360784Sdim return std::move(mod.get()); 605360784Sdim } 606292932Sdim 607360784Sdim static llvm::Expected<PythonModule> Import(const llvm::Twine &name); 608292932Sdim 609360784Sdim llvm::Expected<PythonObject> Get(const llvm::Twine &name); 610292932Sdim 611314564Sdim PythonDictionary GetDictionary() const; 612292932Sdim}; 613292932Sdim 614360784Sdimclass PythonCallable : public TypedPythonObject<PythonCallable> { 615292932Sdimpublic: 616360784Sdim using TypedPythonObject::TypedPythonObject; 617360784Sdim 618314564Sdim struct ArgInfo { 619360784Sdim /* the largest number of positional arguments this callable 620360784Sdim * can accept, or UNBOUNDED, ie UINT_MAX if it's a varargs 621360784Sdim * function and can accept an arbitrary number */ 622360784Sdim unsigned max_positional_args; 623360784Sdim static constexpr unsigned UNBOUNDED = UINT_MAX; // FIXME c++17 inline 624314564Sdim }; 625292932Sdim 626314564Sdim static bool Check(PyObject *py_obj); 627292932Sdim 628360784Sdim llvm::Expected<ArgInfo> GetArgInfo() const; 629292932Sdim 630314564Sdim PythonObject operator()(); 631292932Sdim 632314564Sdim PythonObject operator()(std::initializer_list<PyObject *> args); 633292932Sdim 634314564Sdim PythonObject operator()(std::initializer_list<PythonObject> args); 635292932Sdim 636314564Sdim template <typename Arg, typename... Args> 637314564Sdim PythonObject operator()(const Arg &arg, Args... args) { 638314564Sdim return operator()({arg, args...}); 639314564Sdim } 640292932Sdim}; 641292932Sdim 642360784Sdimclass PythonFile : public TypedPythonObject<PythonFile> { 643314564Sdimpublic: 644360784Sdim using TypedPythonObject::TypedPythonObject; 645292932Sdim 646360784Sdim PythonFile() : TypedPythonObject() {} // MSVC requires this for some reason 647292932Sdim 648314564Sdim static bool Check(PyObject *py_obj); 649292932Sdim 650360784Sdim static llvm::Expected<PythonFile> FromFile(File &file, 651360784Sdim const char *mode = nullptr); 652292932Sdim 653360784Sdim llvm::Expected<lldb::FileSP> ConvertToFile(bool borrowed = false); 654360784Sdim llvm::Expected<lldb::FileSP> 655360784Sdim ConvertToFileForcingUseOfScriptingIOMethods(bool borrowed = false); 656360784Sdim}; 657292932Sdim 658360784Sdimclass PythonException : public llvm::ErrorInfo<PythonException> { 659360784Sdimprivate: 660360784Sdim PyObject *m_exception_type, *m_exception, *m_traceback; 661360784Sdim PyObject *m_repr_bytes; 662292932Sdim 663360784Sdimpublic: 664360784Sdim static char ID; 665360784Sdim const char *toCString() const; 666360784Sdim PythonException(const char *caller = nullptr); 667360784Sdim void Restore(); 668360784Sdim ~PythonException(); 669360784Sdim void log(llvm::raw_ostream &OS) const override; 670360784Sdim std::error_code convertToErrorCode() const override; 671360784Sdim bool Matches(PyObject *exc) const; 672360784Sdim std::string ReadBacktrace() const; 673292932Sdim}; 674292932Sdim 675360784Sdim// This extracts the underlying T out of an Expected<T> and returns it. 676360784Sdim// If the Expected is an Error instead of a T, that error will be converted 677360784Sdim// into a python exception, and this will return a default-constructed T. 678360784Sdim// 679360784Sdim// This is appropriate for use right at the boundary of python calling into 680360784Sdim// C++, such as in a SWIG typemap. In such a context you should simply 681360784Sdim// check if the returned T is valid, and if it is, return a NULL back 682360784Sdim// to python. This will result in the Error being raised as an exception 683360784Sdim// from python code's point of view. 684360784Sdim// 685360784Sdim// For example: 686360784Sdim// ``` 687360784Sdim// Expected<Foo *> efoop = some_cpp_function(); 688360784Sdim// Foo *foop = unwrapOrSetPythonException(efoop); 689360784Sdim// if (!foop) 690360784Sdim// return NULL; 691360784Sdim// do_something(*foop); 692360784Sdim// 693360784Sdim// If the Error returned was itself created because a python exception was 694360784Sdim// raised when C++ code called into python, then the original exception 695360784Sdim// will be restored. Otherwise a simple string exception will be raised. 696360784Sdimtemplate <typename T> T unwrapOrSetPythonException(llvm::Expected<T> expected) { 697360784Sdim if (expected) 698360784Sdim return expected.get(); 699360784Sdim llvm::handleAllErrors( 700360784Sdim expected.takeError(), [](PythonException &E) { E.Restore(); }, 701360784Sdim [](const llvm::ErrorInfoBase &E) { 702360784Sdim PyErr_SetString(PyExc_Exception, E.message().c_str()); 703360784Sdim }); 704360784Sdim return T(); 705360784Sdim} 706360784Sdim 707360784Sdim// This is only here to help incrementally migrate old, exception-unsafe 708360784Sdim// code. 709360784Sdimtemplate <typename T> T unwrapIgnoringErrors(llvm::Expected<T> expected) { 710360784Sdim if (expected) 711360784Sdim return std::move(expected.get()); 712360784Sdim llvm::consumeError(expected.takeError()); 713360784Sdim return T(); 714360784Sdim} 715360784Sdim 716360784Sdimllvm::Expected<PythonObject> runStringOneLine(const llvm::Twine &string, 717360784Sdim const PythonDictionary &globals, 718360784Sdim const PythonDictionary &locals); 719360784Sdim 720360784Sdimllvm::Expected<PythonObject> runStringMultiLine(const llvm::Twine &string, 721360784Sdim const PythonDictionary &globals, 722360784Sdim const PythonDictionary &locals); 723360784Sdim 724360784Sdim// Sometimes the best way to interact with a python interpreter is 725360784Sdim// to run some python code. You construct a PythonScript with 726360784Sdim// script string. The script assigns some function to `_function_` 727360784Sdim// and you get a C++ callable object that calls the python function. 728360784Sdim// 729360784Sdim// Example: 730360784Sdim// 731360784Sdim// const char script[] = R"( 732360784Sdim// def main(x, y): 733360784Sdim// .... 734360784Sdim// )"; 735360784Sdim// 736360784Sdim// Expected<PythonObject> cpp_foo_wrapper(PythonObject x, PythonObject y) { 737360784Sdim// // no need to synchronize access to this global, we already have the GIL 738360784Sdim// static PythonScript foo(script) 739360784Sdim// return foo(x, y); 740360784Sdim// } 741360784Sdimclass PythonScript { 742360784Sdim const char *script; 743360784Sdim PythonCallable function; 744360784Sdim 745360784Sdim llvm::Error Init(); 746360784Sdim 747360784Sdimpublic: 748360784Sdim PythonScript(const char *script) : script(script), function() {} 749360784Sdim 750360784Sdim template <typename... Args> 751360784Sdim llvm::Expected<PythonObject> operator()(Args &&... args) { 752360784Sdim if (llvm::Error error = Init()) 753360784Sdim return std::move(error); 754360784Sdim return function.Call(std::forward<Args>(args)...); 755360784Sdim } 756360784Sdim}; 757360784Sdim 758360784Sdim} // namespace python 759292932Sdim} // namespace lldb_private 760292932Sdim 761292932Sdim#endif 762292932Sdim 763292932Sdim#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H 764