15ffd83dbSDimitry Andric //===-- PythonDataObjects.cpp ---------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric
9480093f4SDimitry Andric #include "lldb/Host/Config.h"
100b57cec5SDimitry Andric
11480093f4SDimitry Andric #if LLDB_ENABLE_PYTHON
120b57cec5SDimitry Andric
130b57cec5SDimitry Andric #include "PythonDataObjects.h"
140b57cec5SDimitry Andric #include "ScriptInterpreterPython.h"
150b57cec5SDimitry Andric
160b57cec5SDimitry Andric #include "lldb/Host/File.h"
170b57cec5SDimitry Andric #include "lldb/Host/FileSystem.h"
180b57cec5SDimitry Andric #include "lldb/Interpreter/ScriptInterpreter.h"
1981ad6265SDimitry Andric #include "lldb/Utility/LLDBLog.h"
209dba64beSDimitry Andric #include "lldb/Utility/Log.h"
210b57cec5SDimitry Andric #include "lldb/Utility/Stream.h"
220b57cec5SDimitry Andric
239dba64beSDimitry Andric #include "llvm/Support/Casting.h"
240b57cec5SDimitry Andric #include "llvm/Support/ConvertUTF.h"
250b57cec5SDimitry Andric #include "llvm/Support/Errno.h"
260b57cec5SDimitry Andric
27fe6060f1SDimitry Andric #include <cstdio>
28fe013be4SDimitry Andric #include <variant>
290b57cec5SDimitry Andric
300b57cec5SDimitry Andric using namespace lldb_private;
310b57cec5SDimitry Andric using namespace lldb;
329dba64beSDimitry Andric using namespace lldb_private::python;
339dba64beSDimitry Andric using llvm::cantFail;
349dba64beSDimitry Andric using llvm::Error;
359dba64beSDimitry Andric using llvm::Expected;
369dba64beSDimitry Andric using llvm::Twine;
370b57cec5SDimitry Andric
As(Expected<PythonObject> && obj)389dba64beSDimitry Andric template <> Expected<bool> python::As<bool>(Expected<PythonObject> &&obj) {
399dba64beSDimitry Andric if (!obj)
409dba64beSDimitry Andric return obj.takeError();
419dba64beSDimitry Andric return obj.get().IsTrue();
429dba64beSDimitry Andric }
439dba64beSDimitry Andric
449dba64beSDimitry Andric template <>
As(Expected<PythonObject> && obj)459dba64beSDimitry Andric Expected<long long> python::As<long long>(Expected<PythonObject> &&obj) {
469dba64beSDimitry Andric if (!obj)
479dba64beSDimitry Andric return obj.takeError();
485ffd83dbSDimitry Andric return obj->AsLongLong();
495ffd83dbSDimitry Andric }
505ffd83dbSDimitry Andric
515ffd83dbSDimitry Andric template <>
525ffd83dbSDimitry Andric Expected<unsigned long long>
As(Expected<PythonObject> && obj)535ffd83dbSDimitry Andric python::As<unsigned long long>(Expected<PythonObject> &&obj) {
545ffd83dbSDimitry Andric if (!obj)
555ffd83dbSDimitry Andric return obj.takeError();
565ffd83dbSDimitry Andric return obj->AsUnsignedLongLong();
579dba64beSDimitry Andric }
589dba64beSDimitry Andric
599dba64beSDimitry Andric template <>
As(Expected<PythonObject> && obj)609dba64beSDimitry Andric Expected<std::string> python::As<std::string>(Expected<PythonObject> &&obj) {
619dba64beSDimitry Andric if (!obj)
629dba64beSDimitry Andric return obj.takeError();
639dba64beSDimitry Andric PyObject *str_obj = PyObject_Str(obj.get().get());
649dba64beSDimitry Andric if (!obj)
659dba64beSDimitry Andric return llvm::make_error<PythonException>();
669dba64beSDimitry Andric auto str = Take<PythonString>(str_obj);
679dba64beSDimitry Andric auto utf8 = str.AsUTF8();
689dba64beSDimitry Andric if (!utf8)
699dba64beSDimitry Andric return utf8.takeError();
705ffd83dbSDimitry Andric return std::string(utf8.get());
715ffd83dbSDimitry Andric }
725ffd83dbSDimitry Andric
python_is_finalizing()7304eeddc0SDimitry Andric static bool python_is_finalizing() {
74*c9157d92SDimitry Andric #if (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 13) || (PY_MAJOR_VERSION > 3)
75*c9157d92SDimitry Andric return Py_IsFinalizing();
76*c9157d92SDimitry Andric #elif PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 7
7704eeddc0SDimitry Andric return _Py_Finalizing != nullptr;
7804eeddc0SDimitry Andric #else
7904eeddc0SDimitry Andric return _Py_IsFinalizing();
8004eeddc0SDimitry Andric #endif
8104eeddc0SDimitry Andric }
8204eeddc0SDimitry Andric
Reset()8304eeddc0SDimitry Andric void PythonObject::Reset() {
8404eeddc0SDimitry Andric if (m_py_obj && Py_IsInitialized()) {
8504eeddc0SDimitry Andric if (python_is_finalizing()) {
8604eeddc0SDimitry Andric // Leak m_py_obj rather than crashing the process.
8704eeddc0SDimitry Andric // https://docs.python.org/3/c-api/init.html#c.PyGILState_Ensure
8804eeddc0SDimitry Andric } else {
8904eeddc0SDimitry Andric PyGILState_STATE state = PyGILState_Ensure();
9004eeddc0SDimitry Andric Py_DECREF(m_py_obj);
9104eeddc0SDimitry Andric PyGILState_Release(state);
9204eeddc0SDimitry Andric }
9304eeddc0SDimitry Andric }
9404eeddc0SDimitry Andric m_py_obj = nullptr;
9504eeddc0SDimitry Andric }
9604eeddc0SDimitry Andric
AsLongLong() const975ffd83dbSDimitry Andric Expected<long long> PythonObject::AsLongLong() const {
985ffd83dbSDimitry Andric if (!m_py_obj)
995ffd83dbSDimitry Andric return nullDeref();
1005ffd83dbSDimitry Andric assert(!PyErr_Occurred());
1015ffd83dbSDimitry Andric long long r = PyLong_AsLongLong(m_py_obj);
1025ffd83dbSDimitry Andric if (PyErr_Occurred())
1035ffd83dbSDimitry Andric return exception();
1045ffd83dbSDimitry Andric return r;
1055ffd83dbSDimitry Andric }
1065ffd83dbSDimitry Andric
AsUnsignedLongLong() const107fe013be4SDimitry Andric Expected<unsigned long long> PythonObject::AsUnsignedLongLong() const {
1085ffd83dbSDimitry Andric if (!m_py_obj)
1095ffd83dbSDimitry Andric return nullDeref();
1105ffd83dbSDimitry Andric assert(!PyErr_Occurred());
1115ffd83dbSDimitry Andric long long r = PyLong_AsUnsignedLongLong(m_py_obj);
1125ffd83dbSDimitry Andric if (PyErr_Occurred())
1135ffd83dbSDimitry Andric return exception();
1145ffd83dbSDimitry Andric return r;
1155ffd83dbSDimitry Andric }
1165ffd83dbSDimitry Andric
1175ffd83dbSDimitry Andric // wraps on overflow, instead of raising an error.
AsModuloUnsignedLongLong() const1185ffd83dbSDimitry Andric Expected<unsigned long long> PythonObject::AsModuloUnsignedLongLong() const {
1195ffd83dbSDimitry Andric if (!m_py_obj)
1205ffd83dbSDimitry Andric return nullDeref();
1215ffd83dbSDimitry Andric assert(!PyErr_Occurred());
1225ffd83dbSDimitry Andric unsigned long long r = PyLong_AsUnsignedLongLongMask(m_py_obj);
123fe013be4SDimitry Andric // FIXME: We should fetch the exception message and hoist it.
1245ffd83dbSDimitry Andric if (PyErr_Occurred())
1255ffd83dbSDimitry Andric return exception();
1265ffd83dbSDimitry Andric return r;
1279dba64beSDimitry Andric }
1289dba64beSDimitry Andric
Serialize(llvm::json::OStream & s) const1299dba64beSDimitry Andric void StructuredPythonObject::Serialize(llvm::json::OStream &s) const {
1309dba64beSDimitry Andric s.value(llvm::formatv("Python Obj: {0:X}", GetValue()).str());
1310b57cec5SDimitry Andric }
1320b57cec5SDimitry Andric
1330b57cec5SDimitry Andric // PythonObject
1340b57cec5SDimitry Andric
Dump(Stream & strm) const1350b57cec5SDimitry Andric void PythonObject::Dump(Stream &strm) const {
1360b57cec5SDimitry Andric if (m_py_obj) {
1370b57cec5SDimitry Andric FILE *file = llvm::sys::RetryAfterSignal(nullptr, ::tmpfile);
1380b57cec5SDimitry Andric if (file) {
1390b57cec5SDimitry Andric ::PyObject_Print(m_py_obj, file, 0);
1400b57cec5SDimitry Andric const long length = ftell(file);
1410b57cec5SDimitry Andric if (length) {
1420b57cec5SDimitry Andric ::rewind(file);
1430b57cec5SDimitry Andric std::vector<char> file_contents(length, '\0');
1440b57cec5SDimitry Andric const size_t length_read =
1450b57cec5SDimitry Andric ::fread(file_contents.data(), 1, file_contents.size(), file);
1460b57cec5SDimitry Andric if (length_read > 0)
1470b57cec5SDimitry Andric strm.Write(file_contents.data(), length_read);
1480b57cec5SDimitry Andric }
1490b57cec5SDimitry Andric ::fclose(file);
1500b57cec5SDimitry Andric }
1510b57cec5SDimitry Andric } else
1520b57cec5SDimitry Andric strm.PutCString("NULL");
1530b57cec5SDimitry Andric }
1540b57cec5SDimitry Andric
GetObjectType() const1550b57cec5SDimitry Andric PyObjectType PythonObject::GetObjectType() const {
1560b57cec5SDimitry Andric if (!IsAllocated())
1570b57cec5SDimitry Andric return PyObjectType::None;
1580b57cec5SDimitry Andric
1590b57cec5SDimitry Andric if (PythonModule::Check(m_py_obj))
1600b57cec5SDimitry Andric return PyObjectType::Module;
1610b57cec5SDimitry Andric if (PythonList::Check(m_py_obj))
1620b57cec5SDimitry Andric return PyObjectType::List;
1630b57cec5SDimitry Andric if (PythonTuple::Check(m_py_obj))
1640b57cec5SDimitry Andric return PyObjectType::Tuple;
1650b57cec5SDimitry Andric if (PythonDictionary::Check(m_py_obj))
1660b57cec5SDimitry Andric return PyObjectType::Dictionary;
1670b57cec5SDimitry Andric if (PythonString::Check(m_py_obj))
1680b57cec5SDimitry Andric return PyObjectType::String;
1690b57cec5SDimitry Andric if (PythonBytes::Check(m_py_obj))
1700b57cec5SDimitry Andric return PyObjectType::Bytes;
1710b57cec5SDimitry Andric if (PythonByteArray::Check(m_py_obj))
1720b57cec5SDimitry Andric return PyObjectType::ByteArray;
1730b57cec5SDimitry Andric if (PythonBoolean::Check(m_py_obj))
1740b57cec5SDimitry Andric return PyObjectType::Boolean;
1750b57cec5SDimitry Andric if (PythonInteger::Check(m_py_obj))
1760b57cec5SDimitry Andric return PyObjectType::Integer;
1770b57cec5SDimitry Andric if (PythonFile::Check(m_py_obj))
1780b57cec5SDimitry Andric return PyObjectType::File;
1790b57cec5SDimitry Andric if (PythonCallable::Check(m_py_obj))
1800b57cec5SDimitry Andric return PyObjectType::Callable;
1810b57cec5SDimitry Andric return PyObjectType::Unknown;
1820b57cec5SDimitry Andric }
1830b57cec5SDimitry Andric
Repr() const1840b57cec5SDimitry Andric PythonString PythonObject::Repr() const {
1850b57cec5SDimitry Andric if (!m_py_obj)
1860b57cec5SDimitry Andric return PythonString();
1870b57cec5SDimitry Andric PyObject *repr = PyObject_Repr(m_py_obj);
1880b57cec5SDimitry Andric if (!repr)
1890b57cec5SDimitry Andric return PythonString();
1900b57cec5SDimitry Andric return PythonString(PyRefType::Owned, repr);
1910b57cec5SDimitry Andric }
1920b57cec5SDimitry Andric
Str() const1930b57cec5SDimitry Andric PythonString PythonObject::Str() const {
1940b57cec5SDimitry Andric if (!m_py_obj)
1950b57cec5SDimitry Andric return PythonString();
1960b57cec5SDimitry Andric PyObject *str = PyObject_Str(m_py_obj);
1970b57cec5SDimitry Andric if (!str)
1980b57cec5SDimitry Andric return PythonString();
1990b57cec5SDimitry Andric return PythonString(PyRefType::Owned, str);
2000b57cec5SDimitry Andric }
2010b57cec5SDimitry Andric
2020b57cec5SDimitry Andric PythonObject
ResolveNameWithDictionary(llvm::StringRef name,const PythonDictionary & dict)2030b57cec5SDimitry Andric PythonObject::ResolveNameWithDictionary(llvm::StringRef name,
2040b57cec5SDimitry Andric const PythonDictionary &dict) {
2050b57cec5SDimitry Andric size_t dot_pos = name.find('.');
2060b57cec5SDimitry Andric llvm::StringRef piece = name.substr(0, dot_pos);
2070b57cec5SDimitry Andric PythonObject result = dict.GetItemForKey(PythonString(piece));
2080b57cec5SDimitry Andric if (dot_pos == llvm::StringRef::npos) {
2090b57cec5SDimitry Andric // There was no dot, we're done.
2100b57cec5SDimitry Andric return result;
2110b57cec5SDimitry Andric }
2120b57cec5SDimitry Andric
2130b57cec5SDimitry Andric // There was a dot. The remaining portion of the name should be looked up in
2140b57cec5SDimitry Andric // the context of the object that was found in the dictionary.
2150b57cec5SDimitry Andric return result.ResolveName(name.substr(dot_pos + 1));
2160b57cec5SDimitry Andric }
2170b57cec5SDimitry Andric
ResolveName(llvm::StringRef name) const2180b57cec5SDimitry Andric PythonObject PythonObject::ResolveName(llvm::StringRef name) const {
2190b57cec5SDimitry Andric // Resolve the name in the context of the specified object. If, for example,
2200b57cec5SDimitry Andric // `this` refers to a PyModule, then this will look for `name` in this
2210b57cec5SDimitry Andric // module. If `this` refers to a PyType, then it will resolve `name` as an
2220b57cec5SDimitry Andric // attribute of that type. If `this` refers to an instance of an object,
2230b57cec5SDimitry Andric // then it will resolve `name` as the value of the specified field.
2240b57cec5SDimitry Andric //
2250b57cec5SDimitry Andric // This function handles dotted names so that, for example, if `m_py_obj`
2260b57cec5SDimitry Andric // refers to the `sys` module, and `name` == "path.append", then it will find
2270b57cec5SDimitry Andric // the function `sys.path.append`.
2280b57cec5SDimitry Andric
2290b57cec5SDimitry Andric size_t dot_pos = name.find('.');
2300b57cec5SDimitry Andric if (dot_pos == llvm::StringRef::npos) {
2310b57cec5SDimitry Andric // No dots in the name, we should be able to find the value immediately as
2320b57cec5SDimitry Andric // an attribute of `m_py_obj`.
2330b57cec5SDimitry Andric return GetAttributeValue(name);
2340b57cec5SDimitry Andric }
2350b57cec5SDimitry Andric
2360b57cec5SDimitry Andric // Look up the first piece of the name, and resolve the rest as a child of
2370b57cec5SDimitry Andric // that.
2380b57cec5SDimitry Andric PythonObject parent = ResolveName(name.substr(0, dot_pos));
2390b57cec5SDimitry Andric if (!parent.IsAllocated())
2400b57cec5SDimitry Andric return PythonObject();
2410b57cec5SDimitry Andric
2420b57cec5SDimitry Andric // Tail recursion.. should be optimized by the compiler
2430b57cec5SDimitry Andric return parent.ResolveName(name.substr(dot_pos + 1));
2440b57cec5SDimitry Andric }
2450b57cec5SDimitry Andric
HasAttribute(llvm::StringRef attr) const2460b57cec5SDimitry Andric bool PythonObject::HasAttribute(llvm::StringRef attr) const {
2470b57cec5SDimitry Andric if (!IsValid())
2480b57cec5SDimitry Andric return false;
2490b57cec5SDimitry Andric PythonString py_attr(attr);
2500b57cec5SDimitry Andric return !!PyObject_HasAttr(m_py_obj, py_attr.get());
2510b57cec5SDimitry Andric }
2520b57cec5SDimitry Andric
GetAttributeValue(llvm::StringRef attr) const2530b57cec5SDimitry Andric PythonObject PythonObject::GetAttributeValue(llvm::StringRef attr) const {
2540b57cec5SDimitry Andric if (!IsValid())
2550b57cec5SDimitry Andric return PythonObject();
2560b57cec5SDimitry Andric
2570b57cec5SDimitry Andric PythonString py_attr(attr);
2580b57cec5SDimitry Andric if (!PyObject_HasAttr(m_py_obj, py_attr.get()))
2590b57cec5SDimitry Andric return PythonObject();
2600b57cec5SDimitry Andric
2610b57cec5SDimitry Andric return PythonObject(PyRefType::Owned,
2620b57cec5SDimitry Andric PyObject_GetAttr(m_py_obj, py_attr.get()));
2630b57cec5SDimitry Andric }
2640b57cec5SDimitry Andric
CreateStructuredObject() const2650b57cec5SDimitry Andric StructuredData::ObjectSP PythonObject::CreateStructuredObject() const {
26604eeddc0SDimitry Andric assert(PyGILState_Check());
2670b57cec5SDimitry Andric switch (GetObjectType()) {
2680b57cec5SDimitry Andric case PyObjectType::Dictionary:
2690b57cec5SDimitry Andric return PythonDictionary(PyRefType::Borrowed, m_py_obj)
2700b57cec5SDimitry Andric .CreateStructuredDictionary();
2710b57cec5SDimitry Andric case PyObjectType::Boolean:
2720b57cec5SDimitry Andric return PythonBoolean(PyRefType::Borrowed, m_py_obj)
2730b57cec5SDimitry Andric .CreateStructuredBoolean();
274fe013be4SDimitry Andric case PyObjectType::Integer: {
275fe013be4SDimitry Andric StructuredData::IntegerSP int_sp =
276fe013be4SDimitry Andric PythonInteger(PyRefType::Borrowed, m_py_obj).CreateStructuredInteger();
277fe013be4SDimitry Andric if (std::holds_alternative<StructuredData::UnsignedIntegerSP>(int_sp))
278fe013be4SDimitry Andric return std::get<StructuredData::UnsignedIntegerSP>(int_sp);
279fe013be4SDimitry Andric if (std::holds_alternative<StructuredData::SignedIntegerSP>(int_sp))
280fe013be4SDimitry Andric return std::get<StructuredData::SignedIntegerSP>(int_sp);
281fe013be4SDimitry Andric return nullptr;
282fe013be4SDimitry Andric };
2830b57cec5SDimitry Andric case PyObjectType::List:
2840b57cec5SDimitry Andric return PythonList(PyRefType::Borrowed, m_py_obj).CreateStructuredArray();
2850b57cec5SDimitry Andric case PyObjectType::String:
2860b57cec5SDimitry Andric return PythonString(PyRefType::Borrowed, m_py_obj).CreateStructuredString();
2870b57cec5SDimitry Andric case PyObjectType::Bytes:
2880b57cec5SDimitry Andric return PythonBytes(PyRefType::Borrowed, m_py_obj).CreateStructuredString();
2890b57cec5SDimitry Andric case PyObjectType::ByteArray:
2900b57cec5SDimitry Andric return PythonByteArray(PyRefType::Borrowed, m_py_obj)
2910b57cec5SDimitry Andric .CreateStructuredString();
2920b57cec5SDimitry Andric case PyObjectType::None:
2930b57cec5SDimitry Andric return StructuredData::ObjectSP();
2940b57cec5SDimitry Andric default:
29504eeddc0SDimitry Andric return StructuredData::ObjectSP(new StructuredPythonObject(
29604eeddc0SDimitry Andric PythonObject(PyRefType::Borrowed, m_py_obj)));
2970b57cec5SDimitry Andric }
2980b57cec5SDimitry Andric }
2990b57cec5SDimitry Andric
3000b57cec5SDimitry Andric // PythonString
3010b57cec5SDimitry Andric
PythonBytes(llvm::ArrayRef<uint8_t> bytes)3029dba64beSDimitry Andric PythonBytes::PythonBytes(llvm::ArrayRef<uint8_t> bytes) { SetBytes(bytes); }
3030b57cec5SDimitry Andric
PythonBytes(const uint8_t * bytes,size_t length)3049dba64beSDimitry Andric PythonBytes::PythonBytes(const uint8_t *bytes, size_t length) {
3050b57cec5SDimitry Andric SetBytes(llvm::ArrayRef<uint8_t>(bytes, length));
3060b57cec5SDimitry Andric }
3070b57cec5SDimitry Andric
Check(PyObject * py_obj)3080b57cec5SDimitry Andric bool PythonBytes::Check(PyObject *py_obj) {
3090b57cec5SDimitry Andric if (!py_obj)
3100b57cec5SDimitry Andric return false;
3110b57cec5SDimitry Andric return PyBytes_Check(py_obj);
3120b57cec5SDimitry Andric }
3130b57cec5SDimitry Andric
GetBytes() const3140b57cec5SDimitry Andric llvm::ArrayRef<uint8_t> PythonBytes::GetBytes() const {
3150b57cec5SDimitry Andric if (!IsValid())
3160b57cec5SDimitry Andric return llvm::ArrayRef<uint8_t>();
3170b57cec5SDimitry Andric
3180b57cec5SDimitry Andric Py_ssize_t size;
3190b57cec5SDimitry Andric char *c;
3200b57cec5SDimitry Andric
3210b57cec5SDimitry Andric PyBytes_AsStringAndSize(m_py_obj, &c, &size);
3220b57cec5SDimitry Andric return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size);
3230b57cec5SDimitry Andric }
3240b57cec5SDimitry Andric
GetSize() const3250b57cec5SDimitry Andric size_t PythonBytes::GetSize() const {
3260b57cec5SDimitry Andric if (!IsValid())
3270b57cec5SDimitry Andric return 0;
3280b57cec5SDimitry Andric return PyBytes_Size(m_py_obj);
3290b57cec5SDimitry Andric }
3300b57cec5SDimitry Andric
SetBytes(llvm::ArrayRef<uint8_t> bytes)3310b57cec5SDimitry Andric void PythonBytes::SetBytes(llvm::ArrayRef<uint8_t> bytes) {
3320b57cec5SDimitry Andric const char *data = reinterpret_cast<const char *>(bytes.data());
3339dba64beSDimitry Andric *this = Take<PythonBytes>(PyBytes_FromStringAndSize(data, bytes.size()));
3340b57cec5SDimitry Andric }
3350b57cec5SDimitry Andric
CreateStructuredString() const3360b57cec5SDimitry Andric StructuredData::StringSP PythonBytes::CreateStructuredString() const {
3370b57cec5SDimitry Andric StructuredData::StringSP result(new StructuredData::String);
3380b57cec5SDimitry Andric Py_ssize_t size;
3390b57cec5SDimitry Andric char *c;
3400b57cec5SDimitry Andric PyBytes_AsStringAndSize(m_py_obj, &c, &size);
3410b57cec5SDimitry Andric result->SetValue(std::string(c, size));
3420b57cec5SDimitry Andric return result;
3430b57cec5SDimitry Andric }
3440b57cec5SDimitry Andric
PythonByteArray(llvm::ArrayRef<uint8_t> bytes)3450b57cec5SDimitry Andric PythonByteArray::PythonByteArray(llvm::ArrayRef<uint8_t> bytes)
3460b57cec5SDimitry Andric : PythonByteArray(bytes.data(), bytes.size()) {}
3470b57cec5SDimitry Andric
PythonByteArray(const uint8_t * bytes,size_t length)3480b57cec5SDimitry Andric PythonByteArray::PythonByteArray(const uint8_t *bytes, size_t length) {
3490b57cec5SDimitry Andric const char *str = reinterpret_cast<const char *>(bytes);
3509dba64beSDimitry Andric *this = Take<PythonByteArray>(PyByteArray_FromStringAndSize(str, length));
3510b57cec5SDimitry Andric }
3520b57cec5SDimitry Andric
Check(PyObject * py_obj)3530b57cec5SDimitry Andric bool PythonByteArray::Check(PyObject *py_obj) {
3540b57cec5SDimitry Andric if (!py_obj)
3550b57cec5SDimitry Andric return false;
3560b57cec5SDimitry Andric return PyByteArray_Check(py_obj);
3570b57cec5SDimitry Andric }
3580b57cec5SDimitry Andric
GetBytes() const3590b57cec5SDimitry Andric llvm::ArrayRef<uint8_t> PythonByteArray::GetBytes() const {
3600b57cec5SDimitry Andric if (!IsValid())
3610b57cec5SDimitry Andric return llvm::ArrayRef<uint8_t>();
3620b57cec5SDimitry Andric
3630b57cec5SDimitry Andric char *c = PyByteArray_AsString(m_py_obj);
3640b57cec5SDimitry Andric size_t size = GetSize();
3650b57cec5SDimitry Andric return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size);
3660b57cec5SDimitry Andric }
3670b57cec5SDimitry Andric
GetSize() const3680b57cec5SDimitry Andric size_t PythonByteArray::GetSize() const {
3690b57cec5SDimitry Andric if (!IsValid())
3700b57cec5SDimitry Andric return 0;
3710b57cec5SDimitry Andric
3720b57cec5SDimitry Andric return PyByteArray_Size(m_py_obj);
3730b57cec5SDimitry Andric }
3740b57cec5SDimitry Andric
CreateStructuredString() const3750b57cec5SDimitry Andric StructuredData::StringSP PythonByteArray::CreateStructuredString() const {
3760b57cec5SDimitry Andric StructuredData::StringSP result(new StructuredData::String);
3770b57cec5SDimitry Andric llvm::ArrayRef<uint8_t> bytes = GetBytes();
3780b57cec5SDimitry Andric const char *str = reinterpret_cast<const char *>(bytes.data());
3790b57cec5SDimitry Andric result->SetValue(std::string(str, bytes.size()));
3800b57cec5SDimitry Andric return result;
3810b57cec5SDimitry Andric }
3820b57cec5SDimitry Andric
3830b57cec5SDimitry Andric // PythonString
3840b57cec5SDimitry Andric
FromUTF8(llvm::StringRef string)3859dba64beSDimitry Andric Expected<PythonString> PythonString::FromUTF8(llvm::StringRef string) {
3869dba64beSDimitry Andric PyObject *str = PyUnicode_FromStringAndSize(string.data(), string.size());
3879dba64beSDimitry Andric if (!str)
3889dba64beSDimitry Andric return llvm::make_error<PythonException>();
3899dba64beSDimitry Andric return Take<PythonString>(str);
3900b57cec5SDimitry Andric }
3910b57cec5SDimitry Andric
PythonString(llvm::StringRef string)3929dba64beSDimitry Andric PythonString::PythonString(llvm::StringRef string) { SetString(string); }
3930b57cec5SDimitry Andric
Check(PyObject * py_obj)3940b57cec5SDimitry Andric bool PythonString::Check(PyObject *py_obj) {
3950b57cec5SDimitry Andric if (!py_obj)
3960b57cec5SDimitry Andric return false;
3970b57cec5SDimitry Andric
3980b57cec5SDimitry Andric if (PyUnicode_Check(py_obj))
3990b57cec5SDimitry Andric return true;
4000b57cec5SDimitry Andric return false;
4010b57cec5SDimitry Andric }
4020b57cec5SDimitry Andric
GetString() const4030b57cec5SDimitry Andric llvm::StringRef PythonString::GetString() const {
4049dba64beSDimitry Andric auto s = AsUTF8();
4059dba64beSDimitry Andric if (!s) {
4069dba64beSDimitry Andric llvm::consumeError(s.takeError());
4079dba64beSDimitry Andric return llvm::StringRef("");
4089dba64beSDimitry Andric }
4099dba64beSDimitry Andric return s.get();
4109dba64beSDimitry Andric }
4119dba64beSDimitry Andric
AsUTF8() const4129dba64beSDimitry Andric Expected<llvm::StringRef> PythonString::AsUTF8() const {
4130b57cec5SDimitry Andric if (!IsValid())
4149dba64beSDimitry Andric return nullDeref();
4150b57cec5SDimitry Andric
4160b57cec5SDimitry Andric Py_ssize_t size;
4170b57cec5SDimitry Andric const char *data;
4180b57cec5SDimitry Andric
4190b57cec5SDimitry Andric data = PyUnicode_AsUTF8AndSize(m_py_obj, &size);
4209dba64beSDimitry Andric
4219dba64beSDimitry Andric if (!data)
4229dba64beSDimitry Andric return exception();
4239dba64beSDimitry Andric
4240b57cec5SDimitry Andric return llvm::StringRef(data, size);
4250b57cec5SDimitry Andric }
4260b57cec5SDimitry Andric
GetSize() const4270b57cec5SDimitry Andric size_t PythonString::GetSize() const {
4280b57cec5SDimitry Andric if (IsValid()) {
429e8d8bef9SDimitry Andric #if PY_MINOR_VERSION >= 3
430e8d8bef9SDimitry Andric return PyUnicode_GetLength(m_py_obj);
431e8d8bef9SDimitry Andric #else
4320b57cec5SDimitry Andric return PyUnicode_GetSize(m_py_obj);
433e8d8bef9SDimitry Andric #endif
4340b57cec5SDimitry Andric }
4350b57cec5SDimitry Andric return 0;
4360b57cec5SDimitry Andric }
4370b57cec5SDimitry Andric
SetString(llvm::StringRef string)4380b57cec5SDimitry Andric void PythonString::SetString(llvm::StringRef string) {
4399dba64beSDimitry Andric auto s = FromUTF8(string);
4409dba64beSDimitry Andric if (!s) {
4419dba64beSDimitry Andric llvm::consumeError(s.takeError());
4429dba64beSDimitry Andric Reset();
4439dba64beSDimitry Andric } else {
4449dba64beSDimitry Andric *this = std::move(s.get());
4459dba64beSDimitry Andric }
4460b57cec5SDimitry Andric }
4470b57cec5SDimitry Andric
CreateStructuredString() const4480b57cec5SDimitry Andric StructuredData::StringSP PythonString::CreateStructuredString() const {
4490b57cec5SDimitry Andric StructuredData::StringSP result(new StructuredData::String);
4500b57cec5SDimitry Andric result->SetValue(GetString());
4510b57cec5SDimitry Andric return result;
4520b57cec5SDimitry Andric }
4530b57cec5SDimitry Andric
4540b57cec5SDimitry Andric // PythonInteger
4550b57cec5SDimitry Andric
PythonInteger(int64_t value)4569dba64beSDimitry Andric PythonInteger::PythonInteger(int64_t value) { SetInteger(value); }
4570b57cec5SDimitry Andric
Check(PyObject * py_obj)4580b57cec5SDimitry Andric bool PythonInteger::Check(PyObject *py_obj) {
4590b57cec5SDimitry Andric if (!py_obj)
4600b57cec5SDimitry Andric return false;
4610b57cec5SDimitry Andric
4620b57cec5SDimitry Andric // Python 3 does not have PyInt_Check. There is only one type of integral
4630b57cec5SDimitry Andric // value, long.
4640b57cec5SDimitry Andric return PyLong_Check(py_obj);
4650b57cec5SDimitry Andric }
4660b57cec5SDimitry Andric
SetInteger(int64_t value)4670b57cec5SDimitry Andric void PythonInteger::SetInteger(int64_t value) {
4689dba64beSDimitry Andric *this = Take<PythonInteger>(PyLong_FromLongLong(value));
4690b57cec5SDimitry Andric }
4700b57cec5SDimitry Andric
CreateStructuredInteger() const4710b57cec5SDimitry Andric StructuredData::IntegerSP PythonInteger::CreateStructuredInteger() const {
472fe013be4SDimitry Andric StructuredData::UnsignedIntegerSP uint_sp = CreateStructuredUnsignedInteger();
473fe013be4SDimitry Andric return uint_sp ? StructuredData::IntegerSP(uint_sp)
474fe013be4SDimitry Andric : CreateStructuredSignedInteger();
4755ffd83dbSDimitry Andric }
476fe013be4SDimitry Andric
477fe013be4SDimitry Andric StructuredData::UnsignedIntegerSP
CreateStructuredUnsignedInteger() const478fe013be4SDimitry Andric PythonInteger::CreateStructuredUnsignedInteger() const {
479fe013be4SDimitry Andric StructuredData::UnsignedIntegerSP result = nullptr;
480fe013be4SDimitry Andric llvm::Expected<unsigned long long> value = AsUnsignedLongLong();
481fe013be4SDimitry Andric if (!value)
482fe013be4SDimitry Andric llvm::consumeError(value.takeError());
483fe013be4SDimitry Andric else
484fe013be4SDimitry Andric result = std::make_shared<StructuredData::UnsignedInteger>(value.get());
485fe013be4SDimitry Andric
486fe013be4SDimitry Andric return result;
487fe013be4SDimitry Andric }
488fe013be4SDimitry Andric
489fe013be4SDimitry Andric StructuredData::SignedIntegerSP
CreateStructuredSignedInteger() const490fe013be4SDimitry Andric PythonInteger::CreateStructuredSignedInteger() const {
491fe013be4SDimitry Andric StructuredData::SignedIntegerSP result = nullptr;
492fe013be4SDimitry Andric llvm::Expected<long long> value = AsLongLong();
493fe013be4SDimitry Andric if (!value)
494fe013be4SDimitry Andric llvm::consumeError(value.takeError());
495fe013be4SDimitry Andric else
496fe013be4SDimitry Andric result = std::make_shared<StructuredData::SignedInteger>(value.get());
497fe013be4SDimitry Andric
4980b57cec5SDimitry Andric return result;
4990b57cec5SDimitry Andric }
5000b57cec5SDimitry Andric
5010b57cec5SDimitry Andric // PythonBoolean
5020b57cec5SDimitry Andric
PythonBoolean(bool value)5030b57cec5SDimitry Andric PythonBoolean::PythonBoolean(bool value) {
5040b57cec5SDimitry Andric SetValue(value);
5050b57cec5SDimitry Andric }
5060b57cec5SDimitry Andric
Check(PyObject * py_obj)5070b57cec5SDimitry Andric bool PythonBoolean::Check(PyObject *py_obj) {
5080b57cec5SDimitry Andric return py_obj ? PyBool_Check(py_obj) : false;
5090b57cec5SDimitry Andric }
5100b57cec5SDimitry Andric
GetValue() const5110b57cec5SDimitry Andric bool PythonBoolean::GetValue() const {
5120b57cec5SDimitry Andric return m_py_obj ? PyObject_IsTrue(m_py_obj) : false;
5130b57cec5SDimitry Andric }
5140b57cec5SDimitry Andric
SetValue(bool value)5150b57cec5SDimitry Andric void PythonBoolean::SetValue(bool value) {
5169dba64beSDimitry Andric *this = Take<PythonBoolean>(PyBool_FromLong(value));
5170b57cec5SDimitry Andric }
5180b57cec5SDimitry Andric
CreateStructuredBoolean() const5190b57cec5SDimitry Andric StructuredData::BooleanSP PythonBoolean::CreateStructuredBoolean() const {
5200b57cec5SDimitry Andric StructuredData::BooleanSP result(new StructuredData::Boolean);
5210b57cec5SDimitry Andric result->SetValue(GetValue());
5220b57cec5SDimitry Andric return result;
5230b57cec5SDimitry Andric }
5240b57cec5SDimitry Andric
5250b57cec5SDimitry Andric // PythonList
5260b57cec5SDimitry Andric
PythonList(PyInitialValue value)5279dba64beSDimitry Andric PythonList::PythonList(PyInitialValue value) {
5280b57cec5SDimitry Andric if (value == PyInitialValue::Empty)
5299dba64beSDimitry Andric *this = Take<PythonList>(PyList_New(0));
5300b57cec5SDimitry Andric }
5310b57cec5SDimitry Andric
PythonList(int list_size)5329dba64beSDimitry Andric PythonList::PythonList(int list_size) {
5339dba64beSDimitry Andric *this = Take<PythonList>(PyList_New(list_size));
5340b57cec5SDimitry Andric }
5350b57cec5SDimitry Andric
Check(PyObject * py_obj)5360b57cec5SDimitry Andric bool PythonList::Check(PyObject *py_obj) {
5370b57cec5SDimitry Andric if (!py_obj)
5380b57cec5SDimitry Andric return false;
5390b57cec5SDimitry Andric return PyList_Check(py_obj);
5400b57cec5SDimitry Andric }
5410b57cec5SDimitry Andric
GetSize() const5420b57cec5SDimitry Andric uint32_t PythonList::GetSize() const {
5430b57cec5SDimitry Andric if (IsValid())
5440b57cec5SDimitry Andric return PyList_GET_SIZE(m_py_obj);
5450b57cec5SDimitry Andric return 0;
5460b57cec5SDimitry Andric }
5470b57cec5SDimitry Andric
GetItemAtIndex(uint32_t index) const5480b57cec5SDimitry Andric PythonObject PythonList::GetItemAtIndex(uint32_t index) const {
5490b57cec5SDimitry Andric if (IsValid())
5500b57cec5SDimitry Andric return PythonObject(PyRefType::Borrowed, PyList_GetItem(m_py_obj, index));
5510b57cec5SDimitry Andric return PythonObject();
5520b57cec5SDimitry Andric }
5530b57cec5SDimitry Andric
SetItemAtIndex(uint32_t index,const PythonObject & object)5540b57cec5SDimitry Andric void PythonList::SetItemAtIndex(uint32_t index, const PythonObject &object) {
5550b57cec5SDimitry Andric if (IsAllocated() && object.IsValid()) {
5560b57cec5SDimitry Andric // PyList_SetItem is documented to "steal" a reference, so we need to
5570b57cec5SDimitry Andric // convert it to an owned reference by incrementing it.
5580b57cec5SDimitry Andric Py_INCREF(object.get());
5590b57cec5SDimitry Andric PyList_SetItem(m_py_obj, index, object.get());
5600b57cec5SDimitry Andric }
5610b57cec5SDimitry Andric }
5620b57cec5SDimitry Andric
AppendItem(const PythonObject & object)5630b57cec5SDimitry Andric void PythonList::AppendItem(const PythonObject &object) {
5640b57cec5SDimitry Andric if (IsAllocated() && object.IsValid()) {
5650b57cec5SDimitry Andric // `PyList_Append` does *not* steal a reference, so do not call `Py_INCREF`
5660b57cec5SDimitry Andric // here like we do with `PyList_SetItem`.
5670b57cec5SDimitry Andric PyList_Append(m_py_obj, object.get());
5680b57cec5SDimitry Andric }
5690b57cec5SDimitry Andric }
5700b57cec5SDimitry Andric
CreateStructuredArray() const5710b57cec5SDimitry Andric StructuredData::ArraySP PythonList::CreateStructuredArray() const {
5720b57cec5SDimitry Andric StructuredData::ArraySP result(new StructuredData::Array);
5730b57cec5SDimitry Andric uint32_t count = GetSize();
5740b57cec5SDimitry Andric for (uint32_t i = 0; i < count; ++i) {
5750b57cec5SDimitry Andric PythonObject obj = GetItemAtIndex(i);
5760b57cec5SDimitry Andric result->AddItem(obj.CreateStructuredObject());
5770b57cec5SDimitry Andric }
5780b57cec5SDimitry Andric return result;
5790b57cec5SDimitry Andric }
5800b57cec5SDimitry Andric
5810b57cec5SDimitry Andric // PythonTuple
5820b57cec5SDimitry Andric
PythonTuple(PyInitialValue value)5839dba64beSDimitry Andric PythonTuple::PythonTuple(PyInitialValue value) {
5840b57cec5SDimitry Andric if (value == PyInitialValue::Empty)
5859dba64beSDimitry Andric *this = Take<PythonTuple>(PyTuple_New(0));
5860b57cec5SDimitry Andric }
5870b57cec5SDimitry Andric
PythonTuple(int tuple_size)5889dba64beSDimitry Andric PythonTuple::PythonTuple(int tuple_size) {
5899dba64beSDimitry Andric *this = Take<PythonTuple>(PyTuple_New(tuple_size));
5900b57cec5SDimitry Andric }
5910b57cec5SDimitry Andric
PythonTuple(std::initializer_list<PythonObject> objects)5920b57cec5SDimitry Andric PythonTuple::PythonTuple(std::initializer_list<PythonObject> objects) {
5930b57cec5SDimitry Andric m_py_obj = PyTuple_New(objects.size());
5940b57cec5SDimitry Andric
5950b57cec5SDimitry Andric uint32_t idx = 0;
5960b57cec5SDimitry Andric for (auto object : objects) {
5970b57cec5SDimitry Andric if (object.IsValid())
5980b57cec5SDimitry Andric SetItemAtIndex(idx, object);
5990b57cec5SDimitry Andric idx++;
6000b57cec5SDimitry Andric }
6010b57cec5SDimitry Andric }
6020b57cec5SDimitry Andric
PythonTuple(std::initializer_list<PyObject * > objects)6030b57cec5SDimitry Andric PythonTuple::PythonTuple(std::initializer_list<PyObject *> objects) {
6040b57cec5SDimitry Andric m_py_obj = PyTuple_New(objects.size());
6050b57cec5SDimitry Andric
6060b57cec5SDimitry Andric uint32_t idx = 0;
6070b57cec5SDimitry Andric for (auto py_object : objects) {
6080b57cec5SDimitry Andric PythonObject object(PyRefType::Borrowed, py_object);
6090b57cec5SDimitry Andric if (object.IsValid())
6100b57cec5SDimitry Andric SetItemAtIndex(idx, object);
6110b57cec5SDimitry Andric idx++;
6120b57cec5SDimitry Andric }
6130b57cec5SDimitry Andric }
6140b57cec5SDimitry Andric
Check(PyObject * py_obj)6150b57cec5SDimitry Andric bool PythonTuple::Check(PyObject *py_obj) {
6160b57cec5SDimitry Andric if (!py_obj)
6170b57cec5SDimitry Andric return false;
6180b57cec5SDimitry Andric return PyTuple_Check(py_obj);
6190b57cec5SDimitry Andric }
6200b57cec5SDimitry Andric
GetSize() const6210b57cec5SDimitry Andric uint32_t PythonTuple::GetSize() const {
6220b57cec5SDimitry Andric if (IsValid())
6230b57cec5SDimitry Andric return PyTuple_GET_SIZE(m_py_obj);
6240b57cec5SDimitry Andric return 0;
6250b57cec5SDimitry Andric }
6260b57cec5SDimitry Andric
GetItemAtIndex(uint32_t index) const6270b57cec5SDimitry Andric PythonObject PythonTuple::GetItemAtIndex(uint32_t index) const {
6280b57cec5SDimitry Andric if (IsValid())
6290b57cec5SDimitry Andric return PythonObject(PyRefType::Borrowed, PyTuple_GetItem(m_py_obj, index));
6300b57cec5SDimitry Andric return PythonObject();
6310b57cec5SDimitry Andric }
6320b57cec5SDimitry Andric
SetItemAtIndex(uint32_t index,const PythonObject & object)6330b57cec5SDimitry Andric void PythonTuple::SetItemAtIndex(uint32_t index, const PythonObject &object) {
6340b57cec5SDimitry Andric if (IsAllocated() && object.IsValid()) {
6350b57cec5SDimitry Andric // PyTuple_SetItem is documented to "steal" a reference, so we need to
6360b57cec5SDimitry Andric // convert it to an owned reference by incrementing it.
6370b57cec5SDimitry Andric Py_INCREF(object.get());
6380b57cec5SDimitry Andric PyTuple_SetItem(m_py_obj, index, object.get());
6390b57cec5SDimitry Andric }
6400b57cec5SDimitry Andric }
6410b57cec5SDimitry Andric
CreateStructuredArray() const6420b57cec5SDimitry Andric StructuredData::ArraySP PythonTuple::CreateStructuredArray() const {
6430b57cec5SDimitry Andric StructuredData::ArraySP result(new StructuredData::Array);
6440b57cec5SDimitry Andric uint32_t count = GetSize();
6450b57cec5SDimitry Andric for (uint32_t i = 0; i < count; ++i) {
6460b57cec5SDimitry Andric PythonObject obj = GetItemAtIndex(i);
6470b57cec5SDimitry Andric result->AddItem(obj.CreateStructuredObject());
6480b57cec5SDimitry Andric }
6490b57cec5SDimitry Andric return result;
6500b57cec5SDimitry Andric }
6510b57cec5SDimitry Andric
6520b57cec5SDimitry Andric // PythonDictionary
6530b57cec5SDimitry Andric
PythonDictionary(PyInitialValue value)6549dba64beSDimitry Andric PythonDictionary::PythonDictionary(PyInitialValue value) {
6550b57cec5SDimitry Andric if (value == PyInitialValue::Empty)
6569dba64beSDimitry Andric *this = Take<PythonDictionary>(PyDict_New());
6570b57cec5SDimitry Andric }
6580b57cec5SDimitry Andric
Check(PyObject * py_obj)6590b57cec5SDimitry Andric bool PythonDictionary::Check(PyObject *py_obj) {
6600b57cec5SDimitry Andric if (!py_obj)
6610b57cec5SDimitry Andric return false;
6620b57cec5SDimitry Andric
6630b57cec5SDimitry Andric return PyDict_Check(py_obj);
6640b57cec5SDimitry Andric }
6650b57cec5SDimitry Andric
HasKey(const llvm::Twine & key) const666*c9157d92SDimitry Andric bool PythonDictionary::HasKey(const llvm::Twine &key) const {
667*c9157d92SDimitry Andric if (!IsValid())
668*c9157d92SDimitry Andric return false;
669*c9157d92SDimitry Andric
670*c9157d92SDimitry Andric PythonString key_object(key.isSingleStringRef() ? key.getSingleStringRef()
671*c9157d92SDimitry Andric : key.str());
672*c9157d92SDimitry Andric
673*c9157d92SDimitry Andric if (int res = PyDict_Contains(m_py_obj, key_object.get()) > 0)
674*c9157d92SDimitry Andric return res;
675*c9157d92SDimitry Andric
676*c9157d92SDimitry Andric PyErr_Print();
677*c9157d92SDimitry Andric return false;
678*c9157d92SDimitry Andric }
679*c9157d92SDimitry Andric
GetSize() const6800b57cec5SDimitry Andric uint32_t PythonDictionary::GetSize() const {
6810b57cec5SDimitry Andric if (IsValid())
6820b57cec5SDimitry Andric return PyDict_Size(m_py_obj);
6830b57cec5SDimitry Andric return 0;
6840b57cec5SDimitry Andric }
6850b57cec5SDimitry Andric
GetKeys() const6860b57cec5SDimitry Andric PythonList PythonDictionary::GetKeys() const {
6870b57cec5SDimitry Andric if (IsValid())
6880b57cec5SDimitry Andric return PythonList(PyRefType::Owned, PyDict_Keys(m_py_obj));
6890b57cec5SDimitry Andric return PythonList(PyInitialValue::Invalid);
6900b57cec5SDimitry Andric }
6910b57cec5SDimitry Andric
GetItemForKey(const PythonObject & key) const6920b57cec5SDimitry Andric PythonObject PythonDictionary::GetItemForKey(const PythonObject &key) const {
6939dba64beSDimitry Andric auto item = GetItem(key);
6949dba64beSDimitry Andric if (!item) {
6959dba64beSDimitry Andric llvm::consumeError(item.takeError());
6960b57cec5SDimitry Andric return PythonObject();
6970b57cec5SDimitry Andric }
6989dba64beSDimitry Andric return std::move(item.get());
6999dba64beSDimitry Andric }
7009dba64beSDimitry Andric
7019dba64beSDimitry Andric Expected<PythonObject>
GetItem(const PythonObject & key) const7029dba64beSDimitry Andric PythonDictionary::GetItem(const PythonObject &key) const {
7039dba64beSDimitry Andric if (!IsValid())
7049dba64beSDimitry Andric return nullDeref();
7059dba64beSDimitry Andric PyObject *o = PyDict_GetItemWithError(m_py_obj, key.get());
7069dba64beSDimitry Andric if (PyErr_Occurred())
7079dba64beSDimitry Andric return exception();
7089dba64beSDimitry Andric if (!o)
7099dba64beSDimitry Andric return keyError();
7109dba64beSDimitry Andric return Retain<PythonObject>(o);
7119dba64beSDimitry Andric }
7129dba64beSDimitry Andric
GetItem(const Twine & key) const7139dba64beSDimitry Andric Expected<PythonObject> PythonDictionary::GetItem(const Twine &key) const {
7149dba64beSDimitry Andric if (!IsValid())
7159dba64beSDimitry Andric return nullDeref();
7169dba64beSDimitry Andric PyObject *o = PyDict_GetItemString(m_py_obj, NullTerminated(key));
7179dba64beSDimitry Andric if (PyErr_Occurred())
7189dba64beSDimitry Andric return exception();
7199dba64beSDimitry Andric if (!o)
7209dba64beSDimitry Andric return keyError();
7219dba64beSDimitry Andric return Retain<PythonObject>(o);
7229dba64beSDimitry Andric }
7239dba64beSDimitry Andric
SetItem(const PythonObject & key,const PythonObject & value) const7249dba64beSDimitry Andric Error PythonDictionary::SetItem(const PythonObject &key,
7259dba64beSDimitry Andric const PythonObject &value) const {
7269dba64beSDimitry Andric if (!IsValid() || !value.IsValid())
7279dba64beSDimitry Andric return nullDeref();
7289dba64beSDimitry Andric int r = PyDict_SetItem(m_py_obj, key.get(), value.get());
7299dba64beSDimitry Andric if (r < 0)
7309dba64beSDimitry Andric return exception();
7319dba64beSDimitry Andric return Error::success();
7329dba64beSDimitry Andric }
7339dba64beSDimitry Andric
SetItem(const Twine & key,const PythonObject & value) const7349dba64beSDimitry Andric Error PythonDictionary::SetItem(const Twine &key,
7359dba64beSDimitry Andric const PythonObject &value) const {
7369dba64beSDimitry Andric if (!IsValid() || !value.IsValid())
7379dba64beSDimitry Andric return nullDeref();
7389dba64beSDimitry Andric int r = PyDict_SetItemString(m_py_obj, NullTerminated(key), value.get());
7399dba64beSDimitry Andric if (r < 0)
7409dba64beSDimitry Andric return exception();
7419dba64beSDimitry Andric return Error::success();
7429dba64beSDimitry Andric }
7430b57cec5SDimitry Andric
SetItemForKey(const PythonObject & key,const PythonObject & value)7440b57cec5SDimitry Andric void PythonDictionary::SetItemForKey(const PythonObject &key,
7450b57cec5SDimitry Andric const PythonObject &value) {
7469dba64beSDimitry Andric Error error = SetItem(key, value);
7479dba64beSDimitry Andric if (error)
7489dba64beSDimitry Andric llvm::consumeError(std::move(error));
7490b57cec5SDimitry Andric }
7500b57cec5SDimitry Andric
7510b57cec5SDimitry Andric StructuredData::DictionarySP
CreateStructuredDictionary() const7520b57cec5SDimitry Andric PythonDictionary::CreateStructuredDictionary() const {
7530b57cec5SDimitry Andric StructuredData::DictionarySP result(new StructuredData::Dictionary);
7540b57cec5SDimitry Andric PythonList keys(GetKeys());
7550b57cec5SDimitry Andric uint32_t num_keys = keys.GetSize();
7560b57cec5SDimitry Andric for (uint32_t i = 0; i < num_keys; ++i) {
7570b57cec5SDimitry Andric PythonObject key = keys.GetItemAtIndex(i);
7580b57cec5SDimitry Andric PythonObject value = GetItemForKey(key);
7590b57cec5SDimitry Andric StructuredData::ObjectSP structured_value = value.CreateStructuredObject();
7600b57cec5SDimitry Andric result->AddItem(key.Str().GetString(), structured_value);
7610b57cec5SDimitry Andric }
7620b57cec5SDimitry Andric return result;
7630b57cec5SDimitry Andric }
7640b57cec5SDimitry Andric
BuiltinsModule()76581ad6265SDimitry Andric PythonModule PythonModule::BuiltinsModule() { return AddModule("builtins"); }
7660b57cec5SDimitry Andric
MainModule()7670b57cec5SDimitry Andric PythonModule PythonModule::MainModule() { return AddModule("__main__"); }
7680b57cec5SDimitry Andric
AddModule(llvm::StringRef module)7690b57cec5SDimitry Andric PythonModule PythonModule::AddModule(llvm::StringRef module) {
7700b57cec5SDimitry Andric std::string str = module.str();
7710b57cec5SDimitry Andric return PythonModule(PyRefType::Borrowed, PyImport_AddModule(str.c_str()));
7720b57cec5SDimitry Andric }
7730b57cec5SDimitry Andric
Import(const Twine & name)7749dba64beSDimitry Andric Expected<PythonModule> PythonModule::Import(const Twine &name) {
7759dba64beSDimitry Andric PyObject *mod = PyImport_ImportModule(NullTerminated(name));
7769dba64beSDimitry Andric if (!mod)
7779dba64beSDimitry Andric return exception();
7789dba64beSDimitry Andric return Take<PythonModule>(mod);
7799dba64beSDimitry Andric }
7809dba64beSDimitry Andric
Get(const Twine & name)7819dba64beSDimitry Andric Expected<PythonObject> PythonModule::Get(const Twine &name) {
7829dba64beSDimitry Andric if (!IsValid())
7839dba64beSDimitry Andric return nullDeref();
7849dba64beSDimitry Andric PyObject *dict = PyModule_GetDict(m_py_obj);
7859dba64beSDimitry Andric if (!dict)
7869dba64beSDimitry Andric return exception();
7879dba64beSDimitry Andric PyObject *item = PyDict_GetItemString(dict, NullTerminated(name));
7889dba64beSDimitry Andric if (!item)
7899dba64beSDimitry Andric return exception();
7909dba64beSDimitry Andric return Retain<PythonObject>(item);
7910b57cec5SDimitry Andric }
7920b57cec5SDimitry Andric
Check(PyObject * py_obj)7930b57cec5SDimitry Andric bool PythonModule::Check(PyObject *py_obj) {
7940b57cec5SDimitry Andric if (!py_obj)
7950b57cec5SDimitry Andric return false;
7960b57cec5SDimitry Andric
7970b57cec5SDimitry Andric return PyModule_Check(py_obj);
7980b57cec5SDimitry Andric }
7990b57cec5SDimitry Andric
GetDictionary() const8000b57cec5SDimitry Andric PythonDictionary PythonModule::GetDictionary() const {
8019dba64beSDimitry Andric if (!IsValid())
8029dba64beSDimitry Andric return PythonDictionary();
8039dba64beSDimitry Andric return Retain<PythonDictionary>(PyModule_GetDict(m_py_obj));
8040b57cec5SDimitry Andric }
8050b57cec5SDimitry Andric
Check(PyObject * py_obj)8060b57cec5SDimitry Andric bool PythonCallable::Check(PyObject *py_obj) {
8070b57cec5SDimitry Andric if (!py_obj)
8080b57cec5SDimitry Andric return false;
8090b57cec5SDimitry Andric
8100b57cec5SDimitry Andric return PyCallable_Check(py_obj);
8110b57cec5SDimitry Andric }
8120b57cec5SDimitry Andric
8139dba64beSDimitry Andric #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3
8149dba64beSDimitry Andric static const char get_arg_info_script[] = R"(
8159dba64beSDimitry Andric from inspect import signature, Parameter, ismethod
8169dba64beSDimitry Andric from collections import namedtuple
817480093f4SDimitry Andric ArgInfo = namedtuple('ArgInfo', ['count', 'has_varargs'])
8189dba64beSDimitry Andric def main(f):
8199dba64beSDimitry Andric count = 0
8209dba64beSDimitry Andric varargs = False
8219dba64beSDimitry Andric for parameter in signature(f).parameters.values():
8229dba64beSDimitry Andric kind = parameter.kind
8239dba64beSDimitry Andric if kind in (Parameter.POSITIONAL_ONLY,
8249dba64beSDimitry Andric Parameter.POSITIONAL_OR_KEYWORD):
8259dba64beSDimitry Andric count += 1
8269dba64beSDimitry Andric elif kind == Parameter.VAR_POSITIONAL:
8279dba64beSDimitry Andric varargs = True
8289dba64beSDimitry Andric elif kind in (Parameter.KEYWORD_ONLY,
8299dba64beSDimitry Andric Parameter.VAR_KEYWORD):
8309dba64beSDimitry Andric pass
8319dba64beSDimitry Andric else:
8329dba64beSDimitry Andric raise Exception(f'unknown parameter kind: {kind}')
833480093f4SDimitry Andric return ArgInfo(count, varargs)
8349dba64beSDimitry Andric )";
8359dba64beSDimitry Andric #endif
8369dba64beSDimitry Andric
GetArgInfo() const8379dba64beSDimitry Andric Expected<PythonCallable::ArgInfo> PythonCallable::GetArgInfo() const {
8389dba64beSDimitry Andric ArgInfo result = {};
8399dba64beSDimitry Andric if (!IsValid())
8409dba64beSDimitry Andric return nullDeref();
8419dba64beSDimitry Andric
8429dba64beSDimitry Andric #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3
8439dba64beSDimitry Andric
8449dba64beSDimitry Andric // no need to synchronize access to this global, we already have the GIL
8459dba64beSDimitry Andric static PythonScript get_arg_info(get_arg_info_script);
8469dba64beSDimitry Andric Expected<PythonObject> pyarginfo = get_arg_info(*this);
8479dba64beSDimitry Andric if (!pyarginfo)
8489dba64beSDimitry Andric return pyarginfo.takeError();
849480093f4SDimitry Andric long long count =
850480093f4SDimitry Andric cantFail(As<long long>(pyarginfo.get().GetAttribute("count")));
851480093f4SDimitry Andric bool has_varargs =
8529dba64beSDimitry Andric cantFail(As<bool>(pyarginfo.get().GetAttribute("has_varargs")));
853480093f4SDimitry Andric result.max_positional_args = has_varargs ? ArgInfo::UNBOUNDED : count;
8549dba64beSDimitry Andric
8559dba64beSDimitry Andric #else
856480093f4SDimitry Andric PyObject *py_func_obj;
8579dba64beSDimitry Andric bool is_bound_method = false;
858480093f4SDimitry Andric bool is_class = false;
859480093f4SDimitry Andric
860480093f4SDimitry Andric if (PyType_Check(m_py_obj) || PyClass_Check(m_py_obj)) {
861480093f4SDimitry Andric auto init = GetAttribute("__init__");
862480093f4SDimitry Andric if (!init)
863480093f4SDimitry Andric return init.takeError();
864480093f4SDimitry Andric py_func_obj = init.get().get();
865480093f4SDimitry Andric is_class = true;
866480093f4SDimitry Andric } else {
867480093f4SDimitry Andric py_func_obj = m_py_obj;
868480093f4SDimitry Andric }
869480093f4SDimitry Andric
8700b57cec5SDimitry Andric if (PyMethod_Check(py_func_obj)) {
8710b57cec5SDimitry Andric py_func_obj = PyMethod_GET_FUNCTION(py_func_obj);
8720b57cec5SDimitry Andric PythonObject im_self = GetAttributeValue("im_self");
8730b57cec5SDimitry Andric if (im_self.IsValid() && !im_self.IsNone())
8749dba64beSDimitry Andric is_bound_method = true;
8750b57cec5SDimitry Andric } else {
8760b57cec5SDimitry Andric // see if this is a callable object with an __call__ method
8770b57cec5SDimitry Andric if (!PyFunction_Check(py_func_obj)) {
8780b57cec5SDimitry Andric PythonObject __call__ = GetAttributeValue("__call__");
8790b57cec5SDimitry Andric if (__call__.IsValid()) {
8800b57cec5SDimitry Andric auto __callable__ = __call__.AsType<PythonCallable>();
8810b57cec5SDimitry Andric if (__callable__.IsValid()) {
8820b57cec5SDimitry Andric py_func_obj = PyMethod_GET_FUNCTION(__callable__.get());
8839dba64beSDimitry Andric PythonObject im_self = __callable__.GetAttributeValue("im_self");
8840b57cec5SDimitry Andric if (im_self.IsValid() && !im_self.IsNone())
8859dba64beSDimitry Andric is_bound_method = true;
8860b57cec5SDimitry Andric }
8870b57cec5SDimitry Andric }
8880b57cec5SDimitry Andric }
8890b57cec5SDimitry Andric }
8900b57cec5SDimitry Andric
8910b57cec5SDimitry Andric if (!py_func_obj)
8920b57cec5SDimitry Andric return result;
8930b57cec5SDimitry Andric
8940b57cec5SDimitry Andric PyCodeObject *code = (PyCodeObject *)PyFunction_GET_CODE(py_func_obj);
8950b57cec5SDimitry Andric if (!code)
8960b57cec5SDimitry Andric return result;
8970b57cec5SDimitry Andric
898480093f4SDimitry Andric auto count = code->co_argcount;
899480093f4SDimitry Andric bool has_varargs = !!(code->co_flags & CO_VARARGS);
900480093f4SDimitry Andric result.max_positional_args =
901480093f4SDimitry Andric has_varargs ? ArgInfo::UNBOUNDED
902480093f4SDimitry Andric : (count - (int)is_bound_method) - (int)is_class;
9039dba64beSDimitry Andric
9049dba64beSDimitry Andric #endif
9059dba64beSDimitry Andric
9060b57cec5SDimitry Andric return result;
9070b57cec5SDimitry Andric }
9080b57cec5SDimitry Andric
9099dba64beSDimitry Andric constexpr unsigned
9109dba64beSDimitry Andric PythonCallable::ArgInfo::UNBOUNDED; // FIXME delete after c++17
9119dba64beSDimitry Andric
operator ()()9120b57cec5SDimitry Andric PythonObject PythonCallable::operator()() {
9130b57cec5SDimitry Andric return PythonObject(PyRefType::Owned, PyObject_CallObject(m_py_obj, nullptr));
9140b57cec5SDimitry Andric }
9150b57cec5SDimitry Andric
9160b57cec5SDimitry Andric PythonObject PythonCallable::
operator ()(std::initializer_list<PyObject * > args)9170b57cec5SDimitry Andric operator()(std::initializer_list<PyObject *> args) {
9180b57cec5SDimitry Andric PythonTuple arg_tuple(args);
9190b57cec5SDimitry Andric return PythonObject(PyRefType::Owned,
9200b57cec5SDimitry Andric PyObject_CallObject(m_py_obj, arg_tuple.get()));
9210b57cec5SDimitry Andric }
9220b57cec5SDimitry Andric
9230b57cec5SDimitry Andric PythonObject PythonCallable::
operator ()(std::initializer_list<PythonObject> args)9240b57cec5SDimitry Andric operator()(std::initializer_list<PythonObject> args) {
9250b57cec5SDimitry Andric PythonTuple arg_tuple(args);
9260b57cec5SDimitry Andric return PythonObject(PyRefType::Owned,
9270b57cec5SDimitry Andric PyObject_CallObject(m_py_obj, arg_tuple.get()));
9280b57cec5SDimitry Andric }
9290b57cec5SDimitry Andric
Check(PyObject * py_obj)9300b57cec5SDimitry Andric bool PythonFile::Check(PyObject *py_obj) {
9319dba64beSDimitry Andric if (!py_obj)
9329dba64beSDimitry Andric return false;
9330b57cec5SDimitry Andric // In Python 3, there is no `PyFile_Check`, and in fact PyFile is not even a
9340b57cec5SDimitry Andric // first-class object type anymore. `PyFile_FromFd` is just a thin wrapper
9350b57cec5SDimitry Andric // over `io.open()`, which returns some object derived from `io.IOBase`. As a
9360b57cec5SDimitry Andric // result, the only way to detect a file in Python 3 is to check whether it
9379dba64beSDimitry Andric // inherits from `io.IOBase`.
9389dba64beSDimitry Andric auto io_module = PythonModule::Import("io");
9399dba64beSDimitry Andric if (!io_module) {
9409dba64beSDimitry Andric llvm::consumeError(io_module.takeError());
9410b57cec5SDimitry Andric return false;
9429dba64beSDimitry Andric }
9439dba64beSDimitry Andric auto iobase = io_module.get().Get("IOBase");
9449dba64beSDimitry Andric if (!iobase) {
9459dba64beSDimitry Andric llvm::consumeError(iobase.takeError());
9460b57cec5SDimitry Andric return false;
9479dba64beSDimitry Andric }
9489dba64beSDimitry Andric int r = PyObject_IsInstance(py_obj, iobase.get().get());
9499dba64beSDimitry Andric if (r < 0) {
9509dba64beSDimitry Andric llvm::consumeError(exception()); // clear the exception and log it.
9519dba64beSDimitry Andric return false;
9529dba64beSDimitry Andric }
9539dba64beSDimitry Andric return !!r;
9540b57cec5SDimitry Andric }
9550b57cec5SDimitry Andric
toCString() const9569dba64beSDimitry Andric const char *PythonException::toCString() const {
9579dba64beSDimitry Andric if (!m_repr_bytes)
9589dba64beSDimitry Andric return "unknown exception";
9599dba64beSDimitry Andric return PyBytes_AS_STRING(m_repr_bytes);
9600b57cec5SDimitry Andric }
9610b57cec5SDimitry Andric
PythonException(const char * caller)9629dba64beSDimitry Andric PythonException::PythonException(const char *caller) {
9639dba64beSDimitry Andric assert(PyErr_Occurred());
964bdd1243dSDimitry Andric m_exception_type = m_exception = m_traceback = m_repr_bytes = nullptr;
9659dba64beSDimitry Andric PyErr_Fetch(&m_exception_type, &m_exception, &m_traceback);
9669dba64beSDimitry Andric PyErr_NormalizeException(&m_exception_type, &m_exception, &m_traceback);
9679dba64beSDimitry Andric PyErr_Clear();
9689dba64beSDimitry Andric if (m_exception) {
9699dba64beSDimitry Andric PyObject *repr = PyObject_Repr(m_exception);
9709dba64beSDimitry Andric if (repr) {
9719dba64beSDimitry Andric m_repr_bytes = PyUnicode_AsEncodedString(repr, "utf-8", nullptr);
9729dba64beSDimitry Andric if (!m_repr_bytes) {
9739dba64beSDimitry Andric PyErr_Clear();
9749dba64beSDimitry Andric }
9759dba64beSDimitry Andric Py_XDECREF(repr);
9769dba64beSDimitry Andric } else {
9779dba64beSDimitry Andric PyErr_Clear();
9789dba64beSDimitry Andric }
9799dba64beSDimitry Andric }
98081ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Script);
9819dba64beSDimitry Andric if (caller)
9829dba64beSDimitry Andric LLDB_LOGF(log, "%s failed with exception: %s", caller, toCString());
9839dba64beSDimitry Andric else
9849dba64beSDimitry Andric LLDB_LOGF(log, "python exception: %s", toCString());
9859dba64beSDimitry Andric }
Restore()9869dba64beSDimitry Andric void PythonException::Restore() {
9879dba64beSDimitry Andric if (m_exception_type && m_exception) {
9889dba64beSDimitry Andric PyErr_Restore(m_exception_type, m_exception, m_traceback);
9899dba64beSDimitry Andric } else {
9909dba64beSDimitry Andric PyErr_SetString(PyExc_Exception, toCString());
9919dba64beSDimitry Andric }
992bdd1243dSDimitry Andric m_exception_type = m_exception = m_traceback = nullptr;
9930b57cec5SDimitry Andric }
9940b57cec5SDimitry Andric
~PythonException()9959dba64beSDimitry Andric PythonException::~PythonException() {
9969dba64beSDimitry Andric Py_XDECREF(m_exception_type);
9979dba64beSDimitry Andric Py_XDECREF(m_exception);
9989dba64beSDimitry Andric Py_XDECREF(m_traceback);
9999dba64beSDimitry Andric Py_XDECREF(m_repr_bytes);
10000b57cec5SDimitry Andric }
10010b57cec5SDimitry Andric
log(llvm::raw_ostream & OS) const10029dba64beSDimitry Andric void PythonException::log(llvm::raw_ostream &OS) const { OS << toCString(); }
10039dba64beSDimitry Andric
convertToErrorCode() const10049dba64beSDimitry Andric std::error_code PythonException::convertToErrorCode() const {
10059dba64beSDimitry Andric return llvm::inconvertibleErrorCode();
10069dba64beSDimitry Andric }
10079dba64beSDimitry Andric
Matches(PyObject * exc) const10089dba64beSDimitry Andric bool PythonException::Matches(PyObject *exc) const {
10099dba64beSDimitry Andric return PyErr_GivenExceptionMatches(m_exception_type, exc);
10109dba64beSDimitry Andric }
10119dba64beSDimitry Andric
10129dba64beSDimitry Andric const char read_exception_script[] = R"(
10139dba64beSDimitry Andric import sys
10149dba64beSDimitry Andric from traceback import print_exception
10159dba64beSDimitry Andric if sys.version_info.major < 3:
10169dba64beSDimitry Andric from StringIO import StringIO
10179dba64beSDimitry Andric else:
10189dba64beSDimitry Andric from io import StringIO
10199dba64beSDimitry Andric def main(exc_type, exc_value, tb):
10209dba64beSDimitry Andric f = StringIO()
10219dba64beSDimitry Andric print_exception(exc_type, exc_value, tb, file=f)
10229dba64beSDimitry Andric return f.getvalue()
10239dba64beSDimitry Andric )";
10249dba64beSDimitry Andric
ReadBacktrace() const10259dba64beSDimitry Andric std::string PythonException::ReadBacktrace() const {
10269dba64beSDimitry Andric
10279dba64beSDimitry Andric if (!m_traceback)
10289dba64beSDimitry Andric return toCString();
10299dba64beSDimitry Andric
10309dba64beSDimitry Andric // no need to synchronize access to this global, we already have the GIL
10319dba64beSDimitry Andric static PythonScript read_exception(read_exception_script);
10329dba64beSDimitry Andric
10339dba64beSDimitry Andric Expected<std::string> backtrace = As<std::string>(
10349dba64beSDimitry Andric read_exception(m_exception_type, m_exception, m_traceback));
10359dba64beSDimitry Andric
10369dba64beSDimitry Andric if (!backtrace) {
10379dba64beSDimitry Andric std::string message =
10389dba64beSDimitry Andric std::string(toCString()) + "\n" +
10395ffd83dbSDimitry Andric "Traceback unavailable, an error occurred while reading it:\n";
10409dba64beSDimitry Andric return (message + llvm::toString(backtrace.takeError()));
10419dba64beSDimitry Andric }
10429dba64beSDimitry Andric
10439dba64beSDimitry Andric return std::move(backtrace.get());
10449dba64beSDimitry Andric }
10459dba64beSDimitry Andric
10469dba64beSDimitry Andric char PythonException::ID = 0;
10479dba64beSDimitry Andric
10489dba64beSDimitry Andric llvm::Expected<File::OpenOptions>
GetOptionsForPyObject(const PythonObject & obj)10499dba64beSDimitry Andric GetOptionsForPyObject(const PythonObject &obj) {
10509dba64beSDimitry Andric auto options = File::OpenOptions(0);
10519dba64beSDimitry Andric auto readable = As<bool>(obj.CallMethod("readable"));
10529dba64beSDimitry Andric if (!readable)
10539dba64beSDimitry Andric return readable.takeError();
10549dba64beSDimitry Andric auto writable = As<bool>(obj.CallMethod("writable"));
10559dba64beSDimitry Andric if (!writable)
10569dba64beSDimitry Andric return writable.takeError();
1057349cc55cSDimitry Andric if (readable.get() && writable.get())
1058349cc55cSDimitry Andric options |= File::eOpenOptionReadWrite;
1059349cc55cSDimitry Andric else if (writable.get())
1060349cc55cSDimitry Andric options |= File::eOpenOptionWriteOnly;
1061349cc55cSDimitry Andric else if (readable.get())
1062349cc55cSDimitry Andric options |= File::eOpenOptionReadOnly;
10639dba64beSDimitry Andric return options;
10649dba64beSDimitry Andric }
10659dba64beSDimitry Andric
10669dba64beSDimitry Andric // Base class template for python files. All it knows how to do
10679dba64beSDimitry Andric // is hold a reference to the python object and close or flush it
10689dba64beSDimitry Andric // when the File is closed.
10699dba64beSDimitry Andric namespace {
10709dba64beSDimitry Andric template <typename Base> class OwnedPythonFile : public Base {
10719dba64beSDimitry Andric public:
10729dba64beSDimitry Andric template <typename... Args>
OwnedPythonFile(const PythonFile & file,bool borrowed,Args...args)10739dba64beSDimitry Andric OwnedPythonFile(const PythonFile &file, bool borrowed, Args... args)
10749dba64beSDimitry Andric : Base(args...), m_py_obj(file), m_borrowed(borrowed) {
10759dba64beSDimitry Andric assert(m_py_obj);
10769dba64beSDimitry Andric }
10779dba64beSDimitry Andric
~OwnedPythonFile()10789dba64beSDimitry Andric ~OwnedPythonFile() override {
10799dba64beSDimitry Andric assert(m_py_obj);
10809dba64beSDimitry Andric GIL takeGIL;
10819dba64beSDimitry Andric Close();
10829dba64beSDimitry Andric // we need to ensure the python object is released while we still
10839dba64beSDimitry Andric // hold the GIL
10849dba64beSDimitry Andric m_py_obj.Reset();
10859dba64beSDimitry Andric }
10869dba64beSDimitry Andric
IsPythonSideValid() const10879dba64beSDimitry Andric bool IsPythonSideValid() const {
10889dba64beSDimitry Andric GIL takeGIL;
10899dba64beSDimitry Andric auto closed = As<bool>(m_py_obj.GetAttribute("closed"));
10909dba64beSDimitry Andric if (!closed) {
10919dba64beSDimitry Andric llvm::consumeError(closed.takeError());
10929dba64beSDimitry Andric return false;
10939dba64beSDimitry Andric }
10949dba64beSDimitry Andric return !closed.get();
10959dba64beSDimitry Andric }
10969dba64beSDimitry Andric
IsValid() const10979dba64beSDimitry Andric bool IsValid() const override {
10989dba64beSDimitry Andric return IsPythonSideValid() && Base::IsValid();
10999dba64beSDimitry Andric }
11009dba64beSDimitry Andric
Close()11019dba64beSDimitry Andric Status Close() override {
11029dba64beSDimitry Andric assert(m_py_obj);
11039dba64beSDimitry Andric Status py_error, base_error;
11049dba64beSDimitry Andric GIL takeGIL;
11059dba64beSDimitry Andric if (!m_borrowed) {
11069dba64beSDimitry Andric auto r = m_py_obj.CallMethod("close");
11079dba64beSDimitry Andric if (!r)
11089dba64beSDimitry Andric py_error = Status(r.takeError());
11099dba64beSDimitry Andric }
11109dba64beSDimitry Andric base_error = Base::Close();
11119dba64beSDimitry Andric if (py_error.Fail())
11129dba64beSDimitry Andric return py_error;
11139dba64beSDimitry Andric return base_error;
11149dba64beSDimitry Andric };
11159dba64beSDimitry Andric
GetPythonObject() const11169dba64beSDimitry Andric PyObject *GetPythonObject() const {
11179dba64beSDimitry Andric assert(m_py_obj.IsValid());
11189dba64beSDimitry Andric return m_py_obj.get();
11199dba64beSDimitry Andric }
11209dba64beSDimitry Andric
11219dba64beSDimitry Andric static bool classof(const File *file) = delete;
11229dba64beSDimitry Andric
11239dba64beSDimitry Andric protected:
11249dba64beSDimitry Andric PythonFile m_py_obj;
11259dba64beSDimitry Andric bool m_borrowed;
11269dba64beSDimitry Andric };
11279dba64beSDimitry Andric } // namespace
11289dba64beSDimitry Andric
11299dba64beSDimitry Andric // A SimplePythonFile is a OwnedPythonFile that just does all I/O as
11309dba64beSDimitry Andric // a NativeFile
11319dba64beSDimitry Andric namespace {
11329dba64beSDimitry Andric class SimplePythonFile : public OwnedPythonFile<NativeFile> {
11339dba64beSDimitry Andric public:
SimplePythonFile(const PythonFile & file,bool borrowed,int fd,File::OpenOptions options)11349dba64beSDimitry Andric SimplePythonFile(const PythonFile &file, bool borrowed, int fd,
11359dba64beSDimitry Andric File::OpenOptions options)
11369dba64beSDimitry Andric : OwnedPythonFile(file, borrowed, fd, options, false) {}
11379dba64beSDimitry Andric
11389dba64beSDimitry Andric static char ID;
isA(const void * classID) const11399dba64beSDimitry Andric bool isA(const void *classID) const override {
11409dba64beSDimitry Andric return classID == &ID || NativeFile::isA(classID);
11419dba64beSDimitry Andric }
classof(const File * file)11429dba64beSDimitry Andric static bool classof(const File *file) { return file->isA(&ID); }
11439dba64beSDimitry Andric };
11449dba64beSDimitry Andric char SimplePythonFile::ID = 0;
11459dba64beSDimitry Andric } // namespace
11469dba64beSDimitry Andric
11479dba64beSDimitry Andric namespace {
11489dba64beSDimitry Andric class PythonBuffer {
11499dba64beSDimitry Andric public:
11509dba64beSDimitry Andric PythonBuffer &operator=(const PythonBuffer &) = delete;
11519dba64beSDimitry Andric PythonBuffer(const PythonBuffer &) = delete;
11529dba64beSDimitry Andric
Create(PythonObject & obj,int flags=PyBUF_SIMPLE)11539dba64beSDimitry Andric static Expected<PythonBuffer> Create(PythonObject &obj,
11549dba64beSDimitry Andric int flags = PyBUF_SIMPLE) {
11559dba64beSDimitry Andric Py_buffer py_buffer = {};
11569dba64beSDimitry Andric PyObject_GetBuffer(obj.get(), &py_buffer, flags);
11579dba64beSDimitry Andric if (!py_buffer.obj)
11589dba64beSDimitry Andric return llvm::make_error<PythonException>();
11599dba64beSDimitry Andric return PythonBuffer(py_buffer);
11609dba64beSDimitry Andric }
11619dba64beSDimitry Andric
PythonBuffer(PythonBuffer && other)11629dba64beSDimitry Andric PythonBuffer(PythonBuffer &&other) {
11639dba64beSDimitry Andric m_buffer = other.m_buffer;
11649dba64beSDimitry Andric other.m_buffer.obj = nullptr;
11659dba64beSDimitry Andric }
11669dba64beSDimitry Andric
~PythonBuffer()11679dba64beSDimitry Andric ~PythonBuffer() {
11689dba64beSDimitry Andric if (m_buffer.obj)
11699dba64beSDimitry Andric PyBuffer_Release(&m_buffer);
11709dba64beSDimitry Andric }
11719dba64beSDimitry Andric
get()11729dba64beSDimitry Andric Py_buffer &get() { return m_buffer; }
11739dba64beSDimitry Andric
11749dba64beSDimitry Andric private:
11759dba64beSDimitry Andric // takes ownership of the buffer.
PythonBuffer(const Py_buffer & py_buffer)11769dba64beSDimitry Andric PythonBuffer(const Py_buffer &py_buffer) : m_buffer(py_buffer) {}
11779dba64beSDimitry Andric Py_buffer m_buffer;
11789dba64beSDimitry Andric };
11799dba64beSDimitry Andric } // namespace
11809dba64beSDimitry Andric
11819dba64beSDimitry Andric // Shared methods between TextPythonFile and BinaryPythonFile
11829dba64beSDimitry Andric namespace {
11839dba64beSDimitry Andric class PythonIOFile : public OwnedPythonFile<File> {
11849dba64beSDimitry Andric public:
PythonIOFile(const PythonFile & file,bool borrowed)11859dba64beSDimitry Andric PythonIOFile(const PythonFile &file, bool borrowed)
11869dba64beSDimitry Andric : OwnedPythonFile(file, borrowed) {}
11879dba64beSDimitry Andric
~PythonIOFile()11889dba64beSDimitry Andric ~PythonIOFile() override { Close(); }
11899dba64beSDimitry Andric
IsValid() const11909dba64beSDimitry Andric bool IsValid() const override { return IsPythonSideValid(); }
11919dba64beSDimitry Andric
Close()11929dba64beSDimitry Andric Status Close() override {
11939dba64beSDimitry Andric assert(m_py_obj);
11949dba64beSDimitry Andric GIL takeGIL;
11959dba64beSDimitry Andric if (m_borrowed)
11969dba64beSDimitry Andric return Flush();
11979dba64beSDimitry Andric auto r = m_py_obj.CallMethod("close");
11989dba64beSDimitry Andric if (!r)
11999dba64beSDimitry Andric return Status(r.takeError());
12009dba64beSDimitry Andric return Status();
12019dba64beSDimitry Andric }
12029dba64beSDimitry Andric
Flush()12039dba64beSDimitry Andric Status Flush() override {
12049dba64beSDimitry Andric GIL takeGIL;
12059dba64beSDimitry Andric auto r = m_py_obj.CallMethod("flush");
12069dba64beSDimitry Andric if (!r)
12079dba64beSDimitry Andric return Status(r.takeError());
12089dba64beSDimitry Andric return Status();
12099dba64beSDimitry Andric }
12109dba64beSDimitry Andric
GetOptions() const12119dba64beSDimitry Andric Expected<File::OpenOptions> GetOptions() const override {
12129dba64beSDimitry Andric GIL takeGIL;
12139dba64beSDimitry Andric return GetOptionsForPyObject(m_py_obj);
12149dba64beSDimitry Andric }
12159dba64beSDimitry Andric
12169dba64beSDimitry Andric static char ID;
isA(const void * classID) const12179dba64beSDimitry Andric bool isA(const void *classID) const override {
12189dba64beSDimitry Andric return classID == &ID || File::isA(classID);
12199dba64beSDimitry Andric }
classof(const File * file)12209dba64beSDimitry Andric static bool classof(const File *file) { return file->isA(&ID); }
12219dba64beSDimitry Andric };
12229dba64beSDimitry Andric char PythonIOFile::ID = 0;
12239dba64beSDimitry Andric } // namespace
12249dba64beSDimitry Andric
12259dba64beSDimitry Andric namespace {
12269dba64beSDimitry Andric class BinaryPythonFile : public PythonIOFile {
12279dba64beSDimitry Andric protected:
12289dba64beSDimitry Andric int m_descriptor;
12299dba64beSDimitry Andric
12309dba64beSDimitry Andric public:
BinaryPythonFile(int fd,const PythonFile & file,bool borrowed)12319dba64beSDimitry Andric BinaryPythonFile(int fd, const PythonFile &file, bool borrowed)
12329dba64beSDimitry Andric : PythonIOFile(file, borrowed),
12339dba64beSDimitry Andric m_descriptor(File::DescriptorIsValid(fd) ? fd
12349dba64beSDimitry Andric : File::kInvalidDescriptor) {}
12359dba64beSDimitry Andric
GetDescriptor() const12369dba64beSDimitry Andric int GetDescriptor() const override { return m_descriptor; }
12379dba64beSDimitry Andric
Write(const void * buf,size_t & num_bytes)12389dba64beSDimitry Andric Status Write(const void *buf, size_t &num_bytes) override {
12399dba64beSDimitry Andric GIL takeGIL;
12409dba64beSDimitry Andric PyObject *pybuffer_p = PyMemoryView_FromMemory(
12419dba64beSDimitry Andric const_cast<char *>((const char *)buf), num_bytes, PyBUF_READ);
12429dba64beSDimitry Andric if (!pybuffer_p)
12439dba64beSDimitry Andric return Status(llvm::make_error<PythonException>());
12449dba64beSDimitry Andric auto pybuffer = Take<PythonObject>(pybuffer_p);
12459dba64beSDimitry Andric num_bytes = 0;
12469dba64beSDimitry Andric auto bytes_written = As<long long>(m_py_obj.CallMethod("write", pybuffer));
12479dba64beSDimitry Andric if (!bytes_written)
12489dba64beSDimitry Andric return Status(bytes_written.takeError());
12499dba64beSDimitry Andric if (bytes_written.get() < 0)
12509dba64beSDimitry Andric return Status(".write() method returned a negative number!");
12519dba64beSDimitry Andric static_assert(sizeof(long long) >= sizeof(size_t), "overflow");
12529dba64beSDimitry Andric num_bytes = bytes_written.get();
12539dba64beSDimitry Andric return Status();
12549dba64beSDimitry Andric }
12559dba64beSDimitry Andric
Read(void * buf,size_t & num_bytes)12569dba64beSDimitry Andric Status Read(void *buf, size_t &num_bytes) override {
12579dba64beSDimitry Andric GIL takeGIL;
12589dba64beSDimitry Andric static_assert(sizeof(long long) >= sizeof(size_t), "overflow");
12599dba64beSDimitry Andric auto pybuffer_obj =
12609dba64beSDimitry Andric m_py_obj.CallMethod("read", (unsigned long long)num_bytes);
12619dba64beSDimitry Andric if (!pybuffer_obj)
12629dba64beSDimitry Andric return Status(pybuffer_obj.takeError());
12639dba64beSDimitry Andric num_bytes = 0;
12649dba64beSDimitry Andric if (pybuffer_obj.get().IsNone()) {
12659dba64beSDimitry Andric // EOF
12669dba64beSDimitry Andric num_bytes = 0;
12679dba64beSDimitry Andric return Status();
12689dba64beSDimitry Andric }
12699dba64beSDimitry Andric auto pybuffer = PythonBuffer::Create(pybuffer_obj.get());
12709dba64beSDimitry Andric if (!pybuffer)
12719dba64beSDimitry Andric return Status(pybuffer.takeError());
12729dba64beSDimitry Andric memcpy(buf, pybuffer.get().get().buf, pybuffer.get().get().len);
12739dba64beSDimitry Andric num_bytes = pybuffer.get().get().len;
12749dba64beSDimitry Andric return Status();
12759dba64beSDimitry Andric }
12769dba64beSDimitry Andric };
12779dba64beSDimitry Andric } // namespace
12789dba64beSDimitry Andric
12799dba64beSDimitry Andric namespace {
12809dba64beSDimitry Andric class TextPythonFile : public PythonIOFile {
12819dba64beSDimitry Andric protected:
12829dba64beSDimitry Andric int m_descriptor;
12839dba64beSDimitry Andric
12849dba64beSDimitry Andric public:
TextPythonFile(int fd,const PythonFile & file,bool borrowed)12859dba64beSDimitry Andric TextPythonFile(int fd, const PythonFile &file, bool borrowed)
12869dba64beSDimitry Andric : PythonIOFile(file, borrowed),
12879dba64beSDimitry Andric m_descriptor(File::DescriptorIsValid(fd) ? fd
12889dba64beSDimitry Andric : File::kInvalidDescriptor) {}
12899dba64beSDimitry Andric
GetDescriptor() const12909dba64beSDimitry Andric int GetDescriptor() const override { return m_descriptor; }
12919dba64beSDimitry Andric
Write(const void * buf,size_t & num_bytes)12929dba64beSDimitry Andric Status Write(const void *buf, size_t &num_bytes) override {
12939dba64beSDimitry Andric GIL takeGIL;
12949dba64beSDimitry Andric auto pystring =
12959dba64beSDimitry Andric PythonString::FromUTF8(llvm::StringRef((const char *)buf, num_bytes));
12969dba64beSDimitry Andric if (!pystring)
12979dba64beSDimitry Andric return Status(pystring.takeError());
12989dba64beSDimitry Andric num_bytes = 0;
12999dba64beSDimitry Andric auto bytes_written =
13009dba64beSDimitry Andric As<long long>(m_py_obj.CallMethod("write", pystring.get()));
13019dba64beSDimitry Andric if (!bytes_written)
13029dba64beSDimitry Andric return Status(bytes_written.takeError());
13039dba64beSDimitry Andric if (bytes_written.get() < 0)
13049dba64beSDimitry Andric return Status(".write() method returned a negative number!");
13059dba64beSDimitry Andric static_assert(sizeof(long long) >= sizeof(size_t), "overflow");
13069dba64beSDimitry Andric num_bytes = bytes_written.get();
13079dba64beSDimitry Andric return Status();
13089dba64beSDimitry Andric }
13099dba64beSDimitry Andric
Read(void * buf,size_t & num_bytes)13109dba64beSDimitry Andric Status Read(void *buf, size_t &num_bytes) override {
13119dba64beSDimitry Andric GIL takeGIL;
13129dba64beSDimitry Andric size_t num_chars = num_bytes / 6;
13139dba64beSDimitry Andric size_t orig_num_bytes = num_bytes;
13149dba64beSDimitry Andric num_bytes = 0;
13159dba64beSDimitry Andric if (orig_num_bytes < 6) {
13169dba64beSDimitry Andric return Status("can't read less than 6 bytes from a utf8 text stream");
13179dba64beSDimitry Andric }
13189dba64beSDimitry Andric auto pystring = As<PythonString>(
13199dba64beSDimitry Andric m_py_obj.CallMethod("read", (unsigned long long)num_chars));
13209dba64beSDimitry Andric if (!pystring)
13219dba64beSDimitry Andric return Status(pystring.takeError());
13229dba64beSDimitry Andric if (pystring.get().IsNone()) {
13239dba64beSDimitry Andric // EOF
13249dba64beSDimitry Andric return Status();
13259dba64beSDimitry Andric }
13269dba64beSDimitry Andric auto stringref = pystring.get().AsUTF8();
13279dba64beSDimitry Andric if (!stringref)
13289dba64beSDimitry Andric return Status(stringref.takeError());
13299dba64beSDimitry Andric num_bytes = stringref.get().size();
13309dba64beSDimitry Andric memcpy(buf, stringref.get().begin(), num_bytes);
13319dba64beSDimitry Andric return Status();
13329dba64beSDimitry Andric }
13339dba64beSDimitry Andric };
13349dba64beSDimitry Andric } // namespace
13359dba64beSDimitry Andric
ConvertToFile(bool borrowed)13369dba64beSDimitry Andric llvm::Expected<FileSP> PythonFile::ConvertToFile(bool borrowed) {
13379dba64beSDimitry Andric if (!IsValid())
13389dba64beSDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(),
13399dba64beSDimitry Andric "invalid PythonFile");
13409dba64beSDimitry Andric
13419dba64beSDimitry Andric int fd = PyObject_AsFileDescriptor(m_py_obj);
13429dba64beSDimitry Andric if (fd < 0) {
13439dba64beSDimitry Andric PyErr_Clear();
13449dba64beSDimitry Andric return ConvertToFileForcingUseOfScriptingIOMethods(borrowed);
13459dba64beSDimitry Andric }
13469dba64beSDimitry Andric auto options = GetOptionsForPyObject(*this);
13479dba64beSDimitry Andric if (!options)
13489dba64beSDimitry Andric return options.takeError();
13499dba64beSDimitry Andric
1350349cc55cSDimitry Andric File::OpenOptions rw =
1351349cc55cSDimitry Andric options.get() & (File::eOpenOptionReadOnly | File::eOpenOptionWriteOnly |
1352349cc55cSDimitry Andric File::eOpenOptionReadWrite);
1353349cc55cSDimitry Andric if (rw == File::eOpenOptionWriteOnly || rw == File::eOpenOptionReadWrite) {
13549dba64beSDimitry Andric // LLDB and python will not share I/O buffers. We should probably
13559dba64beSDimitry Andric // flush the python buffers now.
13569dba64beSDimitry Andric auto r = CallMethod("flush");
13579dba64beSDimitry Andric if (!r)
13589dba64beSDimitry Andric return r.takeError();
1359480093f4SDimitry Andric }
13609dba64beSDimitry Andric
13619dba64beSDimitry Andric FileSP file_sp;
13629dba64beSDimitry Andric if (borrowed) {
1363*c9157d92SDimitry Andric // In this case we don't need to retain the python
13649dba64beSDimitry Andric // object at all.
13659dba64beSDimitry Andric file_sp = std::make_shared<NativeFile>(fd, options.get(), false);
13669dba64beSDimitry Andric } else {
13679dba64beSDimitry Andric file_sp = std::static_pointer_cast<File>(
13689dba64beSDimitry Andric std::make_shared<SimplePythonFile>(*this, borrowed, fd, options.get()));
13699dba64beSDimitry Andric }
13709dba64beSDimitry Andric if (!file_sp->IsValid())
13719dba64beSDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(),
13729dba64beSDimitry Andric "invalid File");
13739dba64beSDimitry Andric
13749dba64beSDimitry Andric return file_sp;
13759dba64beSDimitry Andric }
13769dba64beSDimitry Andric
13779dba64beSDimitry Andric llvm::Expected<FileSP>
ConvertToFileForcingUseOfScriptingIOMethods(bool borrowed)13789dba64beSDimitry Andric PythonFile::ConvertToFileForcingUseOfScriptingIOMethods(bool borrowed) {
13799dba64beSDimitry Andric
13809dba64beSDimitry Andric assert(!PyErr_Occurred());
13819dba64beSDimitry Andric
13829dba64beSDimitry Andric if (!IsValid())
13839dba64beSDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(),
13849dba64beSDimitry Andric "invalid PythonFile");
13859dba64beSDimitry Andric
13869dba64beSDimitry Andric int fd = PyObject_AsFileDescriptor(m_py_obj);
13879dba64beSDimitry Andric if (fd < 0) {
13889dba64beSDimitry Andric PyErr_Clear();
13899dba64beSDimitry Andric fd = File::kInvalidDescriptor;
13909dba64beSDimitry Andric }
13919dba64beSDimitry Andric
13929dba64beSDimitry Andric auto io_module = PythonModule::Import("io");
13939dba64beSDimitry Andric if (!io_module)
13949dba64beSDimitry Andric return io_module.takeError();
13959dba64beSDimitry Andric auto textIOBase = io_module.get().Get("TextIOBase");
13969dba64beSDimitry Andric if (!textIOBase)
13979dba64beSDimitry Andric return textIOBase.takeError();
13989dba64beSDimitry Andric auto rawIOBase = io_module.get().Get("RawIOBase");
13999dba64beSDimitry Andric if (!rawIOBase)
14009dba64beSDimitry Andric return rawIOBase.takeError();
14019dba64beSDimitry Andric auto bufferedIOBase = io_module.get().Get("BufferedIOBase");
14029dba64beSDimitry Andric if (!bufferedIOBase)
14039dba64beSDimitry Andric return bufferedIOBase.takeError();
14049dba64beSDimitry Andric
14059dba64beSDimitry Andric FileSP file_sp;
14069dba64beSDimitry Andric
14079dba64beSDimitry Andric auto isTextIO = IsInstance(textIOBase.get());
14089dba64beSDimitry Andric if (!isTextIO)
14099dba64beSDimitry Andric return isTextIO.takeError();
14109dba64beSDimitry Andric if (isTextIO.get())
14119dba64beSDimitry Andric file_sp = std::static_pointer_cast<File>(
14129dba64beSDimitry Andric std::make_shared<TextPythonFile>(fd, *this, borrowed));
14139dba64beSDimitry Andric
14149dba64beSDimitry Andric auto isRawIO = IsInstance(rawIOBase.get());
14159dba64beSDimitry Andric if (!isRawIO)
14169dba64beSDimitry Andric return isRawIO.takeError();
14179dba64beSDimitry Andric auto isBufferedIO = IsInstance(bufferedIOBase.get());
14189dba64beSDimitry Andric if (!isBufferedIO)
14199dba64beSDimitry Andric return isBufferedIO.takeError();
14209dba64beSDimitry Andric
14219dba64beSDimitry Andric if (isRawIO.get() || isBufferedIO.get()) {
14229dba64beSDimitry Andric file_sp = std::static_pointer_cast<File>(
14239dba64beSDimitry Andric std::make_shared<BinaryPythonFile>(fd, *this, borrowed));
14249dba64beSDimitry Andric }
14259dba64beSDimitry Andric
14269dba64beSDimitry Andric if (!file_sp)
14279dba64beSDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(),
14289dba64beSDimitry Andric "python file is neither text nor binary");
14299dba64beSDimitry Andric
14309dba64beSDimitry Andric if (!file_sp->IsValid())
14319dba64beSDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(),
14329dba64beSDimitry Andric "invalid File");
14339dba64beSDimitry Andric
14349dba64beSDimitry Andric return file_sp;
14359dba64beSDimitry Andric }
14369dba64beSDimitry Andric
FromFile(File & file,const char * mode)14379dba64beSDimitry Andric Expected<PythonFile> PythonFile::FromFile(File &file, const char *mode) {
14389dba64beSDimitry Andric if (!file.IsValid())
14399dba64beSDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(),
14409dba64beSDimitry Andric "invalid file");
14419dba64beSDimitry Andric
14429dba64beSDimitry Andric if (auto *simple = llvm::dyn_cast<SimplePythonFile>(&file))
14439dba64beSDimitry Andric return Retain<PythonFile>(simple->GetPythonObject());
14449dba64beSDimitry Andric if (auto *pythonio = llvm::dyn_cast<PythonIOFile>(&file))
14459dba64beSDimitry Andric return Retain<PythonFile>(pythonio->GetPythonObject());
14469dba64beSDimitry Andric
14479dba64beSDimitry Andric if (!mode) {
14489dba64beSDimitry Andric auto m = file.GetOpenMode();
14499dba64beSDimitry Andric if (!m)
14509dba64beSDimitry Andric return m.takeError();
14519dba64beSDimitry Andric mode = m.get();
14529dba64beSDimitry Andric }
14539dba64beSDimitry Andric
14549dba64beSDimitry Andric PyObject *file_obj;
14559dba64beSDimitry Andric file_obj = PyFile_FromFd(file.GetDescriptor(), nullptr, mode, -1, nullptr,
1456480093f4SDimitry Andric "ignore", nullptr, /*closefd=*/0);
14579dba64beSDimitry Andric
14589dba64beSDimitry Andric if (!file_obj)
14599dba64beSDimitry Andric return exception();
14609dba64beSDimitry Andric
14619dba64beSDimitry Andric return Take<PythonFile>(file_obj);
14620b57cec5SDimitry Andric }
14630b57cec5SDimitry Andric
Init()14649dba64beSDimitry Andric Error PythonScript::Init() {
14659dba64beSDimitry Andric if (function.IsValid())
14669dba64beSDimitry Andric return Error::success();
14670b57cec5SDimitry Andric
14689dba64beSDimitry Andric PythonDictionary globals(PyInitialValue::Empty);
14699dba64beSDimitry Andric auto builtins = PythonModule::BuiltinsModule();
14709dba64beSDimitry Andric if (Error error = globals.SetItem("__builtins__", builtins))
14719dba64beSDimitry Andric return error;
14729dba64beSDimitry Andric PyObject *o =
14739dba64beSDimitry Andric PyRun_String(script, Py_file_input, globals.get(), globals.get());
14749dba64beSDimitry Andric if (!o)
14759dba64beSDimitry Andric return exception();
14769dba64beSDimitry Andric Take<PythonObject>(o);
14779dba64beSDimitry Andric auto f = As<PythonCallable>(globals.GetItem("main"));
14789dba64beSDimitry Andric if (!f)
14799dba64beSDimitry Andric return f.takeError();
14809dba64beSDimitry Andric function = std::move(f.get());
14819dba64beSDimitry Andric
14829dba64beSDimitry Andric return Error::success();
14830b57cec5SDimitry Andric }
14840b57cec5SDimitry Andric
14859dba64beSDimitry Andric llvm::Expected<PythonObject>
runStringOneLine(const llvm::Twine & string,const PythonDictionary & globals,const PythonDictionary & locals)14869dba64beSDimitry Andric python::runStringOneLine(const llvm::Twine &string,
14879dba64beSDimitry Andric const PythonDictionary &globals,
14889dba64beSDimitry Andric const PythonDictionary &locals) {
14899dba64beSDimitry Andric if (!globals.IsValid() || !locals.IsValid())
14909dba64beSDimitry Andric return nullDeref();
14910b57cec5SDimitry Andric
14929dba64beSDimitry Andric PyObject *code =
14939dba64beSDimitry Andric Py_CompileString(NullTerminated(string), "<string>", Py_eval_input);
14949dba64beSDimitry Andric if (!code) {
14959dba64beSDimitry Andric PyErr_Clear();
14969dba64beSDimitry Andric code =
14979dba64beSDimitry Andric Py_CompileString(NullTerminated(string), "<string>", Py_single_input);
14989dba64beSDimitry Andric }
14999dba64beSDimitry Andric if (!code)
15009dba64beSDimitry Andric return exception();
15019dba64beSDimitry Andric auto code_ref = Take<PythonObject>(code);
15029dba64beSDimitry Andric
15039dba64beSDimitry Andric PyObject *result = PyEval_EvalCode(code, globals.get(), locals.get());
15049dba64beSDimitry Andric
15059dba64beSDimitry Andric if (!result)
15069dba64beSDimitry Andric return exception();
15079dba64beSDimitry Andric
15089dba64beSDimitry Andric return Take<PythonObject>(result);
15099dba64beSDimitry Andric }
15109dba64beSDimitry Andric
15119dba64beSDimitry Andric llvm::Expected<PythonObject>
runStringMultiLine(const llvm::Twine & string,const PythonDictionary & globals,const PythonDictionary & locals)15129dba64beSDimitry Andric python::runStringMultiLine(const llvm::Twine &string,
15139dba64beSDimitry Andric const PythonDictionary &globals,
15149dba64beSDimitry Andric const PythonDictionary &locals) {
15159dba64beSDimitry Andric if (!globals.IsValid() || !locals.IsValid())
15169dba64beSDimitry Andric return nullDeref();
15179dba64beSDimitry Andric PyObject *result = PyRun_String(NullTerminated(string), Py_file_input,
15189dba64beSDimitry Andric globals.get(), locals.get());
15199dba64beSDimitry Andric if (!result)
15209dba64beSDimitry Andric return exception();
15219dba64beSDimitry Andric return Take<PythonObject>(result);
15220b57cec5SDimitry Andric }
15230b57cec5SDimitry Andric
15240b57cec5SDimitry Andric #endif
1525