1061da546Spatrick //===-- PythonDataObjects.h--------------------------------------*- C++ -*-===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick
9061da546Spatrick //
10061da546Spatrick // !! FIXME FIXME FIXME !!
11061da546Spatrick //
12061da546Spatrick // Python APIs nearly all can return an exception. They do this
13061da546Spatrick // by returning NULL, or -1, or some such value and setting
14061da546Spatrick // the exception state with PyErr_Set*(). Exceptions must be
15061da546Spatrick // handled before further python API functions are called. Failure
16061da546Spatrick // to do so will result in asserts on debug builds of python.
17061da546Spatrick // It will also sometimes, but not usually result in crashes of
18061da546Spatrick // release builds.
19061da546Spatrick //
20061da546Spatrick // Nearly all the code in this header does not handle python exceptions
21061da546Spatrick // correctly. It should all be converted to return Expected<> or
22061da546Spatrick // Error types to capture the exception.
23061da546Spatrick //
24061da546Spatrick // Everything in this file except functions that return Error or
25061da546Spatrick // Expected<> is considered deprecated and should not be
26061da546Spatrick // used in new code. If you need to use it, fix it first.
27061da546Spatrick //
28061da546Spatrick //
29061da546Spatrick // TODOs for this file
30061da546Spatrick //
31061da546Spatrick // * Make all methods safe for exceptions.
32061da546Spatrick //
33061da546Spatrick // * Eliminate method signatures that must translate exceptions into
34061da546Spatrick // empty objects or NULLs. Almost everything here should return
35061da546Spatrick // Expected<>. It should be acceptable for certain operations that
36061da546Spatrick // can never fail to assert instead, such as the creation of
37061da546Spatrick // PythonString from a string literal.
38061da546Spatrick //
39dda28197Spatrick // * Eliminate Reset(), and make all non-default constructors private.
40061da546Spatrick // Python objects should be created with Retain<> or Take<>, and they
41061da546Spatrick // should be assigned with operator=
42061da546Spatrick //
43061da546Spatrick // * Eliminate default constructors, make python objects always
44061da546Spatrick // nonnull, and use optionals where necessary.
45061da546Spatrick //
46061da546Spatrick
47061da546Spatrick
48061da546Spatrick #ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H
49061da546Spatrick #define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H
50061da546Spatrick
51061da546Spatrick #include "lldb/Host/Config.h"
52061da546Spatrick
53061da546Spatrick #if LLDB_ENABLE_PYTHON
54061da546Spatrick
55061da546Spatrick // LLDB Python header must be included first
56061da546Spatrick #include "lldb-python.h"
57061da546Spatrick
58061da546Spatrick #include "lldb/Host/File.h"
59061da546Spatrick #include "lldb/Utility/StructuredData.h"
60061da546Spatrick
61061da546Spatrick #include "llvm/ADT/ArrayRef.h"
62061da546Spatrick
63061da546Spatrick namespace lldb_private {
64061da546Spatrick namespace python {
65061da546Spatrick
66061da546Spatrick class PythonObject;
67061da546Spatrick class PythonBytes;
68061da546Spatrick class PythonString;
69061da546Spatrick class PythonList;
70061da546Spatrick class PythonDictionary;
71061da546Spatrick class PythonInteger;
72061da546Spatrick class PythonException;
73061da546Spatrick
74*f6aab3d8Srobert class GIL {
75061da546Spatrick public:
GIL()76*f6aab3d8Srobert GIL() {
77*f6aab3d8Srobert m_state = PyGILState_Ensure();
78*f6aab3d8Srobert assert(!PyErr_Occurred());
79061da546Spatrick }
~GIL()80*f6aab3d8Srobert ~GIL() { PyGILState_Release(m_state); }
81061da546Spatrick
82*f6aab3d8Srobert protected:
83*f6aab3d8Srobert PyGILState_STATE m_state;
84061da546Spatrick };
85061da546Spatrick
86061da546Spatrick enum class PyObjectType {
87061da546Spatrick Unknown,
88061da546Spatrick None,
89061da546Spatrick Boolean,
90061da546Spatrick Integer,
91061da546Spatrick Dictionary,
92061da546Spatrick List,
93061da546Spatrick String,
94061da546Spatrick Bytes,
95061da546Spatrick ByteArray,
96061da546Spatrick Module,
97061da546Spatrick Callable,
98061da546Spatrick Tuple,
99061da546Spatrick File
100061da546Spatrick };
101061da546Spatrick
102061da546Spatrick enum class PyRefType {
103061da546Spatrick Borrowed, // We are not given ownership of the incoming PyObject.
104061da546Spatrick // We cannot safely hold it without calling Py_INCREF.
105061da546Spatrick Owned // We have ownership of the incoming PyObject. We should
106061da546Spatrick // not call Py_INCREF.
107061da546Spatrick };
108061da546Spatrick
109061da546Spatrick
110061da546Spatrick // Take a reference that you already own, and turn it into
111061da546Spatrick // a PythonObject.
112061da546Spatrick //
113061da546Spatrick // Most python API methods will return a +1 reference
114061da546Spatrick // if they succeed or NULL if and only if
115061da546Spatrick // they set an exception. Use this to collect such return
116061da546Spatrick // values, after checking for NULL.
117061da546Spatrick //
118061da546Spatrick // If T is not just PythonObject, then obj must be already be
119061da546Spatrick // checked to be of the correct type.
Take(PyObject * obj)120061da546Spatrick template <typename T> T Take(PyObject *obj) {
121061da546Spatrick assert(obj);
122061da546Spatrick assert(!PyErr_Occurred());
123061da546Spatrick T thing(PyRefType::Owned, obj);
124061da546Spatrick assert(thing.IsValid());
125061da546Spatrick return thing;
126061da546Spatrick }
127061da546Spatrick
128061da546Spatrick // Retain a reference you have borrowed, and turn it into
129061da546Spatrick // a PythonObject.
130061da546Spatrick //
131061da546Spatrick // A minority of python APIs return a borrowed reference
132061da546Spatrick // instead of a +1. They will also return NULL if and only
133061da546Spatrick // if they set an exception. Use this to collect such return
134061da546Spatrick // values, after checking for NULL.
135061da546Spatrick //
136061da546Spatrick // If T is not just PythonObject, then obj must be already be
137061da546Spatrick // checked to be of the correct type.
Retain(PyObject * obj)138061da546Spatrick template <typename T> T Retain(PyObject *obj) {
139061da546Spatrick assert(obj);
140061da546Spatrick assert(!PyErr_Occurred());
141061da546Spatrick T thing(PyRefType::Borrowed, obj);
142061da546Spatrick assert(thing.IsValid());
143061da546Spatrick return thing;
144061da546Spatrick }
145061da546Spatrick
146061da546Spatrick // This class can be used like a utility function to convert from
147061da546Spatrick // a llvm-friendly Twine into a null-terminated const char *,
148061da546Spatrick // which is the form python C APIs want their strings in.
149061da546Spatrick //
150061da546Spatrick // Example:
151061da546Spatrick // const llvm::Twine &some_twine;
152061da546Spatrick // PyFoo_Bar(x, y, z, NullTerminated(some_twine));
153061da546Spatrick //
154061da546Spatrick // Why a class instead of a function? If the twine isn't already null
155061da546Spatrick // terminated, it will need a temporary buffer to copy the string
156061da546Spatrick // into. We need that buffer to stick around for the lifetime of the
157061da546Spatrick // statement.
158061da546Spatrick class NullTerminated {
159061da546Spatrick const char *str;
160061da546Spatrick llvm::SmallString<32> storage;
161061da546Spatrick
162061da546Spatrick public:
NullTerminated(const llvm::Twine & twine)163061da546Spatrick NullTerminated(const llvm::Twine &twine) {
164061da546Spatrick llvm::StringRef ref = twine.toNullTerminatedStringRef(storage);
165061da546Spatrick str = ref.begin();
166061da546Spatrick }
167061da546Spatrick operator const char *() { return str; }
168061da546Spatrick };
169061da546Spatrick
nullDeref()170061da546Spatrick inline llvm::Error nullDeref() {
171061da546Spatrick return llvm::createStringError(llvm::inconvertibleErrorCode(),
172061da546Spatrick "A NULL PyObject* was dereferenced");
173061da546Spatrick }
174061da546Spatrick
175061da546Spatrick inline llvm::Error exception(const char *s = nullptr) {
176061da546Spatrick return llvm::make_error<PythonException>(s);
177061da546Spatrick }
178061da546Spatrick
keyError()179061da546Spatrick inline llvm::Error keyError() {
180061da546Spatrick return llvm::createStringError(llvm::inconvertibleErrorCode(),
181061da546Spatrick "key not in dict");
182061da546Spatrick }
183061da546Spatrick
py2_const_cast(const char * s)184061da546Spatrick inline const char *py2_const_cast(const char *s) { return s; }
185061da546Spatrick
186061da546Spatrick enum class PyInitialValue { Invalid, Empty };
187061da546Spatrick
188*f6aab3d8Srobert // DOC: https://docs.python.org/3/c-api/arg.html#building-values
189061da546Spatrick template <typename T, typename Enable = void> struct PythonFormat;
190061da546Spatrick
191*f6aab3d8Srobert template <typename T, char F> struct PassthroughFormat {
192*f6aab3d8Srobert static constexpr char format = F;
getPassthroughFormat193*f6aab3d8Srobert static constexpr T get(T t) { return t; }
194061da546Spatrick };
195061da546Spatrick
196*f6aab3d8Srobert template <> struct PythonFormat<char *> : PassthroughFormat<char *, 's'> {};
197*f6aab3d8Srobert template <> struct PythonFormat<char> : PassthroughFormat<char, 'b'> {};
198*f6aab3d8Srobert template <>
199*f6aab3d8Srobert struct PythonFormat<unsigned char> : PassthroughFormat<unsigned char, 'B'> {};
200*f6aab3d8Srobert template <> struct PythonFormat<short> : PassthroughFormat<short, 'h'> {};
201*f6aab3d8Srobert template <>
202*f6aab3d8Srobert struct PythonFormat<unsigned short> : PassthroughFormat<unsigned short, 'H'> {};
203*f6aab3d8Srobert template <> struct PythonFormat<int> : PassthroughFormat<int, 'i'> {};
204*f6aab3d8Srobert template <>
205*f6aab3d8Srobert struct PythonFormat<unsigned int> : PassthroughFormat<unsigned int, 'I'> {};
206*f6aab3d8Srobert template <> struct PythonFormat<long> : PassthroughFormat<long, 'l'> {};
207*f6aab3d8Srobert template <>
208*f6aab3d8Srobert struct PythonFormat<unsigned long> : PassthroughFormat<unsigned long, 'k'> {};
209*f6aab3d8Srobert template <>
210*f6aab3d8Srobert struct PythonFormat<long long> : PassthroughFormat<long long, 'L'> {};
211*f6aab3d8Srobert template <>
212*f6aab3d8Srobert struct PythonFormat<unsigned long long>
213*f6aab3d8Srobert : PassthroughFormat<unsigned long long, 'K'> {};
214*f6aab3d8Srobert template <>
215*f6aab3d8Srobert struct PythonFormat<PyObject *> : PassthroughFormat<PyObject *, 'O'> {};
216061da546Spatrick
217061da546Spatrick template <typename T>
218061da546Spatrick struct PythonFormat<
219061da546Spatrick T, typename std::enable_if<std::is_base_of<PythonObject, T>::value>::type> {
220061da546Spatrick static constexpr char format = 'O';
221061da546Spatrick static auto get(const T &value) { return value.get(); }
222061da546Spatrick };
223061da546Spatrick
224061da546Spatrick class PythonObject {
225061da546Spatrick public:
226be691f3bSpatrick PythonObject() = default;
227061da546Spatrick
228061da546Spatrick PythonObject(PyRefType type, PyObject *py_obj) {
229061da546Spatrick m_py_obj = py_obj;
230061da546Spatrick // If this is a borrowed reference, we need to convert it to
231061da546Spatrick // an owned reference by incrementing it. If it is an owned
232061da546Spatrick // reference (for example the caller allocated it with PyDict_New()
233061da546Spatrick // then we must *not* increment it.
234061da546Spatrick if (m_py_obj && Py_IsInitialized() && type == PyRefType::Borrowed)
235061da546Spatrick Py_XINCREF(m_py_obj);
236061da546Spatrick }
237061da546Spatrick
238061da546Spatrick PythonObject(const PythonObject &rhs)
239061da546Spatrick : PythonObject(PyRefType::Borrowed, rhs.m_py_obj) {}
240061da546Spatrick
241061da546Spatrick PythonObject(PythonObject &&rhs) {
242061da546Spatrick m_py_obj = rhs.m_py_obj;
243061da546Spatrick rhs.m_py_obj = nullptr;
244061da546Spatrick }
245061da546Spatrick
246061da546Spatrick ~PythonObject() { Reset(); }
247061da546Spatrick
248*f6aab3d8Srobert void Reset();
249061da546Spatrick
250061da546Spatrick void Dump() const {
251061da546Spatrick if (m_py_obj)
252061da546Spatrick _PyObject_Dump(m_py_obj);
253061da546Spatrick else
254061da546Spatrick puts("NULL");
255061da546Spatrick }
256061da546Spatrick
257061da546Spatrick void Dump(Stream &strm) const;
258061da546Spatrick
259061da546Spatrick PyObject *get() const { return m_py_obj; }
260061da546Spatrick
261061da546Spatrick PyObject *release() {
262061da546Spatrick PyObject *result = m_py_obj;
263061da546Spatrick m_py_obj = nullptr;
264061da546Spatrick return result;
265061da546Spatrick }
266061da546Spatrick
267061da546Spatrick PythonObject &operator=(PythonObject other) {
268061da546Spatrick Reset();
269061da546Spatrick m_py_obj = std::exchange(other.m_py_obj, nullptr);
270061da546Spatrick return *this;
271061da546Spatrick }
272061da546Spatrick
273061da546Spatrick PyObjectType GetObjectType() const;
274061da546Spatrick
275061da546Spatrick PythonString Repr() const;
276061da546Spatrick
277061da546Spatrick PythonString Str() const;
278061da546Spatrick
279061da546Spatrick static PythonObject ResolveNameWithDictionary(llvm::StringRef name,
280061da546Spatrick const PythonDictionary &dict);
281061da546Spatrick
282061da546Spatrick template <typename T>
283061da546Spatrick static T ResolveNameWithDictionary(llvm::StringRef name,
284061da546Spatrick const PythonDictionary &dict) {
285061da546Spatrick return ResolveNameWithDictionary(name, dict).AsType<T>();
286061da546Spatrick }
287061da546Spatrick
288061da546Spatrick PythonObject ResolveName(llvm::StringRef name) const;
289061da546Spatrick
290061da546Spatrick template <typename T> T ResolveName(llvm::StringRef name) const {
291061da546Spatrick return ResolveName(name).AsType<T>();
292061da546Spatrick }
293061da546Spatrick
294061da546Spatrick bool HasAttribute(llvm::StringRef attribute) const;
295061da546Spatrick
296061da546Spatrick PythonObject GetAttributeValue(llvm::StringRef attribute) const;
297061da546Spatrick
298061da546Spatrick bool IsNone() const { return m_py_obj == Py_None; }
299061da546Spatrick
300061da546Spatrick bool IsValid() const { return m_py_obj != nullptr; }
301061da546Spatrick
302061da546Spatrick bool IsAllocated() const { return IsValid() && !IsNone(); }
303061da546Spatrick
304061da546Spatrick explicit operator bool() const { return IsValid() && !IsNone(); }
305061da546Spatrick
306061da546Spatrick template <typename T> T AsType() const {
307061da546Spatrick if (!T::Check(m_py_obj))
308061da546Spatrick return T();
309061da546Spatrick return T(PyRefType::Borrowed, m_py_obj);
310061da546Spatrick }
311061da546Spatrick
312061da546Spatrick StructuredData::ObjectSP CreateStructuredObject() const;
313061da546Spatrick
314061da546Spatrick template <typename... T>
315061da546Spatrick llvm::Expected<PythonObject> CallMethod(const char *name,
316061da546Spatrick const T &... t) const {
317061da546Spatrick const char format[] = {'(', PythonFormat<T>::format..., ')', 0};
318061da546Spatrick PyObject *obj =
319061da546Spatrick PyObject_CallMethod(m_py_obj, py2_const_cast(name),
320061da546Spatrick py2_const_cast(format), PythonFormat<T>::get(t)...);
321061da546Spatrick if (!obj)
322061da546Spatrick return exception();
323061da546Spatrick return python::Take<PythonObject>(obj);
324061da546Spatrick }
325061da546Spatrick
326061da546Spatrick template <typename... T>
327061da546Spatrick llvm::Expected<PythonObject> Call(const T &... t) const {
328061da546Spatrick const char format[] = {'(', PythonFormat<T>::format..., ')', 0};
329061da546Spatrick PyObject *obj = PyObject_CallFunction(m_py_obj, py2_const_cast(format),
330061da546Spatrick PythonFormat<T>::get(t)...);
331061da546Spatrick if (!obj)
332061da546Spatrick return exception();
333061da546Spatrick return python::Take<PythonObject>(obj);
334061da546Spatrick }
335061da546Spatrick
336061da546Spatrick llvm::Expected<PythonObject> GetAttribute(const llvm::Twine &name) const {
337061da546Spatrick if (!m_py_obj)
338061da546Spatrick return nullDeref();
339061da546Spatrick PyObject *obj = PyObject_GetAttrString(m_py_obj, NullTerminated(name));
340061da546Spatrick if (!obj)
341061da546Spatrick return exception();
342061da546Spatrick return python::Take<PythonObject>(obj);
343061da546Spatrick }
344061da546Spatrick
345061da546Spatrick llvm::Expected<bool> IsTrue() {
346061da546Spatrick if (!m_py_obj)
347061da546Spatrick return nullDeref();
348061da546Spatrick int r = PyObject_IsTrue(m_py_obj);
349061da546Spatrick if (r < 0)
350061da546Spatrick return exception();
351061da546Spatrick return !!r;
352061da546Spatrick }
353061da546Spatrick
354dda28197Spatrick llvm::Expected<long long> AsLongLong() const;
355dda28197Spatrick
356dda28197Spatrick llvm::Expected<long long> AsUnsignedLongLong() const;
357dda28197Spatrick
358dda28197Spatrick // wraps on overflow, instead of raising an error.
359dda28197Spatrick llvm::Expected<unsigned long long> AsModuloUnsignedLongLong() const;
360061da546Spatrick
361061da546Spatrick llvm::Expected<bool> IsInstance(const PythonObject &cls) {
362061da546Spatrick if (!m_py_obj || !cls.IsValid())
363061da546Spatrick return nullDeref();
364061da546Spatrick int r = PyObject_IsInstance(m_py_obj, cls.get());
365061da546Spatrick if (r < 0)
366061da546Spatrick return exception();
367061da546Spatrick return !!r;
368061da546Spatrick }
369061da546Spatrick
370061da546Spatrick protected:
371be691f3bSpatrick PyObject *m_py_obj = nullptr;
372061da546Spatrick };
373061da546Spatrick
374061da546Spatrick
375061da546Spatrick // This is why C++ needs monads.
376061da546Spatrick template <typename T> llvm::Expected<T> As(llvm::Expected<PythonObject> &&obj) {
377061da546Spatrick if (!obj)
378061da546Spatrick return obj.takeError();
379061da546Spatrick if (!T::Check(obj.get().get()))
380061da546Spatrick return llvm::createStringError(llvm::inconvertibleErrorCode(),
381061da546Spatrick "type error");
382061da546Spatrick return T(PyRefType::Borrowed, std::move(obj.get().get()));
383061da546Spatrick }
384061da546Spatrick
385061da546Spatrick template <> llvm::Expected<bool> As<bool>(llvm::Expected<PythonObject> &&obj);
386061da546Spatrick
387061da546Spatrick template <>
388061da546Spatrick llvm::Expected<long long> As<long long>(llvm::Expected<PythonObject> &&obj);
389061da546Spatrick
390061da546Spatrick template <>
391dda28197Spatrick llvm::Expected<unsigned long long>
392dda28197Spatrick As<unsigned long long>(llvm::Expected<PythonObject> &&obj);
393dda28197Spatrick
394dda28197Spatrick template <>
395061da546Spatrick llvm::Expected<std::string> As<std::string>(llvm::Expected<PythonObject> &&obj);
396061da546Spatrick
397061da546Spatrick
398061da546Spatrick template <class T> class TypedPythonObject : public PythonObject {
399061da546Spatrick public:
400061da546Spatrick TypedPythonObject(PyRefType type, PyObject *py_obj) {
401061da546Spatrick if (!py_obj)
402061da546Spatrick return;
403061da546Spatrick if (T::Check(py_obj))
404061da546Spatrick PythonObject::operator=(PythonObject(type, py_obj));
405061da546Spatrick else if (type == PyRefType::Owned)
406061da546Spatrick Py_DECREF(py_obj);
407061da546Spatrick }
408061da546Spatrick
409be691f3bSpatrick TypedPythonObject() = default;
410061da546Spatrick };
411061da546Spatrick
412061da546Spatrick class PythonBytes : public TypedPythonObject<PythonBytes> {
413061da546Spatrick public:
414061da546Spatrick using TypedPythonObject::TypedPythonObject;
415061da546Spatrick explicit PythonBytes(llvm::ArrayRef<uint8_t> bytes);
416061da546Spatrick PythonBytes(const uint8_t *bytes, size_t length);
417061da546Spatrick
418061da546Spatrick static bool Check(PyObject *py_obj);
419061da546Spatrick
420061da546Spatrick llvm::ArrayRef<uint8_t> GetBytes() const;
421061da546Spatrick
422061da546Spatrick size_t GetSize() const;
423061da546Spatrick
424061da546Spatrick void SetBytes(llvm::ArrayRef<uint8_t> stringbytes);
425061da546Spatrick
426061da546Spatrick StructuredData::StringSP CreateStructuredString() const;
427061da546Spatrick };
428061da546Spatrick
429061da546Spatrick class PythonByteArray : public TypedPythonObject<PythonByteArray> {
430061da546Spatrick public:
431061da546Spatrick using TypedPythonObject::TypedPythonObject;
432061da546Spatrick explicit PythonByteArray(llvm::ArrayRef<uint8_t> bytes);
433061da546Spatrick PythonByteArray(const uint8_t *bytes, size_t length);
434061da546Spatrick PythonByteArray(const PythonBytes &object);
435061da546Spatrick
436061da546Spatrick static bool Check(PyObject *py_obj);
437061da546Spatrick
438061da546Spatrick llvm::ArrayRef<uint8_t> GetBytes() const;
439061da546Spatrick
440061da546Spatrick size_t GetSize() const;
441061da546Spatrick
442061da546Spatrick void SetBytes(llvm::ArrayRef<uint8_t> stringbytes);
443061da546Spatrick
444061da546Spatrick StructuredData::StringSP CreateStructuredString() const;
445061da546Spatrick };
446061da546Spatrick
447061da546Spatrick class PythonString : public TypedPythonObject<PythonString> {
448061da546Spatrick public:
449061da546Spatrick using TypedPythonObject::TypedPythonObject;
450061da546Spatrick static llvm::Expected<PythonString> FromUTF8(llvm::StringRef string);
451061da546Spatrick
452061da546Spatrick PythonString() : TypedPythonObject() {} // MSVC requires this for some reason
453061da546Spatrick
454061da546Spatrick explicit PythonString(llvm::StringRef string); // safe, null on error
455061da546Spatrick
456061da546Spatrick static bool Check(PyObject *py_obj);
457061da546Spatrick
458061da546Spatrick llvm::StringRef GetString() const; // safe, empty string on error
459061da546Spatrick
460061da546Spatrick llvm::Expected<llvm::StringRef> AsUTF8() const;
461061da546Spatrick
462061da546Spatrick size_t GetSize() const;
463061da546Spatrick
464061da546Spatrick void SetString(llvm::StringRef string); // safe, null on error
465061da546Spatrick
466061da546Spatrick StructuredData::StringSP CreateStructuredString() const;
467061da546Spatrick };
468061da546Spatrick
469061da546Spatrick class PythonInteger : public TypedPythonObject<PythonInteger> {
470061da546Spatrick public:
471061da546Spatrick using TypedPythonObject::TypedPythonObject;
472061da546Spatrick
473061da546Spatrick PythonInteger() : TypedPythonObject() {} // MSVC requires this for some reason
474061da546Spatrick
475061da546Spatrick explicit PythonInteger(int64_t value);
476061da546Spatrick
477061da546Spatrick static bool Check(PyObject *py_obj);
478061da546Spatrick
479061da546Spatrick void SetInteger(int64_t value);
480061da546Spatrick
481061da546Spatrick StructuredData::IntegerSP CreateStructuredInteger() const;
482061da546Spatrick };
483061da546Spatrick
484061da546Spatrick class PythonBoolean : public TypedPythonObject<PythonBoolean> {
485061da546Spatrick public:
486061da546Spatrick using TypedPythonObject::TypedPythonObject;
487061da546Spatrick
488061da546Spatrick explicit PythonBoolean(bool value);
489061da546Spatrick
490061da546Spatrick static bool Check(PyObject *py_obj);
491061da546Spatrick
492061da546Spatrick bool GetValue() const;
493061da546Spatrick
494061da546Spatrick void SetValue(bool value);
495061da546Spatrick
496061da546Spatrick StructuredData::BooleanSP CreateStructuredBoolean() const;
497061da546Spatrick };
498061da546Spatrick
499061da546Spatrick class PythonList : public TypedPythonObject<PythonList> {
500061da546Spatrick public:
501061da546Spatrick using TypedPythonObject::TypedPythonObject;
502061da546Spatrick
503061da546Spatrick PythonList() : TypedPythonObject() {} // MSVC requires this for some reason
504061da546Spatrick
505061da546Spatrick explicit PythonList(PyInitialValue value);
506061da546Spatrick explicit PythonList(int list_size);
507061da546Spatrick
508061da546Spatrick static bool Check(PyObject *py_obj);
509061da546Spatrick
510061da546Spatrick uint32_t GetSize() const;
511061da546Spatrick
512061da546Spatrick PythonObject GetItemAtIndex(uint32_t index) const;
513061da546Spatrick
514061da546Spatrick void SetItemAtIndex(uint32_t index, const PythonObject &object);
515061da546Spatrick
516061da546Spatrick void AppendItem(const PythonObject &object);
517061da546Spatrick
518061da546Spatrick StructuredData::ArraySP CreateStructuredArray() const;
519061da546Spatrick };
520061da546Spatrick
521061da546Spatrick class PythonTuple : public TypedPythonObject<PythonTuple> {
522061da546Spatrick public:
523061da546Spatrick using TypedPythonObject::TypedPythonObject;
524061da546Spatrick
525061da546Spatrick explicit PythonTuple(PyInitialValue value);
526061da546Spatrick explicit PythonTuple(int tuple_size);
527061da546Spatrick PythonTuple(std::initializer_list<PythonObject> objects);
528061da546Spatrick PythonTuple(std::initializer_list<PyObject *> objects);
529061da546Spatrick
530061da546Spatrick static bool Check(PyObject *py_obj);
531061da546Spatrick
532061da546Spatrick uint32_t GetSize() const;
533061da546Spatrick
534061da546Spatrick PythonObject GetItemAtIndex(uint32_t index) const;
535061da546Spatrick
536061da546Spatrick void SetItemAtIndex(uint32_t index, const PythonObject &object);
537061da546Spatrick
538061da546Spatrick StructuredData::ArraySP CreateStructuredArray() const;
539061da546Spatrick };
540061da546Spatrick
541061da546Spatrick class PythonDictionary : public TypedPythonObject<PythonDictionary> {
542061da546Spatrick public:
543061da546Spatrick using TypedPythonObject::TypedPythonObject;
544061da546Spatrick
545061da546Spatrick PythonDictionary() : TypedPythonObject() {} // MSVC requires this for some reason
546061da546Spatrick
547061da546Spatrick explicit PythonDictionary(PyInitialValue value);
548061da546Spatrick
549061da546Spatrick static bool Check(PyObject *py_obj);
550061da546Spatrick
551061da546Spatrick uint32_t GetSize() const;
552061da546Spatrick
553061da546Spatrick PythonList GetKeys() const;
554061da546Spatrick
555061da546Spatrick PythonObject GetItemForKey(const PythonObject &key) const; // DEPRECATED
556061da546Spatrick void SetItemForKey(const PythonObject &key,
557061da546Spatrick const PythonObject &value); // DEPRECATED
558061da546Spatrick
559061da546Spatrick llvm::Expected<PythonObject> GetItem(const PythonObject &key) const;
560061da546Spatrick llvm::Expected<PythonObject> GetItem(const llvm::Twine &key) const;
561061da546Spatrick llvm::Error SetItem(const PythonObject &key, const PythonObject &value) const;
562061da546Spatrick llvm::Error SetItem(const llvm::Twine &key, const PythonObject &value) const;
563061da546Spatrick
564061da546Spatrick StructuredData::DictionarySP CreateStructuredDictionary() const;
565061da546Spatrick };
566061da546Spatrick
567061da546Spatrick class PythonModule : public TypedPythonObject<PythonModule> {
568061da546Spatrick public:
569061da546Spatrick using TypedPythonObject::TypedPythonObject;
570061da546Spatrick
571061da546Spatrick static bool Check(PyObject *py_obj);
572061da546Spatrick
573061da546Spatrick static PythonModule BuiltinsModule();
574061da546Spatrick
575061da546Spatrick static PythonModule MainModule();
576061da546Spatrick
577061da546Spatrick static PythonModule AddModule(llvm::StringRef module);
578061da546Spatrick
579061da546Spatrick // safe, returns invalid on error;
580061da546Spatrick static PythonModule ImportModule(llvm::StringRef name) {
581dda28197Spatrick std::string s = std::string(name);
582061da546Spatrick auto mod = Import(s.c_str());
583061da546Spatrick if (!mod) {
584061da546Spatrick llvm::consumeError(mod.takeError());
585061da546Spatrick return PythonModule();
586061da546Spatrick }
587061da546Spatrick return std::move(mod.get());
588061da546Spatrick }
589061da546Spatrick
590061da546Spatrick static llvm::Expected<PythonModule> Import(const llvm::Twine &name);
591061da546Spatrick
592061da546Spatrick llvm::Expected<PythonObject> Get(const llvm::Twine &name);
593061da546Spatrick
594061da546Spatrick PythonDictionary GetDictionary() const;
595061da546Spatrick };
596061da546Spatrick
597061da546Spatrick class PythonCallable : public TypedPythonObject<PythonCallable> {
598061da546Spatrick public:
599061da546Spatrick using TypedPythonObject::TypedPythonObject;
600061da546Spatrick
601061da546Spatrick struct ArgInfo {
602061da546Spatrick /* the largest number of positional arguments this callable
603061da546Spatrick * can accept, or UNBOUNDED, ie UINT_MAX if it's a varargs
604061da546Spatrick * function and can accept an arbitrary number */
605061da546Spatrick unsigned max_positional_args;
606061da546Spatrick static constexpr unsigned UNBOUNDED = UINT_MAX; // FIXME c++17 inline
607061da546Spatrick };
608061da546Spatrick
609061da546Spatrick static bool Check(PyObject *py_obj);
610061da546Spatrick
611061da546Spatrick llvm::Expected<ArgInfo> GetArgInfo() const;
612061da546Spatrick
613061da546Spatrick PythonObject operator()();
614061da546Spatrick
615061da546Spatrick PythonObject operator()(std::initializer_list<PyObject *> args);
616061da546Spatrick
617061da546Spatrick PythonObject operator()(std::initializer_list<PythonObject> args);
618061da546Spatrick
619061da546Spatrick template <typename Arg, typename... Args>
620061da546Spatrick PythonObject operator()(const Arg &arg, Args... args) {
621061da546Spatrick return operator()({arg, args...});
622061da546Spatrick }
623061da546Spatrick };
624061da546Spatrick
625061da546Spatrick class PythonFile : public TypedPythonObject<PythonFile> {
626061da546Spatrick public:
627061da546Spatrick using TypedPythonObject::TypedPythonObject;
628061da546Spatrick
629061da546Spatrick PythonFile() : TypedPythonObject() {} // MSVC requires this for some reason
630061da546Spatrick
631061da546Spatrick static bool Check(PyObject *py_obj);
632061da546Spatrick
633061da546Spatrick static llvm::Expected<PythonFile> FromFile(File &file,
634061da546Spatrick const char *mode = nullptr);
635061da546Spatrick
636061da546Spatrick llvm::Expected<lldb::FileSP> ConvertToFile(bool borrowed = false);
637061da546Spatrick llvm::Expected<lldb::FileSP>
638061da546Spatrick ConvertToFileForcingUseOfScriptingIOMethods(bool borrowed = false);
639061da546Spatrick };
640061da546Spatrick
641061da546Spatrick class PythonException : public llvm::ErrorInfo<PythonException> {
642061da546Spatrick private:
643061da546Spatrick PyObject *m_exception_type, *m_exception, *m_traceback;
644061da546Spatrick PyObject *m_repr_bytes;
645061da546Spatrick
646061da546Spatrick public:
647061da546Spatrick static char ID;
648061da546Spatrick const char *toCString() const;
649061da546Spatrick PythonException(const char *caller = nullptr);
650061da546Spatrick void Restore();
651*f6aab3d8Srobert ~PythonException() override;
652061da546Spatrick void log(llvm::raw_ostream &OS) const override;
653061da546Spatrick std::error_code convertToErrorCode() const override;
654061da546Spatrick bool Matches(PyObject *exc) const;
655061da546Spatrick std::string ReadBacktrace() const;
656061da546Spatrick };
657061da546Spatrick
658061da546Spatrick // This extracts the underlying T out of an Expected<T> and returns it.
659061da546Spatrick // If the Expected is an Error instead of a T, that error will be converted
660061da546Spatrick // into a python exception, and this will return a default-constructed T.
661061da546Spatrick //
662061da546Spatrick // This is appropriate for use right at the boundary of python calling into
663061da546Spatrick // C++, such as in a SWIG typemap. In such a context you should simply
664061da546Spatrick // check if the returned T is valid, and if it is, return a NULL back
665061da546Spatrick // to python. This will result in the Error being raised as an exception
666061da546Spatrick // from python code's point of view.
667061da546Spatrick //
668061da546Spatrick // For example:
669061da546Spatrick // ```
670061da546Spatrick // Expected<Foo *> efoop = some_cpp_function();
671061da546Spatrick // Foo *foop = unwrapOrSetPythonException(efoop);
672061da546Spatrick // if (!foop)
673061da546Spatrick // return NULL;
674061da546Spatrick // do_something(*foop);
675061da546Spatrick //
676061da546Spatrick // If the Error returned was itself created because a python exception was
677061da546Spatrick // raised when C++ code called into python, then the original exception
678061da546Spatrick // will be restored. Otherwise a simple string exception will be raised.
679061da546Spatrick template <typename T> T unwrapOrSetPythonException(llvm::Expected<T> expected) {
680061da546Spatrick if (expected)
681061da546Spatrick return expected.get();
682061da546Spatrick llvm::handleAllErrors(
683061da546Spatrick expected.takeError(), [](PythonException &E) { E.Restore(); },
684061da546Spatrick [](const llvm::ErrorInfoBase &E) {
685061da546Spatrick PyErr_SetString(PyExc_Exception, E.message().c_str());
686061da546Spatrick });
687061da546Spatrick return T();
688061da546Spatrick }
689061da546Spatrick
690061da546Spatrick // This is only here to help incrementally migrate old, exception-unsafe
691061da546Spatrick // code.
692061da546Spatrick template <typename T> T unwrapIgnoringErrors(llvm::Expected<T> expected) {
693061da546Spatrick if (expected)
694061da546Spatrick return std::move(expected.get());
695061da546Spatrick llvm::consumeError(expected.takeError());
696061da546Spatrick return T();
697061da546Spatrick }
698061da546Spatrick
699061da546Spatrick llvm::Expected<PythonObject> runStringOneLine(const llvm::Twine &string,
700061da546Spatrick const PythonDictionary &globals,
701061da546Spatrick const PythonDictionary &locals);
702061da546Spatrick
703061da546Spatrick llvm::Expected<PythonObject> runStringMultiLine(const llvm::Twine &string,
704061da546Spatrick const PythonDictionary &globals,
705061da546Spatrick const PythonDictionary &locals);
706061da546Spatrick
707061da546Spatrick // Sometimes the best way to interact with a python interpreter is
708061da546Spatrick // to run some python code. You construct a PythonScript with
709061da546Spatrick // script string. The script assigns some function to `_function_`
710061da546Spatrick // and you get a C++ callable object that calls the python function.
711061da546Spatrick //
712061da546Spatrick // Example:
713061da546Spatrick //
714061da546Spatrick // const char script[] = R"(
715061da546Spatrick // def main(x, y):
716061da546Spatrick // ....
717061da546Spatrick // )";
718061da546Spatrick //
719061da546Spatrick // Expected<PythonObject> cpp_foo_wrapper(PythonObject x, PythonObject y) {
720061da546Spatrick // // no need to synchronize access to this global, we already have the GIL
721061da546Spatrick // static PythonScript foo(script)
722061da546Spatrick // return foo(x, y);
723061da546Spatrick // }
724061da546Spatrick class PythonScript {
725061da546Spatrick const char *script;
726061da546Spatrick PythonCallable function;
727061da546Spatrick
728061da546Spatrick llvm::Error Init();
729061da546Spatrick
730061da546Spatrick public:
731061da546Spatrick PythonScript(const char *script) : script(script), function() {}
732061da546Spatrick
733061da546Spatrick template <typename... Args>
734061da546Spatrick llvm::Expected<PythonObject> operator()(Args &&... args) {
735061da546Spatrick if (llvm::Error error = Init())
736061da546Spatrick return std::move(error);
737061da546Spatrick return function.Call(std::forward<Args>(args)...);
738061da546Spatrick }
739061da546Spatrick };
740061da546Spatrick
741*f6aab3d8Srobert class StructuredPythonObject : public StructuredData::Generic {
742*f6aab3d8Srobert public:
743*f6aab3d8Srobert StructuredPythonObject() : StructuredData::Generic() {}
744*f6aab3d8Srobert
745*f6aab3d8Srobert // Take ownership of the object we received.
746*f6aab3d8Srobert StructuredPythonObject(PythonObject obj)
747*f6aab3d8Srobert : StructuredData::Generic(obj.release()) {}
748*f6aab3d8Srobert
749*f6aab3d8Srobert ~StructuredPythonObject() override {
750*f6aab3d8Srobert // Hand ownership back to a (temporary) PythonObject instance and let it
751*f6aab3d8Srobert // take care of releasing it.
752*f6aab3d8Srobert PythonObject(PyRefType::Owned, static_cast<PyObject *>(GetValue()));
753*f6aab3d8Srobert }
754*f6aab3d8Srobert
755*f6aab3d8Srobert bool IsValid() const override { return GetValue() && GetValue() != Py_None; }
756*f6aab3d8Srobert
757*f6aab3d8Srobert void Serialize(llvm::json::OStream &s) const override;
758*f6aab3d8Srobert
759*f6aab3d8Srobert private:
760*f6aab3d8Srobert StructuredPythonObject(const StructuredPythonObject &) = delete;
761*f6aab3d8Srobert const StructuredPythonObject &
762*f6aab3d8Srobert operator=(const StructuredPythonObject &) = delete;
763*f6aab3d8Srobert };
764*f6aab3d8Srobert
765061da546Spatrick } // namespace python
766061da546Spatrick } // namespace lldb_private
767061da546Spatrick
768061da546Spatrick #endif
769061da546Spatrick
770061da546Spatrick #endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H
771