xref: /src/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1cfca06d7SDimitry Andric //===-- PythonDataObjects.cpp ---------------------------------------------===//
2e81d9d49SDimitry Andric //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e81d9d49SDimitry Andric //
7e81d9d49SDimitry Andric //===----------------------------------------------------------------------===//
8e81d9d49SDimitry Andric 
9706b4fc4SDimitry Andric #include "lldb/Host/Config.h"
10e81d9d49SDimitry Andric 
11706b4fc4SDimitry Andric #if LLDB_ENABLE_PYTHON
12e81d9d49SDimitry Andric 
13e81d9d49SDimitry Andric #include "PythonDataObjects.h"
14e81d9d49SDimitry Andric #include "ScriptInterpreterPython.h"
15e81d9d49SDimitry Andric 
16e81d9d49SDimitry Andric #include "lldb/Host/File.h"
17f3fbd1c0SDimitry Andric #include "lldb/Host/FileSystem.h"
18e81d9d49SDimitry Andric #include "lldb/Interpreter/ScriptInterpreter.h"
19145449b1SDimitry Andric #include "lldb/Utility/LLDBLog.h"
20ead24645SDimitry Andric #include "lldb/Utility/Log.h"
2174a628f7SDimitry Andric #include "lldb/Utility/Stream.h"
22e81d9d49SDimitry Andric 
23ead24645SDimitry Andric #include "llvm/Support/Casting.h"
24f3fbd1c0SDimitry Andric #include "llvm/Support/ConvertUTF.h"
255f29bb8aSDimitry Andric #include "llvm/Support/Errno.h"
26f3fbd1c0SDimitry Andric 
27344a3780SDimitry Andric #include <cstdio>
287fa27ce4SDimitry Andric #include <variant>
29e81d9d49SDimitry Andric 
30e81d9d49SDimitry Andric using namespace lldb_private;
31e81d9d49SDimitry Andric using namespace lldb;
32ead24645SDimitry Andric using namespace lldb_private::python;
33ead24645SDimitry Andric using llvm::cantFail;
34ead24645SDimitry Andric using llvm::Error;
35ead24645SDimitry Andric using llvm::Expected;
36ead24645SDimitry Andric using llvm::Twine;
37e81d9d49SDimitry Andric 
As(Expected<PythonObject> && obj)38ead24645SDimitry Andric template <> Expected<bool> python::As<bool>(Expected<PythonObject> &&obj) {
39ead24645SDimitry Andric   if (!obj)
40ead24645SDimitry Andric     return obj.takeError();
41ead24645SDimitry Andric   return obj.get().IsTrue();
42ead24645SDimitry Andric }
43ead24645SDimitry Andric 
44ead24645SDimitry Andric template <>
As(Expected<PythonObject> && obj)45ead24645SDimitry Andric Expected<long long> python::As<long long>(Expected<PythonObject> &&obj) {
46ead24645SDimitry Andric   if (!obj)
47ead24645SDimitry Andric     return obj.takeError();
48cfca06d7SDimitry Andric   return obj->AsLongLong();
49cfca06d7SDimitry Andric }
50cfca06d7SDimitry Andric 
51cfca06d7SDimitry Andric template <>
52cfca06d7SDimitry Andric Expected<unsigned long long>
As(Expected<PythonObject> && obj)53cfca06d7SDimitry Andric python::As<unsigned long long>(Expected<PythonObject> &&obj) {
54cfca06d7SDimitry Andric   if (!obj)
55cfca06d7SDimitry Andric     return obj.takeError();
56cfca06d7SDimitry Andric   return obj->AsUnsignedLongLong();
57ead24645SDimitry Andric }
58ead24645SDimitry Andric 
59ead24645SDimitry Andric template <>
As(Expected<PythonObject> && obj)60ead24645SDimitry Andric Expected<std::string> python::As<std::string>(Expected<PythonObject> &&obj) {
61ead24645SDimitry Andric   if (!obj)
62ead24645SDimitry Andric     return obj.takeError();
63ead24645SDimitry Andric   PyObject *str_obj = PyObject_Str(obj.get().get());
64ac9a064cSDimitry Andric   if (!str_obj)
65ead24645SDimitry Andric     return llvm::make_error<PythonException>();
66ead24645SDimitry Andric   auto str = Take<PythonString>(str_obj);
67ead24645SDimitry Andric   auto utf8 = str.AsUTF8();
68ead24645SDimitry Andric   if (!utf8)
69ead24645SDimitry Andric     return utf8.takeError();
70cfca06d7SDimitry Andric   return std::string(utf8.get());
71cfca06d7SDimitry Andric }
72cfca06d7SDimitry Andric 
python_is_finalizing()736f8fc217SDimitry Andric static bool python_is_finalizing() {
74b1c73532SDimitry Andric #if (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 13) || (PY_MAJOR_VERSION > 3)
75b1c73532SDimitry Andric   return Py_IsFinalizing();
76b1c73532SDimitry Andric #elif PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 7
776f8fc217SDimitry Andric   return _Py_Finalizing != nullptr;
786f8fc217SDimitry Andric #else
796f8fc217SDimitry Andric   return _Py_IsFinalizing();
806f8fc217SDimitry Andric #endif
816f8fc217SDimitry Andric }
826f8fc217SDimitry Andric 
Reset()836f8fc217SDimitry Andric void PythonObject::Reset() {
846f8fc217SDimitry Andric   if (m_py_obj && Py_IsInitialized()) {
856f8fc217SDimitry Andric     if (python_is_finalizing()) {
866f8fc217SDimitry Andric       // Leak m_py_obj rather than crashing the process.
876f8fc217SDimitry Andric       // https://docs.python.org/3/c-api/init.html#c.PyGILState_Ensure
886f8fc217SDimitry Andric     } else {
896f8fc217SDimitry Andric       PyGILState_STATE state = PyGILState_Ensure();
906f8fc217SDimitry Andric       Py_DECREF(m_py_obj);
916f8fc217SDimitry Andric       PyGILState_Release(state);
926f8fc217SDimitry Andric     }
936f8fc217SDimitry Andric   }
946f8fc217SDimitry Andric   m_py_obj = nullptr;
956f8fc217SDimitry Andric }
966f8fc217SDimitry Andric 
AsLongLong() const97cfca06d7SDimitry Andric Expected<long long> PythonObject::AsLongLong() const {
98cfca06d7SDimitry Andric   if (!m_py_obj)
99cfca06d7SDimitry Andric     return nullDeref();
100cfca06d7SDimitry Andric   assert(!PyErr_Occurred());
101cfca06d7SDimitry Andric   long long r = PyLong_AsLongLong(m_py_obj);
102cfca06d7SDimitry Andric   if (PyErr_Occurred())
103cfca06d7SDimitry Andric     return exception();
104cfca06d7SDimitry Andric   return r;
105cfca06d7SDimitry Andric }
106cfca06d7SDimitry Andric 
AsUnsignedLongLong() const1077fa27ce4SDimitry Andric Expected<unsigned long long> PythonObject::AsUnsignedLongLong() const {
108cfca06d7SDimitry Andric   if (!m_py_obj)
109cfca06d7SDimitry Andric     return nullDeref();
110cfca06d7SDimitry Andric   assert(!PyErr_Occurred());
111cfca06d7SDimitry Andric   long long r = PyLong_AsUnsignedLongLong(m_py_obj);
112cfca06d7SDimitry Andric   if (PyErr_Occurred())
113cfca06d7SDimitry Andric     return exception();
114cfca06d7SDimitry Andric   return r;
115cfca06d7SDimitry Andric }
116cfca06d7SDimitry Andric 
117cfca06d7SDimitry Andric // wraps on overflow, instead of raising an error.
AsModuloUnsignedLongLong() const118cfca06d7SDimitry Andric Expected<unsigned long long> PythonObject::AsModuloUnsignedLongLong() const {
119cfca06d7SDimitry Andric   if (!m_py_obj)
120cfca06d7SDimitry Andric     return nullDeref();
121cfca06d7SDimitry Andric   assert(!PyErr_Occurred());
122cfca06d7SDimitry Andric   unsigned long long r = PyLong_AsUnsignedLongLongMask(m_py_obj);
1237fa27ce4SDimitry Andric   // FIXME: We should fetch the exception message and hoist it.
124cfca06d7SDimitry Andric   if (PyErr_Occurred())
125cfca06d7SDimitry Andric     return exception();
126cfca06d7SDimitry Andric   return r;
127ead24645SDimitry Andric }
128ead24645SDimitry Andric 
Serialize(llvm::json::OStream & s) const129ead24645SDimitry Andric void StructuredPythonObject::Serialize(llvm::json::OStream &s) const {
130ead24645SDimitry Andric   s.value(llvm::formatv("Python Obj: {0:X}", GetValue()).str());
131e81d9d49SDimitry Andric }
132e81d9d49SDimitry Andric 
133e81d9d49SDimitry Andric // PythonObject
134e81d9d49SDimitry Andric 
Dump(Stream & strm) const13514f1b3e8SDimitry Andric void PythonObject::Dump(Stream &strm) const {
13614f1b3e8SDimitry Andric   if (m_py_obj) {
1375f29bb8aSDimitry Andric     FILE *file = llvm::sys::RetryAfterSignal(nullptr, ::tmpfile);
13814f1b3e8SDimitry Andric     if (file) {
139e81d9d49SDimitry Andric       ::PyObject_Print(m_py_obj, file, 0);
140e81d9d49SDimitry Andric       const long length = ftell(file);
14114f1b3e8SDimitry Andric       if (length) {
142e81d9d49SDimitry Andric         ::rewind(file);
143e81d9d49SDimitry Andric         std::vector<char> file_contents(length, '\0');
14414f1b3e8SDimitry Andric         const size_t length_read =
14514f1b3e8SDimitry Andric             ::fread(file_contents.data(), 1, file_contents.size(), file);
146e81d9d49SDimitry Andric         if (length_read > 0)
147e81d9d49SDimitry Andric           strm.Write(file_contents.data(), length_read);
148e81d9d49SDimitry Andric       }
149e81d9d49SDimitry Andric       ::fclose(file);
150e81d9d49SDimitry Andric     }
15114f1b3e8SDimitry Andric   } else
152e81d9d49SDimitry Andric     strm.PutCString("NULL");
153e81d9d49SDimitry Andric }
154e81d9d49SDimitry Andric 
GetObjectType() const15514f1b3e8SDimitry Andric PyObjectType PythonObject::GetObjectType() const {
156e81d9d49SDimitry Andric   if (!IsAllocated())
157e81d9d49SDimitry Andric     return PyObjectType::None;
158e81d9d49SDimitry Andric 
159e81d9d49SDimitry Andric   if (PythonModule::Check(m_py_obj))
160e81d9d49SDimitry Andric     return PyObjectType::Module;
161e81d9d49SDimitry Andric   if (PythonList::Check(m_py_obj))
162e81d9d49SDimitry Andric     return PyObjectType::List;
163e81d9d49SDimitry Andric   if (PythonTuple::Check(m_py_obj))
164e81d9d49SDimitry Andric     return PyObjectType::Tuple;
165e81d9d49SDimitry Andric   if (PythonDictionary::Check(m_py_obj))
166e81d9d49SDimitry Andric     return PyObjectType::Dictionary;
167e81d9d49SDimitry Andric   if (PythonString::Check(m_py_obj))
168e81d9d49SDimitry Andric     return PyObjectType::String;
1697fed546dSDimitry Andric   if (PythonBytes::Check(m_py_obj))
1707fed546dSDimitry Andric     return PyObjectType::Bytes;
171f3fbd1c0SDimitry Andric   if (PythonByteArray::Check(m_py_obj))
172f3fbd1c0SDimitry Andric     return PyObjectType::ByteArray;
1735f29bb8aSDimitry Andric   if (PythonBoolean::Check(m_py_obj))
1745f29bb8aSDimitry Andric     return PyObjectType::Boolean;
175e81d9d49SDimitry Andric   if (PythonInteger::Check(m_py_obj))
176e81d9d49SDimitry Andric     return PyObjectType::Integer;
177e81d9d49SDimitry Andric   if (PythonFile::Check(m_py_obj))
178e81d9d49SDimitry Andric     return PyObjectType::File;
179e81d9d49SDimitry Andric   if (PythonCallable::Check(m_py_obj))
180e81d9d49SDimitry Andric     return PyObjectType::Callable;
181e81d9d49SDimitry Andric   return PyObjectType::Unknown;
182e81d9d49SDimitry Andric }
183e81d9d49SDimitry Andric 
Repr() const18414f1b3e8SDimitry Andric PythonString PythonObject::Repr() const {
185e81d9d49SDimitry Andric   if (!m_py_obj)
186e81d9d49SDimitry Andric     return PythonString();
187e81d9d49SDimitry Andric   PyObject *repr = PyObject_Repr(m_py_obj);
188e81d9d49SDimitry Andric   if (!repr)
189e81d9d49SDimitry Andric     return PythonString();
190e81d9d49SDimitry Andric   return PythonString(PyRefType::Owned, repr);
191e81d9d49SDimitry Andric }
192e81d9d49SDimitry Andric 
Str() const19314f1b3e8SDimitry Andric PythonString PythonObject::Str() const {
194e81d9d49SDimitry Andric   if (!m_py_obj)
195e81d9d49SDimitry Andric     return PythonString();
196e81d9d49SDimitry Andric   PyObject *str = PyObject_Str(m_py_obj);
197e81d9d49SDimitry Andric   if (!str)
198e81d9d49SDimitry Andric     return PythonString();
199e81d9d49SDimitry Andric   return PythonString(PyRefType::Owned, str);
200e81d9d49SDimitry Andric }
201e81d9d49SDimitry Andric 
202e81d9d49SDimitry Andric PythonObject
ResolveNameWithDictionary(llvm::StringRef name,const PythonDictionary & dict)20314f1b3e8SDimitry Andric PythonObject::ResolveNameWithDictionary(llvm::StringRef name,
20414f1b3e8SDimitry Andric                                         const PythonDictionary &dict) {
2055f29bb8aSDimitry Andric   size_t dot_pos = name.find('.');
206e81d9d49SDimitry Andric   llvm::StringRef piece = name.substr(0, dot_pos);
207e81d9d49SDimitry Andric   PythonObject result = dict.GetItemForKey(PythonString(piece));
20814f1b3e8SDimitry Andric   if (dot_pos == llvm::StringRef::npos) {
209e81d9d49SDimitry Andric     // There was no dot, we're done.
210e81d9d49SDimitry Andric     return result;
211e81d9d49SDimitry Andric   }
212e81d9d49SDimitry Andric 
213e81d9d49SDimitry Andric   // There was a dot.  The remaining portion of the name should be looked up in
214e81d9d49SDimitry Andric   // the context of the object that was found in the dictionary.
215e81d9d49SDimitry Andric   return result.ResolveName(name.substr(dot_pos + 1));
216e81d9d49SDimitry Andric }
217e81d9d49SDimitry Andric 
ResolveName(llvm::StringRef name) const21814f1b3e8SDimitry Andric PythonObject PythonObject::ResolveName(llvm::StringRef name) const {
219f73363f1SDimitry Andric   // Resolve the name in the context of the specified object.  If, for example,
220f73363f1SDimitry Andric   // `this` refers to a PyModule, then this will look for `name` in this
221f73363f1SDimitry Andric   // module.  If `this` refers to a PyType, then it will resolve `name` as an
222f73363f1SDimitry Andric   // attribute of that type.  If `this` refers to an instance of an object,
223f73363f1SDimitry Andric   // then it will resolve `name` as the value of the specified field.
224e81d9d49SDimitry Andric   //
225e81d9d49SDimitry Andric   // This function handles dotted names so that, for example, if `m_py_obj`
226f73363f1SDimitry Andric   // refers to the `sys` module, and `name` == "path.append", then it will find
227f73363f1SDimitry Andric   // the function `sys.path.append`.
228e81d9d49SDimitry Andric 
2295f29bb8aSDimitry Andric   size_t dot_pos = name.find('.');
23014f1b3e8SDimitry Andric   if (dot_pos == llvm::StringRef::npos) {
231f73363f1SDimitry Andric     // No dots in the name, we should be able to find the value immediately as
232f73363f1SDimitry Andric     // an attribute of `m_py_obj`.
233e81d9d49SDimitry Andric     return GetAttributeValue(name);
234e81d9d49SDimitry Andric   }
235e81d9d49SDimitry Andric 
23614f1b3e8SDimitry Andric   // Look up the first piece of the name, and resolve the rest as a child of
23714f1b3e8SDimitry Andric   // that.
238e81d9d49SDimitry Andric   PythonObject parent = ResolveName(name.substr(0, dot_pos));
239e81d9d49SDimitry Andric   if (!parent.IsAllocated())
240e81d9d49SDimitry Andric     return PythonObject();
241e81d9d49SDimitry Andric 
242e81d9d49SDimitry Andric   // Tail recursion.. should be optimized by the compiler
243e81d9d49SDimitry Andric   return parent.ResolveName(name.substr(dot_pos + 1));
244e81d9d49SDimitry Andric }
245e81d9d49SDimitry Andric 
HasAttribute(llvm::StringRef attr) const24614f1b3e8SDimitry Andric bool PythonObject::HasAttribute(llvm::StringRef attr) const {
247e81d9d49SDimitry Andric   if (!IsValid())
248e81d9d49SDimitry Andric     return false;
249e81d9d49SDimitry Andric   PythonString py_attr(attr);
250e81d9d49SDimitry Andric   return !!PyObject_HasAttr(m_py_obj, py_attr.get());
251e81d9d49SDimitry Andric }
252e81d9d49SDimitry Andric 
GetAttributeValue(llvm::StringRef attr) const25314f1b3e8SDimitry Andric PythonObject PythonObject::GetAttributeValue(llvm::StringRef attr) const {
254e81d9d49SDimitry Andric   if (!IsValid())
255e81d9d49SDimitry Andric     return PythonObject();
256e81d9d49SDimitry Andric 
257e81d9d49SDimitry Andric   PythonString py_attr(attr);
258e81d9d49SDimitry Andric   if (!PyObject_HasAttr(m_py_obj, py_attr.get()))
259e81d9d49SDimitry Andric     return PythonObject();
260e81d9d49SDimitry Andric 
261e81d9d49SDimitry Andric   return PythonObject(PyRefType::Owned,
262e81d9d49SDimitry Andric                       PyObject_GetAttr(m_py_obj, py_attr.get()));
263e81d9d49SDimitry Andric }
264e81d9d49SDimitry Andric 
CreateStructuredObject() const26514f1b3e8SDimitry Andric StructuredData::ObjectSP PythonObject::CreateStructuredObject() const {
2666f8fc217SDimitry Andric   assert(PyGILState_Check());
26714f1b3e8SDimitry Andric   switch (GetObjectType()) {
268e81d9d49SDimitry Andric   case PyObjectType::Dictionary:
26914f1b3e8SDimitry Andric     return PythonDictionary(PyRefType::Borrowed, m_py_obj)
27014f1b3e8SDimitry Andric         .CreateStructuredDictionary();
2715f29bb8aSDimitry Andric   case PyObjectType::Boolean:
2725f29bb8aSDimitry Andric     return PythonBoolean(PyRefType::Borrowed, m_py_obj)
2735f29bb8aSDimitry Andric         .CreateStructuredBoolean();
2747fa27ce4SDimitry Andric   case PyObjectType::Integer: {
2757fa27ce4SDimitry Andric     StructuredData::IntegerSP int_sp =
2767fa27ce4SDimitry Andric         PythonInteger(PyRefType::Borrowed, m_py_obj).CreateStructuredInteger();
2777fa27ce4SDimitry Andric     if (std::holds_alternative<StructuredData::UnsignedIntegerSP>(int_sp))
2787fa27ce4SDimitry Andric       return std::get<StructuredData::UnsignedIntegerSP>(int_sp);
2797fa27ce4SDimitry Andric     if (std::holds_alternative<StructuredData::SignedIntegerSP>(int_sp))
2807fa27ce4SDimitry Andric       return std::get<StructuredData::SignedIntegerSP>(int_sp);
2817fa27ce4SDimitry Andric     return nullptr;
2827fa27ce4SDimitry Andric   };
283e81d9d49SDimitry Andric   case PyObjectType::List:
284e81d9d49SDimitry Andric     return PythonList(PyRefType::Borrowed, m_py_obj).CreateStructuredArray();
285e81d9d49SDimitry Andric   case PyObjectType::String:
286e81d9d49SDimitry Andric     return PythonString(PyRefType::Borrowed, m_py_obj).CreateStructuredString();
2877fed546dSDimitry Andric   case PyObjectType::Bytes:
2887fed546dSDimitry Andric     return PythonBytes(PyRefType::Borrowed, m_py_obj).CreateStructuredString();
289f3fbd1c0SDimitry Andric   case PyObjectType::ByteArray:
29014f1b3e8SDimitry Andric     return PythonByteArray(PyRefType::Borrowed, m_py_obj)
29114f1b3e8SDimitry Andric         .CreateStructuredString();
292e81d9d49SDimitry Andric   case PyObjectType::None:
293e81d9d49SDimitry Andric     return StructuredData::ObjectSP();
294e81d9d49SDimitry Andric   default:
2956f8fc217SDimitry Andric     return StructuredData::ObjectSP(new StructuredPythonObject(
2966f8fc217SDimitry Andric         PythonObject(PyRefType::Borrowed, m_py_obj)));
297e81d9d49SDimitry Andric   }
298e81d9d49SDimitry Andric }
299e81d9d49SDimitry Andric 
300e81d9d49SDimitry Andric // PythonString
3017fed546dSDimitry Andric 
PythonBytes(llvm::ArrayRef<uint8_t> bytes)302ead24645SDimitry Andric PythonBytes::PythonBytes(llvm::ArrayRef<uint8_t> bytes) { SetBytes(bytes); }
3037fed546dSDimitry Andric 
PythonBytes(const uint8_t * bytes,size_t length)304ead24645SDimitry Andric PythonBytes::PythonBytes(const uint8_t *bytes, size_t length) {
3057fed546dSDimitry Andric   SetBytes(llvm::ArrayRef<uint8_t>(bytes, length));
3067fed546dSDimitry Andric }
3077fed546dSDimitry Andric 
Check(PyObject * py_obj)30814f1b3e8SDimitry Andric bool PythonBytes::Check(PyObject *py_obj) {
3097fed546dSDimitry Andric   if (!py_obj)
3107fed546dSDimitry Andric     return false;
31194994d37SDimitry Andric   return PyBytes_Check(py_obj);
3127fed546dSDimitry Andric }
3137fed546dSDimitry Andric 
GetBytes() const31414f1b3e8SDimitry Andric llvm::ArrayRef<uint8_t> PythonBytes::GetBytes() const {
3157fed546dSDimitry Andric   if (!IsValid())
3167fed546dSDimitry Andric     return llvm::ArrayRef<uint8_t>();
3177fed546dSDimitry Andric 
3187fed546dSDimitry Andric   Py_ssize_t size;
3197fed546dSDimitry Andric   char *c;
3207fed546dSDimitry Andric 
3217fed546dSDimitry Andric   PyBytes_AsStringAndSize(m_py_obj, &c, &size);
3227fed546dSDimitry Andric   return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size);
3237fed546dSDimitry Andric }
3247fed546dSDimitry Andric 
GetSize() const32514f1b3e8SDimitry Andric size_t PythonBytes::GetSize() const {
3267fed546dSDimitry Andric   if (!IsValid())
3277fed546dSDimitry Andric     return 0;
3287fed546dSDimitry Andric   return PyBytes_Size(m_py_obj);
3297fed546dSDimitry Andric }
3307fed546dSDimitry Andric 
SetBytes(llvm::ArrayRef<uint8_t> bytes)33114f1b3e8SDimitry Andric void PythonBytes::SetBytes(llvm::ArrayRef<uint8_t> bytes) {
3327fed546dSDimitry Andric   const char *data = reinterpret_cast<const char *>(bytes.data());
333ead24645SDimitry Andric   *this = Take<PythonBytes>(PyBytes_FromStringAndSize(data, bytes.size()));
3347fed546dSDimitry Andric }
3357fed546dSDimitry Andric 
CreateStructuredString() const33614f1b3e8SDimitry Andric StructuredData::StringSP PythonBytes::CreateStructuredString() const {
3377fed546dSDimitry Andric   StructuredData::StringSP result(new StructuredData::String);
3387fed546dSDimitry Andric   Py_ssize_t size;
3397fed546dSDimitry Andric   char *c;
3407fed546dSDimitry Andric   PyBytes_AsStringAndSize(m_py_obj, &c, &size);
3417fed546dSDimitry Andric   result->SetValue(std::string(c, size));
3427fed546dSDimitry Andric   return result;
3437fed546dSDimitry Andric }
3447fed546dSDimitry Andric 
PythonByteArray(llvm::ArrayRef<uint8_t> bytes)34514f1b3e8SDimitry Andric PythonByteArray::PythonByteArray(llvm::ArrayRef<uint8_t> bytes)
34614f1b3e8SDimitry Andric     : PythonByteArray(bytes.data(), bytes.size()) {}
347f3fbd1c0SDimitry Andric 
PythonByteArray(const uint8_t * bytes,size_t length)34814f1b3e8SDimitry Andric PythonByteArray::PythonByteArray(const uint8_t *bytes, size_t length) {
349f3fbd1c0SDimitry Andric   const char *str = reinterpret_cast<const char *>(bytes);
350ead24645SDimitry Andric   *this = Take<PythonByteArray>(PyByteArray_FromStringAndSize(str, length));
351f3fbd1c0SDimitry Andric }
352f3fbd1c0SDimitry Andric 
Check(PyObject * py_obj)35314f1b3e8SDimitry Andric bool PythonByteArray::Check(PyObject *py_obj) {
354f3fbd1c0SDimitry Andric   if (!py_obj)
355f3fbd1c0SDimitry Andric     return false;
35694994d37SDimitry Andric   return PyByteArray_Check(py_obj);
357f3fbd1c0SDimitry Andric }
358f3fbd1c0SDimitry Andric 
GetBytes() const35914f1b3e8SDimitry Andric llvm::ArrayRef<uint8_t> PythonByteArray::GetBytes() const {
360f3fbd1c0SDimitry Andric   if (!IsValid())
361f3fbd1c0SDimitry Andric     return llvm::ArrayRef<uint8_t>();
362f3fbd1c0SDimitry Andric 
363f3fbd1c0SDimitry Andric   char *c = PyByteArray_AsString(m_py_obj);
364f3fbd1c0SDimitry Andric   size_t size = GetSize();
365f3fbd1c0SDimitry Andric   return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size);
366f3fbd1c0SDimitry Andric }
367f3fbd1c0SDimitry Andric 
GetSize() const36814f1b3e8SDimitry Andric size_t PythonByteArray::GetSize() const {
369f3fbd1c0SDimitry Andric   if (!IsValid())
370f3fbd1c0SDimitry Andric     return 0;
371f3fbd1c0SDimitry Andric 
372f3fbd1c0SDimitry Andric   return PyByteArray_Size(m_py_obj);
373f3fbd1c0SDimitry Andric }
374f3fbd1c0SDimitry Andric 
CreateStructuredString() const37514f1b3e8SDimitry Andric StructuredData::StringSP PythonByteArray::CreateStructuredString() const {
376f3fbd1c0SDimitry Andric   StructuredData::StringSP result(new StructuredData::String);
377f3fbd1c0SDimitry Andric   llvm::ArrayRef<uint8_t> bytes = GetBytes();
378f3fbd1c0SDimitry Andric   const char *str = reinterpret_cast<const char *>(bytes.data());
379f3fbd1c0SDimitry Andric   result->SetValue(std::string(str, bytes.size()));
380f3fbd1c0SDimitry Andric   return result;
381f3fbd1c0SDimitry Andric }
382f3fbd1c0SDimitry Andric 
3837fed546dSDimitry Andric // PythonString
384e81d9d49SDimitry Andric 
FromUTF8(llvm::StringRef string)385ead24645SDimitry Andric Expected<PythonString> PythonString::FromUTF8(llvm::StringRef string) {
386ead24645SDimitry Andric   PyObject *str = PyUnicode_FromStringAndSize(string.data(), string.size());
387ead24645SDimitry Andric   if (!str)
388ead24645SDimitry Andric     return llvm::make_error<PythonException>();
389ead24645SDimitry Andric   return Take<PythonString>(str);
390e81d9d49SDimitry Andric }
391e81d9d49SDimitry Andric 
PythonString(llvm::StringRef string)392ead24645SDimitry Andric PythonString::PythonString(llvm::StringRef string) { SetString(string); }
393e81d9d49SDimitry Andric 
Check(PyObject * py_obj)39414f1b3e8SDimitry Andric bool PythonString::Check(PyObject *py_obj) {
395e81d9d49SDimitry Andric   if (!py_obj)
396e81d9d49SDimitry Andric     return false;
397e81d9d49SDimitry Andric 
398e81d9d49SDimitry Andric   if (PyUnicode_Check(py_obj))
399e81d9d49SDimitry Andric     return true;
400e81d9d49SDimitry Andric   return false;
401e81d9d49SDimitry Andric }
402e81d9d49SDimitry Andric 
GetString() const40314f1b3e8SDimitry Andric llvm::StringRef PythonString::GetString() const {
404ead24645SDimitry Andric   auto s = AsUTF8();
405ead24645SDimitry Andric   if (!s) {
406ead24645SDimitry Andric     llvm::consumeError(s.takeError());
407ead24645SDimitry Andric     return llvm::StringRef("");
408ead24645SDimitry Andric   }
409ead24645SDimitry Andric   return s.get();
410ead24645SDimitry Andric }
411ead24645SDimitry Andric 
AsUTF8() const412ead24645SDimitry Andric Expected<llvm::StringRef> PythonString::AsUTF8() const {
413e81d9d49SDimitry Andric   if (!IsValid())
414ead24645SDimitry Andric     return nullDeref();
415e81d9d49SDimitry Andric 
416e81d9d49SDimitry Andric   Py_ssize_t size;
417f73363f1SDimitry Andric   const char *data;
418e81d9d49SDimitry Andric 
419f73363f1SDimitry Andric   data = PyUnicode_AsUTF8AndSize(m_py_obj, &size);
420ead24645SDimitry Andric 
421ead24645SDimitry Andric   if (!data)
422ead24645SDimitry Andric     return exception();
423ead24645SDimitry Andric 
424f73363f1SDimitry Andric   return llvm::StringRef(data, size);
425e81d9d49SDimitry Andric }
426e81d9d49SDimitry Andric 
GetSize() const42714f1b3e8SDimitry Andric size_t PythonString::GetSize() const {
42814f1b3e8SDimitry Andric   if (IsValid()) {
429b60736ecSDimitry Andric #if PY_MINOR_VERSION >= 3
430b60736ecSDimitry Andric     return PyUnicode_GetLength(m_py_obj);
431b60736ecSDimitry Andric #else
432e81d9d49SDimitry Andric     return PyUnicode_GetSize(m_py_obj);
433b60736ecSDimitry Andric #endif
434e81d9d49SDimitry Andric   }
435e81d9d49SDimitry Andric   return 0;
436e81d9d49SDimitry Andric }
437e81d9d49SDimitry Andric 
SetString(llvm::StringRef string)43814f1b3e8SDimitry Andric void PythonString::SetString(llvm::StringRef string) {
439ead24645SDimitry Andric   auto s = FromUTF8(string);
440ead24645SDimitry Andric   if (!s) {
441ead24645SDimitry Andric     llvm::consumeError(s.takeError());
442ead24645SDimitry Andric     Reset();
443ead24645SDimitry Andric   } else {
444ead24645SDimitry Andric     *this = std::move(s.get());
445ead24645SDimitry Andric   }
446e81d9d49SDimitry Andric }
447e81d9d49SDimitry Andric 
CreateStructuredString() const44814f1b3e8SDimitry Andric StructuredData::StringSP PythonString::CreateStructuredString() const {
449e81d9d49SDimitry Andric   StructuredData::StringSP result(new StructuredData::String);
450e81d9d49SDimitry Andric   result->SetValue(GetString());
451e81d9d49SDimitry Andric   return result;
452e81d9d49SDimitry Andric }
453e81d9d49SDimitry Andric 
454e81d9d49SDimitry Andric // PythonInteger
455e81d9d49SDimitry Andric 
PythonInteger(int64_t value)456ead24645SDimitry Andric PythonInteger::PythonInteger(int64_t value) { SetInteger(value); }
457e81d9d49SDimitry Andric 
Check(PyObject * py_obj)45814f1b3e8SDimitry Andric bool PythonInteger::Check(PyObject *py_obj) {
459e81d9d49SDimitry Andric   if (!py_obj)
460e81d9d49SDimitry Andric     return false;
461e81d9d49SDimitry Andric 
462f73363f1SDimitry Andric   // Python 3 does not have PyInt_Check.  There is only one type of integral
463f73363f1SDimitry Andric   // value, long.
464e81d9d49SDimitry Andric   return PyLong_Check(py_obj);
465e81d9d49SDimitry Andric }
466e81d9d49SDimitry Andric 
SetInteger(int64_t value)46714f1b3e8SDimitry Andric void PythonInteger::SetInteger(int64_t value) {
468ead24645SDimitry Andric   *this = Take<PythonInteger>(PyLong_FromLongLong(value));
469e81d9d49SDimitry Andric }
470e81d9d49SDimitry Andric 
CreateStructuredInteger() const47114f1b3e8SDimitry Andric StructuredData::IntegerSP PythonInteger::CreateStructuredInteger() const {
4727fa27ce4SDimitry Andric   StructuredData::UnsignedIntegerSP uint_sp = CreateStructuredUnsignedInteger();
4737fa27ce4SDimitry Andric   return uint_sp ? StructuredData::IntegerSP(uint_sp)
4747fa27ce4SDimitry Andric                  : CreateStructuredSignedInteger();
475cfca06d7SDimitry Andric }
4767fa27ce4SDimitry Andric 
4777fa27ce4SDimitry Andric StructuredData::UnsignedIntegerSP
CreateStructuredUnsignedInteger() const4787fa27ce4SDimitry Andric PythonInteger::CreateStructuredUnsignedInteger() const {
4797fa27ce4SDimitry Andric   StructuredData::UnsignedIntegerSP result = nullptr;
4807fa27ce4SDimitry Andric   llvm::Expected<unsigned long long> value = AsUnsignedLongLong();
4817fa27ce4SDimitry Andric   if (!value)
4827fa27ce4SDimitry Andric     llvm::consumeError(value.takeError());
4837fa27ce4SDimitry Andric   else
4847fa27ce4SDimitry Andric     result = std::make_shared<StructuredData::UnsignedInteger>(value.get());
4857fa27ce4SDimitry Andric 
4867fa27ce4SDimitry Andric   return result;
4877fa27ce4SDimitry Andric }
4887fa27ce4SDimitry Andric 
4897fa27ce4SDimitry Andric StructuredData::SignedIntegerSP
CreateStructuredSignedInteger() const4907fa27ce4SDimitry Andric PythonInteger::CreateStructuredSignedInteger() const {
4917fa27ce4SDimitry Andric   StructuredData::SignedIntegerSP result = nullptr;
4927fa27ce4SDimitry Andric   llvm::Expected<long long> value = AsLongLong();
4937fa27ce4SDimitry Andric   if (!value)
4947fa27ce4SDimitry Andric     llvm::consumeError(value.takeError());
4957fa27ce4SDimitry Andric   else
4967fa27ce4SDimitry Andric     result = std::make_shared<StructuredData::SignedInteger>(value.get());
4977fa27ce4SDimitry Andric 
498e81d9d49SDimitry Andric   return result;
499e81d9d49SDimitry Andric }
500e81d9d49SDimitry Andric 
5015f29bb8aSDimitry Andric // PythonBoolean
5025f29bb8aSDimitry Andric 
PythonBoolean(bool value)5035f29bb8aSDimitry Andric PythonBoolean::PythonBoolean(bool value) {
5045f29bb8aSDimitry Andric   SetValue(value);
5055f29bb8aSDimitry Andric }
5065f29bb8aSDimitry Andric 
Check(PyObject * py_obj)5075f29bb8aSDimitry Andric bool PythonBoolean::Check(PyObject *py_obj) {
5085f29bb8aSDimitry Andric   return py_obj ? PyBool_Check(py_obj) : false;
5095f29bb8aSDimitry Andric }
5105f29bb8aSDimitry Andric 
GetValue() const5115f29bb8aSDimitry Andric bool PythonBoolean::GetValue() const {
5125f29bb8aSDimitry Andric   return m_py_obj ? PyObject_IsTrue(m_py_obj) : false;
5135f29bb8aSDimitry Andric }
5145f29bb8aSDimitry Andric 
SetValue(bool value)5155f29bb8aSDimitry Andric void PythonBoolean::SetValue(bool value) {
516ead24645SDimitry Andric   *this = Take<PythonBoolean>(PyBool_FromLong(value));
5175f29bb8aSDimitry Andric }
5185f29bb8aSDimitry Andric 
CreateStructuredBoolean() const5195f29bb8aSDimitry Andric StructuredData::BooleanSP PythonBoolean::CreateStructuredBoolean() const {
5205f29bb8aSDimitry Andric   StructuredData::BooleanSP result(new StructuredData::Boolean);
5215f29bb8aSDimitry Andric   result->SetValue(GetValue());
5225f29bb8aSDimitry Andric   return result;
5235f29bb8aSDimitry Andric }
5245f29bb8aSDimitry Andric 
525e81d9d49SDimitry Andric // PythonList
526e81d9d49SDimitry Andric 
PythonList(PyInitialValue value)527ead24645SDimitry Andric PythonList::PythonList(PyInitialValue value) {
528e81d9d49SDimitry Andric   if (value == PyInitialValue::Empty)
529ead24645SDimitry Andric     *this = Take<PythonList>(PyList_New(0));
530e81d9d49SDimitry Andric }
531e81d9d49SDimitry Andric 
PythonList(int list_size)532ead24645SDimitry Andric PythonList::PythonList(int list_size) {
533ead24645SDimitry Andric   *this = Take<PythonList>(PyList_New(list_size));
534e81d9d49SDimitry Andric }
535e81d9d49SDimitry Andric 
Check(PyObject * py_obj)53614f1b3e8SDimitry Andric bool PythonList::Check(PyObject *py_obj) {
537e81d9d49SDimitry Andric   if (!py_obj)
538e81d9d49SDimitry Andric     return false;
539e81d9d49SDimitry Andric   return PyList_Check(py_obj);
540e81d9d49SDimitry Andric }
541e81d9d49SDimitry Andric 
GetSize() const54214f1b3e8SDimitry Andric uint32_t PythonList::GetSize() const {
543e81d9d49SDimitry Andric   if (IsValid())
544e81d9d49SDimitry Andric     return PyList_GET_SIZE(m_py_obj);
545e81d9d49SDimitry Andric   return 0;
546e81d9d49SDimitry Andric }
547e81d9d49SDimitry Andric 
GetItemAtIndex(uint32_t index) const54814f1b3e8SDimitry Andric PythonObject PythonList::GetItemAtIndex(uint32_t index) const {
549e81d9d49SDimitry Andric   if (IsValid())
550e81d9d49SDimitry Andric     return PythonObject(PyRefType::Borrowed, PyList_GetItem(m_py_obj, index));
551e81d9d49SDimitry Andric   return PythonObject();
552e81d9d49SDimitry Andric }
553e81d9d49SDimitry Andric 
SetItemAtIndex(uint32_t index,const PythonObject & object)55414f1b3e8SDimitry Andric void PythonList::SetItemAtIndex(uint32_t index, const PythonObject &object) {
55514f1b3e8SDimitry Andric   if (IsAllocated() && object.IsValid()) {
556e81d9d49SDimitry Andric     // PyList_SetItem is documented to "steal" a reference, so we need to
557e81d9d49SDimitry Andric     // convert it to an owned reference by incrementing it.
558e81d9d49SDimitry Andric     Py_INCREF(object.get());
559e81d9d49SDimitry Andric     PyList_SetItem(m_py_obj, index, object.get());
560e81d9d49SDimitry Andric   }
561e81d9d49SDimitry Andric }
562e81d9d49SDimitry Andric 
AppendItem(const PythonObject & object)56314f1b3e8SDimitry Andric void PythonList::AppendItem(const PythonObject &object) {
56414f1b3e8SDimitry Andric   if (IsAllocated() && object.IsValid()) {
565e81d9d49SDimitry Andric     // `PyList_Append` does *not* steal a reference, so do not call `Py_INCREF`
566e81d9d49SDimitry Andric     // here like we do with `PyList_SetItem`.
567e81d9d49SDimitry Andric     PyList_Append(m_py_obj, object.get());
568e81d9d49SDimitry Andric   }
569e81d9d49SDimitry Andric }
570e81d9d49SDimitry Andric 
CreateStructuredArray() const57114f1b3e8SDimitry Andric StructuredData::ArraySP PythonList::CreateStructuredArray() const {
572e81d9d49SDimitry Andric   StructuredData::ArraySP result(new StructuredData::Array);
573e81d9d49SDimitry Andric   uint32_t count = GetSize();
57414f1b3e8SDimitry Andric   for (uint32_t i = 0; i < count; ++i) {
575e81d9d49SDimitry Andric     PythonObject obj = GetItemAtIndex(i);
576e81d9d49SDimitry Andric     result->AddItem(obj.CreateStructuredObject());
577e81d9d49SDimitry Andric   }
578e81d9d49SDimitry Andric   return result;
579e81d9d49SDimitry Andric }
580e81d9d49SDimitry Andric 
581e81d9d49SDimitry Andric // PythonTuple
582e81d9d49SDimitry Andric 
PythonTuple(PyInitialValue value)583ead24645SDimitry Andric PythonTuple::PythonTuple(PyInitialValue value) {
584e81d9d49SDimitry Andric   if (value == PyInitialValue::Empty)
585ead24645SDimitry Andric     *this = Take<PythonTuple>(PyTuple_New(0));
586e81d9d49SDimitry Andric }
587e81d9d49SDimitry Andric 
PythonTuple(int tuple_size)588ead24645SDimitry Andric PythonTuple::PythonTuple(int tuple_size) {
589ead24645SDimitry Andric   *this = Take<PythonTuple>(PyTuple_New(tuple_size));
590e81d9d49SDimitry Andric }
591e81d9d49SDimitry Andric 
PythonTuple(std::initializer_list<PythonObject> objects)59214f1b3e8SDimitry Andric PythonTuple::PythonTuple(std::initializer_list<PythonObject> objects) {
593e81d9d49SDimitry Andric   m_py_obj = PyTuple_New(objects.size());
594e81d9d49SDimitry Andric 
595e81d9d49SDimitry Andric   uint32_t idx = 0;
59614f1b3e8SDimitry Andric   for (auto object : objects) {
597e81d9d49SDimitry Andric     if (object.IsValid())
598e81d9d49SDimitry Andric       SetItemAtIndex(idx, object);
599e81d9d49SDimitry Andric     idx++;
600e81d9d49SDimitry Andric   }
601e81d9d49SDimitry Andric }
602e81d9d49SDimitry Andric 
PythonTuple(std::initializer_list<PyObject * > objects)60314f1b3e8SDimitry Andric PythonTuple::PythonTuple(std::initializer_list<PyObject *> objects) {
604e81d9d49SDimitry Andric   m_py_obj = PyTuple_New(objects.size());
605e81d9d49SDimitry Andric 
606e81d9d49SDimitry Andric   uint32_t idx = 0;
60714f1b3e8SDimitry Andric   for (auto py_object : objects) {
608e81d9d49SDimitry Andric     PythonObject object(PyRefType::Borrowed, py_object);
609e81d9d49SDimitry Andric     if (object.IsValid())
610e81d9d49SDimitry Andric       SetItemAtIndex(idx, object);
611e81d9d49SDimitry Andric     idx++;
612e81d9d49SDimitry Andric   }
613e81d9d49SDimitry Andric }
614e81d9d49SDimitry Andric 
Check(PyObject * py_obj)61514f1b3e8SDimitry Andric bool PythonTuple::Check(PyObject *py_obj) {
616e81d9d49SDimitry Andric   if (!py_obj)
617e81d9d49SDimitry Andric     return false;
618e81d9d49SDimitry Andric   return PyTuple_Check(py_obj);
619e81d9d49SDimitry Andric }
620e81d9d49SDimitry Andric 
GetSize() const62114f1b3e8SDimitry Andric uint32_t PythonTuple::GetSize() const {
622e81d9d49SDimitry Andric   if (IsValid())
623e81d9d49SDimitry Andric     return PyTuple_GET_SIZE(m_py_obj);
624e81d9d49SDimitry Andric   return 0;
625e81d9d49SDimitry Andric }
626e81d9d49SDimitry Andric 
GetItemAtIndex(uint32_t index) const62714f1b3e8SDimitry Andric PythonObject PythonTuple::GetItemAtIndex(uint32_t index) const {
628e81d9d49SDimitry Andric   if (IsValid())
629e81d9d49SDimitry Andric     return PythonObject(PyRefType::Borrowed, PyTuple_GetItem(m_py_obj, index));
630e81d9d49SDimitry Andric   return PythonObject();
631e81d9d49SDimitry Andric }
632e81d9d49SDimitry Andric 
SetItemAtIndex(uint32_t index,const PythonObject & object)63314f1b3e8SDimitry Andric void PythonTuple::SetItemAtIndex(uint32_t index, const PythonObject &object) {
63414f1b3e8SDimitry Andric   if (IsAllocated() && object.IsValid()) {
635e81d9d49SDimitry Andric     // PyTuple_SetItem is documented to "steal" a reference, so we need to
636e81d9d49SDimitry Andric     // convert it to an owned reference by incrementing it.
637e81d9d49SDimitry Andric     Py_INCREF(object.get());
638e81d9d49SDimitry Andric     PyTuple_SetItem(m_py_obj, index, object.get());
639e81d9d49SDimitry Andric   }
640e81d9d49SDimitry Andric }
641e81d9d49SDimitry Andric 
CreateStructuredArray() const64214f1b3e8SDimitry Andric StructuredData::ArraySP PythonTuple::CreateStructuredArray() const {
643e81d9d49SDimitry Andric   StructuredData::ArraySP result(new StructuredData::Array);
644e81d9d49SDimitry Andric   uint32_t count = GetSize();
64514f1b3e8SDimitry Andric   for (uint32_t i = 0; i < count; ++i) {
646e81d9d49SDimitry Andric     PythonObject obj = GetItemAtIndex(i);
647e81d9d49SDimitry Andric     result->AddItem(obj.CreateStructuredObject());
648e81d9d49SDimitry Andric   }
649e81d9d49SDimitry Andric   return result;
650e81d9d49SDimitry Andric }
651e81d9d49SDimitry Andric 
652e81d9d49SDimitry Andric // PythonDictionary
653e81d9d49SDimitry Andric 
PythonDictionary(PyInitialValue value)654ead24645SDimitry Andric PythonDictionary::PythonDictionary(PyInitialValue value) {
655e81d9d49SDimitry Andric   if (value == PyInitialValue::Empty)
656ead24645SDimitry Andric     *this = Take<PythonDictionary>(PyDict_New());
657e81d9d49SDimitry Andric }
658e81d9d49SDimitry Andric 
Check(PyObject * py_obj)65914f1b3e8SDimitry Andric bool PythonDictionary::Check(PyObject *py_obj) {
660e81d9d49SDimitry Andric   if (!py_obj)
661e81d9d49SDimitry Andric     return false;
662e81d9d49SDimitry Andric 
663e81d9d49SDimitry Andric   return PyDict_Check(py_obj);
664e81d9d49SDimitry Andric }
665e81d9d49SDimitry Andric 
HasKey(const llvm::Twine & key) const666b1c73532SDimitry Andric bool PythonDictionary::HasKey(const llvm::Twine &key) const {
667b1c73532SDimitry Andric   if (!IsValid())
668b1c73532SDimitry Andric     return false;
669b1c73532SDimitry Andric 
670b1c73532SDimitry Andric   PythonString key_object(key.isSingleStringRef() ? key.getSingleStringRef()
671b1c73532SDimitry Andric                                                   : key.str());
672b1c73532SDimitry Andric 
673b1c73532SDimitry Andric   if (int res = PyDict_Contains(m_py_obj, key_object.get()) > 0)
674b1c73532SDimitry Andric     return res;
675b1c73532SDimitry Andric 
676b1c73532SDimitry Andric   PyErr_Print();
677b1c73532SDimitry Andric   return false;
678b1c73532SDimitry Andric }
679b1c73532SDimitry Andric 
GetSize() const68014f1b3e8SDimitry Andric uint32_t PythonDictionary::GetSize() const {
681e81d9d49SDimitry Andric   if (IsValid())
682e81d9d49SDimitry Andric     return PyDict_Size(m_py_obj);
683e81d9d49SDimitry Andric   return 0;
684e81d9d49SDimitry Andric }
685e81d9d49SDimitry Andric 
GetKeys() const68614f1b3e8SDimitry Andric PythonList PythonDictionary::GetKeys() const {
687e81d9d49SDimitry Andric   if (IsValid())
688e81d9d49SDimitry Andric     return PythonList(PyRefType::Owned, PyDict_Keys(m_py_obj));
689e81d9d49SDimitry Andric   return PythonList(PyInitialValue::Invalid);
690e81d9d49SDimitry Andric }
691e81d9d49SDimitry Andric 
GetItemForKey(const PythonObject & key) const69214f1b3e8SDimitry Andric PythonObject PythonDictionary::GetItemForKey(const PythonObject &key) const {
693ead24645SDimitry Andric   auto item = GetItem(key);
694ead24645SDimitry Andric   if (!item) {
695ead24645SDimitry Andric     llvm::consumeError(item.takeError());
696e81d9d49SDimitry Andric     return PythonObject();
697e81d9d49SDimitry Andric   }
698ead24645SDimitry Andric   return std::move(item.get());
699ead24645SDimitry Andric }
700ead24645SDimitry Andric 
701ead24645SDimitry Andric Expected<PythonObject>
GetItem(const PythonObject & key) const702ead24645SDimitry Andric PythonDictionary::GetItem(const PythonObject &key) const {
703ead24645SDimitry Andric   if (!IsValid())
704ead24645SDimitry Andric     return nullDeref();
705ead24645SDimitry Andric   PyObject *o = PyDict_GetItemWithError(m_py_obj, key.get());
706ead24645SDimitry Andric   if (PyErr_Occurred())
707ead24645SDimitry Andric     return exception();
708ead24645SDimitry Andric   if (!o)
709ead24645SDimitry Andric     return keyError();
710ead24645SDimitry Andric   return Retain<PythonObject>(o);
711ead24645SDimitry Andric }
712ead24645SDimitry Andric 
GetItem(const Twine & key) const713ead24645SDimitry Andric Expected<PythonObject> PythonDictionary::GetItem(const Twine &key) const {
714ead24645SDimitry Andric   if (!IsValid())
715ead24645SDimitry Andric     return nullDeref();
716ead24645SDimitry Andric   PyObject *o = PyDict_GetItemString(m_py_obj, NullTerminated(key));
717ead24645SDimitry Andric   if (PyErr_Occurred())
718ead24645SDimitry Andric     return exception();
719ead24645SDimitry Andric   if (!o)
720ead24645SDimitry Andric     return keyError();
721ead24645SDimitry Andric   return Retain<PythonObject>(o);
722ead24645SDimitry Andric }
723ead24645SDimitry Andric 
SetItem(const PythonObject & key,const PythonObject & value) const724ead24645SDimitry Andric Error PythonDictionary::SetItem(const PythonObject &key,
725ead24645SDimitry Andric                                 const PythonObject &value) const {
726ead24645SDimitry Andric   if (!IsValid() || !value.IsValid())
727ead24645SDimitry Andric     return nullDeref();
728ead24645SDimitry Andric   int r = PyDict_SetItem(m_py_obj, key.get(), value.get());
729ead24645SDimitry Andric   if (r < 0)
730ead24645SDimitry Andric     return exception();
731ead24645SDimitry Andric   return Error::success();
732ead24645SDimitry Andric }
733ead24645SDimitry Andric 
SetItem(const Twine & key,const PythonObject & value) const734ead24645SDimitry Andric Error PythonDictionary::SetItem(const Twine &key,
735ead24645SDimitry Andric                                 const PythonObject &value) const {
736ead24645SDimitry Andric   if (!IsValid() || !value.IsValid())
737ead24645SDimitry Andric     return nullDeref();
738ead24645SDimitry Andric   int r = PyDict_SetItemString(m_py_obj, NullTerminated(key), value.get());
739ead24645SDimitry Andric   if (r < 0)
740ead24645SDimitry Andric     return exception();
741ead24645SDimitry Andric   return Error::success();
742ead24645SDimitry Andric }
743e81d9d49SDimitry Andric 
SetItemForKey(const PythonObject & key,const PythonObject & value)74414f1b3e8SDimitry Andric void PythonDictionary::SetItemForKey(const PythonObject &key,
74514f1b3e8SDimitry Andric                                      const PythonObject &value) {
746ead24645SDimitry Andric   Error error = SetItem(key, value);
747ead24645SDimitry Andric   if (error)
748ead24645SDimitry Andric     llvm::consumeError(std::move(error));
749e81d9d49SDimitry Andric }
750e81d9d49SDimitry Andric 
751e81d9d49SDimitry Andric StructuredData::DictionarySP
CreateStructuredDictionary() const75214f1b3e8SDimitry Andric PythonDictionary::CreateStructuredDictionary() const {
753e81d9d49SDimitry Andric   StructuredData::DictionarySP result(new StructuredData::Dictionary);
754e81d9d49SDimitry Andric   PythonList keys(GetKeys());
755e81d9d49SDimitry Andric   uint32_t num_keys = keys.GetSize();
75614f1b3e8SDimitry Andric   for (uint32_t i = 0; i < num_keys; ++i) {
757e81d9d49SDimitry Andric     PythonObject key = keys.GetItemAtIndex(i);
758e81d9d49SDimitry Andric     PythonObject value = GetItemForKey(key);
759e81d9d49SDimitry Andric     StructuredData::ObjectSP structured_value = value.CreateStructuredObject();
760e81d9d49SDimitry Andric     result->AddItem(key.Str().GetString(), structured_value);
761e81d9d49SDimitry Andric   }
762e81d9d49SDimitry Andric   return result;
763e81d9d49SDimitry Andric }
764e81d9d49SDimitry Andric 
BuiltinsModule()765145449b1SDimitry Andric PythonModule PythonModule::BuiltinsModule() { return AddModule("builtins"); }
766e81d9d49SDimitry Andric 
MainModule()76714f1b3e8SDimitry Andric PythonModule PythonModule::MainModule() { return AddModule("__main__"); }
768e81d9d49SDimitry Andric 
AddModule(llvm::StringRef module)76914f1b3e8SDimitry Andric PythonModule PythonModule::AddModule(llvm::StringRef module) {
770e81d9d49SDimitry Andric   std::string str = module.str();
771e81d9d49SDimitry Andric   return PythonModule(PyRefType::Borrowed, PyImport_AddModule(str.c_str()));
772e81d9d49SDimitry Andric }
773e81d9d49SDimitry Andric 
Import(const Twine & name)774ead24645SDimitry Andric Expected<PythonModule> PythonModule::Import(const Twine &name) {
775ead24645SDimitry Andric   PyObject *mod = PyImport_ImportModule(NullTerminated(name));
776ead24645SDimitry Andric   if (!mod)
777ead24645SDimitry Andric     return exception();
778ead24645SDimitry Andric   return Take<PythonModule>(mod);
779ead24645SDimitry Andric }
780ead24645SDimitry Andric 
Get(const Twine & name)781ead24645SDimitry Andric Expected<PythonObject> PythonModule::Get(const Twine &name) {
782ead24645SDimitry Andric   if (!IsValid())
783ead24645SDimitry Andric     return nullDeref();
784ead24645SDimitry Andric   PyObject *dict = PyModule_GetDict(m_py_obj);
785ead24645SDimitry Andric   if (!dict)
786ead24645SDimitry Andric     return exception();
787ead24645SDimitry Andric   PyObject *item = PyDict_GetItemString(dict, NullTerminated(name));
788ead24645SDimitry Andric   if (!item)
789ead24645SDimitry Andric     return exception();
790ead24645SDimitry Andric   return Retain<PythonObject>(item);
791e81d9d49SDimitry Andric }
792e81d9d49SDimitry Andric 
Check(PyObject * py_obj)79314f1b3e8SDimitry Andric bool PythonModule::Check(PyObject *py_obj) {
794e81d9d49SDimitry Andric   if (!py_obj)
795e81d9d49SDimitry Andric     return false;
796e81d9d49SDimitry Andric 
797e81d9d49SDimitry Andric   return PyModule_Check(py_obj);
798e81d9d49SDimitry Andric }
799e81d9d49SDimitry Andric 
GetDictionary() const80014f1b3e8SDimitry Andric PythonDictionary PythonModule::GetDictionary() const {
801ead24645SDimitry Andric   if (!IsValid())
802ead24645SDimitry Andric     return PythonDictionary();
803ead24645SDimitry Andric   return Retain<PythonDictionary>(PyModule_GetDict(m_py_obj));
804e81d9d49SDimitry Andric }
805e81d9d49SDimitry Andric 
Check(PyObject * py_obj)80614f1b3e8SDimitry Andric bool PythonCallable::Check(PyObject *py_obj) {
807e81d9d49SDimitry Andric   if (!py_obj)
808e81d9d49SDimitry Andric     return false;
809e81d9d49SDimitry Andric 
810e81d9d49SDimitry Andric   return PyCallable_Check(py_obj);
811e81d9d49SDimitry Andric }
812e81d9d49SDimitry Andric 
813ead24645SDimitry Andric #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3
814ead24645SDimitry Andric static const char get_arg_info_script[] = R"(
815ead24645SDimitry Andric from inspect import signature, Parameter, ismethod
816ead24645SDimitry Andric from collections import namedtuple
817706b4fc4SDimitry Andric ArgInfo = namedtuple('ArgInfo', ['count', 'has_varargs'])
818ead24645SDimitry Andric def main(f):
819ead24645SDimitry Andric     count = 0
820ead24645SDimitry Andric     varargs = False
821ead24645SDimitry Andric     for parameter in signature(f).parameters.values():
822ead24645SDimitry Andric         kind = parameter.kind
823ead24645SDimitry Andric         if kind in (Parameter.POSITIONAL_ONLY,
824ead24645SDimitry Andric                     Parameter.POSITIONAL_OR_KEYWORD):
825ead24645SDimitry Andric             count += 1
826ead24645SDimitry Andric         elif kind == Parameter.VAR_POSITIONAL:
827ead24645SDimitry Andric             varargs = True
828ead24645SDimitry Andric         elif kind in (Parameter.KEYWORD_ONLY,
829ead24645SDimitry Andric                       Parameter.VAR_KEYWORD):
830ead24645SDimitry Andric             pass
831ead24645SDimitry Andric         else:
832ead24645SDimitry Andric             raise Exception(f'unknown parameter kind: {kind}')
833706b4fc4SDimitry Andric     return ArgInfo(count, varargs)
834ead24645SDimitry Andric )";
835ead24645SDimitry Andric #endif
836ead24645SDimitry Andric 
GetArgInfo() const837ead24645SDimitry Andric Expected<PythonCallable::ArgInfo> PythonCallable::GetArgInfo() const {
838ead24645SDimitry Andric   ArgInfo result = {};
839ead24645SDimitry Andric   if (!IsValid())
840ead24645SDimitry Andric     return nullDeref();
841ead24645SDimitry Andric 
842ead24645SDimitry Andric #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3
843ead24645SDimitry Andric 
844ead24645SDimitry Andric   // no need to synchronize access to this global, we already have the GIL
845ead24645SDimitry Andric   static PythonScript get_arg_info(get_arg_info_script);
846ead24645SDimitry Andric   Expected<PythonObject> pyarginfo = get_arg_info(*this);
847ead24645SDimitry Andric   if (!pyarginfo)
848ead24645SDimitry Andric     return pyarginfo.takeError();
849706b4fc4SDimitry Andric   long long count =
850706b4fc4SDimitry Andric       cantFail(As<long long>(pyarginfo.get().GetAttribute("count")));
851706b4fc4SDimitry Andric   bool has_varargs =
852ead24645SDimitry Andric       cantFail(As<bool>(pyarginfo.get().GetAttribute("has_varargs")));
853706b4fc4SDimitry Andric   result.max_positional_args = has_varargs ? ArgInfo::UNBOUNDED : count;
854ead24645SDimitry Andric 
855ead24645SDimitry Andric #else
856706b4fc4SDimitry Andric   PyObject *py_func_obj;
857ead24645SDimitry Andric   bool is_bound_method = false;
858706b4fc4SDimitry Andric   bool is_class = false;
859706b4fc4SDimitry Andric 
860706b4fc4SDimitry Andric   if (PyType_Check(m_py_obj) || PyClass_Check(m_py_obj)) {
861706b4fc4SDimitry Andric     auto init = GetAttribute("__init__");
862706b4fc4SDimitry Andric     if (!init)
863706b4fc4SDimitry Andric       return init.takeError();
864706b4fc4SDimitry Andric     py_func_obj = init.get().get();
865706b4fc4SDimitry Andric     is_class = true;
866706b4fc4SDimitry Andric   } else {
867706b4fc4SDimitry Andric     py_func_obj = m_py_obj;
868706b4fc4SDimitry Andric   }
869706b4fc4SDimitry Andric 
87014f1b3e8SDimitry Andric   if (PyMethod_Check(py_func_obj)) {
871e81d9d49SDimitry Andric     py_func_obj = PyMethod_GET_FUNCTION(py_func_obj);
872f3fbd1c0SDimitry Andric     PythonObject im_self = GetAttributeValue("im_self");
873f3fbd1c0SDimitry Andric     if (im_self.IsValid() && !im_self.IsNone())
874ead24645SDimitry Andric       is_bound_method = true;
87514f1b3e8SDimitry Andric   } else {
876f3fbd1c0SDimitry Andric     // see if this is a callable object with an __call__ method
87714f1b3e8SDimitry Andric     if (!PyFunction_Check(py_func_obj)) {
878f3fbd1c0SDimitry Andric       PythonObject __call__ = GetAttributeValue("__call__");
87914f1b3e8SDimitry Andric       if (__call__.IsValid()) {
880f3fbd1c0SDimitry Andric         auto __callable__ = __call__.AsType<PythonCallable>();
88114f1b3e8SDimitry Andric         if (__callable__.IsValid()) {
882f3fbd1c0SDimitry Andric           py_func_obj = PyMethod_GET_FUNCTION(__callable__.get());
883ead24645SDimitry Andric           PythonObject im_self = __callable__.GetAttributeValue("im_self");
884f3fbd1c0SDimitry Andric           if (im_self.IsValid() && !im_self.IsNone())
885ead24645SDimitry Andric             is_bound_method = true;
886f3fbd1c0SDimitry Andric         }
887f3fbd1c0SDimitry Andric       }
888f3fbd1c0SDimitry Andric     }
889f3fbd1c0SDimitry Andric   }
890e81d9d49SDimitry Andric 
891e81d9d49SDimitry Andric   if (!py_func_obj)
892e81d9d49SDimitry Andric     return result;
893e81d9d49SDimitry Andric 
894e81d9d49SDimitry Andric   PyCodeObject *code = (PyCodeObject *)PyFunction_GET_CODE(py_func_obj);
895e81d9d49SDimitry Andric   if (!code)
896e81d9d49SDimitry Andric     return result;
897e81d9d49SDimitry Andric 
898706b4fc4SDimitry Andric   auto count = code->co_argcount;
899706b4fc4SDimitry Andric   bool has_varargs = !!(code->co_flags & CO_VARARGS);
900706b4fc4SDimitry Andric   result.max_positional_args =
901706b4fc4SDimitry Andric       has_varargs ? ArgInfo::UNBOUNDED
902706b4fc4SDimitry Andric                   : (count - (int)is_bound_method) - (int)is_class;
903ead24645SDimitry Andric 
904ead24645SDimitry Andric #endif
905ead24645SDimitry Andric 
906e81d9d49SDimitry Andric   return result;
907e81d9d49SDimitry Andric }
908e81d9d49SDimitry Andric 
909ead24645SDimitry Andric constexpr unsigned
910ead24645SDimitry Andric     PythonCallable::ArgInfo::UNBOUNDED; // FIXME delete after c++17
911ead24645SDimitry Andric 
operator ()()91214f1b3e8SDimitry Andric PythonObject PythonCallable::operator()() {
91314f1b3e8SDimitry Andric   return PythonObject(PyRefType::Owned, PyObject_CallObject(m_py_obj, nullptr));
914e81d9d49SDimitry Andric }
915e81d9d49SDimitry Andric 
91614f1b3e8SDimitry Andric PythonObject PythonCallable::
operator ()(std::initializer_list<PyObject * > args)91714f1b3e8SDimitry Andric operator()(std::initializer_list<PyObject *> args) {
918e81d9d49SDimitry Andric   PythonTuple arg_tuple(args);
919e81d9d49SDimitry Andric   return PythonObject(PyRefType::Owned,
920e81d9d49SDimitry Andric                       PyObject_CallObject(m_py_obj, arg_tuple.get()));
921e81d9d49SDimitry Andric }
922e81d9d49SDimitry Andric 
92314f1b3e8SDimitry Andric PythonObject PythonCallable::
operator ()(std::initializer_list<PythonObject> args)92414f1b3e8SDimitry Andric operator()(std::initializer_list<PythonObject> args) {
925e81d9d49SDimitry Andric   PythonTuple arg_tuple(args);
926e81d9d49SDimitry Andric   return PythonObject(PyRefType::Owned,
927e81d9d49SDimitry Andric                       PyObject_CallObject(m_py_obj, arg_tuple.get()));
928e81d9d49SDimitry Andric }
929e81d9d49SDimitry Andric 
Check(PyObject * py_obj)93014f1b3e8SDimitry Andric bool PythonFile::Check(PyObject *py_obj) {
931ead24645SDimitry Andric   if (!py_obj)
932ead24645SDimitry Andric     return false;
933e81d9d49SDimitry Andric   // In Python 3, there is no `PyFile_Check`, and in fact PyFile is not even a
934e81d9d49SDimitry Andric   // first-class object type anymore.  `PyFile_FromFd` is just a thin wrapper
935f73363f1SDimitry Andric   // over `io.open()`, which returns some object derived from `io.IOBase`. As a
936f73363f1SDimitry Andric   // result, the only way to detect a file in Python 3 is to check whether it
937ead24645SDimitry Andric   // inherits from `io.IOBase`.
938ead24645SDimitry Andric   auto io_module = PythonModule::Import("io");
939ead24645SDimitry Andric   if (!io_module) {
940ead24645SDimitry Andric     llvm::consumeError(io_module.takeError());
941e81d9d49SDimitry Andric     return false;
942ead24645SDimitry Andric   }
943ead24645SDimitry Andric   auto iobase = io_module.get().Get("IOBase");
944ead24645SDimitry Andric   if (!iobase) {
945ead24645SDimitry Andric     llvm::consumeError(iobase.takeError());
946e81d9d49SDimitry Andric     return false;
947ead24645SDimitry Andric   }
948ead24645SDimitry Andric   int r = PyObject_IsInstance(py_obj, iobase.get().get());
949ead24645SDimitry Andric   if (r < 0) {
950ead24645SDimitry Andric     llvm::consumeError(exception()); // clear the exception and log it.
951ead24645SDimitry Andric     return false;
952ead24645SDimitry Andric   }
953ead24645SDimitry Andric   return !!r;
954e81d9d49SDimitry Andric }
955e81d9d49SDimitry Andric 
toCString() const956ead24645SDimitry Andric const char *PythonException::toCString() const {
957ead24645SDimitry Andric   if (!m_repr_bytes)
958ead24645SDimitry Andric     return "unknown exception";
959ead24645SDimitry Andric   return PyBytes_AS_STRING(m_repr_bytes);
960e81d9d49SDimitry Andric }
961e81d9d49SDimitry Andric 
PythonException(const char * caller)962ead24645SDimitry Andric PythonException::PythonException(const char *caller) {
963ead24645SDimitry Andric   assert(PyErr_Occurred());
964e3b55780SDimitry Andric   m_exception_type = m_exception = m_traceback = m_repr_bytes = nullptr;
965ead24645SDimitry Andric   PyErr_Fetch(&m_exception_type, &m_exception, &m_traceback);
966ead24645SDimitry Andric   PyErr_NormalizeException(&m_exception_type, &m_exception, &m_traceback);
967ead24645SDimitry Andric   PyErr_Clear();
968ead24645SDimitry Andric   if (m_exception) {
969ead24645SDimitry Andric     PyObject *repr = PyObject_Repr(m_exception);
970ead24645SDimitry Andric     if (repr) {
971ead24645SDimitry Andric       m_repr_bytes = PyUnicode_AsEncodedString(repr, "utf-8", nullptr);
972ead24645SDimitry Andric       if (!m_repr_bytes) {
973ead24645SDimitry Andric         PyErr_Clear();
974ead24645SDimitry Andric       }
975ead24645SDimitry Andric       Py_XDECREF(repr);
976ead24645SDimitry Andric     } else {
977ead24645SDimitry Andric       PyErr_Clear();
978ead24645SDimitry Andric     }
979ead24645SDimitry Andric   }
980145449b1SDimitry Andric   Log *log = GetLog(LLDBLog::Script);
981ead24645SDimitry Andric   if (caller)
982ead24645SDimitry Andric     LLDB_LOGF(log, "%s failed with exception: %s", caller, toCString());
983ead24645SDimitry Andric   else
984ead24645SDimitry Andric     LLDB_LOGF(log, "python exception: %s", toCString());
985ead24645SDimitry Andric }
Restore()986ead24645SDimitry Andric void PythonException::Restore() {
987ead24645SDimitry Andric   if (m_exception_type && m_exception) {
988ead24645SDimitry Andric     PyErr_Restore(m_exception_type, m_exception, m_traceback);
989ead24645SDimitry Andric   } else {
990ead24645SDimitry Andric     PyErr_SetString(PyExc_Exception, toCString());
991ead24645SDimitry Andric   }
992e3b55780SDimitry Andric   m_exception_type = m_exception = m_traceback = nullptr;
993e81d9d49SDimitry Andric }
994e81d9d49SDimitry Andric 
~PythonException()995ead24645SDimitry Andric PythonException::~PythonException() {
996ead24645SDimitry Andric   Py_XDECREF(m_exception_type);
997ead24645SDimitry Andric   Py_XDECREF(m_exception);
998ead24645SDimitry Andric   Py_XDECREF(m_traceback);
999ead24645SDimitry Andric   Py_XDECREF(m_repr_bytes);
1000e81d9d49SDimitry Andric }
1001e81d9d49SDimitry Andric 
log(llvm::raw_ostream & OS) const1002ead24645SDimitry Andric void PythonException::log(llvm::raw_ostream &OS) const { OS << toCString(); }
1003ead24645SDimitry Andric 
convertToErrorCode() const1004ead24645SDimitry Andric std::error_code PythonException::convertToErrorCode() const {
1005ead24645SDimitry Andric   return llvm::inconvertibleErrorCode();
1006ead24645SDimitry Andric }
1007ead24645SDimitry Andric 
Matches(PyObject * exc) const1008ead24645SDimitry Andric bool PythonException::Matches(PyObject *exc) const {
1009ead24645SDimitry Andric   return PyErr_GivenExceptionMatches(m_exception_type, exc);
1010ead24645SDimitry Andric }
1011ead24645SDimitry Andric 
1012ead24645SDimitry Andric const char read_exception_script[] = R"(
1013ead24645SDimitry Andric import sys
1014ead24645SDimitry Andric from traceback import print_exception
1015ead24645SDimitry Andric if sys.version_info.major < 3:
1016ead24645SDimitry Andric   from StringIO import StringIO
1017ead24645SDimitry Andric else:
1018ead24645SDimitry Andric   from io import StringIO
1019ead24645SDimitry Andric def main(exc_type, exc_value, tb):
1020ead24645SDimitry Andric   f = StringIO()
1021ead24645SDimitry Andric   print_exception(exc_type, exc_value, tb, file=f)
1022ead24645SDimitry Andric   return f.getvalue()
1023ead24645SDimitry Andric )";
1024ead24645SDimitry Andric 
ReadBacktrace() const1025ead24645SDimitry Andric std::string PythonException::ReadBacktrace() const {
1026ead24645SDimitry Andric 
1027ead24645SDimitry Andric   if (!m_traceback)
1028ead24645SDimitry Andric     return toCString();
1029ead24645SDimitry Andric 
1030ead24645SDimitry Andric   // no need to synchronize access to this global, we already have the GIL
1031ead24645SDimitry Andric   static PythonScript read_exception(read_exception_script);
1032ead24645SDimitry Andric 
1033ead24645SDimitry Andric   Expected<std::string> backtrace = As<std::string>(
1034ead24645SDimitry Andric       read_exception(m_exception_type, m_exception, m_traceback));
1035ead24645SDimitry Andric 
1036ead24645SDimitry Andric   if (!backtrace) {
1037ead24645SDimitry Andric     std::string message =
1038ead24645SDimitry Andric         std::string(toCString()) + "\n" +
1039cfca06d7SDimitry Andric         "Traceback unavailable, an error occurred while reading it:\n";
1040ead24645SDimitry Andric     return (message + llvm::toString(backtrace.takeError()));
1041ead24645SDimitry Andric   }
1042ead24645SDimitry Andric 
1043ead24645SDimitry Andric   return std::move(backtrace.get());
1044ead24645SDimitry Andric }
1045ead24645SDimitry Andric 
1046ead24645SDimitry Andric char PythonException::ID = 0;
1047ead24645SDimitry Andric 
1048ead24645SDimitry Andric llvm::Expected<File::OpenOptions>
GetOptionsForPyObject(const PythonObject & obj)1049ead24645SDimitry Andric GetOptionsForPyObject(const PythonObject &obj) {
1050ead24645SDimitry Andric   auto options = File::OpenOptions(0);
1051ead24645SDimitry Andric   auto readable = As<bool>(obj.CallMethod("readable"));
1052ead24645SDimitry Andric   if (!readable)
1053ead24645SDimitry Andric     return readable.takeError();
1054ead24645SDimitry Andric   auto writable = As<bool>(obj.CallMethod("writable"));
1055ead24645SDimitry Andric   if (!writable)
1056ead24645SDimitry Andric     return writable.takeError();
1057c0981da4SDimitry Andric   if (readable.get() && writable.get())
1058c0981da4SDimitry Andric     options |= File::eOpenOptionReadWrite;
1059c0981da4SDimitry Andric   else if (writable.get())
1060c0981da4SDimitry Andric     options |= File::eOpenOptionWriteOnly;
1061c0981da4SDimitry Andric   else if (readable.get())
1062c0981da4SDimitry Andric     options |= File::eOpenOptionReadOnly;
1063ead24645SDimitry Andric   return options;
1064ead24645SDimitry Andric }
1065ead24645SDimitry Andric 
1066ead24645SDimitry Andric // Base class template for python files.   All it knows how to do
1067ead24645SDimitry Andric // is hold a reference to the python object and close or flush it
1068ead24645SDimitry Andric // when the File is closed.
1069ead24645SDimitry Andric namespace {
1070ead24645SDimitry Andric template <typename Base> class OwnedPythonFile : public Base {
1071ead24645SDimitry Andric public:
1072ead24645SDimitry Andric   template <typename... Args>
OwnedPythonFile(const PythonFile & file,bool borrowed,Args...args)1073ead24645SDimitry Andric   OwnedPythonFile(const PythonFile &file, bool borrowed, Args... args)
1074ead24645SDimitry Andric       : Base(args...), m_py_obj(file), m_borrowed(borrowed) {
1075ead24645SDimitry Andric     assert(m_py_obj);
1076ead24645SDimitry Andric   }
1077ead24645SDimitry Andric 
~OwnedPythonFile()1078ead24645SDimitry Andric   ~OwnedPythonFile() override {
1079ead24645SDimitry Andric     assert(m_py_obj);
1080ead24645SDimitry Andric     GIL takeGIL;
1081ead24645SDimitry Andric     Close();
1082ead24645SDimitry Andric     // we need to ensure the python object is released while we still
1083ead24645SDimitry Andric     // hold the GIL
1084ead24645SDimitry Andric     m_py_obj.Reset();
1085ead24645SDimitry Andric   }
1086ead24645SDimitry Andric 
IsPythonSideValid() const1087ead24645SDimitry Andric   bool IsPythonSideValid() const {
1088ead24645SDimitry Andric     GIL takeGIL;
1089ead24645SDimitry Andric     auto closed = As<bool>(m_py_obj.GetAttribute("closed"));
1090ead24645SDimitry Andric     if (!closed) {
1091ead24645SDimitry Andric       llvm::consumeError(closed.takeError());
1092ead24645SDimitry Andric       return false;
1093ead24645SDimitry Andric     }
1094ead24645SDimitry Andric     return !closed.get();
1095ead24645SDimitry Andric   }
1096ead24645SDimitry Andric 
IsValid() const1097ead24645SDimitry Andric   bool IsValid() const override {
1098ead24645SDimitry Andric     return IsPythonSideValid() && Base::IsValid();
1099ead24645SDimitry Andric   }
1100ead24645SDimitry Andric 
Close()1101ead24645SDimitry Andric   Status Close() override {
1102ead24645SDimitry Andric     assert(m_py_obj);
1103ead24645SDimitry Andric     Status py_error, base_error;
1104ead24645SDimitry Andric     GIL takeGIL;
1105ead24645SDimitry Andric     if (!m_borrowed) {
1106ead24645SDimitry Andric       auto r = m_py_obj.CallMethod("close");
1107ead24645SDimitry Andric       if (!r)
1108ead24645SDimitry Andric         py_error = Status(r.takeError());
1109ead24645SDimitry Andric     }
1110ead24645SDimitry Andric     base_error = Base::Close();
1111ead24645SDimitry Andric     if (py_error.Fail())
1112ead24645SDimitry Andric       return py_error;
1113ead24645SDimitry Andric     return base_error;
1114ead24645SDimitry Andric   };
1115ead24645SDimitry Andric 
GetPythonObject() const1116ead24645SDimitry Andric   PyObject *GetPythonObject() const {
1117ead24645SDimitry Andric     assert(m_py_obj.IsValid());
1118ead24645SDimitry Andric     return m_py_obj.get();
1119ead24645SDimitry Andric   }
1120ead24645SDimitry Andric 
1121ead24645SDimitry Andric   static bool classof(const File *file) = delete;
1122ead24645SDimitry Andric 
1123ead24645SDimitry Andric protected:
1124ead24645SDimitry Andric   PythonFile m_py_obj;
1125ead24645SDimitry Andric   bool m_borrowed;
1126ead24645SDimitry Andric };
1127ead24645SDimitry Andric } // namespace
1128ead24645SDimitry Andric 
1129ead24645SDimitry Andric // A SimplePythonFile is a OwnedPythonFile that just does all I/O as
1130ead24645SDimitry Andric // a NativeFile
1131ead24645SDimitry Andric namespace {
1132ead24645SDimitry Andric class SimplePythonFile : public OwnedPythonFile<NativeFile> {
1133ead24645SDimitry Andric public:
SimplePythonFile(const PythonFile & file,bool borrowed,int fd,File::OpenOptions options)1134ead24645SDimitry Andric   SimplePythonFile(const PythonFile &file, bool borrowed, int fd,
1135ead24645SDimitry Andric                    File::OpenOptions options)
1136ead24645SDimitry Andric       : OwnedPythonFile(file, borrowed, fd, options, false) {}
1137ead24645SDimitry Andric 
1138ead24645SDimitry Andric   static char ID;
isA(const void * classID) const1139ead24645SDimitry Andric   bool isA(const void *classID) const override {
1140ead24645SDimitry Andric     return classID == &ID || NativeFile::isA(classID);
1141ead24645SDimitry Andric   }
classof(const File * file)1142ead24645SDimitry Andric   static bool classof(const File *file) { return file->isA(&ID); }
1143ead24645SDimitry Andric };
1144ead24645SDimitry Andric char SimplePythonFile::ID = 0;
1145ead24645SDimitry Andric } // namespace
1146ead24645SDimitry Andric 
1147ead24645SDimitry Andric namespace {
1148ead24645SDimitry Andric class PythonBuffer {
1149ead24645SDimitry Andric public:
1150ead24645SDimitry Andric   PythonBuffer &operator=(const PythonBuffer &) = delete;
1151ead24645SDimitry Andric   PythonBuffer(const PythonBuffer &) = delete;
1152ead24645SDimitry Andric 
Create(PythonObject & obj,int flags=PyBUF_SIMPLE)1153ead24645SDimitry Andric   static Expected<PythonBuffer> Create(PythonObject &obj,
1154ead24645SDimitry Andric                                        int flags = PyBUF_SIMPLE) {
1155ead24645SDimitry Andric     Py_buffer py_buffer = {};
1156ead24645SDimitry Andric     PyObject_GetBuffer(obj.get(), &py_buffer, flags);
1157ead24645SDimitry Andric     if (!py_buffer.obj)
1158ead24645SDimitry Andric       return llvm::make_error<PythonException>();
1159ead24645SDimitry Andric     return PythonBuffer(py_buffer);
1160ead24645SDimitry Andric   }
1161ead24645SDimitry Andric 
PythonBuffer(PythonBuffer && other)1162ead24645SDimitry Andric   PythonBuffer(PythonBuffer &&other) {
1163ead24645SDimitry Andric     m_buffer = other.m_buffer;
1164ead24645SDimitry Andric     other.m_buffer.obj = nullptr;
1165ead24645SDimitry Andric   }
1166ead24645SDimitry Andric 
~PythonBuffer()1167ead24645SDimitry Andric   ~PythonBuffer() {
1168ead24645SDimitry Andric     if (m_buffer.obj)
1169ead24645SDimitry Andric       PyBuffer_Release(&m_buffer);
1170ead24645SDimitry Andric   }
1171ead24645SDimitry Andric 
get()1172ead24645SDimitry Andric   Py_buffer &get() { return m_buffer; }
1173ead24645SDimitry Andric 
1174ead24645SDimitry Andric private:
1175ead24645SDimitry Andric   // takes ownership of the buffer.
PythonBuffer(const Py_buffer & py_buffer)1176ead24645SDimitry Andric   PythonBuffer(const Py_buffer &py_buffer) : m_buffer(py_buffer) {}
1177ead24645SDimitry Andric   Py_buffer m_buffer;
1178ead24645SDimitry Andric };
1179ead24645SDimitry Andric } // namespace
1180ead24645SDimitry Andric 
1181ead24645SDimitry Andric // Shared methods between TextPythonFile and BinaryPythonFile
1182ead24645SDimitry Andric namespace {
1183ead24645SDimitry Andric class PythonIOFile : public OwnedPythonFile<File> {
1184ead24645SDimitry Andric public:
PythonIOFile(const PythonFile & file,bool borrowed)1185ead24645SDimitry Andric   PythonIOFile(const PythonFile &file, bool borrowed)
1186ead24645SDimitry Andric       : OwnedPythonFile(file, borrowed) {}
1187ead24645SDimitry Andric 
~PythonIOFile()1188ead24645SDimitry Andric   ~PythonIOFile() override { Close(); }
1189ead24645SDimitry Andric 
IsValid() const1190ead24645SDimitry Andric   bool IsValid() const override { return IsPythonSideValid(); }
1191ead24645SDimitry Andric 
Close()1192ead24645SDimitry Andric   Status Close() override {
1193ead24645SDimitry Andric     assert(m_py_obj);
1194ead24645SDimitry Andric     GIL takeGIL;
1195ead24645SDimitry Andric     if (m_borrowed)
1196ead24645SDimitry Andric       return Flush();
1197ead24645SDimitry Andric     auto r = m_py_obj.CallMethod("close");
1198ead24645SDimitry Andric     if (!r)
1199ead24645SDimitry Andric       return Status(r.takeError());
1200ead24645SDimitry Andric     return Status();
1201ead24645SDimitry Andric   }
1202ead24645SDimitry Andric 
Flush()1203ead24645SDimitry Andric   Status Flush() override {
1204ead24645SDimitry Andric     GIL takeGIL;
1205ead24645SDimitry Andric     auto r = m_py_obj.CallMethod("flush");
1206ead24645SDimitry Andric     if (!r)
1207ead24645SDimitry Andric       return Status(r.takeError());
1208ead24645SDimitry Andric     return Status();
1209ead24645SDimitry Andric   }
1210ead24645SDimitry Andric 
GetOptions() const1211ead24645SDimitry Andric   Expected<File::OpenOptions> GetOptions() const override {
1212ead24645SDimitry Andric     GIL takeGIL;
1213ead24645SDimitry Andric     return GetOptionsForPyObject(m_py_obj);
1214ead24645SDimitry Andric   }
1215ead24645SDimitry Andric 
1216ead24645SDimitry Andric   static char ID;
isA(const void * classID) const1217ead24645SDimitry Andric   bool isA(const void *classID) const override {
1218ead24645SDimitry Andric     return classID == &ID || File::isA(classID);
1219ead24645SDimitry Andric   }
classof(const File * file)1220ead24645SDimitry Andric   static bool classof(const File *file) { return file->isA(&ID); }
1221ead24645SDimitry Andric };
1222ead24645SDimitry Andric char PythonIOFile::ID = 0;
1223ead24645SDimitry Andric } // namespace
1224ead24645SDimitry Andric 
1225ead24645SDimitry Andric namespace {
1226ead24645SDimitry Andric class BinaryPythonFile : public PythonIOFile {
1227ead24645SDimitry Andric protected:
1228ead24645SDimitry Andric   int m_descriptor;
1229ead24645SDimitry Andric 
1230ead24645SDimitry Andric public:
BinaryPythonFile(int fd,const PythonFile & file,bool borrowed)1231ead24645SDimitry Andric   BinaryPythonFile(int fd, const PythonFile &file, bool borrowed)
1232ead24645SDimitry Andric       : PythonIOFile(file, borrowed),
1233ead24645SDimitry Andric         m_descriptor(File::DescriptorIsValid(fd) ? fd
1234ead24645SDimitry Andric                                                  : File::kInvalidDescriptor) {}
1235ead24645SDimitry Andric 
GetDescriptor() const1236ead24645SDimitry Andric   int GetDescriptor() const override { return m_descriptor; }
1237ead24645SDimitry Andric 
Write(const void * buf,size_t & num_bytes)1238ead24645SDimitry Andric   Status Write(const void *buf, size_t &num_bytes) override {
1239ead24645SDimitry Andric     GIL takeGIL;
1240ead24645SDimitry Andric     PyObject *pybuffer_p = PyMemoryView_FromMemory(
1241ead24645SDimitry Andric         const_cast<char *>((const char *)buf), num_bytes, PyBUF_READ);
1242ead24645SDimitry Andric     if (!pybuffer_p)
1243ead24645SDimitry Andric       return Status(llvm::make_error<PythonException>());
1244ead24645SDimitry Andric     auto pybuffer = Take<PythonObject>(pybuffer_p);
1245ead24645SDimitry Andric     num_bytes = 0;
1246ead24645SDimitry Andric     auto bytes_written = As<long long>(m_py_obj.CallMethod("write", pybuffer));
1247ead24645SDimitry Andric     if (!bytes_written)
1248ead24645SDimitry Andric       return Status(bytes_written.takeError());
1249ead24645SDimitry Andric     if (bytes_written.get() < 0)
1250ead24645SDimitry Andric       return Status(".write() method returned a negative number!");
1251ead24645SDimitry Andric     static_assert(sizeof(long long) >= sizeof(size_t), "overflow");
1252ead24645SDimitry Andric     num_bytes = bytes_written.get();
1253ead24645SDimitry Andric     return Status();
1254ead24645SDimitry Andric   }
1255ead24645SDimitry Andric 
Read(void * buf,size_t & num_bytes)1256ead24645SDimitry Andric   Status Read(void *buf, size_t &num_bytes) override {
1257ead24645SDimitry Andric     GIL takeGIL;
1258ead24645SDimitry Andric     static_assert(sizeof(long long) >= sizeof(size_t), "overflow");
1259ead24645SDimitry Andric     auto pybuffer_obj =
1260ead24645SDimitry Andric         m_py_obj.CallMethod("read", (unsigned long long)num_bytes);
1261ead24645SDimitry Andric     if (!pybuffer_obj)
1262ead24645SDimitry Andric       return Status(pybuffer_obj.takeError());
1263ead24645SDimitry Andric     num_bytes = 0;
1264ead24645SDimitry Andric     if (pybuffer_obj.get().IsNone()) {
1265ead24645SDimitry Andric       // EOF
1266ead24645SDimitry Andric       num_bytes = 0;
1267ead24645SDimitry Andric       return Status();
1268ead24645SDimitry Andric     }
1269ead24645SDimitry Andric     auto pybuffer = PythonBuffer::Create(pybuffer_obj.get());
1270ead24645SDimitry Andric     if (!pybuffer)
1271ead24645SDimitry Andric       return Status(pybuffer.takeError());
1272ead24645SDimitry Andric     memcpy(buf, pybuffer.get().get().buf, pybuffer.get().get().len);
1273ead24645SDimitry Andric     num_bytes = pybuffer.get().get().len;
1274ead24645SDimitry Andric     return Status();
1275ead24645SDimitry Andric   }
1276ead24645SDimitry Andric };
1277ead24645SDimitry Andric } // namespace
1278ead24645SDimitry Andric 
1279ead24645SDimitry Andric namespace {
1280ead24645SDimitry Andric class TextPythonFile : public PythonIOFile {
1281ead24645SDimitry Andric protected:
1282ead24645SDimitry Andric   int m_descriptor;
1283ead24645SDimitry Andric 
1284ead24645SDimitry Andric public:
TextPythonFile(int fd,const PythonFile & file,bool borrowed)1285ead24645SDimitry Andric   TextPythonFile(int fd, const PythonFile &file, bool borrowed)
1286ead24645SDimitry Andric       : PythonIOFile(file, borrowed),
1287ead24645SDimitry Andric         m_descriptor(File::DescriptorIsValid(fd) ? fd
1288ead24645SDimitry Andric                                                  : File::kInvalidDescriptor) {}
1289ead24645SDimitry Andric 
GetDescriptor() const1290ead24645SDimitry Andric   int GetDescriptor() const override { return m_descriptor; }
1291ead24645SDimitry Andric 
Write(const void * buf,size_t & num_bytes)1292ead24645SDimitry Andric   Status Write(const void *buf, size_t &num_bytes) override {
1293ead24645SDimitry Andric     GIL takeGIL;
1294ead24645SDimitry Andric     auto pystring =
1295ead24645SDimitry Andric         PythonString::FromUTF8(llvm::StringRef((const char *)buf, num_bytes));
1296ead24645SDimitry Andric     if (!pystring)
1297ead24645SDimitry Andric       return Status(pystring.takeError());
1298ead24645SDimitry Andric     num_bytes = 0;
1299ead24645SDimitry Andric     auto bytes_written =
1300ead24645SDimitry Andric         As<long long>(m_py_obj.CallMethod("write", pystring.get()));
1301ead24645SDimitry Andric     if (!bytes_written)
1302ead24645SDimitry Andric       return Status(bytes_written.takeError());
1303ead24645SDimitry Andric     if (bytes_written.get() < 0)
1304ead24645SDimitry Andric       return Status(".write() method returned a negative number!");
1305ead24645SDimitry Andric     static_assert(sizeof(long long) >= sizeof(size_t), "overflow");
1306ead24645SDimitry Andric     num_bytes = bytes_written.get();
1307ead24645SDimitry Andric     return Status();
1308ead24645SDimitry Andric   }
1309ead24645SDimitry Andric 
Read(void * buf,size_t & num_bytes)1310ead24645SDimitry Andric   Status Read(void *buf, size_t &num_bytes) override {
1311ead24645SDimitry Andric     GIL takeGIL;
1312ead24645SDimitry Andric     size_t num_chars = num_bytes / 6;
1313ead24645SDimitry Andric     size_t orig_num_bytes = num_bytes;
1314ead24645SDimitry Andric     num_bytes = 0;
1315ead24645SDimitry Andric     if (orig_num_bytes < 6) {
1316ead24645SDimitry Andric       return Status("can't read less than 6 bytes from a utf8 text stream");
1317ead24645SDimitry Andric     }
1318ead24645SDimitry Andric     auto pystring = As<PythonString>(
1319ead24645SDimitry Andric         m_py_obj.CallMethod("read", (unsigned long long)num_chars));
1320ead24645SDimitry Andric     if (!pystring)
1321ead24645SDimitry Andric       return Status(pystring.takeError());
1322ead24645SDimitry Andric     if (pystring.get().IsNone()) {
1323ead24645SDimitry Andric       // EOF
1324ead24645SDimitry Andric       return Status();
1325ead24645SDimitry Andric     }
1326ead24645SDimitry Andric     auto stringref = pystring.get().AsUTF8();
1327ead24645SDimitry Andric     if (!stringref)
1328ead24645SDimitry Andric       return Status(stringref.takeError());
1329ead24645SDimitry Andric     num_bytes = stringref.get().size();
1330ead24645SDimitry Andric     memcpy(buf, stringref.get().begin(), num_bytes);
1331ead24645SDimitry Andric     return Status();
1332ead24645SDimitry Andric   }
1333ead24645SDimitry Andric };
1334ead24645SDimitry Andric } // namespace
1335ead24645SDimitry Andric 
ConvertToFile(bool borrowed)1336ead24645SDimitry Andric llvm::Expected<FileSP> PythonFile::ConvertToFile(bool borrowed) {
1337ead24645SDimitry Andric   if (!IsValid())
1338ead24645SDimitry Andric     return llvm::createStringError(llvm::inconvertibleErrorCode(),
1339ead24645SDimitry Andric                                    "invalid PythonFile");
1340ead24645SDimitry Andric 
1341ead24645SDimitry Andric   int fd = PyObject_AsFileDescriptor(m_py_obj);
1342ead24645SDimitry Andric   if (fd < 0) {
1343ead24645SDimitry Andric     PyErr_Clear();
1344ead24645SDimitry Andric     return ConvertToFileForcingUseOfScriptingIOMethods(borrowed);
1345ead24645SDimitry Andric   }
1346ead24645SDimitry Andric   auto options = GetOptionsForPyObject(*this);
1347ead24645SDimitry Andric   if (!options)
1348ead24645SDimitry Andric     return options.takeError();
1349ead24645SDimitry Andric 
1350c0981da4SDimitry Andric   File::OpenOptions rw =
1351c0981da4SDimitry Andric       options.get() & (File::eOpenOptionReadOnly | File::eOpenOptionWriteOnly |
1352c0981da4SDimitry Andric                        File::eOpenOptionReadWrite);
1353c0981da4SDimitry Andric   if (rw == File::eOpenOptionWriteOnly || rw == File::eOpenOptionReadWrite) {
1354ead24645SDimitry Andric     // LLDB and python will not share I/O buffers.  We should probably
1355ead24645SDimitry Andric     // flush the python buffers now.
1356ead24645SDimitry Andric     auto r = CallMethod("flush");
1357ead24645SDimitry Andric     if (!r)
1358ead24645SDimitry Andric       return r.takeError();
1359706b4fc4SDimitry Andric   }
1360ead24645SDimitry Andric 
1361ead24645SDimitry Andric   FileSP file_sp;
1362ead24645SDimitry Andric   if (borrowed) {
1363b1c73532SDimitry Andric     // In this case we don't need to retain the python
1364ead24645SDimitry Andric     // object at all.
1365ead24645SDimitry Andric     file_sp = std::make_shared<NativeFile>(fd, options.get(), false);
1366ead24645SDimitry Andric   } else {
1367ead24645SDimitry Andric     file_sp = std::static_pointer_cast<File>(
1368ead24645SDimitry Andric         std::make_shared<SimplePythonFile>(*this, borrowed, fd, options.get()));
1369ead24645SDimitry Andric   }
1370ead24645SDimitry Andric   if (!file_sp->IsValid())
1371ead24645SDimitry Andric     return llvm::createStringError(llvm::inconvertibleErrorCode(),
1372ead24645SDimitry Andric                                    "invalid File");
1373ead24645SDimitry Andric 
1374ead24645SDimitry Andric   return file_sp;
1375ead24645SDimitry Andric }
1376ead24645SDimitry Andric 
1377ead24645SDimitry Andric llvm::Expected<FileSP>
ConvertToFileForcingUseOfScriptingIOMethods(bool borrowed)1378ead24645SDimitry Andric PythonFile::ConvertToFileForcingUseOfScriptingIOMethods(bool borrowed) {
1379ead24645SDimitry Andric 
1380ead24645SDimitry Andric   assert(!PyErr_Occurred());
1381ead24645SDimitry Andric 
1382ead24645SDimitry Andric   if (!IsValid())
1383ead24645SDimitry Andric     return llvm::createStringError(llvm::inconvertibleErrorCode(),
1384ead24645SDimitry Andric                                    "invalid PythonFile");
1385ead24645SDimitry Andric 
1386ead24645SDimitry Andric   int fd = PyObject_AsFileDescriptor(m_py_obj);
1387ead24645SDimitry Andric   if (fd < 0) {
1388ead24645SDimitry Andric     PyErr_Clear();
1389ead24645SDimitry Andric     fd = File::kInvalidDescriptor;
1390ead24645SDimitry Andric   }
1391ead24645SDimitry Andric 
1392ead24645SDimitry Andric   auto io_module = PythonModule::Import("io");
1393ead24645SDimitry Andric   if (!io_module)
1394ead24645SDimitry Andric     return io_module.takeError();
1395ead24645SDimitry Andric   auto textIOBase = io_module.get().Get("TextIOBase");
1396ead24645SDimitry Andric   if (!textIOBase)
1397ead24645SDimitry Andric     return textIOBase.takeError();
1398ead24645SDimitry Andric   auto rawIOBase = io_module.get().Get("RawIOBase");
1399ead24645SDimitry Andric   if (!rawIOBase)
1400ead24645SDimitry Andric     return rawIOBase.takeError();
1401ead24645SDimitry Andric   auto bufferedIOBase = io_module.get().Get("BufferedIOBase");
1402ead24645SDimitry Andric   if (!bufferedIOBase)
1403ead24645SDimitry Andric     return bufferedIOBase.takeError();
1404ead24645SDimitry Andric 
1405ead24645SDimitry Andric   FileSP file_sp;
1406ead24645SDimitry Andric 
1407ead24645SDimitry Andric   auto isTextIO = IsInstance(textIOBase.get());
1408ead24645SDimitry Andric   if (!isTextIO)
1409ead24645SDimitry Andric     return isTextIO.takeError();
1410ead24645SDimitry Andric   if (isTextIO.get())
1411ead24645SDimitry Andric     file_sp = std::static_pointer_cast<File>(
1412ead24645SDimitry Andric         std::make_shared<TextPythonFile>(fd, *this, borrowed));
1413ead24645SDimitry Andric 
1414ead24645SDimitry Andric   auto isRawIO = IsInstance(rawIOBase.get());
1415ead24645SDimitry Andric   if (!isRawIO)
1416ead24645SDimitry Andric     return isRawIO.takeError();
1417ead24645SDimitry Andric   auto isBufferedIO = IsInstance(bufferedIOBase.get());
1418ead24645SDimitry Andric   if (!isBufferedIO)
1419ead24645SDimitry Andric     return isBufferedIO.takeError();
1420ead24645SDimitry Andric 
1421ead24645SDimitry Andric   if (isRawIO.get() || isBufferedIO.get()) {
1422ead24645SDimitry Andric     file_sp = std::static_pointer_cast<File>(
1423ead24645SDimitry Andric         std::make_shared<BinaryPythonFile>(fd, *this, borrowed));
1424ead24645SDimitry Andric   }
1425ead24645SDimitry Andric 
1426ead24645SDimitry Andric   if (!file_sp)
1427ead24645SDimitry Andric     return llvm::createStringError(llvm::inconvertibleErrorCode(),
1428ead24645SDimitry Andric                                    "python file is neither text nor binary");
1429ead24645SDimitry Andric 
1430ead24645SDimitry Andric   if (!file_sp->IsValid())
1431ead24645SDimitry Andric     return llvm::createStringError(llvm::inconvertibleErrorCode(),
1432ead24645SDimitry Andric                                    "invalid File");
1433ead24645SDimitry Andric 
1434ead24645SDimitry Andric   return file_sp;
1435ead24645SDimitry Andric }
1436ead24645SDimitry Andric 
FromFile(File & file,const char * mode)1437ead24645SDimitry Andric Expected<PythonFile> PythonFile::FromFile(File &file, const char *mode) {
1438ead24645SDimitry Andric   if (!file.IsValid())
1439ead24645SDimitry Andric     return llvm::createStringError(llvm::inconvertibleErrorCode(),
1440ead24645SDimitry Andric                                    "invalid file");
1441ead24645SDimitry Andric 
1442ead24645SDimitry Andric   if (auto *simple = llvm::dyn_cast<SimplePythonFile>(&file))
1443ead24645SDimitry Andric     return Retain<PythonFile>(simple->GetPythonObject());
1444ead24645SDimitry Andric   if (auto *pythonio = llvm::dyn_cast<PythonIOFile>(&file))
1445ead24645SDimitry Andric     return Retain<PythonFile>(pythonio->GetPythonObject());
1446ead24645SDimitry Andric 
1447ead24645SDimitry Andric   if (!mode) {
1448ead24645SDimitry Andric     auto m = file.GetOpenMode();
1449ead24645SDimitry Andric     if (!m)
1450ead24645SDimitry Andric       return m.takeError();
1451ead24645SDimitry Andric     mode = m.get();
1452ead24645SDimitry Andric   }
1453ead24645SDimitry Andric 
1454ead24645SDimitry Andric   PyObject *file_obj;
1455ead24645SDimitry Andric   file_obj = PyFile_FromFd(file.GetDescriptor(), nullptr, mode, -1, nullptr,
1456706b4fc4SDimitry Andric                            "ignore", nullptr, /*closefd=*/0);
1457ead24645SDimitry Andric 
1458ead24645SDimitry Andric   if (!file_obj)
1459ead24645SDimitry Andric     return exception();
1460ead24645SDimitry Andric 
1461ead24645SDimitry Andric   return Take<PythonFile>(file_obj);
1462e81d9d49SDimitry Andric }
1463e81d9d49SDimitry Andric 
Init()1464ead24645SDimitry Andric Error PythonScript::Init() {
1465ead24645SDimitry Andric   if (function.IsValid())
1466ead24645SDimitry Andric     return Error::success();
1467f3fbd1c0SDimitry Andric 
1468ead24645SDimitry Andric   PythonDictionary globals(PyInitialValue::Empty);
1469ead24645SDimitry Andric   auto builtins = PythonModule::BuiltinsModule();
1470ead24645SDimitry Andric   if (Error error = globals.SetItem("__builtins__", builtins))
1471ead24645SDimitry Andric     return error;
1472ead24645SDimitry Andric   PyObject *o =
1473ead24645SDimitry Andric       PyRun_String(script, Py_file_input, globals.get(), globals.get());
1474ead24645SDimitry Andric   if (!o)
1475ead24645SDimitry Andric     return exception();
1476ead24645SDimitry Andric   Take<PythonObject>(o);
1477ead24645SDimitry Andric   auto f = As<PythonCallable>(globals.GetItem("main"));
1478ead24645SDimitry Andric   if (!f)
1479ead24645SDimitry Andric     return f.takeError();
1480ead24645SDimitry Andric   function = std::move(f.get());
1481ead24645SDimitry Andric 
1482ead24645SDimitry Andric   return Error::success();
1483f3fbd1c0SDimitry Andric }
1484f3fbd1c0SDimitry Andric 
1485ead24645SDimitry Andric llvm::Expected<PythonObject>
runStringOneLine(const llvm::Twine & string,const PythonDictionary & globals,const PythonDictionary & locals)1486ead24645SDimitry Andric python::runStringOneLine(const llvm::Twine &string,
1487ead24645SDimitry Andric                          const PythonDictionary &globals,
1488ead24645SDimitry Andric                          const PythonDictionary &locals) {
1489ead24645SDimitry Andric   if (!globals.IsValid() || !locals.IsValid())
1490ead24645SDimitry Andric     return nullDeref();
1491e81d9d49SDimitry Andric 
1492ead24645SDimitry Andric   PyObject *code =
1493ead24645SDimitry Andric       Py_CompileString(NullTerminated(string), "<string>", Py_eval_input);
1494ead24645SDimitry Andric   if (!code) {
1495ead24645SDimitry Andric     PyErr_Clear();
1496ead24645SDimitry Andric     code =
1497ead24645SDimitry Andric         Py_CompileString(NullTerminated(string), "<string>", Py_single_input);
1498ead24645SDimitry Andric   }
1499ead24645SDimitry Andric   if (!code)
1500ead24645SDimitry Andric     return exception();
1501ead24645SDimitry Andric   auto code_ref = Take<PythonObject>(code);
1502ead24645SDimitry Andric 
1503ead24645SDimitry Andric   PyObject *result = PyEval_EvalCode(code, globals.get(), locals.get());
1504ead24645SDimitry Andric 
1505ead24645SDimitry Andric   if (!result)
1506ead24645SDimitry Andric     return exception();
1507ead24645SDimitry Andric 
1508ead24645SDimitry Andric   return Take<PythonObject>(result);
1509ead24645SDimitry Andric }
1510ead24645SDimitry Andric 
1511ead24645SDimitry Andric llvm::Expected<PythonObject>
runStringMultiLine(const llvm::Twine & string,const PythonDictionary & globals,const PythonDictionary & locals)1512ead24645SDimitry Andric python::runStringMultiLine(const llvm::Twine &string,
1513ead24645SDimitry Andric                            const PythonDictionary &globals,
1514ead24645SDimitry Andric                            const PythonDictionary &locals) {
1515ead24645SDimitry Andric   if (!globals.IsValid() || !locals.IsValid())
1516ead24645SDimitry Andric     return nullDeref();
1517ead24645SDimitry Andric   PyObject *result = PyRun_String(NullTerminated(string), Py_file_input,
1518ead24645SDimitry Andric                                   globals.get(), locals.get());
1519ead24645SDimitry Andric   if (!result)
1520ead24645SDimitry Andric     return exception();
1521ead24645SDimitry Andric   return Take<PythonObject>(result);
1522e81d9d49SDimitry Andric }
1523e81d9d49SDimitry Andric 
1524e81d9d49SDimitry Andric #endif
1525