180814287SRaphael Isemann //===-- PythonDataObjects.cpp ---------------------------------------------===//
22c1f46dcSZachary Turner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
62c1f46dcSZachary Turner //
72c1f46dcSZachary Turner //===----------------------------------------------------------------------===//
82c1f46dcSZachary Turner
959998b7bSJonas Devlieghere #include "lldb/Host/Config.h"
10d68983e3SPavel Labath
114e26cf2cSJonas Devlieghere #if LLDB_ENABLE_PYTHON
12d68983e3SPavel Labath
132c1f46dcSZachary Turner #include "PythonDataObjects.h"
142c1f46dcSZachary Turner #include "ScriptInterpreterPython.h"
152c1f46dcSZachary Turner
162c1f46dcSZachary Turner #include "lldb/Host/File.h"
17190fadcdSZachary Turner #include "lldb/Host/FileSystem.h"
182c1f46dcSZachary Turner #include "lldb/Interpreter/ScriptInterpreter.h"
19c34698a8SPavel Labath #include "lldb/Utility/LLDBLog.h"
20085328eeSLawrence D'Anna #include "lldb/Utility/Log.h"
21bf9a7730SZachary Turner #include "lldb/Utility/Stream.h"
222c1f46dcSZachary Turner
239a6c7572SJonas Devlieghere #include "llvm/ADT/StringSwitch.h"
24d9b553ecSLawrence D'Anna #include "llvm/Support/Casting.h"
25190fadcdSZachary Turner #include "llvm/Support/ConvertUTF.h"
262819136fSMichal Gorny #include "llvm/Support/Errno.h"
27190fadcdSZachary Turner
2876e47d48SRaphael Isemann #include <cstdio>
292c1f46dcSZachary Turner
302c1f46dcSZachary Turner using namespace lldb_private;
312c1f46dcSZachary Turner using namespace lldb;
32085328eeSLawrence D'Anna using namespace lldb_private::python;
33c86a6acaSLawrence D'Anna using llvm::cantFail;
34085328eeSLawrence D'Anna using llvm::Error;
35085328eeSLawrence D'Anna using llvm::Expected;
36722b6189SLawrence D'Anna using llvm::Twine;
37085328eeSLawrence D'Anna
As(Expected<PythonObject> && obj)38085328eeSLawrence D'Anna template <> Expected<bool> python::As<bool>(Expected<PythonObject> &&obj) {
39085328eeSLawrence D'Anna if (!obj)
40085328eeSLawrence D'Anna return obj.takeError();
41085328eeSLawrence D'Anna return obj.get().IsTrue();
42085328eeSLawrence D'Anna }
43085328eeSLawrence D'Anna
44085328eeSLawrence D'Anna template <>
As(Expected<PythonObject> && obj)45085328eeSLawrence D'Anna Expected<long long> python::As<long long>(Expected<PythonObject> &&obj) {
46085328eeSLawrence D'Anna if (!obj)
47085328eeSLawrence D'Anna return obj.takeError();
4852712d3fSLawrence D'Anna return obj->AsLongLong();
4952712d3fSLawrence D'Anna }
5052712d3fSLawrence D'Anna
5152712d3fSLawrence D'Anna template <>
5252712d3fSLawrence D'Anna Expected<unsigned long long>
As(Expected<PythonObject> && obj)5352712d3fSLawrence D'Anna python::As<unsigned long long>(Expected<PythonObject> &&obj) {
5452712d3fSLawrence D'Anna if (!obj)
5552712d3fSLawrence D'Anna return obj.takeError();
5652712d3fSLawrence D'Anna return obj->AsUnsignedLongLong();
57085328eeSLawrence D'Anna }
582c1f46dcSZachary Turner
59c86a6acaSLawrence D'Anna template <>
As(Expected<PythonObject> && obj)60c86a6acaSLawrence D'Anna Expected<std::string> python::As<std::string>(Expected<PythonObject> &&obj) {
61c86a6acaSLawrence D'Anna if (!obj)
62c86a6acaSLawrence D'Anna return obj.takeError();
63c86a6acaSLawrence D'Anna PyObject *str_obj = PyObject_Str(obj.get().get());
64c86a6acaSLawrence D'Anna if (!obj)
65c86a6acaSLawrence D'Anna return llvm::make_error<PythonException>();
66c86a6acaSLawrence D'Anna auto str = Take<PythonString>(str_obj);
67c86a6acaSLawrence D'Anna auto utf8 = str.AsUTF8();
68c86a6acaSLawrence D'Anna if (!utf8)
69c86a6acaSLawrence D'Anna return utf8.takeError();
7019580c37SBenjamin Kramer return std::string(utf8.get());
71c86a6acaSLawrence D'Anna }
72c86a6acaSLawrence D'Anna
python_is_finalizing()736ff4af8eSPavel Labath static bool python_is_finalizing() {
74*90537673SJonas Devlieghere #if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 7
756ff4af8eSPavel Labath return _Py_Finalizing != nullptr;
766ff4af8eSPavel Labath #else
776ff4af8eSPavel Labath return _Py_IsFinalizing();
786ff4af8eSPavel Labath #endif
796ff4af8eSPavel Labath }
806ff4af8eSPavel Labath
Reset()816ff4af8eSPavel Labath void PythonObject::Reset() {
826ff4af8eSPavel Labath if (m_py_obj && Py_IsInitialized()) {
836ff4af8eSPavel Labath if (python_is_finalizing()) {
846ff4af8eSPavel Labath // Leak m_py_obj rather than crashing the process.
856ff4af8eSPavel Labath // https://docs.python.org/3/c-api/init.html#c.PyGILState_Ensure
866ff4af8eSPavel Labath } else {
876ff4af8eSPavel Labath PyGILState_STATE state = PyGILState_Ensure();
886ff4af8eSPavel Labath Py_DECREF(m_py_obj);
896ff4af8eSPavel Labath PyGILState_Release(state);
906ff4af8eSPavel Labath }
916ff4af8eSPavel Labath }
926ff4af8eSPavel Labath m_py_obj = nullptr;
936ff4af8eSPavel Labath }
946ff4af8eSPavel Labath
AsLongLong() const9552712d3fSLawrence D'Anna Expected<long long> PythonObject::AsLongLong() const {
9652712d3fSLawrence D'Anna if (!m_py_obj)
9752712d3fSLawrence D'Anna return nullDeref();
9852712d3fSLawrence D'Anna assert(!PyErr_Occurred());
9952712d3fSLawrence D'Anna long long r = PyLong_AsLongLong(m_py_obj);
10052712d3fSLawrence D'Anna if (PyErr_Occurred())
10152712d3fSLawrence D'Anna return exception();
10252712d3fSLawrence D'Anna return r;
10352712d3fSLawrence D'Anna }
10452712d3fSLawrence D'Anna
AsUnsignedLongLong() const10552712d3fSLawrence D'Anna Expected<long long> PythonObject::AsUnsignedLongLong() const {
10652712d3fSLawrence D'Anna if (!m_py_obj)
10752712d3fSLawrence D'Anna return nullDeref();
10852712d3fSLawrence D'Anna assert(!PyErr_Occurred());
10952712d3fSLawrence D'Anna long long r = PyLong_AsUnsignedLongLong(m_py_obj);
11052712d3fSLawrence D'Anna if (PyErr_Occurred())
11152712d3fSLawrence D'Anna return exception();
11252712d3fSLawrence D'Anna return r;
11352712d3fSLawrence D'Anna }
11452712d3fSLawrence D'Anna
11552712d3fSLawrence D'Anna // wraps on overflow, instead of raising an error.
AsModuloUnsignedLongLong() const11652712d3fSLawrence D'Anna Expected<unsigned long long> PythonObject::AsModuloUnsignedLongLong() const {
11752712d3fSLawrence D'Anna if (!m_py_obj)
11852712d3fSLawrence D'Anna return nullDeref();
11952712d3fSLawrence D'Anna assert(!PyErr_Occurred());
12052712d3fSLawrence D'Anna unsigned long long r = PyLong_AsUnsignedLongLongMask(m_py_obj);
12152712d3fSLawrence D'Anna if (PyErr_Occurred())
12252712d3fSLawrence D'Anna return exception();
12352712d3fSLawrence D'Anna return r;
12452712d3fSLawrence D'Anna }
12552712d3fSLawrence D'Anna
Serialize(llvm::json::OStream & s) const1262783d817SJonas Devlieghere void StructuredPythonObject::Serialize(llvm::json::OStream &s) const {
1272783d817SJonas Devlieghere s.value(llvm::formatv("Python Obj: {0:X}", GetValue()).str());
1282c1f46dcSZachary Turner }
1292c1f46dcSZachary Turner
1302c1f46dcSZachary Turner // PythonObject
1312c1f46dcSZachary Turner
Dump(Stream & strm) const132b9c1b51eSKate Stone void PythonObject::Dump(Stream &strm) const {
133b9c1b51eSKate Stone if (m_py_obj) {
1342819136fSMichal Gorny FILE *file = llvm::sys::RetryAfterSignal(nullptr, ::tmpfile);
135b9c1b51eSKate Stone if (file) {
1362c1f46dcSZachary Turner ::PyObject_Print(m_py_obj, file, 0);
1372c1f46dcSZachary Turner const long length = ftell(file);
138b9c1b51eSKate Stone if (length) {
1392c1f46dcSZachary Turner ::rewind(file);
1402c1f46dcSZachary Turner std::vector<char> file_contents(length, '\0');
141b9c1b51eSKate Stone const size_t length_read =
142b9c1b51eSKate Stone ::fread(file_contents.data(), 1, file_contents.size(), file);
1432c1f46dcSZachary Turner if (length_read > 0)
1442c1f46dcSZachary Turner strm.Write(file_contents.data(), length_read);
1452c1f46dcSZachary Turner }
1462c1f46dcSZachary Turner ::fclose(file);
1472c1f46dcSZachary Turner }
148b9c1b51eSKate Stone } else
1492c1f46dcSZachary Turner strm.PutCString("NULL");
1502c1f46dcSZachary Turner }
1512c1f46dcSZachary Turner
GetObjectType() const152b9c1b51eSKate Stone PyObjectType PythonObject::GetObjectType() const {
153f8b22f8fSZachary Turner if (!IsAllocated())
1542c1f46dcSZachary Turner return PyObjectType::None;
1552c1f46dcSZachary Turner
1567841efbbSZachary Turner if (PythonModule::Check(m_py_obj))
1577841efbbSZachary Turner return PyObjectType::Module;
15818426935SZachary Turner if (PythonList::Check(m_py_obj))
1592c1f46dcSZachary Turner return PyObjectType::List;
160a1405147SZachary Turner if (PythonTuple::Check(m_py_obj))
161a1405147SZachary Turner return PyObjectType::Tuple;
16218426935SZachary Turner if (PythonDictionary::Check(m_py_obj))
1632c1f46dcSZachary Turner return PyObjectType::Dictionary;
16418426935SZachary Turner if (PythonString::Check(m_py_obj))
16522c8efcdSZachary Turner return PyObjectType::String;
1665a72c02bSZachary Turner if (PythonBytes::Check(m_py_obj))
1675a72c02bSZachary Turner return PyObjectType::Bytes;
168f9d6d204SZachary Turner if (PythonByteArray::Check(m_py_obj))
169f9d6d204SZachary Turner return PyObjectType::ByteArray;
170b81d715cSTatyana Krasnukha if (PythonBoolean::Check(m_py_obj))
171b81d715cSTatyana Krasnukha return PyObjectType::Boolean;
17218426935SZachary Turner if (PythonInteger::Check(m_py_obj))
17322c8efcdSZachary Turner return PyObjectType::Integer;
1749c40264fSZachary Turner if (PythonFile::Check(m_py_obj))
1759c40264fSZachary Turner return PyObjectType::File;
176a1405147SZachary Turner if (PythonCallable::Check(m_py_obj))
177a1405147SZachary Turner return PyObjectType::Callable;
1782c1f46dcSZachary Turner return PyObjectType::Unknown;
1792c1f46dcSZachary Turner }
1802c1f46dcSZachary Turner
Repr() const181b9c1b51eSKate Stone PythonString PythonObject::Repr() const {
1822c1f46dcSZachary Turner if (!m_py_obj)
1832c1f46dcSZachary Turner return PythonString();
1842c1f46dcSZachary Turner PyObject *repr = PyObject_Repr(m_py_obj);
1852c1f46dcSZachary Turner if (!repr)
1862c1f46dcSZachary Turner return PythonString();
187f8b22f8fSZachary Turner return PythonString(PyRefType::Owned, repr);
1882c1f46dcSZachary Turner }
1892c1f46dcSZachary Turner
Str() const190b9c1b51eSKate Stone PythonString PythonObject::Str() const {
1912c1f46dcSZachary Turner if (!m_py_obj)
1922c1f46dcSZachary Turner return PythonString();
1932c1f46dcSZachary Turner PyObject *str = PyObject_Str(m_py_obj);
1942c1f46dcSZachary Turner if (!str)
1952c1f46dcSZachary Turner return PythonString();
196f8b22f8fSZachary Turner return PythonString(PyRefType::Owned, str);
1972c1f46dcSZachary Turner }
1982c1f46dcSZachary Turner
1997841efbbSZachary Turner PythonObject
ResolveNameWithDictionary(llvm::StringRef name,const PythonDictionary & dict)200b9c1b51eSKate Stone PythonObject::ResolveNameWithDictionary(llvm::StringRef name,
201b9c1b51eSKate Stone const PythonDictionary &dict) {
202c712bac7SJonas Devlieghere size_t dot_pos = name.find('.');
203a1405147SZachary Turner llvm::StringRef piece = name.substr(0, dot_pos);
204a1405147SZachary Turner PythonObject result = dict.GetItemForKey(PythonString(piece));
205b9c1b51eSKate Stone if (dot_pos == llvm::StringRef::npos) {
206a1405147SZachary Turner // There was no dot, we're done.
207a1405147SZachary Turner return result;
208a1405147SZachary Turner }
209a1405147SZachary Turner
210a1405147SZachary Turner // There was a dot. The remaining portion of the name should be looked up in
211a1405147SZachary Turner // the context of the object that was found in the dictionary.
212a1405147SZachary Turner return result.ResolveName(name.substr(dot_pos + 1));
2137841efbbSZachary Turner }
2147841efbbSZachary Turner
ResolveName(llvm::StringRef name) const215b9c1b51eSKate Stone PythonObject PythonObject::ResolveName(llvm::StringRef name) const {
21605097246SAdrian Prantl // Resolve the name in the context of the specified object. If, for example,
21705097246SAdrian Prantl // `this` refers to a PyModule, then this will look for `name` in this
21805097246SAdrian Prantl // module. If `this` refers to a PyType, then it will resolve `name` as an
21905097246SAdrian Prantl // attribute of that type. If `this` refers to an instance of an object,
22005097246SAdrian Prantl // then it will resolve `name` as the value of the specified field.
2217841efbbSZachary Turner //
2227841efbbSZachary Turner // This function handles dotted names so that, for example, if `m_py_obj`
22305097246SAdrian Prantl // refers to the `sys` module, and `name` == "path.append", then it will find
22405097246SAdrian Prantl // the function `sys.path.append`.
2257841efbbSZachary Turner
226c712bac7SJonas Devlieghere size_t dot_pos = name.find('.');
227b9c1b51eSKate Stone if (dot_pos == llvm::StringRef::npos) {
22805097246SAdrian Prantl // No dots in the name, we should be able to find the value immediately as
22905097246SAdrian Prantl // an attribute of `m_py_obj`.
2307841efbbSZachary Turner return GetAttributeValue(name);
2317841efbbSZachary Turner }
2327841efbbSZachary Turner
233b9c1b51eSKate Stone // Look up the first piece of the name, and resolve the rest as a child of
234b9c1b51eSKate Stone // that.
2357841efbbSZachary Turner PythonObject parent = ResolveName(name.substr(0, dot_pos));
2367841efbbSZachary Turner if (!parent.IsAllocated())
2377841efbbSZachary Turner return PythonObject();
2387841efbbSZachary Turner
2397841efbbSZachary Turner // Tail recursion.. should be optimized by the compiler
2407841efbbSZachary Turner return parent.ResolveName(name.substr(dot_pos + 1));
2417841efbbSZachary Turner }
2427841efbbSZachary Turner
HasAttribute(llvm::StringRef attr) const243b9c1b51eSKate Stone bool PythonObject::HasAttribute(llvm::StringRef attr) const {
2449c40264fSZachary Turner if (!IsValid())
2459c40264fSZachary Turner return false;
2469c40264fSZachary Turner PythonString py_attr(attr);
2479c40264fSZachary Turner return !!PyObject_HasAttr(m_py_obj, py_attr.get());
2489c40264fSZachary Turner }
2499c40264fSZachary Turner
GetAttributeValue(llvm::StringRef attr) const250b9c1b51eSKate Stone PythonObject PythonObject::GetAttributeValue(llvm::StringRef attr) const {
2517d6d218eSZachary Turner if (!IsValid())
2527d6d218eSZachary Turner return PythonObject();
2537d6d218eSZachary Turner
2547d6d218eSZachary Turner PythonString py_attr(attr);
2557d6d218eSZachary Turner if (!PyObject_HasAttr(m_py_obj, py_attr.get()))
2567d6d218eSZachary Turner return PythonObject();
2577d6d218eSZachary Turner
2587d6d218eSZachary Turner return PythonObject(PyRefType::Owned,
2597d6d218eSZachary Turner PyObject_GetAttr(m_py_obj, py_attr.get()));
2607d6d218eSZachary Turner }
2617d6d218eSZachary Turner
CreateStructuredObject() const262b9c1b51eSKate Stone StructuredData::ObjectSP PythonObject::CreateStructuredObject() const {
263a6598575SRalf Grosse-Kunstleve assert(PyGILState_Check());
264b9c1b51eSKate Stone switch (GetObjectType()) {
2652c1f46dcSZachary Turner case PyObjectType::Dictionary:
266b9c1b51eSKate Stone return PythonDictionary(PyRefType::Borrowed, m_py_obj)
267b9c1b51eSKate Stone .CreateStructuredDictionary();
268b81d715cSTatyana Krasnukha case PyObjectType::Boolean:
269b81d715cSTatyana Krasnukha return PythonBoolean(PyRefType::Borrowed, m_py_obj)
270b81d715cSTatyana Krasnukha .CreateStructuredBoolean();
2712c1f46dcSZachary Turner case PyObjectType::Integer:
272b9c1b51eSKate Stone return PythonInteger(PyRefType::Borrowed, m_py_obj)
273b9c1b51eSKate Stone .CreateStructuredInteger();
2742c1f46dcSZachary Turner case PyObjectType::List:
275f8b22f8fSZachary Turner return PythonList(PyRefType::Borrowed, m_py_obj).CreateStructuredArray();
2762c1f46dcSZachary Turner case PyObjectType::String:
277f8b22f8fSZachary Turner return PythonString(PyRefType::Borrowed, m_py_obj).CreateStructuredString();
2785a72c02bSZachary Turner case PyObjectType::Bytes:
2795a72c02bSZachary Turner return PythonBytes(PyRefType::Borrowed, m_py_obj).CreateStructuredString();
280f9d6d204SZachary Turner case PyObjectType::ByteArray:
281b9c1b51eSKate Stone return PythonByteArray(PyRefType::Borrowed, m_py_obj)
282b9c1b51eSKate Stone .CreateStructuredString();
2832c1f46dcSZachary Turner case PyObjectType::None:
2842c1f46dcSZachary Turner return StructuredData::ObjectSP();
2852c1f46dcSZachary Turner default:
286c154f397SPavel Labath return StructuredData::ObjectSP(new StructuredPythonObject(
287c154f397SPavel Labath PythonObject(PyRefType::Borrowed, m_py_obj)));
2882c1f46dcSZachary Turner }
2892c1f46dcSZachary Turner }
2902c1f46dcSZachary Turner
2912c1f46dcSZachary Turner // PythonString
2925a72c02bSZachary Turner
PythonBytes(llvm::ArrayRef<uint8_t> bytes)293d3bd5b3dSLawrence D'Anna PythonBytes::PythonBytes(llvm::ArrayRef<uint8_t> bytes) { SetBytes(bytes); }
2945a72c02bSZachary Turner
PythonBytes(const uint8_t * bytes,size_t length)295d3bd5b3dSLawrence D'Anna PythonBytes::PythonBytes(const uint8_t *bytes, size_t length) {
2965a72c02bSZachary Turner SetBytes(llvm::ArrayRef<uint8_t>(bytes, length));
2975a72c02bSZachary Turner }
2985a72c02bSZachary Turner
Check(PyObject * py_obj)299b9c1b51eSKate Stone bool PythonBytes::Check(PyObject *py_obj) {
3005a72c02bSZachary Turner if (!py_obj)
3015a72c02bSZachary Turner return false;
302a6682a41SJonas Devlieghere return PyBytes_Check(py_obj);
3035a72c02bSZachary Turner }
3045a72c02bSZachary Turner
GetBytes() const305b9c1b51eSKate Stone llvm::ArrayRef<uint8_t> PythonBytes::GetBytes() const {
3065a72c02bSZachary Turner if (!IsValid())
3075a72c02bSZachary Turner return llvm::ArrayRef<uint8_t>();
3085a72c02bSZachary Turner
3095a72c02bSZachary Turner Py_ssize_t size;
3105a72c02bSZachary Turner char *c;
3115a72c02bSZachary Turner
3125a72c02bSZachary Turner PyBytes_AsStringAndSize(m_py_obj, &c, &size);
3135a72c02bSZachary Turner return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size);
3145a72c02bSZachary Turner }
3155a72c02bSZachary Turner
GetSize() const316b9c1b51eSKate Stone size_t PythonBytes::GetSize() const {
3175a72c02bSZachary Turner if (!IsValid())
3185a72c02bSZachary Turner return 0;
3195a72c02bSZachary Turner return PyBytes_Size(m_py_obj);
3205a72c02bSZachary Turner }
3215a72c02bSZachary Turner
SetBytes(llvm::ArrayRef<uint8_t> bytes)322b9c1b51eSKate Stone void PythonBytes::SetBytes(llvm::ArrayRef<uint8_t> bytes) {
3235a72c02bSZachary Turner const char *data = reinterpret_cast<const char *>(bytes.data());
32404edd189SLawrence D'Anna *this = Take<PythonBytes>(PyBytes_FromStringAndSize(data, bytes.size()));
3255a72c02bSZachary Turner }
3265a72c02bSZachary Turner
CreateStructuredString() const327b9c1b51eSKate Stone StructuredData::StringSP PythonBytes::CreateStructuredString() const {
3285a72c02bSZachary Turner StructuredData::StringSP result(new StructuredData::String);
3295a72c02bSZachary Turner Py_ssize_t size;
3305a72c02bSZachary Turner char *c;
3315a72c02bSZachary Turner PyBytes_AsStringAndSize(m_py_obj, &c, &size);
3325a72c02bSZachary Turner result->SetValue(std::string(c, size));
3335a72c02bSZachary Turner return result;
3345a72c02bSZachary Turner }
3355a72c02bSZachary Turner
PythonByteArray(llvm::ArrayRef<uint8_t> bytes)336b9c1b51eSKate Stone PythonByteArray::PythonByteArray(llvm::ArrayRef<uint8_t> bytes)
337b9c1b51eSKate Stone : PythonByteArray(bytes.data(), bytes.size()) {}
338f9d6d204SZachary Turner
PythonByteArray(const uint8_t * bytes,size_t length)339b9c1b51eSKate Stone PythonByteArray::PythonByteArray(const uint8_t *bytes, size_t length) {
340f9d6d204SZachary Turner const char *str = reinterpret_cast<const char *>(bytes);
341722b6189SLawrence D'Anna *this = Take<PythonByteArray>(PyByteArray_FromStringAndSize(str, length));
342f9d6d204SZachary Turner }
343f9d6d204SZachary Turner
Check(PyObject * py_obj)344b9c1b51eSKate Stone bool PythonByteArray::Check(PyObject *py_obj) {
345f9d6d204SZachary Turner if (!py_obj)
346f9d6d204SZachary Turner return false;
347a6682a41SJonas Devlieghere return PyByteArray_Check(py_obj);
348f9d6d204SZachary Turner }
349f9d6d204SZachary Turner
GetBytes() const350b9c1b51eSKate Stone llvm::ArrayRef<uint8_t> PythonByteArray::GetBytes() const {
351f9d6d204SZachary Turner if (!IsValid())
352f9d6d204SZachary Turner return llvm::ArrayRef<uint8_t>();
353f9d6d204SZachary Turner
354f9d6d204SZachary Turner char *c = PyByteArray_AsString(m_py_obj);
355f9d6d204SZachary Turner size_t size = GetSize();
356f9d6d204SZachary Turner return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size);
357f9d6d204SZachary Turner }
358f9d6d204SZachary Turner
GetSize() const359b9c1b51eSKate Stone size_t PythonByteArray::GetSize() const {
360f9d6d204SZachary Turner if (!IsValid())
361f9d6d204SZachary Turner return 0;
362f9d6d204SZachary Turner
363f9d6d204SZachary Turner return PyByteArray_Size(m_py_obj);
364f9d6d204SZachary Turner }
365f9d6d204SZachary Turner
CreateStructuredString() const366b9c1b51eSKate Stone StructuredData::StringSP PythonByteArray::CreateStructuredString() const {
367f9d6d204SZachary Turner StructuredData::StringSP result(new StructuredData::String);
368f9d6d204SZachary Turner llvm::ArrayRef<uint8_t> bytes = GetBytes();
369f9d6d204SZachary Turner const char *str = reinterpret_cast<const char *>(bytes.data());
370f9d6d204SZachary Turner result->SetValue(std::string(str, bytes.size()));
371f9d6d204SZachary Turner return result;
372f9d6d204SZachary Turner }
373f9d6d204SZachary Turner
3745a72c02bSZachary Turner // PythonString
3752c1f46dcSZachary Turner
FromUTF8(llvm::StringRef string)376085328eeSLawrence D'Anna Expected<PythonString> PythonString::FromUTF8(llvm::StringRef string) {
377085328eeSLawrence D'Anna PyObject *str = PyUnicode_FromStringAndSize(string.data(), string.size());
378085328eeSLawrence D'Anna if (!str)
379085328eeSLawrence D'Anna return llvm::make_error<PythonException>();
380085328eeSLawrence D'Anna return Take<PythonString>(str);
381085328eeSLawrence D'Anna }
382085328eeSLawrence D'Anna
PythonString(llvm::StringRef string)383d3bd5b3dSLawrence D'Anna PythonString::PythonString(llvm::StringRef string) { SetString(string); }
3842c1f46dcSZachary Turner
Check(PyObject * py_obj)385b9c1b51eSKate Stone bool PythonString::Check(PyObject *py_obj) {
38622c8efcdSZachary Turner if (!py_obj)
38722c8efcdSZachary Turner return false;
38818426935SZachary Turner
3897d6d218eSZachary Turner if (PyUnicode_Check(py_obj))
3907d6d218eSZachary Turner return true;
3917d6d218eSZachary Turner return false;
39222c8efcdSZachary Turner }
39322c8efcdSZachary Turner
GetString() const394b9c1b51eSKate Stone llvm::StringRef PythonString::GetString() const {
395085328eeSLawrence D'Anna auto s = AsUTF8();
396085328eeSLawrence D'Anna if (!s) {
397085328eeSLawrence D'Anna llvm::consumeError(s.takeError());
398085328eeSLawrence D'Anna return llvm::StringRef("");
399085328eeSLawrence D'Anna }
400085328eeSLawrence D'Anna return s.get();
401085328eeSLawrence D'Anna }
402085328eeSLawrence D'Anna
AsUTF8() const403085328eeSLawrence D'Anna Expected<llvm::StringRef> PythonString::AsUTF8() const {
40418426935SZachary Turner if (!IsValid())
405085328eeSLawrence D'Anna return nullDeref();
40618426935SZachary Turner
40722c8efcdSZachary Turner Py_ssize_t size;
4085457b426SPavel Labath const char *data;
40918426935SZachary Turner
4105457b426SPavel Labath data = PyUnicode_AsUTF8AndSize(m_py_obj, &size);
411085328eeSLawrence D'Anna
412085328eeSLawrence D'Anna if (!data)
413085328eeSLawrence D'Anna return exception();
414085328eeSLawrence D'Anna
4155457b426SPavel Labath return llvm::StringRef(data, size);
41622c8efcdSZachary Turner }
4172c1f46dcSZachary Turner
GetSize() const418b9c1b51eSKate Stone size_t PythonString::GetSize() const {
419b9c1b51eSKate Stone if (IsValid()) {
42075012a80STatyana Krasnukha #if PY_MINOR_VERSION >= 3
42175012a80STatyana Krasnukha return PyUnicode_GetLength(m_py_obj);
42275012a80STatyana Krasnukha #else
42318426935SZachary Turner return PyUnicode_GetSize(m_py_obj);
42475012a80STatyana Krasnukha #endif
42518426935SZachary Turner }
4262c1f46dcSZachary Turner return 0;
4272c1f46dcSZachary Turner }
4282c1f46dcSZachary Turner
SetString(llvm::StringRef string)429b9c1b51eSKate Stone void PythonString::SetString(llvm::StringRef string) {
430085328eeSLawrence D'Anna auto s = FromUTF8(string);
431085328eeSLawrence D'Anna if (!s) {
432085328eeSLawrence D'Anna llvm::consumeError(s.takeError());
433085328eeSLawrence D'Anna Reset();
434085328eeSLawrence D'Anna } else {
43503819d1cSLawrence D'Anna *this = std::move(s.get());
436085328eeSLawrence D'Anna }
4372c1f46dcSZachary Turner }
4382c1f46dcSZachary Turner
CreateStructuredString() const439b9c1b51eSKate Stone StructuredData::StringSP PythonString::CreateStructuredString() const {
4402c1f46dcSZachary Turner StructuredData::StringSP result(new StructuredData::String);
4412c1f46dcSZachary Turner result->SetValue(GetString());
4422c1f46dcSZachary Turner return result;
4432c1f46dcSZachary Turner }
4442c1f46dcSZachary Turner
4452c1f46dcSZachary Turner // PythonInteger
4462c1f46dcSZachary Turner
PythonInteger(int64_t value)447d3bd5b3dSLawrence D'Anna PythonInteger::PythonInteger(int64_t value) { SetInteger(value); }
4482c1f46dcSZachary Turner
Check(PyObject * py_obj)449b9c1b51eSKate Stone bool PythonInteger::Check(PyObject *py_obj) {
45022c8efcdSZachary Turner if (!py_obj)
45122c8efcdSZachary Turner return false;
45222c8efcdSZachary Turner
45305097246SAdrian Prantl // Python 3 does not have PyInt_Check. There is only one type of integral
45405097246SAdrian Prantl // value, long.
45522c8efcdSZachary Turner return PyLong_Check(py_obj);
4562c1f46dcSZachary Turner }
4572c1f46dcSZachary Turner
SetInteger(int64_t value)458b9c1b51eSKate Stone void PythonInteger::SetInteger(int64_t value) {
45904edd189SLawrence D'Anna *this = Take<PythonInteger>(PyLong_FromLongLong(value));
4602c1f46dcSZachary Turner }
4612c1f46dcSZachary Turner
CreateStructuredInteger() const462b9c1b51eSKate Stone StructuredData::IntegerSP PythonInteger::CreateStructuredInteger() const {
4632c1f46dcSZachary Turner StructuredData::IntegerSP result(new StructuredData::Integer);
46452712d3fSLawrence D'Anna // FIXME this is really not ideal. Errors are silently converted to 0
46552712d3fSLawrence D'Anna // and overflows are silently wrapped. But we'd need larger changes
46652712d3fSLawrence D'Anna // to StructuredData to fix it, so that's how it is for now.
46752712d3fSLawrence D'Anna llvm::Expected<unsigned long long> value = AsModuloUnsignedLongLong();
46852712d3fSLawrence D'Anna if (!value) {
46952712d3fSLawrence D'Anna llvm::consumeError(value.takeError());
47052712d3fSLawrence D'Anna result->SetValue(0);
47152712d3fSLawrence D'Anna } else {
47252712d3fSLawrence D'Anna result->SetValue(value.get());
47352712d3fSLawrence D'Anna }
4742c1f46dcSZachary Turner return result;
4752c1f46dcSZachary Turner }
4762c1f46dcSZachary Turner
477b81d715cSTatyana Krasnukha // PythonBoolean
478b81d715cSTatyana Krasnukha
PythonBoolean(bool value)479b81d715cSTatyana Krasnukha PythonBoolean::PythonBoolean(bool value) {
480b81d715cSTatyana Krasnukha SetValue(value);
481b81d715cSTatyana Krasnukha }
482b81d715cSTatyana Krasnukha
Check(PyObject * py_obj)483b81d715cSTatyana Krasnukha bool PythonBoolean::Check(PyObject *py_obj) {
484b81d715cSTatyana Krasnukha return py_obj ? PyBool_Check(py_obj) : false;
485b81d715cSTatyana Krasnukha }
486b81d715cSTatyana Krasnukha
GetValue() const487b81d715cSTatyana Krasnukha bool PythonBoolean::GetValue() const {
488b81d715cSTatyana Krasnukha return m_py_obj ? PyObject_IsTrue(m_py_obj) : false;
489b81d715cSTatyana Krasnukha }
490b81d715cSTatyana Krasnukha
SetValue(bool value)491b81d715cSTatyana Krasnukha void PythonBoolean::SetValue(bool value) {
49204edd189SLawrence D'Anna *this = Take<PythonBoolean>(PyBool_FromLong(value));
493b81d715cSTatyana Krasnukha }
494b81d715cSTatyana Krasnukha
CreateStructuredBoolean() const495b81d715cSTatyana Krasnukha StructuredData::BooleanSP PythonBoolean::CreateStructuredBoolean() const {
496b81d715cSTatyana Krasnukha StructuredData::BooleanSP result(new StructuredData::Boolean);
497b81d715cSTatyana Krasnukha result->SetValue(GetValue());
498b81d715cSTatyana Krasnukha return result;
499b81d715cSTatyana Krasnukha }
500b81d715cSTatyana Krasnukha
5012c1f46dcSZachary Turner // PythonList
5022c1f46dcSZachary Turner
PythonList(PyInitialValue value)503d3bd5b3dSLawrence D'Anna PythonList::PythonList(PyInitialValue value) {
504f8b22f8fSZachary Turner if (value == PyInitialValue::Empty)
505722b6189SLawrence D'Anna *this = Take<PythonList>(PyList_New(0));
5062c1f46dcSZachary Turner }
5072c1f46dcSZachary Turner
PythonList(int list_size)508d3bd5b3dSLawrence D'Anna PythonList::PythonList(int list_size) {
509722b6189SLawrence D'Anna *this = Take<PythonList>(PyList_New(list_size));
51087f47729SZachary Turner }
51187f47729SZachary Turner
Check(PyObject * py_obj)512b9c1b51eSKate Stone bool PythonList::Check(PyObject *py_obj) {
51322c8efcdSZachary Turner if (!py_obj)
51422c8efcdSZachary Turner return false;
51522c8efcdSZachary Turner return PyList_Check(py_obj);
51622c8efcdSZachary Turner }
51722c8efcdSZachary Turner
GetSize() const518b9c1b51eSKate Stone uint32_t PythonList::GetSize() const {
519f8b22f8fSZachary Turner if (IsValid())
5202c1f46dcSZachary Turner return PyList_GET_SIZE(m_py_obj);
5212c1f46dcSZachary Turner return 0;
5222c1f46dcSZachary Turner }
5232c1f46dcSZachary Turner
GetItemAtIndex(uint32_t index) const524b9c1b51eSKate Stone PythonObject PythonList::GetItemAtIndex(uint32_t index) const {
525f8b22f8fSZachary Turner if (IsValid())
526f8b22f8fSZachary Turner return PythonObject(PyRefType::Borrowed, PyList_GetItem(m_py_obj, index));
5272c1f46dcSZachary Turner return PythonObject();
5282c1f46dcSZachary Turner }
5292c1f46dcSZachary Turner
SetItemAtIndex(uint32_t index,const PythonObject & object)530b9c1b51eSKate Stone void PythonList::SetItemAtIndex(uint32_t index, const PythonObject &object) {
531b9c1b51eSKate Stone if (IsAllocated() && object.IsValid()) {
532f8b22f8fSZachary Turner // PyList_SetItem is documented to "steal" a reference, so we need to
533f8b22f8fSZachary Turner // convert it to an owned reference by incrementing it.
534f8b22f8fSZachary Turner Py_INCREF(object.get());
5352c1f46dcSZachary Turner PyList_SetItem(m_py_obj, index, object.get());
5362c1f46dcSZachary Turner }
537f8b22f8fSZachary Turner }
5382c1f46dcSZachary Turner
AppendItem(const PythonObject & object)539b9c1b51eSKate Stone void PythonList::AppendItem(const PythonObject &object) {
540b9c1b51eSKate Stone if (IsAllocated() && object.IsValid()) {
541f8b22f8fSZachary Turner // `PyList_Append` does *not* steal a reference, so do not call `Py_INCREF`
542f8b22f8fSZachary Turner // here like we do with `PyList_SetItem`.
5432c1f46dcSZachary Turner PyList_Append(m_py_obj, object.get());
5442c1f46dcSZachary Turner }
545f8b22f8fSZachary Turner }
5462c1f46dcSZachary Turner
CreateStructuredArray() const547b9c1b51eSKate Stone StructuredData::ArraySP PythonList::CreateStructuredArray() const {
5482c1f46dcSZachary Turner StructuredData::ArraySP result(new StructuredData::Array);
5492c1f46dcSZachary Turner uint32_t count = GetSize();
550b9c1b51eSKate Stone for (uint32_t i = 0; i < count; ++i) {
5512c1f46dcSZachary Turner PythonObject obj = GetItemAtIndex(i);
5522c1f46dcSZachary Turner result->AddItem(obj.CreateStructuredObject());
5532c1f46dcSZachary Turner }
5542c1f46dcSZachary Turner return result;
5552c1f46dcSZachary Turner }
5562c1f46dcSZachary Turner
557a1405147SZachary Turner // PythonTuple
558a1405147SZachary Turner
PythonTuple(PyInitialValue value)559d3bd5b3dSLawrence D'Anna PythonTuple::PythonTuple(PyInitialValue value) {
560a1405147SZachary Turner if (value == PyInitialValue::Empty)
561722b6189SLawrence D'Anna *this = Take<PythonTuple>(PyTuple_New(0));
562a1405147SZachary Turner }
563a1405147SZachary Turner
PythonTuple(int tuple_size)564d3bd5b3dSLawrence D'Anna PythonTuple::PythonTuple(int tuple_size) {
565722b6189SLawrence D'Anna *this = Take<PythonTuple>(PyTuple_New(tuple_size));
566a1405147SZachary Turner }
567a1405147SZachary Turner
PythonTuple(std::initializer_list<PythonObject> objects)568b9c1b51eSKate Stone PythonTuple::PythonTuple(std::initializer_list<PythonObject> objects) {
569a1405147SZachary Turner m_py_obj = PyTuple_New(objects.size());
570a1405147SZachary Turner
571a1405147SZachary Turner uint32_t idx = 0;
572b9c1b51eSKate Stone for (auto object : objects) {
573a1405147SZachary Turner if (object.IsValid())
574a1405147SZachary Turner SetItemAtIndex(idx, object);
575a1405147SZachary Turner idx++;
576a1405147SZachary Turner }
577a1405147SZachary Turner }
578a1405147SZachary Turner
PythonTuple(std::initializer_list<PyObject * > objects)579b9c1b51eSKate Stone PythonTuple::PythonTuple(std::initializer_list<PyObject *> objects) {
580a1405147SZachary Turner m_py_obj = PyTuple_New(objects.size());
581a1405147SZachary Turner
582a1405147SZachary Turner uint32_t idx = 0;
583b9c1b51eSKate Stone for (auto py_object : objects) {
584a1405147SZachary Turner PythonObject object(PyRefType::Borrowed, py_object);
585a1405147SZachary Turner if (object.IsValid())
586a1405147SZachary Turner SetItemAtIndex(idx, object);
587a1405147SZachary Turner idx++;
588a1405147SZachary Turner }
589a1405147SZachary Turner }
590a1405147SZachary Turner
Check(PyObject * py_obj)591b9c1b51eSKate Stone bool PythonTuple::Check(PyObject *py_obj) {
592a1405147SZachary Turner if (!py_obj)
593a1405147SZachary Turner return false;
594a1405147SZachary Turner return PyTuple_Check(py_obj);
595a1405147SZachary Turner }
596a1405147SZachary Turner
GetSize() const597b9c1b51eSKate Stone uint32_t PythonTuple::GetSize() const {
598a1405147SZachary Turner if (IsValid())
599a1405147SZachary Turner return PyTuple_GET_SIZE(m_py_obj);
600a1405147SZachary Turner return 0;
601a1405147SZachary Turner }
602a1405147SZachary Turner
GetItemAtIndex(uint32_t index) const603b9c1b51eSKate Stone PythonObject PythonTuple::GetItemAtIndex(uint32_t index) const {
604a1405147SZachary Turner if (IsValid())
605a1405147SZachary Turner return PythonObject(PyRefType::Borrowed, PyTuple_GetItem(m_py_obj, index));
606a1405147SZachary Turner return PythonObject();
607a1405147SZachary Turner }
608a1405147SZachary Turner
SetItemAtIndex(uint32_t index,const PythonObject & object)609b9c1b51eSKate Stone void PythonTuple::SetItemAtIndex(uint32_t index, const PythonObject &object) {
610b9c1b51eSKate Stone if (IsAllocated() && object.IsValid()) {
611a1405147SZachary Turner // PyTuple_SetItem is documented to "steal" a reference, so we need to
612a1405147SZachary Turner // convert it to an owned reference by incrementing it.
613a1405147SZachary Turner Py_INCREF(object.get());
614a1405147SZachary Turner PyTuple_SetItem(m_py_obj, index, object.get());
615a1405147SZachary Turner }
616a1405147SZachary Turner }
617a1405147SZachary Turner
CreateStructuredArray() const618b9c1b51eSKate Stone StructuredData::ArraySP PythonTuple::CreateStructuredArray() const {
619a1405147SZachary Turner StructuredData::ArraySP result(new StructuredData::Array);
620a1405147SZachary Turner uint32_t count = GetSize();
621b9c1b51eSKate Stone for (uint32_t i = 0; i < count; ++i) {
622a1405147SZachary Turner PythonObject obj = GetItemAtIndex(i);
623a1405147SZachary Turner result->AddItem(obj.CreateStructuredObject());
624a1405147SZachary Turner }
625a1405147SZachary Turner return result;
626a1405147SZachary Turner }
627a1405147SZachary Turner
6282c1f46dcSZachary Turner // PythonDictionary
6292c1f46dcSZachary Turner
PythonDictionary(PyInitialValue value)630d3bd5b3dSLawrence D'Anna PythonDictionary::PythonDictionary(PyInitialValue value) {
631f8b22f8fSZachary Turner if (value == PyInitialValue::Empty)
632722b6189SLawrence D'Anna *this = Take<PythonDictionary>(PyDict_New());
6332c1f46dcSZachary Turner }
6342c1f46dcSZachary Turner
Check(PyObject * py_obj)635b9c1b51eSKate Stone bool PythonDictionary::Check(PyObject *py_obj) {
63622c8efcdSZachary Turner if (!py_obj)
63722c8efcdSZachary Turner return false;
63822c8efcdSZachary Turner
63922c8efcdSZachary Turner return PyDict_Check(py_obj);
64022c8efcdSZachary Turner }
64122c8efcdSZachary Turner
GetSize() const642b9c1b51eSKate Stone uint32_t PythonDictionary::GetSize() const {
643f8b22f8fSZachary Turner if (IsValid())
6442c1f46dcSZachary Turner return PyDict_Size(m_py_obj);
6452c1f46dcSZachary Turner return 0;
6462c1f46dcSZachary Turner }
6472c1f46dcSZachary Turner
GetKeys() const648b9c1b51eSKate Stone PythonList PythonDictionary::GetKeys() const {
649f8b22f8fSZachary Turner if (IsValid())
650f8b22f8fSZachary Turner return PythonList(PyRefType::Owned, PyDict_Keys(m_py_obj));
651f8b22f8fSZachary Turner return PythonList(PyInitialValue::Invalid);
6522c1f46dcSZachary Turner }
6532c1f46dcSZachary Turner
GetItemForKey(const PythonObject & key) const654b9c1b51eSKate Stone PythonObject PythonDictionary::GetItemForKey(const PythonObject &key) const {
655c86a6acaSLawrence D'Anna auto item = GetItem(key);
656c86a6acaSLawrence D'Anna if (!item) {
657c86a6acaSLawrence D'Anna llvm::consumeError(item.takeError());
6582c1f46dcSZachary Turner return PythonObject();
6592c1f46dcSZachary Turner }
660c86a6acaSLawrence D'Anna return std::move(item.get());
661c86a6acaSLawrence D'Anna }
662c86a6acaSLawrence D'Anna
663c86a6acaSLawrence D'Anna Expected<PythonObject>
GetItem(const PythonObject & key) const664c86a6acaSLawrence D'Anna PythonDictionary::GetItem(const PythonObject &key) const {
665c86a6acaSLawrence D'Anna if (!IsValid())
666c86a6acaSLawrence D'Anna return nullDeref();
667c86a6acaSLawrence D'Anna PyObject *o = PyDict_GetItemWithError(m_py_obj, key.get());
668c86a6acaSLawrence D'Anna if (PyErr_Occurred())
669c86a6acaSLawrence D'Anna return exception();
670c86a6acaSLawrence D'Anna if (!o)
671c86a6acaSLawrence D'Anna return keyError();
672c86a6acaSLawrence D'Anna return Retain<PythonObject>(o);
673c86a6acaSLawrence D'Anna }
674c86a6acaSLawrence D'Anna
GetItem(const Twine & key) const675722b6189SLawrence D'Anna Expected<PythonObject> PythonDictionary::GetItem(const Twine &key) const {
676c86a6acaSLawrence D'Anna if (!IsValid())
677c86a6acaSLawrence D'Anna return nullDeref();
678722b6189SLawrence D'Anna PyObject *o = PyDict_GetItemString(m_py_obj, NullTerminated(key));
679c86a6acaSLawrence D'Anna if (PyErr_Occurred())
680c86a6acaSLawrence D'Anna return exception();
681c86a6acaSLawrence D'Anna if (!o)
682c86a6acaSLawrence D'Anna return keyError();
683c86a6acaSLawrence D'Anna return Retain<PythonObject>(o);
684c86a6acaSLawrence D'Anna }
685c86a6acaSLawrence D'Anna
SetItem(const PythonObject & key,const PythonObject & value) const686c86a6acaSLawrence D'Anna Error PythonDictionary::SetItem(const PythonObject &key,
687c86a6acaSLawrence D'Anna const PythonObject &value) const {
688c86a6acaSLawrence D'Anna if (!IsValid() || !value.IsValid())
689c86a6acaSLawrence D'Anna return nullDeref();
690c86a6acaSLawrence D'Anna int r = PyDict_SetItem(m_py_obj, key.get(), value.get());
691c86a6acaSLawrence D'Anna if (r < 0)
692c86a6acaSLawrence D'Anna return exception();
693c86a6acaSLawrence D'Anna return Error::success();
694c86a6acaSLawrence D'Anna }
695c86a6acaSLawrence D'Anna
SetItem(const Twine & key,const PythonObject & value) const696722b6189SLawrence D'Anna Error PythonDictionary::SetItem(const Twine &key,
697c86a6acaSLawrence D'Anna const PythonObject &value) const {
698c86a6acaSLawrence D'Anna if (!IsValid() || !value.IsValid())
699c86a6acaSLawrence D'Anna return nullDeref();
700722b6189SLawrence D'Anna int r = PyDict_SetItemString(m_py_obj, NullTerminated(key), value.get());
701c86a6acaSLawrence D'Anna if (r < 0)
702c86a6acaSLawrence D'Anna return exception();
703c86a6acaSLawrence D'Anna return Error::success();
704c86a6acaSLawrence D'Anna }
7052c1f46dcSZachary Turner
SetItemForKey(const PythonObject & key,const PythonObject & value)706b9c1b51eSKate Stone void PythonDictionary::SetItemForKey(const PythonObject &key,
707b9c1b51eSKate Stone const PythonObject &value) {
708c86a6acaSLawrence D'Anna Error error = SetItem(key, value);
709c86a6acaSLawrence D'Anna if (error)
710c86a6acaSLawrence D'Anna llvm::consumeError(std::move(error));
7112c1f46dcSZachary Turner }
7122c1f46dcSZachary Turner
7132c1f46dcSZachary Turner StructuredData::DictionarySP
CreateStructuredDictionary() const714b9c1b51eSKate Stone PythonDictionary::CreateStructuredDictionary() const {
7152c1f46dcSZachary Turner StructuredData::DictionarySP result(new StructuredData::Dictionary);
7162c1f46dcSZachary Turner PythonList keys(GetKeys());
7172c1f46dcSZachary Turner uint32_t num_keys = keys.GetSize();
718b9c1b51eSKate Stone for (uint32_t i = 0; i < num_keys; ++i) {
7192c1f46dcSZachary Turner PythonObject key = keys.GetItemAtIndex(i);
7202c1f46dcSZachary Turner PythonObject value = GetItemForKey(key);
7212c1f46dcSZachary Turner StructuredData::ObjectSP structured_value = value.CreateStructuredObject();
722f8b22f8fSZachary Turner result->AddItem(key.Str().GetString(), structured_value);
7232c1f46dcSZachary Turner }
7242c1f46dcSZachary Turner return result;
7252c1f46dcSZachary Turner }
7262c1f46dcSZachary Turner
BuiltinsModule()727*90537673SJonas Devlieghere PythonModule PythonModule::BuiltinsModule() { return AddModule("builtins"); }
728a1405147SZachary Turner
MainModule()729b9c1b51eSKate Stone PythonModule PythonModule::MainModule() { return AddModule("__main__"); }
730a1405147SZachary Turner
AddModule(llvm::StringRef module)731b9c1b51eSKate Stone PythonModule PythonModule::AddModule(llvm::StringRef module) {
732a1405147SZachary Turner std::string str = module.str();
733a1405147SZachary Turner return PythonModule(PyRefType::Borrowed, PyImport_AddModule(str.c_str()));
7347841efbbSZachary Turner }
7357841efbbSZachary Turner
Import(const Twine & name)736722b6189SLawrence D'Anna Expected<PythonModule> PythonModule::Import(const Twine &name) {
737722b6189SLawrence D'Anna PyObject *mod = PyImport_ImportModule(NullTerminated(name));
738085328eeSLawrence D'Anna if (!mod)
739085328eeSLawrence D'Anna return exception();
740085328eeSLawrence D'Anna return Take<PythonModule>(mod);
741085328eeSLawrence D'Anna }
742085328eeSLawrence D'Anna
Get(const Twine & name)743722b6189SLawrence D'Anna Expected<PythonObject> PythonModule::Get(const Twine &name) {
744085328eeSLawrence D'Anna if (!IsValid())
745085328eeSLawrence D'Anna return nullDeref();
746085328eeSLawrence D'Anna PyObject *dict = PyModule_GetDict(m_py_obj);
747085328eeSLawrence D'Anna if (!dict)
748085328eeSLawrence D'Anna return exception();
749722b6189SLawrence D'Anna PyObject *item = PyDict_GetItemString(dict, NullTerminated(name));
750085328eeSLawrence D'Anna if (!item)
751085328eeSLawrence D'Anna return exception();
752085328eeSLawrence D'Anna return Retain<PythonObject>(item);
7532419f1d5SZachary Turner }
7542419f1d5SZachary Turner
Check(PyObject * py_obj)755b9c1b51eSKate Stone bool PythonModule::Check(PyObject *py_obj) {
7567841efbbSZachary Turner if (!py_obj)
7577841efbbSZachary Turner return false;
7587841efbbSZachary Turner
7597841efbbSZachary Turner return PyModule_Check(py_obj);
7607841efbbSZachary Turner }
7617841efbbSZachary Turner
GetDictionary() const762b9c1b51eSKate Stone PythonDictionary PythonModule::GetDictionary() const {
763722b6189SLawrence D'Anna if (!IsValid())
764722b6189SLawrence D'Anna return PythonDictionary();
765722b6189SLawrence D'Anna return Retain<PythonDictionary>(PyModule_GetDict(m_py_obj));
7667841efbbSZachary Turner }
7677841efbbSZachary Turner
Check(PyObject * py_obj)768b9c1b51eSKate Stone bool PythonCallable::Check(PyObject *py_obj) {
769a1405147SZachary Turner if (!py_obj)
770a1405147SZachary Turner return false;
771a1405147SZachary Turner
772a1405147SZachary Turner return PyCallable_Check(py_obj);
773a1405147SZachary Turner }
774a1405147SZachary Turner
775c86a6acaSLawrence D'Anna #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3
776c86a6acaSLawrence D'Anna static const char get_arg_info_script[] = R"(
777c86a6acaSLawrence D'Anna from inspect import signature, Parameter, ismethod
778c86a6acaSLawrence D'Anna from collections import namedtuple
779adbf64ccSLawrence D'Anna ArgInfo = namedtuple('ArgInfo', ['count', 'has_varargs'])
78004edd189SLawrence D'Anna def main(f):
781c86a6acaSLawrence D'Anna count = 0
782c86a6acaSLawrence D'Anna varargs = False
783c86a6acaSLawrence D'Anna for parameter in signature(f).parameters.values():
784c86a6acaSLawrence D'Anna kind = parameter.kind
785c86a6acaSLawrence D'Anna if kind in (Parameter.POSITIONAL_ONLY,
786c86a6acaSLawrence D'Anna Parameter.POSITIONAL_OR_KEYWORD):
787c86a6acaSLawrence D'Anna count += 1
788c86a6acaSLawrence D'Anna elif kind == Parameter.VAR_POSITIONAL:
789c86a6acaSLawrence D'Anna varargs = True
790c86a6acaSLawrence D'Anna elif kind in (Parameter.KEYWORD_ONLY,
791c86a6acaSLawrence D'Anna Parameter.VAR_KEYWORD):
792c86a6acaSLawrence D'Anna pass
793c86a6acaSLawrence D'Anna else:
794c86a6acaSLawrence D'Anna raise Exception(f'unknown parameter kind: {kind}')
795adbf64ccSLawrence D'Anna return ArgInfo(count, varargs)
796c86a6acaSLawrence D'Anna )";
797c86a6acaSLawrence D'Anna #endif
798c86a6acaSLawrence D'Anna
GetArgInfo() const799c86a6acaSLawrence D'Anna Expected<PythonCallable::ArgInfo> PythonCallable::GetArgInfo() const {
800c86a6acaSLawrence D'Anna ArgInfo result = {};
801c86a6acaSLawrence D'Anna if (!IsValid())
802c86a6acaSLawrence D'Anna return nullDeref();
803c86a6acaSLawrence D'Anna
804c86a6acaSLawrence D'Anna #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3
805c86a6acaSLawrence D'Anna
80604edd189SLawrence D'Anna // no need to synchronize access to this global, we already have the GIL
80704edd189SLawrence D'Anna static PythonScript get_arg_info(get_arg_info_script);
80804edd189SLawrence D'Anna Expected<PythonObject> pyarginfo = get_arg_info(*this);
809c86a6acaSLawrence D'Anna if (!pyarginfo)
810c86a6acaSLawrence D'Anna return pyarginfo.takeError();
811adbf64ccSLawrence D'Anna long long count =
812adbf64ccSLawrence D'Anna cantFail(As<long long>(pyarginfo.get().GetAttribute("count")));
813adbf64ccSLawrence D'Anna bool has_varargs =
814c86a6acaSLawrence D'Anna cantFail(As<bool>(pyarginfo.get().GetAttribute("has_varargs")));
815adbf64ccSLawrence D'Anna result.max_positional_args = has_varargs ? ArgInfo::UNBOUNDED : count;
816c86a6acaSLawrence D'Anna
817c86a6acaSLawrence D'Anna #else
818adbf64ccSLawrence D'Anna PyObject *py_func_obj;
8192386537cSLawrence D'Anna bool is_bound_method = false;
820adbf64ccSLawrence D'Anna bool is_class = false;
821adbf64ccSLawrence D'Anna
822adbf64ccSLawrence D'Anna if (PyType_Check(m_py_obj) || PyClass_Check(m_py_obj)) {
823adbf64ccSLawrence D'Anna auto init = GetAttribute("__init__");
824adbf64ccSLawrence D'Anna if (!init)
825adbf64ccSLawrence D'Anna return init.takeError();
826adbf64ccSLawrence D'Anna py_func_obj = init.get().get();
827adbf64ccSLawrence D'Anna is_class = true;
828adbf64ccSLawrence D'Anna } else {
829adbf64ccSLawrence D'Anna py_func_obj = m_py_obj;
830adbf64ccSLawrence D'Anna }
831adbf64ccSLawrence D'Anna
832b9c1b51eSKate Stone if (PyMethod_Check(py_func_obj)) {
833a1405147SZachary Turner py_func_obj = PyMethod_GET_FUNCTION(py_func_obj);
834a5d6765cSEnrico Granata PythonObject im_self = GetAttributeValue("im_self");
835a5d6765cSEnrico Granata if (im_self.IsValid() && !im_self.IsNone())
8362386537cSLawrence D'Anna is_bound_method = true;
837b9c1b51eSKate Stone } else {
838a5d6765cSEnrico Granata // see if this is a callable object with an __call__ method
839b9c1b51eSKate Stone if (!PyFunction_Check(py_func_obj)) {
840a5d6765cSEnrico Granata PythonObject __call__ = GetAttributeValue("__call__");
841b9c1b51eSKate Stone if (__call__.IsValid()) {
842a5d6765cSEnrico Granata auto __callable__ = __call__.AsType<PythonCallable>();
843b9c1b51eSKate Stone if (__callable__.IsValid()) {
844a5d6765cSEnrico Granata py_func_obj = PyMethod_GET_FUNCTION(__callable__.get());
8452386537cSLawrence D'Anna PythonObject im_self = __callable__.GetAttributeValue("im_self");
846a5d6765cSEnrico Granata if (im_self.IsValid() && !im_self.IsNone())
8472386537cSLawrence D'Anna is_bound_method = true;
848a5d6765cSEnrico Granata }
849a5d6765cSEnrico Granata }
850a5d6765cSEnrico Granata }
851a5d6765cSEnrico Granata }
852a1405147SZachary Turner
853a1405147SZachary Turner if (!py_func_obj)
854b58fb2f4SZachary Turner return result;
855a1405147SZachary Turner
856a1405147SZachary Turner PyCodeObject *code = (PyCodeObject *)PyFunction_GET_CODE(py_func_obj);
857a1405147SZachary Turner if (!code)
858b58fb2f4SZachary Turner return result;
859a1405147SZachary Turner
860adbf64ccSLawrence D'Anna auto count = code->co_argcount;
861adbf64ccSLawrence D'Anna bool has_varargs = !!(code->co_flags & CO_VARARGS);
862adbf64ccSLawrence D'Anna result.max_positional_args =
863adbf64ccSLawrence D'Anna has_varargs ? ArgInfo::UNBOUNDED
864adbf64ccSLawrence D'Anna : (count - (int)is_bound_method) - (int)is_class;
865c86a6acaSLawrence D'Anna
866c86a6acaSLawrence D'Anna #endif
867c86a6acaSLawrence D'Anna
868b58fb2f4SZachary Turner return result;
869b58fb2f4SZachary Turner }
870b58fb2f4SZachary Turner
8712386537cSLawrence D'Anna constexpr unsigned
8722386537cSLawrence D'Anna PythonCallable::ArgInfo::UNBOUNDED; // FIXME delete after c++17
8732386537cSLawrence D'Anna
operator ()()874b9c1b51eSKate Stone PythonObject PythonCallable::operator()() {
875b9c1b51eSKate Stone return PythonObject(PyRefType::Owned, PyObject_CallObject(m_py_obj, nullptr));
876a1405147SZachary Turner }
877a1405147SZachary Turner
878b9c1b51eSKate Stone PythonObject PythonCallable::
operator ()(std::initializer_list<PyObject * > args)879b9c1b51eSKate Stone operator()(std::initializer_list<PyObject *> args) {
880a1405147SZachary Turner PythonTuple arg_tuple(args);
881a1405147SZachary Turner return PythonObject(PyRefType::Owned,
882a1405147SZachary Turner PyObject_CallObject(m_py_obj, arg_tuple.get()));
883a1405147SZachary Turner }
884a1405147SZachary Turner
885b9c1b51eSKate Stone PythonObject PythonCallable::
operator ()(std::initializer_list<PythonObject> args)886b9c1b51eSKate Stone operator()(std::initializer_list<PythonObject> args) {
887a1405147SZachary Turner PythonTuple arg_tuple(args);
888a1405147SZachary Turner return PythonObject(PyRefType::Owned,
889a1405147SZachary Turner PyObject_CallObject(m_py_obj, arg_tuple.get()));
890a1405147SZachary Turner }
891a1405147SZachary Turner
Check(PyObject * py_obj)892b9c1b51eSKate Stone bool PythonFile::Check(PyObject *py_obj) {
89396898eb6SLawrence D'Anna if (!py_obj)
89496898eb6SLawrence D'Anna return false;
8959c40264fSZachary Turner // In Python 3, there is no `PyFile_Check`, and in fact PyFile is not even a
8969c40264fSZachary Turner // first-class object type anymore. `PyFile_FromFd` is just a thin wrapper
89705097246SAdrian Prantl // over `io.open()`, which returns some object derived from `io.IOBase`. As a
89805097246SAdrian Prantl // result, the only way to detect a file in Python 3 is to check whether it
89921b8a8aeSLawrence D'Anna // inherits from `io.IOBase`.
90021b8a8aeSLawrence D'Anna auto io_module = PythonModule::Import("io");
90121b8a8aeSLawrence D'Anna if (!io_module) {
90221b8a8aeSLawrence D'Anna llvm::consumeError(io_module.takeError());
9039c40264fSZachary Turner return false;
90421b8a8aeSLawrence D'Anna }
90521b8a8aeSLawrence D'Anna auto iobase = io_module.get().Get("IOBase");
90621b8a8aeSLawrence D'Anna if (!iobase) {
90721b8a8aeSLawrence D'Anna llvm::consumeError(iobase.takeError());
9089c40264fSZachary Turner return false;
90921b8a8aeSLawrence D'Anna }
91021b8a8aeSLawrence D'Anna int r = PyObject_IsInstance(py_obj, iobase.get().get());
91121b8a8aeSLawrence D'Anna if (r < 0) {
91221b8a8aeSLawrence D'Anna llvm::consumeError(exception()); // clear the exception and log it.
91321b8a8aeSLawrence D'Anna return false;
91421b8a8aeSLawrence D'Anna }
91521b8a8aeSLawrence D'Anna return !!r;
9169c40264fSZachary Turner }
9179c40264fSZachary Turner
toCString() const918085328eeSLawrence D'Anna const char *PythonException::toCString() const {
919085328eeSLawrence D'Anna if (!m_repr_bytes)
920085328eeSLawrence D'Anna return "unknown exception";
921085328eeSLawrence D'Anna return PyBytes_AS_STRING(m_repr_bytes);
922085328eeSLawrence D'Anna }
923085328eeSLawrence D'Anna
PythonException(const char * caller)924085328eeSLawrence D'Anna PythonException::PythonException(const char *caller) {
925085328eeSLawrence D'Anna assert(PyErr_Occurred());
926085328eeSLawrence D'Anna m_exception_type = m_exception = m_traceback = m_repr_bytes = NULL;
927085328eeSLawrence D'Anna PyErr_Fetch(&m_exception_type, &m_exception, &m_traceback);
928085328eeSLawrence D'Anna PyErr_NormalizeException(&m_exception_type, &m_exception, &m_traceback);
929085328eeSLawrence D'Anna PyErr_Clear();
930085328eeSLawrence D'Anna if (m_exception) {
931085328eeSLawrence D'Anna PyObject *repr = PyObject_Repr(m_exception);
932085328eeSLawrence D'Anna if (repr) {
933085328eeSLawrence D'Anna m_repr_bytes = PyUnicode_AsEncodedString(repr, "utf-8", nullptr);
934085328eeSLawrence D'Anna if (!m_repr_bytes) {
935085328eeSLawrence D'Anna PyErr_Clear();
936085328eeSLawrence D'Anna }
937085328eeSLawrence D'Anna Py_XDECREF(repr);
938085328eeSLawrence D'Anna } else {
939085328eeSLawrence D'Anna PyErr_Clear();
940085328eeSLawrence D'Anna }
941085328eeSLawrence D'Anna }
942a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Script);
943085328eeSLawrence D'Anna if (caller)
944085328eeSLawrence D'Anna LLDB_LOGF(log, "%s failed with exception: %s", caller, toCString());
945085328eeSLawrence D'Anna else
946085328eeSLawrence D'Anna LLDB_LOGF(log, "python exception: %s", toCString());
947085328eeSLawrence D'Anna }
Restore()948085328eeSLawrence D'Anna void PythonException::Restore() {
949085328eeSLawrence D'Anna if (m_exception_type && m_exception) {
950085328eeSLawrence D'Anna PyErr_Restore(m_exception_type, m_exception, m_traceback);
951085328eeSLawrence D'Anna } else {
952085328eeSLawrence D'Anna PyErr_SetString(PyExc_Exception, toCString());
953085328eeSLawrence D'Anna }
954085328eeSLawrence D'Anna m_exception_type = m_exception = m_traceback = NULL;
955085328eeSLawrence D'Anna }
956085328eeSLawrence D'Anna
~PythonException()957085328eeSLawrence D'Anna PythonException::~PythonException() {
958085328eeSLawrence D'Anna Py_XDECREF(m_exception_type);
959085328eeSLawrence D'Anna Py_XDECREF(m_exception);
960085328eeSLawrence D'Anna Py_XDECREF(m_traceback);
961085328eeSLawrence D'Anna Py_XDECREF(m_repr_bytes);
962085328eeSLawrence D'Anna }
963085328eeSLawrence D'Anna
log(llvm::raw_ostream & OS) const964085328eeSLawrence D'Anna void PythonException::log(llvm::raw_ostream &OS) const { OS << toCString(); }
965085328eeSLawrence D'Anna
convertToErrorCode() const966085328eeSLawrence D'Anna std::error_code PythonException::convertToErrorCode() const {
967085328eeSLawrence D'Anna return llvm::inconvertibleErrorCode();
968085328eeSLawrence D'Anna }
969085328eeSLawrence D'Anna
Matches(PyObject * exc) const97004edd189SLawrence D'Anna bool PythonException::Matches(PyObject *exc) const {
97104edd189SLawrence D'Anna return PyErr_GivenExceptionMatches(m_exception_type, exc);
97204edd189SLawrence D'Anna }
97304edd189SLawrence D'Anna
97404edd189SLawrence D'Anna const char read_exception_script[] = R"(
97504edd189SLawrence D'Anna import sys
97604edd189SLawrence D'Anna from traceback import print_exception
97704edd189SLawrence D'Anna if sys.version_info.major < 3:
97804edd189SLawrence D'Anna from StringIO import StringIO
97904edd189SLawrence D'Anna else:
98004edd189SLawrence D'Anna from io import StringIO
98104edd189SLawrence D'Anna def main(exc_type, exc_value, tb):
98204edd189SLawrence D'Anna f = StringIO()
98304edd189SLawrence D'Anna print_exception(exc_type, exc_value, tb, file=f)
98404edd189SLawrence D'Anna return f.getvalue()
98504edd189SLawrence D'Anna )";
98604edd189SLawrence D'Anna
ReadBacktrace() const98704edd189SLawrence D'Anna std::string PythonException::ReadBacktrace() const {
98804edd189SLawrence D'Anna
98904edd189SLawrence D'Anna if (!m_traceback)
99004edd189SLawrence D'Anna return toCString();
99104edd189SLawrence D'Anna
99204edd189SLawrence D'Anna // no need to synchronize access to this global, we already have the GIL
99304edd189SLawrence D'Anna static PythonScript read_exception(read_exception_script);
99404edd189SLawrence D'Anna
99504edd189SLawrence D'Anna Expected<std::string> backtrace = As<std::string>(
99604edd189SLawrence D'Anna read_exception(m_exception_type, m_exception, m_traceback));
99704edd189SLawrence D'Anna
99804edd189SLawrence D'Anna if (!backtrace) {
99904edd189SLawrence D'Anna std::string message =
100004edd189SLawrence D'Anna std::string(toCString()) + "\n" +
1001e9264b74SKazuaki Ishizaki "Traceback unavailable, an error occurred while reading it:\n";
100204edd189SLawrence D'Anna return (message + llvm::toString(backtrace.takeError()));
100304edd189SLawrence D'Anna }
100404edd189SLawrence D'Anna
100504edd189SLawrence D'Anna return std::move(backtrace.get());
100604edd189SLawrence D'Anna }
100704edd189SLawrence D'Anna
1008085328eeSLawrence D'Anna char PythonException::ID = 0;
1009085328eeSLawrence D'Anna
101062c9fe42SLawrence D'Anna llvm::Expected<File::OpenOptions>
GetOptionsForPyObject(const PythonObject & obj)101162c9fe42SLawrence D'Anna GetOptionsForPyObject(const PythonObject &obj) {
101262c9fe42SLawrence D'Anna auto options = File::OpenOptions(0);
101321b8a8aeSLawrence D'Anna auto readable = As<bool>(obj.CallMethod("readable"));
101421b8a8aeSLawrence D'Anna if (!readable)
101521b8a8aeSLawrence D'Anna return readable.takeError();
101621b8a8aeSLawrence D'Anna auto writable = As<bool>(obj.CallMethod("writable"));
101721b8a8aeSLawrence D'Anna if (!writable)
101821b8a8aeSLawrence D'Anna return writable.takeError();
101914735cabSMichał Górny if (readable.get() && writable.get())
102014735cabSMichał Górny options |= File::eOpenOptionReadWrite;
102114735cabSMichał Górny else if (writable.get())
102214735cabSMichał Górny options |= File::eOpenOptionWriteOnly;
102314735cabSMichał Górny else if (readable.get())
102414735cabSMichał Górny options |= File::eOpenOptionReadOnly;
102562c9fe42SLawrence D'Anna return options;
102621b8a8aeSLawrence D'Anna }
102721b8a8aeSLawrence D'Anna
102821b8a8aeSLawrence D'Anna // Base class template for python files. All it knows how to do
102921b8a8aeSLawrence D'Anna // is hold a reference to the python object and close or flush it
103021b8a8aeSLawrence D'Anna // when the File is closed.
103121b8a8aeSLawrence D'Anna namespace {
103221b8a8aeSLawrence D'Anna template <typename Base> class OwnedPythonFile : public Base {
103321b8a8aeSLawrence D'Anna public:
103421b8a8aeSLawrence D'Anna template <typename... Args>
OwnedPythonFile(const PythonFile & file,bool borrowed,Args...args)103521b8a8aeSLawrence D'Anna OwnedPythonFile(const PythonFile &file, bool borrowed, Args... args)
103621b8a8aeSLawrence D'Anna : Base(args...), m_py_obj(file), m_borrowed(borrowed) {
103721b8a8aeSLawrence D'Anna assert(m_py_obj);
103821b8a8aeSLawrence D'Anna }
103921b8a8aeSLawrence D'Anna
~OwnedPythonFile()104021b8a8aeSLawrence D'Anna ~OwnedPythonFile() override {
104121b8a8aeSLawrence D'Anna assert(m_py_obj);
104221b8a8aeSLawrence D'Anna GIL takeGIL;
104321b8a8aeSLawrence D'Anna Close();
1044722b6189SLawrence D'Anna // we need to ensure the python object is released while we still
1045722b6189SLawrence D'Anna // hold the GIL
104621b8a8aeSLawrence D'Anna m_py_obj.Reset();
104721b8a8aeSLawrence D'Anna }
104821b8a8aeSLawrence D'Anna
IsPythonSideValid() const104921b8a8aeSLawrence D'Anna bool IsPythonSideValid() const {
105021b8a8aeSLawrence D'Anna GIL takeGIL;
105121b8a8aeSLawrence D'Anna auto closed = As<bool>(m_py_obj.GetAttribute("closed"));
105221b8a8aeSLawrence D'Anna if (!closed) {
105321b8a8aeSLawrence D'Anna llvm::consumeError(closed.takeError());
105421b8a8aeSLawrence D'Anna return false;
105521b8a8aeSLawrence D'Anna }
105621b8a8aeSLawrence D'Anna return !closed.get();
105721b8a8aeSLawrence D'Anna }
105821b8a8aeSLawrence D'Anna
IsValid() const105921b8a8aeSLawrence D'Anna bool IsValid() const override {
106021b8a8aeSLawrence D'Anna return IsPythonSideValid() && Base::IsValid();
106121b8a8aeSLawrence D'Anna }
106221b8a8aeSLawrence D'Anna
Close()106321b8a8aeSLawrence D'Anna Status Close() override {
106421b8a8aeSLawrence D'Anna assert(m_py_obj);
106521b8a8aeSLawrence D'Anna Status py_error, base_error;
106621b8a8aeSLawrence D'Anna GIL takeGIL;
106721b8a8aeSLawrence D'Anna if (!m_borrowed) {
106821b8a8aeSLawrence D'Anna auto r = m_py_obj.CallMethod("close");
106921b8a8aeSLawrence D'Anna if (!r)
107021b8a8aeSLawrence D'Anna py_error = Status(r.takeError());
107121b8a8aeSLawrence D'Anna }
107221b8a8aeSLawrence D'Anna base_error = Base::Close();
107321b8a8aeSLawrence D'Anna if (py_error.Fail())
107421b8a8aeSLawrence D'Anna return py_error;
107521b8a8aeSLawrence D'Anna return base_error;
107621b8a8aeSLawrence D'Anna };
107721b8a8aeSLawrence D'Anna
GetPythonObject() const1078d9b553ecSLawrence D'Anna PyObject *GetPythonObject() const {
1079d9b553ecSLawrence D'Anna assert(m_py_obj.IsValid());
1080d9b553ecSLawrence D'Anna return m_py_obj.get();
1081d9b553ecSLawrence D'Anna }
1082d9b553ecSLawrence D'Anna
1083d9b553ecSLawrence D'Anna static bool classof(const File *file) = delete;
1084d9b553ecSLawrence D'Anna
108521b8a8aeSLawrence D'Anna protected:
108621b8a8aeSLawrence D'Anna PythonFile m_py_obj;
108721b8a8aeSLawrence D'Anna bool m_borrowed;
108821b8a8aeSLawrence D'Anna };
108921b8a8aeSLawrence D'Anna } // namespace
109021b8a8aeSLawrence D'Anna
109121b8a8aeSLawrence D'Anna // A SimplePythonFile is a OwnedPythonFile that just does all I/O as
109221b8a8aeSLawrence D'Anna // a NativeFile
109321b8a8aeSLawrence D'Anna namespace {
109421b8a8aeSLawrence D'Anna class SimplePythonFile : public OwnedPythonFile<NativeFile> {
109521b8a8aeSLawrence D'Anna public:
SimplePythonFile(const PythonFile & file,bool borrowed,int fd,File::OpenOptions options)109621b8a8aeSLawrence D'Anna SimplePythonFile(const PythonFile &file, bool borrowed, int fd,
109762c9fe42SLawrence D'Anna File::OpenOptions options)
109821b8a8aeSLawrence D'Anna : OwnedPythonFile(file, borrowed, fd, options, false) {}
1099d9b553ecSLawrence D'Anna
1100d9b553ecSLawrence D'Anna static char ID;
isA(const void * classID) const1101d9b553ecSLawrence D'Anna bool isA(const void *classID) const override {
1102d9b553ecSLawrence D'Anna return classID == &ID || NativeFile::isA(classID);
1103d9b553ecSLawrence D'Anna }
classof(const File * file)1104d9b553ecSLawrence D'Anna static bool classof(const File *file) { return file->isA(&ID); }
110521b8a8aeSLawrence D'Anna };
1106d9b553ecSLawrence D'Anna char SimplePythonFile::ID = 0;
110721b8a8aeSLawrence D'Anna } // namespace
110821b8a8aeSLawrence D'Anna
110921b8a8aeSLawrence D'Anna namespace {
111021b8a8aeSLawrence D'Anna class PythonBuffer {
111121b8a8aeSLawrence D'Anna public:
111221b8a8aeSLawrence D'Anna PythonBuffer &operator=(const PythonBuffer &) = delete;
111321b8a8aeSLawrence D'Anna PythonBuffer(const PythonBuffer &) = delete;
111421b8a8aeSLawrence D'Anna
Create(PythonObject & obj,int flags=PyBUF_SIMPLE)111521b8a8aeSLawrence D'Anna static Expected<PythonBuffer> Create(PythonObject &obj,
111621b8a8aeSLawrence D'Anna int flags = PyBUF_SIMPLE) {
111721b8a8aeSLawrence D'Anna Py_buffer py_buffer = {};
111821b8a8aeSLawrence D'Anna PyObject_GetBuffer(obj.get(), &py_buffer, flags);
111921b8a8aeSLawrence D'Anna if (!py_buffer.obj)
112021b8a8aeSLawrence D'Anna return llvm::make_error<PythonException>();
112121b8a8aeSLawrence D'Anna return PythonBuffer(py_buffer);
112221b8a8aeSLawrence D'Anna }
112321b8a8aeSLawrence D'Anna
PythonBuffer(PythonBuffer && other)112421b8a8aeSLawrence D'Anna PythonBuffer(PythonBuffer &&other) {
112521b8a8aeSLawrence D'Anna m_buffer = other.m_buffer;
112621b8a8aeSLawrence D'Anna other.m_buffer.obj = nullptr;
112721b8a8aeSLawrence D'Anna }
112821b8a8aeSLawrence D'Anna
~PythonBuffer()112921b8a8aeSLawrence D'Anna ~PythonBuffer() {
113021b8a8aeSLawrence D'Anna if (m_buffer.obj)
113121b8a8aeSLawrence D'Anna PyBuffer_Release(&m_buffer);
113221b8a8aeSLawrence D'Anna }
113321b8a8aeSLawrence D'Anna
get()113421b8a8aeSLawrence D'Anna Py_buffer &get() { return m_buffer; }
113521b8a8aeSLawrence D'Anna
113621b8a8aeSLawrence D'Anna private:
113721b8a8aeSLawrence D'Anna // takes ownership of the buffer.
PythonBuffer(const Py_buffer & py_buffer)113821b8a8aeSLawrence D'Anna PythonBuffer(const Py_buffer &py_buffer) : m_buffer(py_buffer) {}
113921b8a8aeSLawrence D'Anna Py_buffer m_buffer;
114021b8a8aeSLawrence D'Anna };
114121b8a8aeSLawrence D'Anna } // namespace
114221b8a8aeSLawrence D'Anna
114321b8a8aeSLawrence D'Anna // Shared methods between TextPythonFile and BinaryPythonFile
114421b8a8aeSLawrence D'Anna namespace {
114521b8a8aeSLawrence D'Anna class PythonIOFile : public OwnedPythonFile<File> {
114621b8a8aeSLawrence D'Anna public:
PythonIOFile(const PythonFile & file,bool borrowed)114721b8a8aeSLawrence D'Anna PythonIOFile(const PythonFile &file, bool borrowed)
114821b8a8aeSLawrence D'Anna : OwnedPythonFile(file, borrowed) {}
114921b8a8aeSLawrence D'Anna
~PythonIOFile()115021b8a8aeSLawrence D'Anna ~PythonIOFile() override { Close(); }
115121b8a8aeSLawrence D'Anna
IsValid() const115221b8a8aeSLawrence D'Anna bool IsValid() const override { return IsPythonSideValid(); }
115321b8a8aeSLawrence D'Anna
Close()115421b8a8aeSLawrence D'Anna Status Close() override {
115521b8a8aeSLawrence D'Anna assert(m_py_obj);
115621b8a8aeSLawrence D'Anna GIL takeGIL;
115721b8a8aeSLawrence D'Anna if (m_borrowed)
115821b8a8aeSLawrence D'Anna return Flush();
115921b8a8aeSLawrence D'Anna auto r = m_py_obj.CallMethod("close");
116021b8a8aeSLawrence D'Anna if (!r)
116121b8a8aeSLawrence D'Anna return Status(r.takeError());
116221b8a8aeSLawrence D'Anna return Status();
116321b8a8aeSLawrence D'Anna }
116421b8a8aeSLawrence D'Anna
Flush()116521b8a8aeSLawrence D'Anna Status Flush() override {
116621b8a8aeSLawrence D'Anna GIL takeGIL;
116721b8a8aeSLawrence D'Anna auto r = m_py_obj.CallMethod("flush");
116821b8a8aeSLawrence D'Anna if (!r)
116921b8a8aeSLawrence D'Anna return Status(r.takeError());
117021b8a8aeSLawrence D'Anna return Status();
117121b8a8aeSLawrence D'Anna }
117221b8a8aeSLawrence D'Anna
GetOptions() const1173d9b553ecSLawrence D'Anna Expected<File::OpenOptions> GetOptions() const override {
1174d9b553ecSLawrence D'Anna GIL takeGIL;
1175d9b553ecSLawrence D'Anna return GetOptionsForPyObject(m_py_obj);
1176d9b553ecSLawrence D'Anna }
1177d9b553ecSLawrence D'Anna
1178d9b553ecSLawrence D'Anna static char ID;
isA(const void * classID) const1179d9b553ecSLawrence D'Anna bool isA(const void *classID) const override {
1180d9b553ecSLawrence D'Anna return classID == &ID || File::isA(classID);
1181d9b553ecSLawrence D'Anna }
classof(const File * file)1182d9b553ecSLawrence D'Anna static bool classof(const File *file) { return file->isA(&ID); }
118321b8a8aeSLawrence D'Anna };
1184d9b553ecSLawrence D'Anna char PythonIOFile::ID = 0;
118521b8a8aeSLawrence D'Anna } // namespace
118621b8a8aeSLawrence D'Anna
118721b8a8aeSLawrence D'Anna namespace {
118821b8a8aeSLawrence D'Anna class BinaryPythonFile : public PythonIOFile {
118921b8a8aeSLawrence D'Anna protected:
119021b8a8aeSLawrence D'Anna int m_descriptor;
119121b8a8aeSLawrence D'Anna
119221b8a8aeSLawrence D'Anna public:
BinaryPythonFile(int fd,const PythonFile & file,bool borrowed)119321b8a8aeSLawrence D'Anna BinaryPythonFile(int fd, const PythonFile &file, bool borrowed)
119421b8a8aeSLawrence D'Anna : PythonIOFile(file, borrowed),
119521b8a8aeSLawrence D'Anna m_descriptor(File::DescriptorIsValid(fd) ? fd
119621b8a8aeSLawrence D'Anna : File::kInvalidDescriptor) {}
119721b8a8aeSLawrence D'Anna
GetDescriptor() const119821b8a8aeSLawrence D'Anna int GetDescriptor() const override { return m_descriptor; }
119921b8a8aeSLawrence D'Anna
Write(const void * buf,size_t & num_bytes)120021b8a8aeSLawrence D'Anna Status Write(const void *buf, size_t &num_bytes) override {
120121b8a8aeSLawrence D'Anna GIL takeGIL;
120221b8a8aeSLawrence D'Anna PyObject *pybuffer_p = PyMemoryView_FromMemory(
120321b8a8aeSLawrence D'Anna const_cast<char *>((const char *)buf), num_bytes, PyBUF_READ);
120421b8a8aeSLawrence D'Anna if (!pybuffer_p)
120521b8a8aeSLawrence D'Anna return Status(llvm::make_error<PythonException>());
120621b8a8aeSLawrence D'Anna auto pybuffer = Take<PythonObject>(pybuffer_p);
120721b8a8aeSLawrence D'Anna num_bytes = 0;
120821b8a8aeSLawrence D'Anna auto bytes_written = As<long long>(m_py_obj.CallMethod("write", pybuffer));
120921b8a8aeSLawrence D'Anna if (!bytes_written)
121021b8a8aeSLawrence D'Anna return Status(bytes_written.takeError());
121121b8a8aeSLawrence D'Anna if (bytes_written.get() < 0)
121221b8a8aeSLawrence D'Anna return Status(".write() method returned a negative number!");
121321b8a8aeSLawrence D'Anna static_assert(sizeof(long long) >= sizeof(size_t), "overflow");
121421b8a8aeSLawrence D'Anna num_bytes = bytes_written.get();
121521b8a8aeSLawrence D'Anna return Status();
121621b8a8aeSLawrence D'Anna }
121721b8a8aeSLawrence D'Anna
Read(void * buf,size_t & num_bytes)121821b8a8aeSLawrence D'Anna Status Read(void *buf, size_t &num_bytes) override {
121921b8a8aeSLawrence D'Anna GIL takeGIL;
122021b8a8aeSLawrence D'Anna static_assert(sizeof(long long) >= sizeof(size_t), "overflow");
122121b8a8aeSLawrence D'Anna auto pybuffer_obj =
122221b8a8aeSLawrence D'Anna m_py_obj.CallMethod("read", (unsigned long long)num_bytes);
122321b8a8aeSLawrence D'Anna if (!pybuffer_obj)
122421b8a8aeSLawrence D'Anna return Status(pybuffer_obj.takeError());
122521b8a8aeSLawrence D'Anna num_bytes = 0;
122621b8a8aeSLawrence D'Anna if (pybuffer_obj.get().IsNone()) {
122721b8a8aeSLawrence D'Anna // EOF
122821b8a8aeSLawrence D'Anna num_bytes = 0;
122921b8a8aeSLawrence D'Anna return Status();
123021b8a8aeSLawrence D'Anna }
123121b8a8aeSLawrence D'Anna auto pybuffer = PythonBuffer::Create(pybuffer_obj.get());
123221b8a8aeSLawrence D'Anna if (!pybuffer)
123321b8a8aeSLawrence D'Anna return Status(pybuffer.takeError());
123421b8a8aeSLawrence D'Anna memcpy(buf, pybuffer.get().get().buf, pybuffer.get().get().len);
123521b8a8aeSLawrence D'Anna num_bytes = pybuffer.get().get().len;
123621b8a8aeSLawrence D'Anna return Status();
123721b8a8aeSLawrence D'Anna }
123821b8a8aeSLawrence D'Anna };
123921b8a8aeSLawrence D'Anna } // namespace
124021b8a8aeSLawrence D'Anna
124121b8a8aeSLawrence D'Anna namespace {
124221b8a8aeSLawrence D'Anna class TextPythonFile : public PythonIOFile {
124321b8a8aeSLawrence D'Anna protected:
124421b8a8aeSLawrence D'Anna int m_descriptor;
124521b8a8aeSLawrence D'Anna
124621b8a8aeSLawrence D'Anna public:
TextPythonFile(int fd,const PythonFile & file,bool borrowed)124721b8a8aeSLawrence D'Anna TextPythonFile(int fd, const PythonFile &file, bool borrowed)
124821b8a8aeSLawrence D'Anna : PythonIOFile(file, borrowed),
124921b8a8aeSLawrence D'Anna m_descriptor(File::DescriptorIsValid(fd) ? fd
125021b8a8aeSLawrence D'Anna : File::kInvalidDescriptor) {}
125121b8a8aeSLawrence D'Anna
GetDescriptor() const125221b8a8aeSLawrence D'Anna int GetDescriptor() const override { return m_descriptor; }
125321b8a8aeSLawrence D'Anna
Write(const void * buf,size_t & num_bytes)125421b8a8aeSLawrence D'Anna Status Write(const void *buf, size_t &num_bytes) override {
125521b8a8aeSLawrence D'Anna GIL takeGIL;
125621b8a8aeSLawrence D'Anna auto pystring =
125721b8a8aeSLawrence D'Anna PythonString::FromUTF8(llvm::StringRef((const char *)buf, num_bytes));
125821b8a8aeSLawrence D'Anna if (!pystring)
125921b8a8aeSLawrence D'Anna return Status(pystring.takeError());
126021b8a8aeSLawrence D'Anna num_bytes = 0;
126121b8a8aeSLawrence D'Anna auto bytes_written =
126221b8a8aeSLawrence D'Anna As<long long>(m_py_obj.CallMethod("write", pystring.get()));
126321b8a8aeSLawrence D'Anna if (!bytes_written)
126421b8a8aeSLawrence D'Anna return Status(bytes_written.takeError());
126521b8a8aeSLawrence D'Anna if (bytes_written.get() < 0)
126621b8a8aeSLawrence D'Anna return Status(".write() method returned a negative number!");
126721b8a8aeSLawrence D'Anna static_assert(sizeof(long long) >= sizeof(size_t), "overflow");
126821b8a8aeSLawrence D'Anna num_bytes = bytes_written.get();
126921b8a8aeSLawrence D'Anna return Status();
127021b8a8aeSLawrence D'Anna }
127121b8a8aeSLawrence D'Anna
Read(void * buf,size_t & num_bytes)127221b8a8aeSLawrence D'Anna Status Read(void *buf, size_t &num_bytes) override {
127321b8a8aeSLawrence D'Anna GIL takeGIL;
127421b8a8aeSLawrence D'Anna size_t num_chars = num_bytes / 6;
127521b8a8aeSLawrence D'Anna size_t orig_num_bytes = num_bytes;
127621b8a8aeSLawrence D'Anna num_bytes = 0;
127721b8a8aeSLawrence D'Anna if (orig_num_bytes < 6) {
127821b8a8aeSLawrence D'Anna return Status("can't read less than 6 bytes from a utf8 text stream");
127921b8a8aeSLawrence D'Anna }
128021b8a8aeSLawrence D'Anna auto pystring = As<PythonString>(
128121b8a8aeSLawrence D'Anna m_py_obj.CallMethod("read", (unsigned long long)num_chars));
128221b8a8aeSLawrence D'Anna if (!pystring)
128321b8a8aeSLawrence D'Anna return Status(pystring.takeError());
128421b8a8aeSLawrence D'Anna if (pystring.get().IsNone()) {
128521b8a8aeSLawrence D'Anna // EOF
128621b8a8aeSLawrence D'Anna return Status();
128721b8a8aeSLawrence D'Anna }
128821b8a8aeSLawrence D'Anna auto stringref = pystring.get().AsUTF8();
128921b8a8aeSLawrence D'Anna if (!stringref)
129021b8a8aeSLawrence D'Anna return Status(stringref.takeError());
129121b8a8aeSLawrence D'Anna num_bytes = stringref.get().size();
129221b8a8aeSLawrence D'Anna memcpy(buf, stringref.get().begin(), num_bytes);
129321b8a8aeSLawrence D'Anna return Status();
129421b8a8aeSLawrence D'Anna }
129521b8a8aeSLawrence D'Anna };
129621b8a8aeSLawrence D'Anna } // namespace
129721b8a8aeSLawrence D'Anna
ConvertToFile(bool borrowed)129821b8a8aeSLawrence D'Anna llvm::Expected<FileSP> PythonFile::ConvertToFile(bool borrowed) {
129921b8a8aeSLawrence D'Anna if (!IsValid())
130021b8a8aeSLawrence D'Anna return llvm::createStringError(llvm::inconvertibleErrorCode(),
130121b8a8aeSLawrence D'Anna "invalid PythonFile");
130221b8a8aeSLawrence D'Anna
130321b8a8aeSLawrence D'Anna int fd = PyObject_AsFileDescriptor(m_py_obj);
130421b8a8aeSLawrence D'Anna if (fd < 0) {
130521b8a8aeSLawrence D'Anna PyErr_Clear();
130621b8a8aeSLawrence D'Anna return ConvertToFileForcingUseOfScriptingIOMethods(borrowed);
130721b8a8aeSLawrence D'Anna }
130821b8a8aeSLawrence D'Anna auto options = GetOptionsForPyObject(*this);
130921b8a8aeSLawrence D'Anna if (!options)
131021b8a8aeSLawrence D'Anna return options.takeError();
131121b8a8aeSLawrence D'Anna
131214735cabSMichał Górny File::OpenOptions rw =
131314735cabSMichał Górny options.get() & (File::eOpenOptionReadOnly | File::eOpenOptionWriteOnly |
131414735cabSMichał Górny File::eOpenOptionReadWrite);
131514735cabSMichał Górny if (rw == File::eOpenOptionWriteOnly || rw == File::eOpenOptionReadWrite) {
131621b8a8aeSLawrence D'Anna // LLDB and python will not share I/O buffers. We should probably
131721b8a8aeSLawrence D'Anna // flush the python buffers now.
131821b8a8aeSLawrence D'Anna auto r = CallMethod("flush");
131921b8a8aeSLawrence D'Anna if (!r)
132021b8a8aeSLawrence D'Anna return r.takeError();
1321267cc329SMichal Gorny }
132221b8a8aeSLawrence D'Anna
132321b8a8aeSLawrence D'Anna FileSP file_sp;
132421b8a8aeSLawrence D'Anna if (borrowed) {
132521b8a8aeSLawrence D'Anna // In this case we we don't need to retain the python
132621b8a8aeSLawrence D'Anna // object at all.
132721b8a8aeSLawrence D'Anna file_sp = std::make_shared<NativeFile>(fd, options.get(), false);
132821b8a8aeSLawrence D'Anna } else {
132921b8a8aeSLawrence D'Anna file_sp = std::static_pointer_cast<File>(
133021b8a8aeSLawrence D'Anna std::make_shared<SimplePythonFile>(*this, borrowed, fd, options.get()));
133121b8a8aeSLawrence D'Anna }
133221b8a8aeSLawrence D'Anna if (!file_sp->IsValid())
133321b8a8aeSLawrence D'Anna return llvm::createStringError(llvm::inconvertibleErrorCode(),
133421b8a8aeSLawrence D'Anna "invalid File");
133521b8a8aeSLawrence D'Anna
133621b8a8aeSLawrence D'Anna return file_sp;
133721b8a8aeSLawrence D'Anna }
133821b8a8aeSLawrence D'Anna
133921b8a8aeSLawrence D'Anna llvm::Expected<FileSP>
ConvertToFileForcingUseOfScriptingIOMethods(bool borrowed)134021b8a8aeSLawrence D'Anna PythonFile::ConvertToFileForcingUseOfScriptingIOMethods(bool borrowed) {
134121b8a8aeSLawrence D'Anna
134221b8a8aeSLawrence D'Anna assert(!PyErr_Occurred());
134321b8a8aeSLawrence D'Anna
134421b8a8aeSLawrence D'Anna if (!IsValid())
134521b8a8aeSLawrence D'Anna return llvm::createStringError(llvm::inconvertibleErrorCode(),
134621b8a8aeSLawrence D'Anna "invalid PythonFile");
134721b8a8aeSLawrence D'Anna
134821b8a8aeSLawrence D'Anna int fd = PyObject_AsFileDescriptor(m_py_obj);
134921b8a8aeSLawrence D'Anna if (fd < 0) {
135021b8a8aeSLawrence D'Anna PyErr_Clear();
135121b8a8aeSLawrence D'Anna fd = File::kInvalidDescriptor;
135221b8a8aeSLawrence D'Anna }
135321b8a8aeSLawrence D'Anna
135421b8a8aeSLawrence D'Anna auto io_module = PythonModule::Import("io");
135521b8a8aeSLawrence D'Anna if (!io_module)
135621b8a8aeSLawrence D'Anna return io_module.takeError();
135721b8a8aeSLawrence D'Anna auto textIOBase = io_module.get().Get("TextIOBase");
135821b8a8aeSLawrence D'Anna if (!textIOBase)
135921b8a8aeSLawrence D'Anna return textIOBase.takeError();
136021b8a8aeSLawrence D'Anna auto rawIOBase = io_module.get().Get("RawIOBase");
136121b8a8aeSLawrence D'Anna if (!rawIOBase)
136221b8a8aeSLawrence D'Anna return rawIOBase.takeError();
136321b8a8aeSLawrence D'Anna auto bufferedIOBase = io_module.get().Get("BufferedIOBase");
136421b8a8aeSLawrence D'Anna if (!bufferedIOBase)
136521b8a8aeSLawrence D'Anna return bufferedIOBase.takeError();
136621b8a8aeSLawrence D'Anna
136721b8a8aeSLawrence D'Anna FileSP file_sp;
136821b8a8aeSLawrence D'Anna
136921b8a8aeSLawrence D'Anna auto isTextIO = IsInstance(textIOBase.get());
137021b8a8aeSLawrence D'Anna if (!isTextIO)
137121b8a8aeSLawrence D'Anna return isTextIO.takeError();
137221b8a8aeSLawrence D'Anna if (isTextIO.get())
137321b8a8aeSLawrence D'Anna file_sp = std::static_pointer_cast<File>(
137421b8a8aeSLawrence D'Anna std::make_shared<TextPythonFile>(fd, *this, borrowed));
137521b8a8aeSLawrence D'Anna
137621b8a8aeSLawrence D'Anna auto isRawIO = IsInstance(rawIOBase.get());
137721b8a8aeSLawrence D'Anna if (!isRawIO)
137821b8a8aeSLawrence D'Anna return isRawIO.takeError();
137921b8a8aeSLawrence D'Anna auto isBufferedIO = IsInstance(bufferedIOBase.get());
138021b8a8aeSLawrence D'Anna if (!isBufferedIO)
138121b8a8aeSLawrence D'Anna return isBufferedIO.takeError();
138221b8a8aeSLawrence D'Anna
138321b8a8aeSLawrence D'Anna if (isRawIO.get() || isBufferedIO.get()) {
138421b8a8aeSLawrence D'Anna file_sp = std::static_pointer_cast<File>(
138521b8a8aeSLawrence D'Anna std::make_shared<BinaryPythonFile>(fd, *this, borrowed));
138621b8a8aeSLawrence D'Anna }
138721b8a8aeSLawrence D'Anna
138821b8a8aeSLawrence D'Anna if (!file_sp)
138921b8a8aeSLawrence D'Anna return llvm::createStringError(llvm::inconvertibleErrorCode(),
139021b8a8aeSLawrence D'Anna "python file is neither text nor binary");
139121b8a8aeSLawrence D'Anna
139221b8a8aeSLawrence D'Anna if (!file_sp->IsValid())
139321b8a8aeSLawrence D'Anna return llvm::createStringError(llvm::inconvertibleErrorCode(),
139421b8a8aeSLawrence D'Anna "invalid File");
139521b8a8aeSLawrence D'Anna
139621b8a8aeSLawrence D'Anna return file_sp;
139721b8a8aeSLawrence D'Anna }
139821b8a8aeSLawrence D'Anna
FromFile(File & file,const char * mode)1399d9b553ecSLawrence D'Anna Expected<PythonFile> PythonFile::FromFile(File &file, const char *mode) {
1400d9b553ecSLawrence D'Anna if (!file.IsValid())
1401d9b553ecSLawrence D'Anna return llvm::createStringError(llvm::inconvertibleErrorCode(),
1402d9b553ecSLawrence D'Anna "invalid file");
1403d9b553ecSLawrence D'Anna
1404d9b553ecSLawrence D'Anna if (auto *simple = llvm::dyn_cast<SimplePythonFile>(&file))
1405d9b553ecSLawrence D'Anna return Retain<PythonFile>(simple->GetPythonObject());
1406d9b553ecSLawrence D'Anna if (auto *pythonio = llvm::dyn_cast<PythonIOFile>(&file))
1407d9b553ecSLawrence D'Anna return Retain<PythonFile>(pythonio->GetPythonObject());
1408d9b553ecSLawrence D'Anna
1409d9b553ecSLawrence D'Anna if (!mode) {
1410d9b553ecSLawrence D'Anna auto m = file.GetOpenMode();
1411d9b553ecSLawrence D'Anna if (!m)
1412d9b553ecSLawrence D'Anna return m.takeError();
1413d9b553ecSLawrence D'Anna mode = m.get();
1414d9b553ecSLawrence D'Anna }
1415d9b553ecSLawrence D'Anna
1416d9b553ecSLawrence D'Anna PyObject *file_obj;
1417d9b553ecSLawrence D'Anna file_obj = PyFile_FromFd(file.GetDescriptor(), nullptr, mode, -1, nullptr,
14183071ebf7SLawrence D'Anna "ignore", nullptr, /*closefd=*/0);
1419d9b553ecSLawrence D'Anna
1420d9b553ecSLawrence D'Anna if (!file_obj)
1421d9b553ecSLawrence D'Anna return exception();
1422d9b553ecSLawrence D'Anna
1423d9b553ecSLawrence D'Anna return Take<PythonFile>(file_obj);
1424d9b553ecSLawrence D'Anna }
1425d9b553ecSLawrence D'Anna
Init()142604edd189SLawrence D'Anna Error PythonScript::Init() {
142704edd189SLawrence D'Anna if (function.IsValid())
142804edd189SLawrence D'Anna return Error::success();
142904edd189SLawrence D'Anna
143004edd189SLawrence D'Anna PythonDictionary globals(PyInitialValue::Empty);
143104edd189SLawrence D'Anna auto builtins = PythonModule::BuiltinsModule();
143204edd189SLawrence D'Anna if (Error error = globals.SetItem("__builtins__", builtins))
143304edd189SLawrence D'Anna return error;
143404edd189SLawrence D'Anna PyObject *o =
143504edd189SLawrence D'Anna PyRun_String(script, Py_file_input, globals.get(), globals.get());
143604edd189SLawrence D'Anna if (!o)
143704edd189SLawrence D'Anna return exception();
143804edd189SLawrence D'Anna Take<PythonObject>(o);
143904edd189SLawrence D'Anna auto f = As<PythonCallable>(globals.GetItem("main"));
144004edd189SLawrence D'Anna if (!f)
144104edd189SLawrence D'Anna return f.takeError();
144204edd189SLawrence D'Anna function = std::move(f.get());
144304edd189SLawrence D'Anna
144404edd189SLawrence D'Anna return Error::success();
144504edd189SLawrence D'Anna }
144604edd189SLawrence D'Anna
144704edd189SLawrence D'Anna llvm::Expected<PythonObject>
runStringOneLine(const llvm::Twine & string,const PythonDictionary & globals,const PythonDictionary & locals)144804edd189SLawrence D'Anna python::runStringOneLine(const llvm::Twine &string,
144904edd189SLawrence D'Anna const PythonDictionary &globals,
145004edd189SLawrence D'Anna const PythonDictionary &locals) {
145104edd189SLawrence D'Anna if (!globals.IsValid() || !locals.IsValid())
145204edd189SLawrence D'Anna return nullDeref();
145304edd189SLawrence D'Anna
145404edd189SLawrence D'Anna PyObject *code =
145504edd189SLawrence D'Anna Py_CompileString(NullTerminated(string), "<string>", Py_eval_input);
145604edd189SLawrence D'Anna if (!code) {
145704edd189SLawrence D'Anna PyErr_Clear();
145804edd189SLawrence D'Anna code =
145904edd189SLawrence D'Anna Py_CompileString(NullTerminated(string), "<string>", Py_single_input);
146004edd189SLawrence D'Anna }
146104edd189SLawrence D'Anna if (!code)
146204edd189SLawrence D'Anna return exception();
146304edd189SLawrence D'Anna auto code_ref = Take<PythonObject>(code);
146404edd189SLawrence D'Anna
146504edd189SLawrence D'Anna PyObject *result = PyEval_EvalCode(code, globals.get(), locals.get());
146604edd189SLawrence D'Anna
146704edd189SLawrence D'Anna if (!result)
146804edd189SLawrence D'Anna return exception();
146904edd189SLawrence D'Anna
147004edd189SLawrence D'Anna return Take<PythonObject>(result);
147104edd189SLawrence D'Anna }
147204edd189SLawrence D'Anna
147304edd189SLawrence D'Anna llvm::Expected<PythonObject>
runStringMultiLine(const llvm::Twine & string,const PythonDictionary & globals,const PythonDictionary & locals)147404edd189SLawrence D'Anna python::runStringMultiLine(const llvm::Twine &string,
147504edd189SLawrence D'Anna const PythonDictionary &globals,
147604edd189SLawrence D'Anna const PythonDictionary &locals) {
147704edd189SLawrence D'Anna if (!globals.IsValid() || !locals.IsValid())
147804edd189SLawrence D'Anna return nullDeref();
147904edd189SLawrence D'Anna PyObject *result = PyRun_String(NullTerminated(string), Py_file_input,
148004edd189SLawrence D'Anna globals.get(), locals.get());
148104edd189SLawrence D'Anna if (!result)
148204edd189SLawrence D'Anna return exception();
148304edd189SLawrence D'Anna return Take<PythonObject>(result);
148404edd189SLawrence D'Anna }
148504edd189SLawrence D'Anna
1486d68983e3SPavel Labath #endif
1487