Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
39638 views
1
//===-- PythonDataObjects.h--------------------------------------*- C++ -*-===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
//
10
// !! FIXME FIXME FIXME !!
11
//
12
// Python APIs nearly all can return an exception. They do this
13
// by returning NULL, or -1, or some such value and setting
14
// the exception state with PyErr_Set*(). Exceptions must be
15
// handled before further python API functions are called. Failure
16
// to do so will result in asserts on debug builds of python.
17
// It will also sometimes, but not usually result in crashes of
18
// release builds.
19
//
20
// Nearly all the code in this header does not handle python exceptions
21
// correctly. It should all be converted to return Expected<> or
22
// Error types to capture the exception.
23
//
24
// Everything in this file except functions that return Error or
25
// Expected<> is considered deprecated and should not be
26
// used in new code. If you need to use it, fix it first.
27
//
28
//
29
// TODOs for this file
30
//
31
// * Make all methods safe for exceptions.
32
//
33
// * Eliminate method signatures that must translate exceptions into
34
// empty objects or NULLs. Almost everything here should return
35
// Expected<>. It should be acceptable for certain operations that
36
// can never fail to assert instead, such as the creation of
37
// PythonString from a string literal.
38
//
39
// * Eliminate Reset(), and make all non-default constructors private.
40
// Python objects should be created with Retain<> or Take<>, and they
41
// should be assigned with operator=
42
//
43
// * Eliminate default constructors, make python objects always
44
// nonnull, and use optionals where necessary.
45
//
46
47
48
#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H
49
#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H
50
51
#include "lldb/Host/Config.h"
52
53
#if LLDB_ENABLE_PYTHON
54
55
// LLDB Python header must be included first
56
#include "lldb-python.h"
57
58
#include "lldb/Host/File.h"
59
#include "lldb/Utility/StructuredData.h"
60
61
#include "llvm/ADT/ArrayRef.h"
62
63
namespace lldb_private {
64
namespace python {
65
66
class PythonObject;
67
class PythonBytes;
68
class PythonString;
69
class PythonList;
70
class PythonDictionary;
71
class PythonInteger;
72
class PythonException;
73
74
class GIL {
75
public:
76
GIL() {
77
m_state = PyGILState_Ensure();
78
assert(!PyErr_Occurred());
79
}
80
~GIL() { PyGILState_Release(m_state); }
81
82
protected:
83
PyGILState_STATE m_state;
84
};
85
86
enum class PyObjectType {
87
Unknown,
88
None,
89
Boolean,
90
Integer,
91
Dictionary,
92
List,
93
String,
94
Bytes,
95
ByteArray,
96
Module,
97
Callable,
98
Tuple,
99
File
100
};
101
102
enum class PyRefType {
103
Borrowed, // We are not given ownership of the incoming PyObject.
104
// We cannot safely hold it without calling Py_INCREF.
105
Owned // We have ownership of the incoming PyObject. We should
106
// not call Py_INCREF.
107
};
108
109
110
// Take a reference that you already own, and turn it into
111
// a PythonObject.
112
//
113
// Most python API methods will return a +1 reference
114
// if they succeed or NULL if and only if
115
// they set an exception. Use this to collect such return
116
// values, after checking for NULL.
117
//
118
// If T is not just PythonObject, then obj must be already be
119
// checked to be of the correct type.
120
template <typename T> T Take(PyObject *obj) {
121
assert(obj);
122
assert(!PyErr_Occurred());
123
T thing(PyRefType::Owned, obj);
124
assert(thing.IsValid());
125
return thing;
126
}
127
128
// Retain a reference you have borrowed, and turn it into
129
// a PythonObject.
130
//
131
// A minority of python APIs return a borrowed reference
132
// instead of a +1. They will also return NULL if and only
133
// if they set an exception. Use this to collect such return
134
// values, after checking for NULL.
135
//
136
// If T is not just PythonObject, then obj must be already be
137
// checked to be of the correct type.
138
template <typename T> T Retain(PyObject *obj) {
139
assert(obj);
140
assert(!PyErr_Occurred());
141
T thing(PyRefType::Borrowed, obj);
142
assert(thing.IsValid());
143
return thing;
144
}
145
146
// This class can be used like a utility function to convert from
147
// a llvm-friendly Twine into a null-terminated const char *,
148
// which is the form python C APIs want their strings in.
149
//
150
// Example:
151
// const llvm::Twine &some_twine;
152
// PyFoo_Bar(x, y, z, NullTerminated(some_twine));
153
//
154
// Why a class instead of a function? If the twine isn't already null
155
// terminated, it will need a temporary buffer to copy the string
156
// into. We need that buffer to stick around for the lifetime of the
157
// statement.
158
class NullTerminated {
159
const char *str;
160
llvm::SmallString<32> storage;
161
162
public:
163
NullTerminated(const llvm::Twine &twine) {
164
llvm::StringRef ref = twine.toNullTerminatedStringRef(storage);
165
str = ref.begin();
166
}
167
operator const char *() { return str; }
168
};
169
170
inline llvm::Error nullDeref() {
171
return llvm::createStringError(llvm::inconvertibleErrorCode(),
172
"A NULL PyObject* was dereferenced");
173
}
174
175
inline llvm::Error exception(const char *s = nullptr) {
176
return llvm::make_error<PythonException>(s);
177
}
178
179
inline llvm::Error keyError() {
180
return llvm::createStringError(llvm::inconvertibleErrorCode(),
181
"key not in dict");
182
}
183
184
inline const char *py2_const_cast(const char *s) { return s; }
185
186
enum class PyInitialValue { Invalid, Empty };
187
188
// DOC: https://docs.python.org/3/c-api/arg.html#building-values
189
template <typename T, typename Enable = void> struct PythonFormat;
190
191
template <typename T, char F> struct PassthroughFormat {
192
static constexpr char format = F;
193
static constexpr T get(T t) { return t; }
194
};
195
196
template <> struct PythonFormat<char *> : PassthroughFormat<char *, 's'> {};
197
template <> struct PythonFormat<const char *> :
198
PassthroughFormat<const char *, 's'> {};
199
template <> struct PythonFormat<char> : PassthroughFormat<char, 'b'> {};
200
template <>
201
struct PythonFormat<unsigned char> : PassthroughFormat<unsigned char, 'B'> {};
202
template <> struct PythonFormat<short> : PassthroughFormat<short, 'h'> {};
203
template <>
204
struct PythonFormat<unsigned short> : PassthroughFormat<unsigned short, 'H'> {};
205
template <> struct PythonFormat<int> : PassthroughFormat<int, 'i'> {};
206
template <> struct PythonFormat<bool> : PassthroughFormat<bool, 'p'> {};
207
template <>
208
struct PythonFormat<unsigned int> : PassthroughFormat<unsigned int, 'I'> {};
209
template <> struct PythonFormat<long> : PassthroughFormat<long, 'l'> {};
210
template <>
211
struct PythonFormat<unsigned long> : PassthroughFormat<unsigned long, 'k'> {};
212
template <>
213
struct PythonFormat<long long> : PassthroughFormat<long long, 'L'> {};
214
template <>
215
struct PythonFormat<unsigned long long>
216
: PassthroughFormat<unsigned long long, 'K'> {};
217
template <>
218
struct PythonFormat<PyObject *> : PassthroughFormat<PyObject *, 'O'> {};
219
220
template <typename T>
221
struct PythonFormat<
222
T, typename std::enable_if<std::is_base_of<PythonObject, T>::value>::type> {
223
static constexpr char format = 'O';
224
static auto get(const T &value) { return value.get(); }
225
};
226
227
class PythonObject {
228
public:
229
PythonObject() = default;
230
231
PythonObject(PyRefType type, PyObject *py_obj) {
232
m_py_obj = py_obj;
233
// If this is a borrowed reference, we need to convert it to
234
// an owned reference by incrementing it. If it is an owned
235
// reference (for example the caller allocated it with PyDict_New()
236
// then we must *not* increment it.
237
if (m_py_obj && Py_IsInitialized() && type == PyRefType::Borrowed)
238
Py_XINCREF(m_py_obj);
239
}
240
241
PythonObject(const PythonObject &rhs)
242
: PythonObject(PyRefType::Borrowed, rhs.m_py_obj) {}
243
244
PythonObject(PythonObject &&rhs) {
245
m_py_obj = rhs.m_py_obj;
246
rhs.m_py_obj = nullptr;
247
}
248
249
~PythonObject() { Reset(); }
250
251
void Reset();
252
253
void Dump() const {
254
if (m_py_obj)
255
_PyObject_Dump(m_py_obj);
256
else
257
puts("NULL");
258
}
259
260
void Dump(Stream &strm) const;
261
262
PyObject *get() const { return m_py_obj; }
263
264
PyObject *release() {
265
PyObject *result = m_py_obj;
266
m_py_obj = nullptr;
267
return result;
268
}
269
270
PythonObject &operator=(PythonObject other) {
271
Reset();
272
m_py_obj = std::exchange(other.m_py_obj, nullptr);
273
return *this;
274
}
275
276
PyObjectType GetObjectType() const;
277
278
PythonString Repr() const;
279
280
PythonString Str() const;
281
282
static PythonObject ResolveNameWithDictionary(llvm::StringRef name,
283
const PythonDictionary &dict);
284
285
template <typename T>
286
static T ResolveNameWithDictionary(llvm::StringRef name,
287
const PythonDictionary &dict) {
288
return ResolveNameWithDictionary(name, dict).AsType<T>();
289
}
290
291
PythonObject ResolveName(llvm::StringRef name) const;
292
293
template <typename T> T ResolveName(llvm::StringRef name) const {
294
return ResolveName(name).AsType<T>();
295
}
296
297
bool HasAttribute(llvm::StringRef attribute) const;
298
299
PythonObject GetAttributeValue(llvm::StringRef attribute) const;
300
301
bool IsNone() const { return m_py_obj == Py_None; }
302
303
bool IsValid() const { return m_py_obj != nullptr; }
304
305
bool IsAllocated() const { return IsValid() && !IsNone(); }
306
307
explicit operator bool() const { return IsValid() && !IsNone(); }
308
309
template <typename T> T AsType() const {
310
if (!T::Check(m_py_obj))
311
return T();
312
return T(PyRefType::Borrowed, m_py_obj);
313
}
314
315
StructuredData::ObjectSP CreateStructuredObject() const;
316
317
template <typename... T>
318
llvm::Expected<PythonObject> CallMethod(const char *name,
319
const T &... t) const {
320
const char format[] = {'(', PythonFormat<T>::format..., ')', 0};
321
PyObject *obj =
322
PyObject_CallMethod(m_py_obj, py2_const_cast(name),
323
py2_const_cast(format), PythonFormat<T>::get(t)...);
324
if (!obj)
325
return exception();
326
return python::Take<PythonObject>(obj);
327
}
328
329
template <typename... T>
330
llvm::Expected<PythonObject> Call(const T &... t) const {
331
const char format[] = {'(', PythonFormat<T>::format..., ')', 0};
332
PyObject *obj = PyObject_CallFunction(m_py_obj, py2_const_cast(format),
333
PythonFormat<T>::get(t)...);
334
if (!obj)
335
return exception();
336
return python::Take<PythonObject>(obj);
337
}
338
339
llvm::Expected<PythonObject> GetAttribute(const llvm::Twine &name) const {
340
if (!m_py_obj)
341
return nullDeref();
342
PyObject *obj = PyObject_GetAttrString(m_py_obj, NullTerminated(name));
343
if (!obj)
344
return exception();
345
return python::Take<PythonObject>(obj);
346
}
347
348
llvm::Expected<PythonObject> GetType() const {
349
if (!m_py_obj)
350
return nullDeref();
351
PyObject *obj = PyObject_Type(m_py_obj);
352
if (!obj)
353
return exception();
354
return python::Take<PythonObject>(obj);
355
}
356
357
llvm::Expected<bool> IsTrue() {
358
if (!m_py_obj)
359
return nullDeref();
360
int r = PyObject_IsTrue(m_py_obj);
361
if (r < 0)
362
return exception();
363
return !!r;
364
}
365
366
llvm::Expected<long long> AsLongLong() const;
367
368
llvm::Expected<unsigned long long> AsUnsignedLongLong() const;
369
370
// wraps on overflow, instead of raising an error.
371
llvm::Expected<unsigned long long> AsModuloUnsignedLongLong() const;
372
373
llvm::Expected<bool> IsInstance(const PythonObject &cls) {
374
if (!m_py_obj || !cls.IsValid())
375
return nullDeref();
376
int r = PyObject_IsInstance(m_py_obj, cls.get());
377
if (r < 0)
378
return exception();
379
return !!r;
380
}
381
382
protected:
383
PyObject *m_py_obj = nullptr;
384
};
385
386
387
// This is why C++ needs monads.
388
template <typename T> llvm::Expected<T> As(llvm::Expected<PythonObject> &&obj) {
389
if (!obj)
390
return obj.takeError();
391
if (!T::Check(obj.get().get()))
392
return llvm::createStringError(llvm::inconvertibleErrorCode(),
393
"type error");
394
return T(PyRefType::Borrowed, std::move(obj.get().get()));
395
}
396
397
template <> llvm::Expected<bool> As<bool>(llvm::Expected<PythonObject> &&obj);
398
399
template <>
400
llvm::Expected<long long> As<long long>(llvm::Expected<PythonObject> &&obj);
401
402
template <>
403
llvm::Expected<unsigned long long>
404
As<unsigned long long>(llvm::Expected<PythonObject> &&obj);
405
406
template <>
407
llvm::Expected<std::string> As<std::string>(llvm::Expected<PythonObject> &&obj);
408
409
410
template <class T> class TypedPythonObject : public PythonObject {
411
public:
412
TypedPythonObject(PyRefType type, PyObject *py_obj) {
413
if (!py_obj)
414
return;
415
if (T::Check(py_obj))
416
PythonObject::operator=(PythonObject(type, py_obj));
417
else if (type == PyRefType::Owned)
418
Py_DECREF(py_obj);
419
}
420
421
TypedPythonObject() = default;
422
};
423
424
class PythonBytes : public TypedPythonObject<PythonBytes> {
425
public:
426
using TypedPythonObject::TypedPythonObject;
427
explicit PythonBytes(llvm::ArrayRef<uint8_t> bytes);
428
PythonBytes(const uint8_t *bytes, size_t length);
429
430
static bool Check(PyObject *py_obj);
431
432
llvm::ArrayRef<uint8_t> GetBytes() const;
433
434
size_t GetSize() const;
435
436
void SetBytes(llvm::ArrayRef<uint8_t> stringbytes);
437
438
StructuredData::StringSP CreateStructuredString() const;
439
};
440
441
class PythonByteArray : public TypedPythonObject<PythonByteArray> {
442
public:
443
using TypedPythonObject::TypedPythonObject;
444
explicit PythonByteArray(llvm::ArrayRef<uint8_t> bytes);
445
PythonByteArray(const uint8_t *bytes, size_t length);
446
PythonByteArray(const PythonBytes &object);
447
448
static bool Check(PyObject *py_obj);
449
450
llvm::ArrayRef<uint8_t> GetBytes() const;
451
452
size_t GetSize() const;
453
454
void SetBytes(llvm::ArrayRef<uint8_t> stringbytes);
455
456
StructuredData::StringSP CreateStructuredString() const;
457
};
458
459
class PythonString : public TypedPythonObject<PythonString> {
460
public:
461
using TypedPythonObject::TypedPythonObject;
462
static llvm::Expected<PythonString> FromUTF8(llvm::StringRef string);
463
464
PythonString() : TypedPythonObject() {} // MSVC requires this for some reason
465
466
explicit PythonString(llvm::StringRef string); // safe, null on error
467
468
static bool Check(PyObject *py_obj);
469
470
llvm::StringRef GetString() const; // safe, empty string on error
471
472
llvm::Expected<llvm::StringRef> AsUTF8() const;
473
474
size_t GetSize() const;
475
476
void SetString(llvm::StringRef string); // safe, null on error
477
478
StructuredData::StringSP CreateStructuredString() const;
479
};
480
481
class PythonInteger : public TypedPythonObject<PythonInteger> {
482
public:
483
using TypedPythonObject::TypedPythonObject;
484
485
PythonInteger() : TypedPythonObject() {} // MSVC requires this for some reason
486
487
explicit PythonInteger(int64_t value);
488
489
static bool Check(PyObject *py_obj);
490
491
void SetInteger(int64_t value);
492
493
StructuredData::IntegerSP CreateStructuredInteger() const;
494
495
StructuredData::UnsignedIntegerSP CreateStructuredUnsignedInteger() const;
496
497
StructuredData::SignedIntegerSP CreateStructuredSignedInteger() const;
498
};
499
500
class PythonBoolean : public TypedPythonObject<PythonBoolean> {
501
public:
502
using TypedPythonObject::TypedPythonObject;
503
504
explicit PythonBoolean(bool value);
505
506
static bool Check(PyObject *py_obj);
507
508
bool GetValue() const;
509
510
void SetValue(bool value);
511
512
StructuredData::BooleanSP CreateStructuredBoolean() const;
513
};
514
515
class PythonList : public TypedPythonObject<PythonList> {
516
public:
517
using TypedPythonObject::TypedPythonObject;
518
519
PythonList() : TypedPythonObject() {} // MSVC requires this for some reason
520
521
explicit PythonList(PyInitialValue value);
522
explicit PythonList(int list_size);
523
524
static bool Check(PyObject *py_obj);
525
526
uint32_t GetSize() const;
527
528
PythonObject GetItemAtIndex(uint32_t index) const;
529
530
void SetItemAtIndex(uint32_t index, const PythonObject &object);
531
532
void AppendItem(const PythonObject &object);
533
534
StructuredData::ArraySP CreateStructuredArray() const;
535
};
536
537
class PythonTuple : public TypedPythonObject<PythonTuple> {
538
public:
539
using TypedPythonObject::TypedPythonObject;
540
541
explicit PythonTuple(PyInitialValue value);
542
explicit PythonTuple(int tuple_size);
543
PythonTuple(std::initializer_list<PythonObject> objects);
544
PythonTuple(std::initializer_list<PyObject *> objects);
545
546
static bool Check(PyObject *py_obj);
547
548
uint32_t GetSize() const;
549
550
PythonObject GetItemAtIndex(uint32_t index) const;
551
552
void SetItemAtIndex(uint32_t index, const PythonObject &object);
553
554
StructuredData::ArraySP CreateStructuredArray() const;
555
};
556
557
class PythonDictionary : public TypedPythonObject<PythonDictionary> {
558
public:
559
using TypedPythonObject::TypedPythonObject;
560
561
PythonDictionary() : TypedPythonObject() {} // MSVC requires this for some reason
562
563
explicit PythonDictionary(PyInitialValue value);
564
565
static bool Check(PyObject *py_obj);
566
567
bool HasKey(const llvm::Twine &key) const;
568
569
uint32_t GetSize() const;
570
571
PythonList GetKeys() const;
572
573
PythonObject GetItemForKey(const PythonObject &key) const; // DEPRECATED
574
void SetItemForKey(const PythonObject &key,
575
const PythonObject &value); // DEPRECATED
576
577
llvm::Expected<PythonObject> GetItem(const PythonObject &key) const;
578
llvm::Expected<PythonObject> GetItem(const llvm::Twine &key) const;
579
llvm::Error SetItem(const PythonObject &key, const PythonObject &value) const;
580
llvm::Error SetItem(const llvm::Twine &key, const PythonObject &value) const;
581
582
StructuredData::DictionarySP CreateStructuredDictionary() const;
583
};
584
585
class PythonModule : public TypedPythonObject<PythonModule> {
586
public:
587
using TypedPythonObject::TypedPythonObject;
588
589
static bool Check(PyObject *py_obj);
590
591
static PythonModule BuiltinsModule();
592
593
static PythonModule MainModule();
594
595
static PythonModule AddModule(llvm::StringRef module);
596
597
// safe, returns invalid on error;
598
static PythonModule ImportModule(llvm::StringRef name) {
599
std::string s = std::string(name);
600
auto mod = Import(s.c_str());
601
if (!mod) {
602
llvm::consumeError(mod.takeError());
603
return PythonModule();
604
}
605
return std::move(mod.get());
606
}
607
608
static llvm::Expected<PythonModule> Import(const llvm::Twine &name);
609
610
llvm::Expected<PythonObject> Get(const llvm::Twine &name);
611
612
PythonDictionary GetDictionary() const;
613
};
614
615
class PythonCallable : public TypedPythonObject<PythonCallable> {
616
public:
617
using TypedPythonObject::TypedPythonObject;
618
619
struct ArgInfo {
620
/* the largest number of positional arguments this callable
621
* can accept, or UNBOUNDED, ie UINT_MAX if it's a varargs
622
* function and can accept an arbitrary number */
623
unsigned max_positional_args;
624
static constexpr unsigned UNBOUNDED = UINT_MAX; // FIXME c++17 inline
625
};
626
627
static bool Check(PyObject *py_obj);
628
629
llvm::Expected<ArgInfo> GetArgInfo() const;
630
631
PythonObject operator()();
632
633
PythonObject operator()(std::initializer_list<PyObject *> args);
634
635
PythonObject operator()(std::initializer_list<PythonObject> args);
636
637
template <typename Arg, typename... Args>
638
PythonObject operator()(const Arg &arg, Args... args) {
639
return operator()({arg, args...});
640
}
641
};
642
643
class PythonFile : public TypedPythonObject<PythonFile> {
644
public:
645
using TypedPythonObject::TypedPythonObject;
646
647
PythonFile() : TypedPythonObject() {} // MSVC requires this for some reason
648
649
static bool Check(PyObject *py_obj);
650
651
static llvm::Expected<PythonFile> FromFile(File &file,
652
const char *mode = nullptr);
653
654
llvm::Expected<lldb::FileSP> ConvertToFile(bool borrowed = false);
655
llvm::Expected<lldb::FileSP>
656
ConvertToFileForcingUseOfScriptingIOMethods(bool borrowed = false);
657
};
658
659
class PythonException : public llvm::ErrorInfo<PythonException> {
660
private:
661
PyObject *m_exception_type, *m_exception, *m_traceback;
662
PyObject *m_repr_bytes;
663
664
public:
665
static char ID;
666
const char *toCString() const;
667
PythonException(const char *caller = nullptr);
668
void Restore();
669
~PythonException() override;
670
void log(llvm::raw_ostream &OS) const override;
671
std::error_code convertToErrorCode() const override;
672
bool Matches(PyObject *exc) const;
673
std::string ReadBacktrace() const;
674
};
675
676
// This extracts the underlying T out of an Expected<T> and returns it.
677
// If the Expected is an Error instead of a T, that error will be converted
678
// into a python exception, and this will return a default-constructed T.
679
//
680
// This is appropriate for use right at the boundary of python calling into
681
// C++, such as in a SWIG typemap. In such a context you should simply
682
// check if the returned T is valid, and if it is, return a NULL back
683
// to python. This will result in the Error being raised as an exception
684
// from python code's point of view.
685
//
686
// For example:
687
// ```
688
// Expected<Foo *> efoop = some_cpp_function();
689
// Foo *foop = unwrapOrSetPythonException(efoop);
690
// if (!foop)
691
// return NULL;
692
// do_something(*foop);
693
//
694
// If the Error returned was itself created because a python exception was
695
// raised when C++ code called into python, then the original exception
696
// will be restored. Otherwise a simple string exception will be raised.
697
template <typename T> T unwrapOrSetPythonException(llvm::Expected<T> expected) {
698
if (expected)
699
return expected.get();
700
llvm::handleAllErrors(
701
expected.takeError(), [](PythonException &E) { E.Restore(); },
702
[](const llvm::ErrorInfoBase &E) {
703
PyErr_SetString(PyExc_Exception, E.message().c_str());
704
});
705
return T();
706
}
707
708
// This is only here to help incrementally migrate old, exception-unsafe
709
// code.
710
template <typename T> T unwrapIgnoringErrors(llvm::Expected<T> expected) {
711
if (expected)
712
return std::move(expected.get());
713
llvm::consumeError(expected.takeError());
714
return T();
715
}
716
717
llvm::Expected<PythonObject> runStringOneLine(const llvm::Twine &string,
718
const PythonDictionary &globals,
719
const PythonDictionary &locals);
720
721
llvm::Expected<PythonObject> runStringMultiLine(const llvm::Twine &string,
722
const PythonDictionary &globals,
723
const PythonDictionary &locals);
724
725
// Sometimes the best way to interact with a python interpreter is
726
// to run some python code. You construct a PythonScript with
727
// script string. The script assigns some function to `_function_`
728
// and you get a C++ callable object that calls the python function.
729
//
730
// Example:
731
//
732
// const char script[] = R"(
733
// def main(x, y):
734
// ....
735
// )";
736
//
737
// Expected<PythonObject> cpp_foo_wrapper(PythonObject x, PythonObject y) {
738
// // no need to synchronize access to this global, we already have the GIL
739
// static PythonScript foo(script)
740
// return foo(x, y);
741
// }
742
class PythonScript {
743
const char *script;
744
PythonCallable function;
745
746
llvm::Error Init();
747
748
public:
749
PythonScript(const char *script) : script(script), function() {}
750
751
template <typename... Args>
752
llvm::Expected<PythonObject> operator()(Args &&... args) {
753
if (llvm::Error error = Init())
754
return std::move(error);
755
return function.Call(std::forward<Args>(args)...);
756
}
757
};
758
759
class StructuredPythonObject : public StructuredData::Generic {
760
public:
761
StructuredPythonObject() : StructuredData::Generic() {}
762
763
// Take ownership of the object we received.
764
StructuredPythonObject(PythonObject obj)
765
: StructuredData::Generic(obj.release()) {}
766
767
~StructuredPythonObject() override {
768
// Hand ownership back to a (temporary) PythonObject instance and let it
769
// take care of releasing it.
770
PythonObject(PyRefType::Owned, static_cast<PyObject *>(GetValue()));
771
}
772
773
bool IsValid() const override { return GetValue() && GetValue() != Py_None; }
774
775
void Serialize(llvm::json::OStream &s) const override;
776
777
private:
778
StructuredPythonObject(const StructuredPythonObject &) = delete;
779
const StructuredPythonObject &
780
operator=(const StructuredPythonObject &) = delete;
781
};
782
783
} // namespace python
784
} // namespace lldb_private
785
786
#endif
787
788
#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H
789
790