15ffd83dbSDimitry Andric //===-- PythonDataObjects.cpp ---------------------------------------------===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric 
9480093f4SDimitry Andric #include "lldb/Host/Config.h"
10*0b57cec5SDimitry Andric 
11480093f4SDimitry Andric #if LLDB_ENABLE_PYTHON
12*0b57cec5SDimitry Andric 
13*0b57cec5SDimitry Andric #include "PythonDataObjects.h"
14*0b57cec5SDimitry Andric #include "ScriptInterpreterPython.h"
15*0b57cec5SDimitry Andric 
16*0b57cec5SDimitry Andric #include "lldb/Host/File.h"
17*0b57cec5SDimitry Andric #include "lldb/Host/FileSystem.h"
18*0b57cec5SDimitry Andric #include "lldb/Interpreter/ScriptInterpreter.h"
199dba64beSDimitry Andric #include "lldb/Utility/Log.h"
20*0b57cec5SDimitry Andric #include "lldb/Utility/Stream.h"
21*0b57cec5SDimitry Andric 
22*0b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h"
239dba64beSDimitry Andric #include "llvm/Support/Casting.h"
24*0b57cec5SDimitry Andric #include "llvm/Support/ConvertUTF.h"
25*0b57cec5SDimitry Andric #include "llvm/Support/Errno.h"
26*0b57cec5SDimitry Andric 
27fe6060f1SDimitry Andric #include <cstdio>
28*0b57cec5SDimitry Andric 
29*0b57cec5SDimitry Andric using namespace lldb_private;
30*0b57cec5SDimitry Andric using namespace lldb;
319dba64beSDimitry Andric using namespace lldb_private::python;
329dba64beSDimitry Andric using llvm::cantFail;
339dba64beSDimitry Andric using llvm::Error;
349dba64beSDimitry Andric using llvm::Expected;
359dba64beSDimitry Andric using llvm::Twine;
36*0b57cec5SDimitry Andric 
379dba64beSDimitry Andric template <> Expected<bool> python::As<bool>(Expected<PythonObject> &&obj) {
389dba64beSDimitry Andric   if (!obj)
399dba64beSDimitry Andric     return obj.takeError();
409dba64beSDimitry Andric   return obj.get().IsTrue();
419dba64beSDimitry Andric }
429dba64beSDimitry Andric 
439dba64beSDimitry Andric template <>
449dba64beSDimitry Andric Expected<long long> python::As<long long>(Expected<PythonObject> &&obj) {
459dba64beSDimitry Andric   if (!obj)
469dba64beSDimitry Andric     return obj.takeError();
475ffd83dbSDimitry Andric   return obj->AsLongLong();
485ffd83dbSDimitry Andric }
495ffd83dbSDimitry Andric 
505ffd83dbSDimitry Andric template <>
515ffd83dbSDimitry Andric Expected<unsigned long long>
525ffd83dbSDimitry Andric python::As<unsigned long long>(Expected<PythonObject> &&obj) {
535ffd83dbSDimitry Andric   if (!obj)
545ffd83dbSDimitry Andric     return obj.takeError();
555ffd83dbSDimitry Andric   return obj->AsUnsignedLongLong();
569dba64beSDimitry Andric }
579dba64beSDimitry Andric 
589dba64beSDimitry Andric template <>
599dba64beSDimitry Andric Expected<std::string> python::As<std::string>(Expected<PythonObject> &&obj) {
609dba64beSDimitry Andric   if (!obj)
619dba64beSDimitry Andric     return obj.takeError();
629dba64beSDimitry Andric   PyObject *str_obj = PyObject_Str(obj.get().get());
639dba64beSDimitry Andric   if (!obj)
649dba64beSDimitry Andric     return llvm::make_error<PythonException>();
659dba64beSDimitry Andric   auto str = Take<PythonString>(str_obj);
669dba64beSDimitry Andric   auto utf8 = str.AsUTF8();
679dba64beSDimitry Andric   if (!utf8)
689dba64beSDimitry Andric     return utf8.takeError();
695ffd83dbSDimitry Andric   return std::string(utf8.get());
705ffd83dbSDimitry Andric }
715ffd83dbSDimitry Andric 
7204eeddc0SDimitry Andric static bool python_is_finalizing() {
7304eeddc0SDimitry Andric #if PY_MAJOR_VERSION == 2
7404eeddc0SDimitry Andric   return false;
7504eeddc0SDimitry Andric #elif PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 7
7604eeddc0SDimitry Andric   return _Py_Finalizing != nullptr;
7704eeddc0SDimitry Andric #else
7804eeddc0SDimitry Andric   return _Py_IsFinalizing();
7904eeddc0SDimitry Andric #endif
8004eeddc0SDimitry Andric }
8104eeddc0SDimitry Andric 
8204eeddc0SDimitry Andric void PythonObject::Reset() {
8304eeddc0SDimitry Andric   if (m_py_obj && Py_IsInitialized()) {
8404eeddc0SDimitry Andric     if (python_is_finalizing()) {
8504eeddc0SDimitry Andric       // Leak m_py_obj rather than crashing the process.
8604eeddc0SDimitry Andric       // https://docs.python.org/3/c-api/init.html#c.PyGILState_Ensure
8704eeddc0SDimitry Andric     } else {
8804eeddc0SDimitry Andric       PyGILState_STATE state = PyGILState_Ensure();
8904eeddc0SDimitry Andric       Py_DECREF(m_py_obj);
9004eeddc0SDimitry Andric       PyGILState_Release(state);
9104eeddc0SDimitry Andric     }
9204eeddc0SDimitry Andric   }
9304eeddc0SDimitry Andric   m_py_obj = nullptr;
9404eeddc0SDimitry Andric }
9504eeddc0SDimitry Andric 
965ffd83dbSDimitry Andric Expected<long long> PythonObject::AsLongLong() const {
975ffd83dbSDimitry Andric   if (!m_py_obj)
985ffd83dbSDimitry Andric     return nullDeref();
995ffd83dbSDimitry Andric #if PY_MAJOR_VERSION < 3
1005ffd83dbSDimitry Andric   if (!PyLong_Check(m_py_obj)) {
1015ffd83dbSDimitry Andric     PythonInteger i(PyRefType::Borrowed, m_py_obj);
1025ffd83dbSDimitry Andric     return i.AsLongLong();
1035ffd83dbSDimitry Andric   }
1045ffd83dbSDimitry Andric #endif
1055ffd83dbSDimitry Andric   assert(!PyErr_Occurred());
1065ffd83dbSDimitry Andric   long long r = PyLong_AsLongLong(m_py_obj);
1075ffd83dbSDimitry Andric   if (PyErr_Occurred())
1085ffd83dbSDimitry Andric     return exception();
1095ffd83dbSDimitry Andric   return r;
1105ffd83dbSDimitry Andric }
1115ffd83dbSDimitry Andric 
1125ffd83dbSDimitry Andric Expected<long long> PythonObject::AsUnsignedLongLong() const {
1135ffd83dbSDimitry Andric   if (!m_py_obj)
1145ffd83dbSDimitry Andric     return nullDeref();
1155ffd83dbSDimitry Andric #if PY_MAJOR_VERSION < 3
1165ffd83dbSDimitry Andric   if (!PyLong_Check(m_py_obj)) {
1175ffd83dbSDimitry Andric     PythonInteger i(PyRefType::Borrowed, m_py_obj);
1185ffd83dbSDimitry Andric     return i.AsUnsignedLongLong();
1195ffd83dbSDimitry Andric   }
1205ffd83dbSDimitry Andric #endif
1215ffd83dbSDimitry Andric   assert(!PyErr_Occurred());
1225ffd83dbSDimitry Andric   long long r = PyLong_AsUnsignedLongLong(m_py_obj);
1235ffd83dbSDimitry Andric   if (PyErr_Occurred())
1245ffd83dbSDimitry Andric     return exception();
1255ffd83dbSDimitry Andric   return r;
1265ffd83dbSDimitry Andric }
1275ffd83dbSDimitry Andric 
1285ffd83dbSDimitry Andric // wraps on overflow, instead of raising an error.
1295ffd83dbSDimitry Andric Expected<unsigned long long> PythonObject::AsModuloUnsignedLongLong() const {
1305ffd83dbSDimitry Andric   if (!m_py_obj)
1315ffd83dbSDimitry Andric     return nullDeref();
1325ffd83dbSDimitry Andric #if PY_MAJOR_VERSION < 3
1335ffd83dbSDimitry Andric   if (!PyLong_Check(m_py_obj)) {
1345ffd83dbSDimitry Andric     PythonInteger i(PyRefType::Borrowed, m_py_obj);
1355ffd83dbSDimitry Andric     return i.AsModuloUnsignedLongLong();
1365ffd83dbSDimitry Andric   }
1375ffd83dbSDimitry Andric #endif
1385ffd83dbSDimitry Andric   assert(!PyErr_Occurred());
1395ffd83dbSDimitry Andric   unsigned long long r = PyLong_AsUnsignedLongLongMask(m_py_obj);
1405ffd83dbSDimitry Andric   if (PyErr_Occurred())
1415ffd83dbSDimitry Andric     return exception();
1425ffd83dbSDimitry Andric   return r;
1439dba64beSDimitry Andric }
1449dba64beSDimitry Andric 
1459dba64beSDimitry Andric void StructuredPythonObject::Serialize(llvm::json::OStream &s) const {
1469dba64beSDimitry Andric   s.value(llvm::formatv("Python Obj: {0:X}", GetValue()).str());
147*0b57cec5SDimitry Andric }
148*0b57cec5SDimitry Andric 
149*0b57cec5SDimitry Andric // PythonObject
150*0b57cec5SDimitry Andric 
151*0b57cec5SDimitry Andric void PythonObject::Dump(Stream &strm) const {
152*0b57cec5SDimitry Andric   if (m_py_obj) {
153*0b57cec5SDimitry Andric     FILE *file = llvm::sys::RetryAfterSignal(nullptr, ::tmpfile);
154*0b57cec5SDimitry Andric     if (file) {
155*0b57cec5SDimitry Andric       ::PyObject_Print(m_py_obj, file, 0);
156*0b57cec5SDimitry Andric       const long length = ftell(file);
157*0b57cec5SDimitry Andric       if (length) {
158*0b57cec5SDimitry Andric         ::rewind(file);
159*0b57cec5SDimitry Andric         std::vector<char> file_contents(length, '\0');
160*0b57cec5SDimitry Andric         const size_t length_read =
161*0b57cec5SDimitry Andric             ::fread(file_contents.data(), 1, file_contents.size(), file);
162*0b57cec5SDimitry Andric         if (length_read > 0)
163*0b57cec5SDimitry Andric           strm.Write(file_contents.data(), length_read);
164*0b57cec5SDimitry Andric       }
165*0b57cec5SDimitry Andric       ::fclose(file);
166*0b57cec5SDimitry Andric     }
167*0b57cec5SDimitry Andric   } else
168*0b57cec5SDimitry Andric     strm.PutCString("NULL");
169*0b57cec5SDimitry Andric }
170*0b57cec5SDimitry Andric 
171*0b57cec5SDimitry Andric PyObjectType PythonObject::GetObjectType() const {
172*0b57cec5SDimitry Andric   if (!IsAllocated())
173*0b57cec5SDimitry Andric     return PyObjectType::None;
174*0b57cec5SDimitry Andric 
175*0b57cec5SDimitry Andric   if (PythonModule::Check(m_py_obj))
176*0b57cec5SDimitry Andric     return PyObjectType::Module;
177*0b57cec5SDimitry Andric   if (PythonList::Check(m_py_obj))
178*0b57cec5SDimitry Andric     return PyObjectType::List;
179*0b57cec5SDimitry Andric   if (PythonTuple::Check(m_py_obj))
180*0b57cec5SDimitry Andric     return PyObjectType::Tuple;
181*0b57cec5SDimitry Andric   if (PythonDictionary::Check(m_py_obj))
182*0b57cec5SDimitry Andric     return PyObjectType::Dictionary;
183*0b57cec5SDimitry Andric   if (PythonString::Check(m_py_obj))
184*0b57cec5SDimitry Andric     return PyObjectType::String;
185*0b57cec5SDimitry Andric #if PY_MAJOR_VERSION >= 3
186*0b57cec5SDimitry Andric   if (PythonBytes::Check(m_py_obj))
187*0b57cec5SDimitry Andric     return PyObjectType::Bytes;
188*0b57cec5SDimitry Andric #endif
189*0b57cec5SDimitry Andric   if (PythonByteArray::Check(m_py_obj))
190*0b57cec5SDimitry Andric     return PyObjectType::ByteArray;
191*0b57cec5SDimitry Andric   if (PythonBoolean::Check(m_py_obj))
192*0b57cec5SDimitry Andric     return PyObjectType::Boolean;
193*0b57cec5SDimitry Andric   if (PythonInteger::Check(m_py_obj))
194*0b57cec5SDimitry Andric     return PyObjectType::Integer;
195*0b57cec5SDimitry Andric   if (PythonFile::Check(m_py_obj))
196*0b57cec5SDimitry Andric     return PyObjectType::File;
197*0b57cec5SDimitry Andric   if (PythonCallable::Check(m_py_obj))
198*0b57cec5SDimitry Andric     return PyObjectType::Callable;
199*0b57cec5SDimitry Andric   return PyObjectType::Unknown;
200*0b57cec5SDimitry Andric }
201*0b57cec5SDimitry Andric 
202*0b57cec5SDimitry Andric PythonString PythonObject::Repr() const {
203*0b57cec5SDimitry Andric   if (!m_py_obj)
204*0b57cec5SDimitry Andric     return PythonString();
205*0b57cec5SDimitry Andric   PyObject *repr = PyObject_Repr(m_py_obj);
206*0b57cec5SDimitry Andric   if (!repr)
207*0b57cec5SDimitry Andric     return PythonString();
208*0b57cec5SDimitry Andric   return PythonString(PyRefType::Owned, repr);
209*0b57cec5SDimitry Andric }
210*0b57cec5SDimitry Andric 
211*0b57cec5SDimitry Andric PythonString PythonObject::Str() const {
212*0b57cec5SDimitry Andric   if (!m_py_obj)
213*0b57cec5SDimitry Andric     return PythonString();
214*0b57cec5SDimitry Andric   PyObject *str = PyObject_Str(m_py_obj);
215*0b57cec5SDimitry Andric   if (!str)
216*0b57cec5SDimitry Andric     return PythonString();
217*0b57cec5SDimitry Andric   return PythonString(PyRefType::Owned, str);
218*0b57cec5SDimitry Andric }
219*0b57cec5SDimitry Andric 
220*0b57cec5SDimitry Andric PythonObject
221*0b57cec5SDimitry Andric PythonObject::ResolveNameWithDictionary(llvm::StringRef name,
222*0b57cec5SDimitry Andric                                         const PythonDictionary &dict) {
223*0b57cec5SDimitry Andric   size_t dot_pos = name.find('.');
224*0b57cec5SDimitry Andric   llvm::StringRef piece = name.substr(0, dot_pos);
225*0b57cec5SDimitry Andric   PythonObject result = dict.GetItemForKey(PythonString(piece));
226*0b57cec5SDimitry Andric   if (dot_pos == llvm::StringRef::npos) {
227*0b57cec5SDimitry Andric     // There was no dot, we're done.
228*0b57cec5SDimitry Andric     return result;
229*0b57cec5SDimitry Andric   }
230*0b57cec5SDimitry Andric 
231*0b57cec5SDimitry Andric   // There was a dot.  The remaining portion of the name should be looked up in
232*0b57cec5SDimitry Andric   // the context of the object that was found in the dictionary.
233*0b57cec5SDimitry Andric   return result.ResolveName(name.substr(dot_pos + 1));
234*0b57cec5SDimitry Andric }
235*0b57cec5SDimitry Andric 
236*0b57cec5SDimitry Andric PythonObject PythonObject::ResolveName(llvm::StringRef name) const {
237*0b57cec5SDimitry Andric   // Resolve the name in the context of the specified object.  If, for example,
238*0b57cec5SDimitry Andric   // `this` refers to a PyModule, then this will look for `name` in this
239*0b57cec5SDimitry Andric   // module.  If `this` refers to a PyType, then it will resolve `name` as an
240*0b57cec5SDimitry Andric   // attribute of that type.  If `this` refers to an instance of an object,
241*0b57cec5SDimitry Andric   // then it will resolve `name` as the value of the specified field.
242*0b57cec5SDimitry Andric   //
243*0b57cec5SDimitry Andric   // This function handles dotted names so that, for example, if `m_py_obj`
244*0b57cec5SDimitry Andric   // refers to the `sys` module, and `name` == "path.append", then it will find
245*0b57cec5SDimitry Andric   // the function `sys.path.append`.
246*0b57cec5SDimitry Andric 
247*0b57cec5SDimitry Andric   size_t dot_pos = name.find('.');
248*0b57cec5SDimitry Andric   if (dot_pos == llvm::StringRef::npos) {
249*0b57cec5SDimitry Andric     // No dots in the name, we should be able to find the value immediately as
250*0b57cec5SDimitry Andric     // an attribute of `m_py_obj`.
251*0b57cec5SDimitry Andric     return GetAttributeValue(name);
252*0b57cec5SDimitry Andric   }
253*0b57cec5SDimitry Andric 
254*0b57cec5SDimitry Andric   // Look up the first piece of the name, and resolve the rest as a child of
255*0b57cec5SDimitry Andric   // that.
256*0b57cec5SDimitry Andric   PythonObject parent = ResolveName(name.substr(0, dot_pos));
257*0b57cec5SDimitry Andric   if (!parent.IsAllocated())
258*0b57cec5SDimitry Andric     return PythonObject();
259*0b57cec5SDimitry Andric 
260*0b57cec5SDimitry Andric   // Tail recursion.. should be optimized by the compiler
261*0b57cec5SDimitry Andric   return parent.ResolveName(name.substr(dot_pos + 1));
262*0b57cec5SDimitry Andric }
263*0b57cec5SDimitry Andric 
264*0b57cec5SDimitry Andric bool PythonObject::HasAttribute(llvm::StringRef attr) const {
265*0b57cec5SDimitry Andric   if (!IsValid())
266*0b57cec5SDimitry Andric     return false;
267*0b57cec5SDimitry Andric   PythonString py_attr(attr);
268*0b57cec5SDimitry Andric   return !!PyObject_HasAttr(m_py_obj, py_attr.get());
269*0b57cec5SDimitry Andric }
270*0b57cec5SDimitry Andric 
271*0b57cec5SDimitry Andric PythonObject PythonObject::GetAttributeValue(llvm::StringRef attr) const {
272*0b57cec5SDimitry Andric   if (!IsValid())
273*0b57cec5SDimitry Andric     return PythonObject();
274*0b57cec5SDimitry Andric 
275*0b57cec5SDimitry Andric   PythonString py_attr(attr);
276*0b57cec5SDimitry Andric   if (!PyObject_HasAttr(m_py_obj, py_attr.get()))
277*0b57cec5SDimitry Andric     return PythonObject();
278*0b57cec5SDimitry Andric 
279*0b57cec5SDimitry Andric   return PythonObject(PyRefType::Owned,
280*0b57cec5SDimitry Andric                       PyObject_GetAttr(m_py_obj, py_attr.get()));
281*0b57cec5SDimitry Andric }
282*0b57cec5SDimitry Andric 
283*0b57cec5SDimitry Andric StructuredData::ObjectSP PythonObject::CreateStructuredObject() const {
28404eeddc0SDimitry Andric #if PY_MAJOR_VERSION >= 3
28504eeddc0SDimitry Andric   assert(PyGILState_Check());
28604eeddc0SDimitry Andric #endif
287*0b57cec5SDimitry Andric   switch (GetObjectType()) {
288*0b57cec5SDimitry Andric   case PyObjectType::Dictionary:
289*0b57cec5SDimitry Andric     return PythonDictionary(PyRefType::Borrowed, m_py_obj)
290*0b57cec5SDimitry Andric         .CreateStructuredDictionary();
291*0b57cec5SDimitry Andric   case PyObjectType::Boolean:
292*0b57cec5SDimitry Andric     return PythonBoolean(PyRefType::Borrowed, m_py_obj)
293*0b57cec5SDimitry Andric         .CreateStructuredBoolean();
294*0b57cec5SDimitry Andric   case PyObjectType::Integer:
295*0b57cec5SDimitry Andric     return PythonInteger(PyRefType::Borrowed, m_py_obj)
296*0b57cec5SDimitry Andric         .CreateStructuredInteger();
297*0b57cec5SDimitry Andric   case PyObjectType::List:
298*0b57cec5SDimitry Andric     return PythonList(PyRefType::Borrowed, m_py_obj).CreateStructuredArray();
299*0b57cec5SDimitry Andric   case PyObjectType::String:
300*0b57cec5SDimitry Andric     return PythonString(PyRefType::Borrowed, m_py_obj).CreateStructuredString();
301*0b57cec5SDimitry Andric   case PyObjectType::Bytes:
302*0b57cec5SDimitry Andric     return PythonBytes(PyRefType::Borrowed, m_py_obj).CreateStructuredString();
303*0b57cec5SDimitry Andric   case PyObjectType::ByteArray:
304*0b57cec5SDimitry Andric     return PythonByteArray(PyRefType::Borrowed, m_py_obj)
305*0b57cec5SDimitry Andric         .CreateStructuredString();
306*0b57cec5SDimitry Andric   case PyObjectType::None:
307*0b57cec5SDimitry Andric     return StructuredData::ObjectSP();
308*0b57cec5SDimitry Andric   default:
30904eeddc0SDimitry Andric     return StructuredData::ObjectSP(new StructuredPythonObject(
31004eeddc0SDimitry Andric         PythonObject(PyRefType::Borrowed, m_py_obj)));
311*0b57cec5SDimitry Andric   }
312*0b57cec5SDimitry Andric }
313*0b57cec5SDimitry Andric 
314*0b57cec5SDimitry Andric // PythonString
315*0b57cec5SDimitry Andric 
3169dba64beSDimitry Andric PythonBytes::PythonBytes(llvm::ArrayRef<uint8_t> bytes) { SetBytes(bytes); }
317*0b57cec5SDimitry Andric 
3189dba64beSDimitry Andric PythonBytes::PythonBytes(const uint8_t *bytes, size_t length) {
319*0b57cec5SDimitry Andric   SetBytes(llvm::ArrayRef<uint8_t>(bytes, length));
320*0b57cec5SDimitry Andric }
321*0b57cec5SDimitry Andric 
322*0b57cec5SDimitry Andric bool PythonBytes::Check(PyObject *py_obj) {
323*0b57cec5SDimitry Andric   if (!py_obj)
324*0b57cec5SDimitry Andric     return false;
325*0b57cec5SDimitry Andric   return PyBytes_Check(py_obj);
326*0b57cec5SDimitry Andric }
327*0b57cec5SDimitry Andric 
328*0b57cec5SDimitry Andric llvm::ArrayRef<uint8_t> PythonBytes::GetBytes() const {
329*0b57cec5SDimitry Andric   if (!IsValid())
330*0b57cec5SDimitry Andric     return llvm::ArrayRef<uint8_t>();
331*0b57cec5SDimitry Andric 
332*0b57cec5SDimitry Andric   Py_ssize_t size;
333*0b57cec5SDimitry Andric   char *c;
334*0b57cec5SDimitry Andric 
335*0b57cec5SDimitry Andric   PyBytes_AsStringAndSize(m_py_obj, &c, &size);
336*0b57cec5SDimitry Andric   return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size);
337*0b57cec5SDimitry Andric }
338*0b57cec5SDimitry Andric 
339*0b57cec5SDimitry Andric size_t PythonBytes::GetSize() const {
340*0b57cec5SDimitry Andric   if (!IsValid())
341*0b57cec5SDimitry Andric     return 0;
342*0b57cec5SDimitry Andric   return PyBytes_Size(m_py_obj);
343*0b57cec5SDimitry Andric }
344*0b57cec5SDimitry Andric 
345*0b57cec5SDimitry Andric void PythonBytes::SetBytes(llvm::ArrayRef<uint8_t> bytes) {
346*0b57cec5SDimitry Andric   const char *data = reinterpret_cast<const char *>(bytes.data());
3479dba64beSDimitry Andric   *this = Take<PythonBytes>(PyBytes_FromStringAndSize(data, bytes.size()));
348*0b57cec5SDimitry Andric }
349*0b57cec5SDimitry Andric 
350*0b57cec5SDimitry Andric StructuredData::StringSP PythonBytes::CreateStructuredString() const {
351*0b57cec5SDimitry Andric   StructuredData::StringSP result(new StructuredData::String);
352*0b57cec5SDimitry Andric   Py_ssize_t size;
353*0b57cec5SDimitry Andric   char *c;
354*0b57cec5SDimitry Andric   PyBytes_AsStringAndSize(m_py_obj, &c, &size);
355*0b57cec5SDimitry Andric   result->SetValue(std::string(c, size));
356*0b57cec5SDimitry Andric   return result;
357*0b57cec5SDimitry Andric }
358*0b57cec5SDimitry Andric 
359*0b57cec5SDimitry Andric PythonByteArray::PythonByteArray(llvm::ArrayRef<uint8_t> bytes)
360*0b57cec5SDimitry Andric     : PythonByteArray(bytes.data(), bytes.size()) {}
361*0b57cec5SDimitry Andric 
362*0b57cec5SDimitry Andric PythonByteArray::PythonByteArray(const uint8_t *bytes, size_t length) {
363*0b57cec5SDimitry Andric   const char *str = reinterpret_cast<const char *>(bytes);
3649dba64beSDimitry Andric   *this = Take<PythonByteArray>(PyByteArray_FromStringAndSize(str, length));
365*0b57cec5SDimitry Andric }
366*0b57cec5SDimitry Andric 
367*0b57cec5SDimitry Andric bool PythonByteArray::Check(PyObject *py_obj) {
368*0b57cec5SDimitry Andric   if (!py_obj)
369*0b57cec5SDimitry Andric     return false;
370*0b57cec5SDimitry Andric   return PyByteArray_Check(py_obj);
371*0b57cec5SDimitry Andric }
372*0b57cec5SDimitry Andric 
373*0b57cec5SDimitry Andric llvm::ArrayRef<uint8_t> PythonByteArray::GetBytes() const {
374*0b57cec5SDimitry Andric   if (!IsValid())
375*0b57cec5SDimitry Andric     return llvm::ArrayRef<uint8_t>();
376*0b57cec5SDimitry Andric 
377*0b57cec5SDimitry Andric   char *c = PyByteArray_AsString(m_py_obj);
378*0b57cec5SDimitry Andric   size_t size = GetSize();
379*0b57cec5SDimitry Andric   return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size);
380*0b57cec5SDimitry Andric }
381*0b57cec5SDimitry Andric 
382*0b57cec5SDimitry Andric size_t PythonByteArray::GetSize() const {
383*0b57cec5SDimitry Andric   if (!IsValid())
384*0b57cec5SDimitry Andric     return 0;
385*0b57cec5SDimitry Andric 
386*0b57cec5SDimitry Andric   return PyByteArray_Size(m_py_obj);
387*0b57cec5SDimitry Andric }
388*0b57cec5SDimitry Andric 
389*0b57cec5SDimitry Andric StructuredData::StringSP PythonByteArray::CreateStructuredString() const {
390*0b57cec5SDimitry Andric   StructuredData::StringSP result(new StructuredData::String);
391*0b57cec5SDimitry Andric   llvm::ArrayRef<uint8_t> bytes = GetBytes();
392*0b57cec5SDimitry Andric   const char *str = reinterpret_cast<const char *>(bytes.data());
393*0b57cec5SDimitry Andric   result->SetValue(std::string(str, bytes.size()));
394*0b57cec5SDimitry Andric   return result;
395*0b57cec5SDimitry Andric }
396*0b57cec5SDimitry Andric 
397*0b57cec5SDimitry Andric // PythonString
398*0b57cec5SDimitry Andric 
3999dba64beSDimitry Andric Expected<PythonString> PythonString::FromUTF8(llvm::StringRef string) {
4009dba64beSDimitry Andric #if PY_MAJOR_VERSION >= 3
4019dba64beSDimitry Andric   PyObject *str = PyUnicode_FromStringAndSize(string.data(), string.size());
4029dba64beSDimitry Andric #else
4039dba64beSDimitry Andric   PyObject *str = PyString_FromStringAndSize(string.data(), string.size());
4049dba64beSDimitry Andric #endif
4059dba64beSDimitry Andric   if (!str)
4069dba64beSDimitry Andric     return llvm::make_error<PythonException>();
4079dba64beSDimitry Andric   return Take<PythonString>(str);
408*0b57cec5SDimitry Andric }
409*0b57cec5SDimitry Andric 
4109dba64beSDimitry Andric PythonString::PythonString(llvm::StringRef string) { SetString(string); }
411*0b57cec5SDimitry Andric 
412*0b57cec5SDimitry Andric bool PythonString::Check(PyObject *py_obj) {
413*0b57cec5SDimitry Andric   if (!py_obj)
414*0b57cec5SDimitry Andric     return false;
415*0b57cec5SDimitry Andric 
416*0b57cec5SDimitry Andric   if (PyUnicode_Check(py_obj))
417*0b57cec5SDimitry Andric     return true;
418*0b57cec5SDimitry Andric #if PY_MAJOR_VERSION < 3
419*0b57cec5SDimitry Andric   if (PyString_Check(py_obj))
420*0b57cec5SDimitry Andric     return true;
421*0b57cec5SDimitry Andric #endif
422*0b57cec5SDimitry Andric   return false;
423*0b57cec5SDimitry Andric }
424*0b57cec5SDimitry Andric 
4259dba64beSDimitry Andric void PythonString::Convert(PyRefType &type, PyObject *&py_obj) {
426*0b57cec5SDimitry Andric #if PY_MAJOR_VERSION < 3
427*0b57cec5SDimitry Andric   // In Python 2, Don't store PyUnicode objects directly, because we need
428*0b57cec5SDimitry Andric   // access to their underlying character buffers which Python 2 doesn't
429*0b57cec5SDimitry Andric   // provide.
4309dba64beSDimitry Andric   if (PyUnicode_Check(py_obj)) {
4319dba64beSDimitry Andric     PyObject *s = PyUnicode_AsUTF8String(py_obj);
4329dba64beSDimitry Andric     if (s == nullptr) {
4339dba64beSDimitry Andric       PyErr_Clear();
4349dba64beSDimitry Andric       if (type == PyRefType::Owned)
4359dba64beSDimitry Andric         Py_DECREF(py_obj);
4369dba64beSDimitry Andric       return;
4379dba64beSDimitry Andric     }
4389dba64beSDimitry Andric     if (type == PyRefType::Owned)
4399dba64beSDimitry Andric       Py_DECREF(py_obj);
4409dba64beSDimitry Andric     else
4419dba64beSDimitry Andric       type = PyRefType::Owned;
4429dba64beSDimitry Andric     py_obj = s;
4439dba64beSDimitry Andric   }
444*0b57cec5SDimitry Andric #endif
445*0b57cec5SDimitry Andric }
446*0b57cec5SDimitry Andric 
447*0b57cec5SDimitry Andric llvm::StringRef PythonString::GetString() const {
4489dba64beSDimitry Andric   auto s = AsUTF8();
4499dba64beSDimitry Andric   if (!s) {
4509dba64beSDimitry Andric     llvm::consumeError(s.takeError());
4519dba64beSDimitry Andric     return llvm::StringRef("");
4529dba64beSDimitry Andric   }
4539dba64beSDimitry Andric   return s.get();
4549dba64beSDimitry Andric }
4559dba64beSDimitry Andric 
4569dba64beSDimitry Andric Expected<llvm::StringRef> PythonString::AsUTF8() const {
457*0b57cec5SDimitry Andric   if (!IsValid())
4589dba64beSDimitry Andric     return nullDeref();
459*0b57cec5SDimitry Andric 
460*0b57cec5SDimitry Andric   Py_ssize_t size;
461*0b57cec5SDimitry Andric   const char *data;
462*0b57cec5SDimitry Andric 
463*0b57cec5SDimitry Andric #if PY_MAJOR_VERSION >= 3
464*0b57cec5SDimitry Andric   data = PyUnicode_AsUTF8AndSize(m_py_obj, &size);
465*0b57cec5SDimitry Andric #else
4669dba64beSDimitry Andric   char *c = NULL;
4679dba64beSDimitry Andric   int r = PyString_AsStringAndSize(m_py_obj, &c, &size);
4689dba64beSDimitry Andric   if (r < 0)
4699dba64beSDimitry Andric     c = NULL;
470*0b57cec5SDimitry Andric   data = c;
471*0b57cec5SDimitry Andric #endif
4729dba64beSDimitry Andric 
4739dba64beSDimitry Andric   if (!data)
4749dba64beSDimitry Andric     return exception();
4759dba64beSDimitry Andric 
476*0b57cec5SDimitry Andric   return llvm::StringRef(data, size);
477*0b57cec5SDimitry Andric }
478*0b57cec5SDimitry Andric 
479*0b57cec5SDimitry Andric size_t PythonString::GetSize() const {
480*0b57cec5SDimitry Andric   if (IsValid()) {
481*0b57cec5SDimitry Andric #if PY_MAJOR_VERSION >= 3
482e8d8bef9SDimitry Andric #if PY_MINOR_VERSION >= 3
483e8d8bef9SDimitry Andric     return PyUnicode_GetLength(m_py_obj);
484e8d8bef9SDimitry Andric #else
485*0b57cec5SDimitry Andric     return PyUnicode_GetSize(m_py_obj);
486e8d8bef9SDimitry Andric #endif
487*0b57cec5SDimitry Andric #else
488*0b57cec5SDimitry Andric     return PyString_Size(m_py_obj);
489*0b57cec5SDimitry Andric #endif
490*0b57cec5SDimitry Andric   }
491*0b57cec5SDimitry Andric   return 0;
492*0b57cec5SDimitry Andric }
493*0b57cec5SDimitry Andric 
494*0b57cec5SDimitry Andric void PythonString::SetString(llvm::StringRef string) {
4959dba64beSDimitry Andric   auto s = FromUTF8(string);
4969dba64beSDimitry Andric   if (!s) {
4979dba64beSDimitry Andric     llvm::consumeError(s.takeError());
4989dba64beSDimitry Andric     Reset();
4999dba64beSDimitry Andric   } else {
5009dba64beSDimitry Andric     *this = std::move(s.get());
5019dba64beSDimitry Andric   }
502*0b57cec5SDimitry Andric }
503*0b57cec5SDimitry Andric 
504*0b57cec5SDimitry Andric StructuredData::StringSP PythonString::CreateStructuredString() const {
505*0b57cec5SDimitry Andric   StructuredData::StringSP result(new StructuredData::String);
506*0b57cec5SDimitry Andric   result->SetValue(GetString());
507*0b57cec5SDimitry Andric   return result;
508*0b57cec5SDimitry Andric }
509*0b57cec5SDimitry Andric 
510*0b57cec5SDimitry Andric // PythonInteger
511*0b57cec5SDimitry Andric 
5129dba64beSDimitry Andric PythonInteger::PythonInteger(int64_t value) { SetInteger(value); }
513*0b57cec5SDimitry Andric 
514*0b57cec5SDimitry Andric bool PythonInteger::Check(PyObject *py_obj) {
515*0b57cec5SDimitry Andric   if (!py_obj)
516*0b57cec5SDimitry Andric     return false;
517*0b57cec5SDimitry Andric 
518*0b57cec5SDimitry Andric #if PY_MAJOR_VERSION >= 3
519*0b57cec5SDimitry Andric   // Python 3 does not have PyInt_Check.  There is only one type of integral
520*0b57cec5SDimitry Andric   // value, long.
521*0b57cec5SDimitry Andric   return PyLong_Check(py_obj);
522*0b57cec5SDimitry Andric #else
523*0b57cec5SDimitry Andric   return PyLong_Check(py_obj) || PyInt_Check(py_obj);
524*0b57cec5SDimitry Andric #endif
525*0b57cec5SDimitry Andric }
526*0b57cec5SDimitry Andric 
5279dba64beSDimitry Andric void PythonInteger::Convert(PyRefType &type, PyObject *&py_obj) {
528*0b57cec5SDimitry Andric #if PY_MAJOR_VERSION < 3
529*0b57cec5SDimitry Andric   // Always store this as a PyLong, which makes interoperability between Python
530*0b57cec5SDimitry Andric   // 2.x and Python 3.x easier.  This is only necessary in 2.x, since 3.x
531*0b57cec5SDimitry Andric   // doesn't even have a PyInt.
532*0b57cec5SDimitry Andric   if (PyInt_Check(py_obj)) {
533*0b57cec5SDimitry Andric     // Since we converted the original object to a different type, the new
534*0b57cec5SDimitry Andric     // object is an owned object regardless of the ownership semantics
535*0b57cec5SDimitry Andric     // requested by the user.
5369dba64beSDimitry Andric     long long value = PyInt_AsLong(py_obj);
5379dba64beSDimitry Andric     PyObject *l = nullptr;
5389dba64beSDimitry Andric     if (!PyErr_Occurred())
5399dba64beSDimitry Andric       l = PyLong_FromLongLong(value);
5409dba64beSDimitry Andric     if (l == nullptr) {
5419dba64beSDimitry Andric       PyErr_Clear();
5429dba64beSDimitry Andric       if (type == PyRefType::Owned)
5439dba64beSDimitry Andric         Py_DECREF(py_obj);
5449dba64beSDimitry Andric       return;
5459dba64beSDimitry Andric     }
5469dba64beSDimitry Andric     if (type == PyRefType::Owned)
5479dba64beSDimitry Andric       Py_DECREF(py_obj);
5489dba64beSDimitry Andric     else
5499dba64beSDimitry Andric       type = PyRefType::Owned;
5509dba64beSDimitry Andric     py_obj = l;
551*0b57cec5SDimitry Andric   }
552*0b57cec5SDimitry Andric #endif
553*0b57cec5SDimitry Andric }
554*0b57cec5SDimitry Andric 
555*0b57cec5SDimitry Andric void PythonInteger::SetInteger(int64_t value) {
5569dba64beSDimitry Andric   *this = Take<PythonInteger>(PyLong_FromLongLong(value));
557*0b57cec5SDimitry Andric }
558*0b57cec5SDimitry Andric 
559*0b57cec5SDimitry Andric StructuredData::IntegerSP PythonInteger::CreateStructuredInteger() const {
560*0b57cec5SDimitry Andric   StructuredData::IntegerSP result(new StructuredData::Integer);
5615ffd83dbSDimitry Andric   // FIXME this is really not ideal.   Errors are silently converted to 0
5625ffd83dbSDimitry Andric   // and overflows are silently wrapped.   But we'd need larger changes
5635ffd83dbSDimitry Andric   // to StructuredData to fix it, so that's how it is for now.
5645ffd83dbSDimitry Andric   llvm::Expected<unsigned long long> value = AsModuloUnsignedLongLong();
5655ffd83dbSDimitry Andric   if (!value) {
5665ffd83dbSDimitry Andric     llvm::consumeError(value.takeError());
5675ffd83dbSDimitry Andric     result->SetValue(0);
5685ffd83dbSDimitry Andric   } else {
5695ffd83dbSDimitry Andric     result->SetValue(value.get());
5705ffd83dbSDimitry Andric   }
571*0b57cec5SDimitry Andric   return result;
572*0b57cec5SDimitry Andric }
573*0b57cec5SDimitry Andric 
574*0b57cec5SDimitry Andric // PythonBoolean
575*0b57cec5SDimitry Andric 
576*0b57cec5SDimitry Andric PythonBoolean::PythonBoolean(bool value) {
577*0b57cec5SDimitry Andric   SetValue(value);
578*0b57cec5SDimitry Andric }
579*0b57cec5SDimitry Andric 
580*0b57cec5SDimitry Andric bool PythonBoolean::Check(PyObject *py_obj) {
581*0b57cec5SDimitry Andric   return py_obj ? PyBool_Check(py_obj) : false;
582*0b57cec5SDimitry Andric }
583*0b57cec5SDimitry Andric 
584*0b57cec5SDimitry Andric bool PythonBoolean::GetValue() const {
585*0b57cec5SDimitry Andric   return m_py_obj ? PyObject_IsTrue(m_py_obj) : false;
586*0b57cec5SDimitry Andric }
587*0b57cec5SDimitry Andric 
588*0b57cec5SDimitry Andric void PythonBoolean::SetValue(bool value) {
5899dba64beSDimitry Andric   *this = Take<PythonBoolean>(PyBool_FromLong(value));
590*0b57cec5SDimitry Andric }
591*0b57cec5SDimitry Andric 
592*0b57cec5SDimitry Andric StructuredData::BooleanSP PythonBoolean::CreateStructuredBoolean() const {
593*0b57cec5SDimitry Andric   StructuredData::BooleanSP result(new StructuredData::Boolean);
594*0b57cec5SDimitry Andric   result->SetValue(GetValue());
595*0b57cec5SDimitry Andric   return result;
596*0b57cec5SDimitry Andric }
597*0b57cec5SDimitry Andric 
598*0b57cec5SDimitry Andric // PythonList
599*0b57cec5SDimitry Andric 
6009dba64beSDimitry Andric PythonList::PythonList(PyInitialValue value) {
601*0b57cec5SDimitry Andric   if (value == PyInitialValue::Empty)
6029dba64beSDimitry Andric     *this = Take<PythonList>(PyList_New(0));
603*0b57cec5SDimitry Andric }
604*0b57cec5SDimitry Andric 
6059dba64beSDimitry Andric PythonList::PythonList(int list_size) {
6069dba64beSDimitry Andric   *this = Take<PythonList>(PyList_New(list_size));
607*0b57cec5SDimitry Andric }
608*0b57cec5SDimitry Andric 
609*0b57cec5SDimitry Andric bool PythonList::Check(PyObject *py_obj) {
610*0b57cec5SDimitry Andric   if (!py_obj)
611*0b57cec5SDimitry Andric     return false;
612*0b57cec5SDimitry Andric   return PyList_Check(py_obj);
613*0b57cec5SDimitry Andric }
614*0b57cec5SDimitry Andric 
615*0b57cec5SDimitry Andric uint32_t PythonList::GetSize() const {
616*0b57cec5SDimitry Andric   if (IsValid())
617*0b57cec5SDimitry Andric     return PyList_GET_SIZE(m_py_obj);
618*0b57cec5SDimitry Andric   return 0;
619*0b57cec5SDimitry Andric }
620*0b57cec5SDimitry Andric 
621*0b57cec5SDimitry Andric PythonObject PythonList::GetItemAtIndex(uint32_t index) const {
622*0b57cec5SDimitry Andric   if (IsValid())
623*0b57cec5SDimitry Andric     return PythonObject(PyRefType::Borrowed, PyList_GetItem(m_py_obj, index));
624*0b57cec5SDimitry Andric   return PythonObject();
625*0b57cec5SDimitry Andric }
626*0b57cec5SDimitry Andric 
627*0b57cec5SDimitry Andric void PythonList::SetItemAtIndex(uint32_t index, const PythonObject &object) {
628*0b57cec5SDimitry Andric   if (IsAllocated() && object.IsValid()) {
629*0b57cec5SDimitry Andric     // PyList_SetItem is documented to "steal" a reference, so we need to
630*0b57cec5SDimitry Andric     // convert it to an owned reference by incrementing it.
631*0b57cec5SDimitry Andric     Py_INCREF(object.get());
632*0b57cec5SDimitry Andric     PyList_SetItem(m_py_obj, index, object.get());
633*0b57cec5SDimitry Andric   }
634*0b57cec5SDimitry Andric }
635*0b57cec5SDimitry Andric 
636*0b57cec5SDimitry Andric void PythonList::AppendItem(const PythonObject &object) {
637*0b57cec5SDimitry Andric   if (IsAllocated() && object.IsValid()) {
638*0b57cec5SDimitry Andric     // `PyList_Append` does *not* steal a reference, so do not call `Py_INCREF`
639*0b57cec5SDimitry Andric     // here like we do with `PyList_SetItem`.
640*0b57cec5SDimitry Andric     PyList_Append(m_py_obj, object.get());
641*0b57cec5SDimitry Andric   }
642*0b57cec5SDimitry Andric }
643*0b57cec5SDimitry Andric 
644*0b57cec5SDimitry Andric StructuredData::ArraySP PythonList::CreateStructuredArray() const {
645*0b57cec5SDimitry Andric   StructuredData::ArraySP result(new StructuredData::Array);
646*0b57cec5SDimitry Andric   uint32_t count = GetSize();
647*0b57cec5SDimitry Andric   for (uint32_t i = 0; i < count; ++i) {
648*0b57cec5SDimitry Andric     PythonObject obj = GetItemAtIndex(i);
649*0b57cec5SDimitry Andric     result->AddItem(obj.CreateStructuredObject());
650*0b57cec5SDimitry Andric   }
651*0b57cec5SDimitry Andric   return result;
652*0b57cec5SDimitry Andric }
653*0b57cec5SDimitry Andric 
654*0b57cec5SDimitry Andric // PythonTuple
655*0b57cec5SDimitry Andric 
6569dba64beSDimitry Andric PythonTuple::PythonTuple(PyInitialValue value) {
657*0b57cec5SDimitry Andric   if (value == PyInitialValue::Empty)
6589dba64beSDimitry Andric     *this = Take<PythonTuple>(PyTuple_New(0));
659*0b57cec5SDimitry Andric }
660*0b57cec5SDimitry Andric 
6619dba64beSDimitry Andric PythonTuple::PythonTuple(int tuple_size) {
6629dba64beSDimitry Andric   *this = Take<PythonTuple>(PyTuple_New(tuple_size));
663*0b57cec5SDimitry Andric }
664*0b57cec5SDimitry Andric 
665*0b57cec5SDimitry Andric PythonTuple::PythonTuple(std::initializer_list<PythonObject> objects) {
666*0b57cec5SDimitry Andric   m_py_obj = PyTuple_New(objects.size());
667*0b57cec5SDimitry Andric 
668*0b57cec5SDimitry Andric   uint32_t idx = 0;
669*0b57cec5SDimitry Andric   for (auto object : objects) {
670*0b57cec5SDimitry Andric     if (object.IsValid())
671*0b57cec5SDimitry Andric       SetItemAtIndex(idx, object);
672*0b57cec5SDimitry Andric     idx++;
673*0b57cec5SDimitry Andric   }
674*0b57cec5SDimitry Andric }
675*0b57cec5SDimitry Andric 
676*0b57cec5SDimitry Andric PythonTuple::PythonTuple(std::initializer_list<PyObject *> objects) {
677*0b57cec5SDimitry Andric   m_py_obj = PyTuple_New(objects.size());
678*0b57cec5SDimitry Andric 
679*0b57cec5SDimitry Andric   uint32_t idx = 0;
680*0b57cec5SDimitry Andric   for (auto py_object : objects) {
681*0b57cec5SDimitry Andric     PythonObject object(PyRefType::Borrowed, py_object);
682*0b57cec5SDimitry Andric     if (object.IsValid())
683*0b57cec5SDimitry Andric       SetItemAtIndex(idx, object);
684*0b57cec5SDimitry Andric     idx++;
685*0b57cec5SDimitry Andric   }
686*0b57cec5SDimitry Andric }
687*0b57cec5SDimitry Andric 
688*0b57cec5SDimitry Andric bool PythonTuple::Check(PyObject *py_obj) {
689*0b57cec5SDimitry Andric   if (!py_obj)
690*0b57cec5SDimitry Andric     return false;
691*0b57cec5SDimitry Andric   return PyTuple_Check(py_obj);
692*0b57cec5SDimitry Andric }
693*0b57cec5SDimitry Andric 
694*0b57cec5SDimitry Andric uint32_t PythonTuple::GetSize() const {
695*0b57cec5SDimitry Andric   if (IsValid())
696*0b57cec5SDimitry Andric     return PyTuple_GET_SIZE(m_py_obj);
697*0b57cec5SDimitry Andric   return 0;
698*0b57cec5SDimitry Andric }
699*0b57cec5SDimitry Andric 
700*0b57cec5SDimitry Andric PythonObject PythonTuple::GetItemAtIndex(uint32_t index) const {
701*0b57cec5SDimitry Andric   if (IsValid())
702*0b57cec5SDimitry Andric     return PythonObject(PyRefType::Borrowed, PyTuple_GetItem(m_py_obj, index));
703*0b57cec5SDimitry Andric   return PythonObject();
704*0b57cec5SDimitry Andric }
705*0b57cec5SDimitry Andric 
706*0b57cec5SDimitry Andric void PythonTuple::SetItemAtIndex(uint32_t index, const PythonObject &object) {
707*0b57cec5SDimitry Andric   if (IsAllocated() && object.IsValid()) {
708*0b57cec5SDimitry Andric     // PyTuple_SetItem is documented to "steal" a reference, so we need to
709*0b57cec5SDimitry Andric     // convert it to an owned reference by incrementing it.
710*0b57cec5SDimitry Andric     Py_INCREF(object.get());
711*0b57cec5SDimitry Andric     PyTuple_SetItem(m_py_obj, index, object.get());
712*0b57cec5SDimitry Andric   }
713*0b57cec5SDimitry Andric }
714*0b57cec5SDimitry Andric 
715*0b57cec5SDimitry Andric StructuredData::ArraySP PythonTuple::CreateStructuredArray() const {
716*0b57cec5SDimitry Andric   StructuredData::ArraySP result(new StructuredData::Array);
717*0b57cec5SDimitry Andric   uint32_t count = GetSize();
718*0b57cec5SDimitry Andric   for (uint32_t i = 0; i < count; ++i) {
719*0b57cec5SDimitry Andric     PythonObject obj = GetItemAtIndex(i);
720*0b57cec5SDimitry Andric     result->AddItem(obj.CreateStructuredObject());
721*0b57cec5SDimitry Andric   }
722*0b57cec5SDimitry Andric   return result;
723*0b57cec5SDimitry Andric }
724*0b57cec5SDimitry Andric 
725*0b57cec5SDimitry Andric // PythonDictionary
726*0b57cec5SDimitry Andric 
7279dba64beSDimitry Andric PythonDictionary::PythonDictionary(PyInitialValue value) {
728*0b57cec5SDimitry Andric   if (value == PyInitialValue::Empty)
7299dba64beSDimitry Andric     *this = Take<PythonDictionary>(PyDict_New());
730*0b57cec5SDimitry Andric }
731*0b57cec5SDimitry Andric 
732*0b57cec5SDimitry Andric bool PythonDictionary::Check(PyObject *py_obj) {
733*0b57cec5SDimitry Andric   if (!py_obj)
734*0b57cec5SDimitry Andric     return false;
735*0b57cec5SDimitry Andric 
736*0b57cec5SDimitry Andric   return PyDict_Check(py_obj);
737*0b57cec5SDimitry Andric }
738*0b57cec5SDimitry Andric 
739*0b57cec5SDimitry Andric uint32_t PythonDictionary::GetSize() const {
740*0b57cec5SDimitry Andric   if (IsValid())
741*0b57cec5SDimitry Andric     return PyDict_Size(m_py_obj);
742*0b57cec5SDimitry Andric   return 0;
743*0b57cec5SDimitry Andric }
744*0b57cec5SDimitry Andric 
745*0b57cec5SDimitry Andric PythonList PythonDictionary::GetKeys() const {
746*0b57cec5SDimitry Andric   if (IsValid())
747*0b57cec5SDimitry Andric     return PythonList(PyRefType::Owned, PyDict_Keys(m_py_obj));
748*0b57cec5SDimitry Andric   return PythonList(PyInitialValue::Invalid);
749*0b57cec5SDimitry Andric }
750*0b57cec5SDimitry Andric 
751*0b57cec5SDimitry Andric PythonObject PythonDictionary::GetItemForKey(const PythonObject &key) const {
7529dba64beSDimitry Andric   auto item = GetItem(key);
7539dba64beSDimitry Andric   if (!item) {
7549dba64beSDimitry Andric     llvm::consumeError(item.takeError());
755*0b57cec5SDimitry Andric     return PythonObject();
756*0b57cec5SDimitry Andric   }
7579dba64beSDimitry Andric   return std::move(item.get());
7589dba64beSDimitry Andric }
7599dba64beSDimitry Andric 
7609dba64beSDimitry Andric Expected<PythonObject>
7619dba64beSDimitry Andric PythonDictionary::GetItem(const PythonObject &key) const {
7629dba64beSDimitry Andric   if (!IsValid())
7639dba64beSDimitry Andric     return nullDeref();
7649dba64beSDimitry Andric #if PY_MAJOR_VERSION >= 3
7659dba64beSDimitry Andric   PyObject *o = PyDict_GetItemWithError(m_py_obj, key.get());
7669dba64beSDimitry Andric   if (PyErr_Occurred())
7679dba64beSDimitry Andric     return exception();
7689dba64beSDimitry Andric #else
7699dba64beSDimitry Andric   PyObject *o = PyDict_GetItem(m_py_obj, key.get());
7709dba64beSDimitry Andric #endif
7719dba64beSDimitry Andric   if (!o)
7729dba64beSDimitry Andric     return keyError();
7739dba64beSDimitry Andric   return Retain<PythonObject>(o);
7749dba64beSDimitry Andric }
7759dba64beSDimitry Andric 
7769dba64beSDimitry Andric Expected<PythonObject> PythonDictionary::GetItem(const Twine &key) const {
7779dba64beSDimitry Andric   if (!IsValid())
7789dba64beSDimitry Andric     return nullDeref();
7799dba64beSDimitry Andric   PyObject *o = PyDict_GetItemString(m_py_obj, NullTerminated(key));
7809dba64beSDimitry Andric   if (PyErr_Occurred())
7819dba64beSDimitry Andric     return exception();
7829dba64beSDimitry Andric   if (!o)
7839dba64beSDimitry Andric     return keyError();
7849dba64beSDimitry Andric   return Retain<PythonObject>(o);
7859dba64beSDimitry Andric }
7869dba64beSDimitry Andric 
7879dba64beSDimitry Andric Error PythonDictionary::SetItem(const PythonObject &key,
7889dba64beSDimitry Andric                                 const PythonObject &value) const {
7899dba64beSDimitry Andric   if (!IsValid() || !value.IsValid())
7909dba64beSDimitry Andric     return nullDeref();
7919dba64beSDimitry Andric   int r = PyDict_SetItem(m_py_obj, key.get(), value.get());
7929dba64beSDimitry Andric   if (r < 0)
7939dba64beSDimitry Andric     return exception();
7949dba64beSDimitry Andric   return Error::success();
7959dba64beSDimitry Andric }
7969dba64beSDimitry Andric 
7979dba64beSDimitry Andric Error PythonDictionary::SetItem(const Twine &key,
7989dba64beSDimitry Andric                                 const PythonObject &value) const {
7999dba64beSDimitry Andric   if (!IsValid() || !value.IsValid())
8009dba64beSDimitry Andric     return nullDeref();
8019dba64beSDimitry Andric   int r = PyDict_SetItemString(m_py_obj, NullTerminated(key), value.get());
8029dba64beSDimitry Andric   if (r < 0)
8039dba64beSDimitry Andric     return exception();
8049dba64beSDimitry Andric   return Error::success();
8059dba64beSDimitry Andric }
806*0b57cec5SDimitry Andric 
807*0b57cec5SDimitry Andric void PythonDictionary::SetItemForKey(const PythonObject &key,
808*0b57cec5SDimitry Andric                                      const PythonObject &value) {
8099dba64beSDimitry Andric   Error error = SetItem(key, value);
8109dba64beSDimitry Andric   if (error)
8119dba64beSDimitry Andric     llvm::consumeError(std::move(error));
812*0b57cec5SDimitry Andric }
813*0b57cec5SDimitry Andric 
814*0b57cec5SDimitry Andric StructuredData::DictionarySP
815*0b57cec5SDimitry Andric PythonDictionary::CreateStructuredDictionary() const {
816*0b57cec5SDimitry Andric   StructuredData::DictionarySP result(new StructuredData::Dictionary);
817*0b57cec5SDimitry Andric   PythonList keys(GetKeys());
818*0b57cec5SDimitry Andric   uint32_t num_keys = keys.GetSize();
819*0b57cec5SDimitry Andric   for (uint32_t i = 0; i < num_keys; ++i) {
820*0b57cec5SDimitry Andric     PythonObject key = keys.GetItemAtIndex(i);
821*0b57cec5SDimitry Andric     PythonObject value = GetItemForKey(key);
822*0b57cec5SDimitry Andric     StructuredData::ObjectSP structured_value = value.CreateStructuredObject();
823*0b57cec5SDimitry Andric     result->AddItem(key.Str().GetString(), structured_value);
824*0b57cec5SDimitry Andric   }
825*0b57cec5SDimitry Andric   return result;
826*0b57cec5SDimitry Andric }
827*0b57cec5SDimitry Andric 
828*0b57cec5SDimitry Andric PythonModule PythonModule::BuiltinsModule() {
829*0b57cec5SDimitry Andric #if PY_MAJOR_VERSION >= 3
830*0b57cec5SDimitry Andric   return AddModule("builtins");
831*0b57cec5SDimitry Andric #else
832*0b57cec5SDimitry Andric   return AddModule("__builtin__");
833*0b57cec5SDimitry Andric #endif
834*0b57cec5SDimitry Andric }
835*0b57cec5SDimitry Andric 
836*0b57cec5SDimitry Andric PythonModule PythonModule::MainModule() { return AddModule("__main__"); }
837*0b57cec5SDimitry Andric 
838*0b57cec5SDimitry Andric PythonModule PythonModule::AddModule(llvm::StringRef module) {
839*0b57cec5SDimitry Andric   std::string str = module.str();
840*0b57cec5SDimitry Andric   return PythonModule(PyRefType::Borrowed, PyImport_AddModule(str.c_str()));
841*0b57cec5SDimitry Andric }
842*0b57cec5SDimitry Andric 
8439dba64beSDimitry Andric Expected<PythonModule> PythonModule::Import(const Twine &name) {
8449dba64beSDimitry Andric   PyObject *mod = PyImport_ImportModule(NullTerminated(name));
8459dba64beSDimitry Andric   if (!mod)
8469dba64beSDimitry Andric     return exception();
8479dba64beSDimitry Andric   return Take<PythonModule>(mod);
8489dba64beSDimitry Andric }
8499dba64beSDimitry Andric 
8509dba64beSDimitry Andric Expected<PythonObject> PythonModule::Get(const Twine &name) {
8519dba64beSDimitry Andric   if (!IsValid())
8529dba64beSDimitry Andric     return nullDeref();
8539dba64beSDimitry Andric   PyObject *dict = PyModule_GetDict(m_py_obj);
8549dba64beSDimitry Andric   if (!dict)
8559dba64beSDimitry Andric     return exception();
8569dba64beSDimitry Andric   PyObject *item = PyDict_GetItemString(dict, NullTerminated(name));
8579dba64beSDimitry Andric   if (!item)
8589dba64beSDimitry Andric     return exception();
8599dba64beSDimitry Andric   return Retain<PythonObject>(item);
860*0b57cec5SDimitry Andric }
861*0b57cec5SDimitry Andric 
862*0b57cec5SDimitry Andric bool PythonModule::Check(PyObject *py_obj) {
863*0b57cec5SDimitry Andric   if (!py_obj)
864*0b57cec5SDimitry Andric     return false;
865*0b57cec5SDimitry Andric 
866*0b57cec5SDimitry Andric   return PyModule_Check(py_obj);
867*0b57cec5SDimitry Andric }
868*0b57cec5SDimitry Andric 
869*0b57cec5SDimitry Andric PythonDictionary PythonModule::GetDictionary() const {
8709dba64beSDimitry Andric   if (!IsValid())
8719dba64beSDimitry Andric     return PythonDictionary();
8729dba64beSDimitry Andric   return Retain<PythonDictionary>(PyModule_GetDict(m_py_obj));
873*0b57cec5SDimitry Andric }
874*0b57cec5SDimitry Andric 
875*0b57cec5SDimitry Andric bool PythonCallable::Check(PyObject *py_obj) {
876*0b57cec5SDimitry Andric   if (!py_obj)
877*0b57cec5SDimitry Andric     return false;
878*0b57cec5SDimitry Andric 
879*0b57cec5SDimitry Andric   return PyCallable_Check(py_obj);
880*0b57cec5SDimitry Andric }
881*0b57cec5SDimitry Andric 
8829dba64beSDimitry Andric #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3
8839dba64beSDimitry Andric static const char get_arg_info_script[] = R"(
8849dba64beSDimitry Andric from inspect import signature, Parameter, ismethod
8859dba64beSDimitry Andric from collections import namedtuple
886480093f4SDimitry Andric ArgInfo = namedtuple('ArgInfo', ['count', 'has_varargs'])
8879dba64beSDimitry Andric def main(f):
8889dba64beSDimitry Andric     count = 0
8899dba64beSDimitry Andric     varargs = False
8909dba64beSDimitry Andric     for parameter in signature(f).parameters.values():
8919dba64beSDimitry Andric         kind = parameter.kind
8929dba64beSDimitry Andric         if kind in (Parameter.POSITIONAL_ONLY,
8939dba64beSDimitry Andric                     Parameter.POSITIONAL_OR_KEYWORD):
8949dba64beSDimitry Andric             count += 1
8959dba64beSDimitry Andric         elif kind == Parameter.VAR_POSITIONAL:
8969dba64beSDimitry Andric             varargs = True
8979dba64beSDimitry Andric         elif kind in (Parameter.KEYWORD_ONLY,
8989dba64beSDimitry Andric                       Parameter.VAR_KEYWORD):
8999dba64beSDimitry Andric             pass
9009dba64beSDimitry Andric         else:
9019dba64beSDimitry Andric             raise Exception(f'unknown parameter kind: {kind}')
902480093f4SDimitry Andric     return ArgInfo(count, varargs)
9039dba64beSDimitry Andric )";
9049dba64beSDimitry Andric #endif
9059dba64beSDimitry Andric 
9069dba64beSDimitry Andric Expected<PythonCallable::ArgInfo> PythonCallable::GetArgInfo() const {
9079dba64beSDimitry Andric   ArgInfo result = {};
9089dba64beSDimitry Andric   if (!IsValid())
9099dba64beSDimitry Andric     return nullDeref();
9109dba64beSDimitry Andric 
9119dba64beSDimitry Andric #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3
9129dba64beSDimitry Andric 
9139dba64beSDimitry Andric   // no need to synchronize access to this global, we already have the GIL
9149dba64beSDimitry Andric   static PythonScript get_arg_info(get_arg_info_script);
9159dba64beSDimitry Andric   Expected<PythonObject> pyarginfo = get_arg_info(*this);
9169dba64beSDimitry Andric   if (!pyarginfo)
9179dba64beSDimitry Andric     return pyarginfo.takeError();
918480093f4SDimitry Andric   long long count =
919480093f4SDimitry Andric       cantFail(As<long long>(pyarginfo.get().GetAttribute("count")));
920480093f4SDimitry Andric   bool has_varargs =
9219dba64beSDimitry Andric       cantFail(As<bool>(pyarginfo.get().GetAttribute("has_varargs")));
922480093f4SDimitry Andric   result.max_positional_args = has_varargs ? ArgInfo::UNBOUNDED : count;
9239dba64beSDimitry Andric 
9249dba64beSDimitry Andric #else
925480093f4SDimitry Andric   PyObject *py_func_obj;
9269dba64beSDimitry Andric   bool is_bound_method = false;
927480093f4SDimitry Andric   bool is_class = false;
928480093f4SDimitry Andric 
929480093f4SDimitry Andric   if (PyType_Check(m_py_obj) || PyClass_Check(m_py_obj)) {
930480093f4SDimitry Andric     auto init = GetAttribute("__init__");
931480093f4SDimitry Andric     if (!init)
932480093f4SDimitry Andric       return init.takeError();
933480093f4SDimitry Andric     py_func_obj = init.get().get();
934480093f4SDimitry Andric     is_class = true;
935480093f4SDimitry Andric   } else {
936480093f4SDimitry Andric     py_func_obj = m_py_obj;
937480093f4SDimitry Andric   }
938480093f4SDimitry Andric 
939*0b57cec5SDimitry Andric   if (PyMethod_Check(py_func_obj)) {
940*0b57cec5SDimitry Andric     py_func_obj = PyMethod_GET_FUNCTION(py_func_obj);
941*0b57cec5SDimitry Andric     PythonObject im_self = GetAttributeValue("im_self");
942*0b57cec5SDimitry Andric     if (im_self.IsValid() && !im_self.IsNone())
9439dba64beSDimitry Andric       is_bound_method = true;
944*0b57cec5SDimitry Andric   } else {
945*0b57cec5SDimitry Andric     // see if this is a callable object with an __call__ method
946*0b57cec5SDimitry Andric     if (!PyFunction_Check(py_func_obj)) {
947*0b57cec5SDimitry Andric       PythonObject __call__ = GetAttributeValue("__call__");
948*0b57cec5SDimitry Andric       if (__call__.IsValid()) {
949*0b57cec5SDimitry Andric         auto __callable__ = __call__.AsType<PythonCallable>();
950*0b57cec5SDimitry Andric         if (__callable__.IsValid()) {
951*0b57cec5SDimitry Andric           py_func_obj = PyMethod_GET_FUNCTION(__callable__.get());
9529dba64beSDimitry Andric           PythonObject im_self = __callable__.GetAttributeValue("im_self");
953*0b57cec5SDimitry Andric           if (im_self.IsValid() && !im_self.IsNone())
9549dba64beSDimitry Andric             is_bound_method = true;
955*0b57cec5SDimitry Andric         }
956*0b57cec5SDimitry Andric       }
957*0b57cec5SDimitry Andric     }
958*0b57cec5SDimitry Andric   }
959*0b57cec5SDimitry Andric 
960*0b57cec5SDimitry Andric   if (!py_func_obj)
961*0b57cec5SDimitry Andric     return result;
962*0b57cec5SDimitry Andric 
963*0b57cec5SDimitry Andric   PyCodeObject *code = (PyCodeObject *)PyFunction_GET_CODE(py_func_obj);
964*0b57cec5SDimitry Andric   if (!code)
965*0b57cec5SDimitry Andric     return result;
966*0b57cec5SDimitry Andric 
967480093f4SDimitry Andric   auto count = code->co_argcount;
968480093f4SDimitry Andric   bool has_varargs = !!(code->co_flags & CO_VARARGS);
969480093f4SDimitry Andric   result.max_positional_args =
970480093f4SDimitry Andric       has_varargs ? ArgInfo::UNBOUNDED
971480093f4SDimitry Andric                   : (count - (int)is_bound_method) - (int)is_class;
9729dba64beSDimitry Andric 
9739dba64beSDimitry Andric #endif
9749dba64beSDimitry Andric 
975*0b57cec5SDimitry Andric   return result;
976*0b57cec5SDimitry Andric }
977*0b57cec5SDimitry Andric 
9789dba64beSDimitry Andric constexpr unsigned
9799dba64beSDimitry Andric     PythonCallable::ArgInfo::UNBOUNDED; // FIXME delete after c++17
9809dba64beSDimitry Andric 
981*0b57cec5SDimitry Andric PythonObject PythonCallable::operator()() {
982*0b57cec5SDimitry Andric   return PythonObject(PyRefType::Owned, PyObject_CallObject(m_py_obj, nullptr));
983*0b57cec5SDimitry Andric }
984*0b57cec5SDimitry Andric 
985*0b57cec5SDimitry Andric PythonObject PythonCallable::
986*0b57cec5SDimitry Andric operator()(std::initializer_list<PyObject *> args) {
987*0b57cec5SDimitry Andric   PythonTuple arg_tuple(args);
988*0b57cec5SDimitry Andric   return PythonObject(PyRefType::Owned,
989*0b57cec5SDimitry Andric                       PyObject_CallObject(m_py_obj, arg_tuple.get()));
990*0b57cec5SDimitry Andric }
991*0b57cec5SDimitry Andric 
992*0b57cec5SDimitry Andric PythonObject PythonCallable::
993*0b57cec5SDimitry Andric operator()(std::initializer_list<PythonObject> args) {
994*0b57cec5SDimitry Andric   PythonTuple arg_tuple(args);
995*0b57cec5SDimitry Andric   return PythonObject(PyRefType::Owned,
996*0b57cec5SDimitry Andric                       PyObject_CallObject(m_py_obj, arg_tuple.get()));
997*0b57cec5SDimitry Andric }
998*0b57cec5SDimitry Andric 
999*0b57cec5SDimitry Andric bool PythonFile::Check(PyObject *py_obj) {
10009dba64beSDimitry Andric   if (!py_obj)
10019dba64beSDimitry Andric     return false;
1002*0b57cec5SDimitry Andric #if PY_MAJOR_VERSION < 3
1003*0b57cec5SDimitry Andric   return PyFile_Check(py_obj);
1004*0b57cec5SDimitry Andric #else
1005*0b57cec5SDimitry Andric   // In Python 3, there is no `PyFile_Check`, and in fact PyFile is not even a
1006*0b57cec5SDimitry Andric   // first-class object type anymore.  `PyFile_FromFd` is just a thin wrapper
1007*0b57cec5SDimitry Andric   // over `io.open()`, which returns some object derived from `io.IOBase`. As a
1008*0b57cec5SDimitry Andric   // result, the only way to detect a file in Python 3 is to check whether it
10099dba64beSDimitry Andric   // inherits from `io.IOBase`.
10109dba64beSDimitry Andric   auto io_module = PythonModule::Import("io");
10119dba64beSDimitry Andric   if (!io_module) {
10129dba64beSDimitry Andric     llvm::consumeError(io_module.takeError());
1013*0b57cec5SDimitry Andric     return false;
10149dba64beSDimitry Andric   }
10159dba64beSDimitry Andric   auto iobase = io_module.get().Get("IOBase");
10169dba64beSDimitry Andric   if (!iobase) {
10179dba64beSDimitry Andric     llvm::consumeError(iobase.takeError());
1018*0b57cec5SDimitry Andric     return false;
10199dba64beSDimitry Andric   }
10209dba64beSDimitry Andric   int r = PyObject_IsInstance(py_obj, iobase.get().get());
10219dba64beSDimitry Andric   if (r < 0) {
10229dba64beSDimitry Andric     llvm::consumeError(exception()); // clear the exception and log it.
10239dba64beSDimitry Andric     return false;
10249dba64beSDimitry Andric   }
10259dba64beSDimitry Andric   return !!r;
1026*0b57cec5SDimitry Andric #endif
1027*0b57cec5SDimitry Andric }
1028*0b57cec5SDimitry Andric 
10299dba64beSDimitry Andric const char *PythonException::toCString() const {
10309dba64beSDimitry Andric   if (!m_repr_bytes)
10319dba64beSDimitry Andric     return "unknown exception";
10329dba64beSDimitry Andric   return PyBytes_AS_STRING(m_repr_bytes);
1033*0b57cec5SDimitry Andric }
1034*0b57cec5SDimitry Andric 
10359dba64beSDimitry Andric PythonException::PythonException(const char *caller) {
10369dba64beSDimitry Andric   assert(PyErr_Occurred());
10379dba64beSDimitry Andric   m_exception_type = m_exception = m_traceback = m_repr_bytes = NULL;
10389dba64beSDimitry Andric   PyErr_Fetch(&m_exception_type, &m_exception, &m_traceback);
10399dba64beSDimitry Andric   PyErr_NormalizeException(&m_exception_type, &m_exception, &m_traceback);
10409dba64beSDimitry Andric   PyErr_Clear();
10419dba64beSDimitry Andric   if (m_exception) {
10429dba64beSDimitry Andric     PyObject *repr = PyObject_Repr(m_exception);
10439dba64beSDimitry Andric     if (repr) {
10449dba64beSDimitry Andric       m_repr_bytes = PyUnicode_AsEncodedString(repr, "utf-8", nullptr);
10459dba64beSDimitry Andric       if (!m_repr_bytes) {
10469dba64beSDimitry Andric         PyErr_Clear();
10479dba64beSDimitry Andric       }
10489dba64beSDimitry Andric       Py_XDECREF(repr);
10499dba64beSDimitry Andric     } else {
10509dba64beSDimitry Andric       PyErr_Clear();
10519dba64beSDimitry Andric     }
10529dba64beSDimitry Andric   }
10539dba64beSDimitry Andric   Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT);
10549dba64beSDimitry Andric   if (caller)
10559dba64beSDimitry Andric     LLDB_LOGF(log, "%s failed with exception: %s", caller, toCString());
10569dba64beSDimitry Andric   else
10579dba64beSDimitry Andric     LLDB_LOGF(log, "python exception: %s", toCString());
10589dba64beSDimitry Andric }
10599dba64beSDimitry Andric void PythonException::Restore() {
10609dba64beSDimitry Andric   if (m_exception_type && m_exception) {
10619dba64beSDimitry Andric     PyErr_Restore(m_exception_type, m_exception, m_traceback);
10629dba64beSDimitry Andric   } else {
10639dba64beSDimitry Andric     PyErr_SetString(PyExc_Exception, toCString());
10649dba64beSDimitry Andric   }
10659dba64beSDimitry Andric   m_exception_type = m_exception = m_traceback = NULL;
1066*0b57cec5SDimitry Andric }
1067*0b57cec5SDimitry Andric 
10689dba64beSDimitry Andric PythonException::~PythonException() {
10699dba64beSDimitry Andric   Py_XDECREF(m_exception_type);
10709dba64beSDimitry Andric   Py_XDECREF(m_exception);
10719dba64beSDimitry Andric   Py_XDECREF(m_traceback);
10729dba64beSDimitry Andric   Py_XDECREF(m_repr_bytes);
1073*0b57cec5SDimitry Andric }
1074*0b57cec5SDimitry Andric 
10759dba64beSDimitry Andric void PythonException::log(llvm::raw_ostream &OS) const { OS << toCString(); }
10769dba64beSDimitry Andric 
10779dba64beSDimitry Andric std::error_code PythonException::convertToErrorCode() const {
10789dba64beSDimitry Andric   return llvm::inconvertibleErrorCode();
10799dba64beSDimitry Andric }
10809dba64beSDimitry Andric 
10819dba64beSDimitry Andric bool PythonException::Matches(PyObject *exc) const {
10829dba64beSDimitry Andric   return PyErr_GivenExceptionMatches(m_exception_type, exc);
10839dba64beSDimitry Andric }
10849dba64beSDimitry Andric 
10859dba64beSDimitry Andric const char read_exception_script[] = R"(
10869dba64beSDimitry Andric import sys
10879dba64beSDimitry Andric from traceback import print_exception
10889dba64beSDimitry Andric if sys.version_info.major < 3:
10899dba64beSDimitry Andric   from StringIO import StringIO
10909dba64beSDimitry Andric else:
10919dba64beSDimitry Andric   from io import StringIO
10929dba64beSDimitry Andric def main(exc_type, exc_value, tb):
10939dba64beSDimitry Andric   f = StringIO()
10949dba64beSDimitry Andric   print_exception(exc_type, exc_value, tb, file=f)
10959dba64beSDimitry Andric   return f.getvalue()
10969dba64beSDimitry Andric )";
10979dba64beSDimitry Andric 
10989dba64beSDimitry Andric std::string PythonException::ReadBacktrace() const {
10999dba64beSDimitry Andric 
11009dba64beSDimitry Andric   if (!m_traceback)
11019dba64beSDimitry Andric     return toCString();
11029dba64beSDimitry Andric 
11039dba64beSDimitry Andric   // no need to synchronize access to this global, we already have the GIL
11049dba64beSDimitry Andric   static PythonScript read_exception(read_exception_script);
11059dba64beSDimitry Andric 
11069dba64beSDimitry Andric   Expected<std::string> backtrace = As<std::string>(
11079dba64beSDimitry Andric       read_exception(m_exception_type, m_exception, m_traceback));
11089dba64beSDimitry Andric 
11099dba64beSDimitry Andric   if (!backtrace) {
11109dba64beSDimitry Andric     std::string message =
11119dba64beSDimitry Andric         std::string(toCString()) + "\n" +
11125ffd83dbSDimitry Andric         "Traceback unavailable, an error occurred while reading it:\n";
11139dba64beSDimitry Andric     return (message + llvm::toString(backtrace.takeError()));
11149dba64beSDimitry Andric   }
11159dba64beSDimitry Andric 
11169dba64beSDimitry Andric   return std::move(backtrace.get());
11179dba64beSDimitry Andric }
11189dba64beSDimitry Andric 
11199dba64beSDimitry Andric char PythonException::ID = 0;
11209dba64beSDimitry Andric 
11219dba64beSDimitry Andric llvm::Expected<File::OpenOptions>
11229dba64beSDimitry Andric GetOptionsForPyObject(const PythonObject &obj) {
1123*0b57cec5SDimitry Andric #if PY_MAJOR_VERSION >= 3
11249dba64beSDimitry Andric   auto options = File::OpenOptions(0);
11259dba64beSDimitry Andric   auto readable = As<bool>(obj.CallMethod("readable"));
11269dba64beSDimitry Andric   if (!readable)
11279dba64beSDimitry Andric     return readable.takeError();
11289dba64beSDimitry Andric   auto writable = As<bool>(obj.CallMethod("writable"));
11299dba64beSDimitry Andric   if (!writable)
11309dba64beSDimitry Andric     return writable.takeError();
1131349cc55cSDimitry Andric   if (readable.get() && writable.get())
1132349cc55cSDimitry Andric     options |= File::eOpenOptionReadWrite;
1133349cc55cSDimitry Andric   else if (writable.get())
1134349cc55cSDimitry Andric     options |= File::eOpenOptionWriteOnly;
1135349cc55cSDimitry Andric   else if (readable.get())
1136349cc55cSDimitry Andric     options |= File::eOpenOptionReadOnly;
11379dba64beSDimitry Andric   return options;
11389dba64beSDimitry Andric #else
11399dba64beSDimitry Andric   PythonString py_mode = obj.GetAttributeValue("mode").AsType<PythonString>();
11409dba64beSDimitry Andric   return File::GetOptionsFromMode(py_mode.GetString());
11419dba64beSDimitry Andric #endif
11429dba64beSDimitry Andric }
11439dba64beSDimitry Andric 
11449dba64beSDimitry Andric // Base class template for python files.   All it knows how to do
11459dba64beSDimitry Andric // is hold a reference to the python object and close or flush it
11469dba64beSDimitry Andric // when the File is closed.
11479dba64beSDimitry Andric namespace {
11489dba64beSDimitry Andric template <typename Base> class OwnedPythonFile : public Base {
11499dba64beSDimitry Andric public:
11509dba64beSDimitry Andric   template <typename... Args>
11519dba64beSDimitry Andric   OwnedPythonFile(const PythonFile &file, bool borrowed, Args... args)
11529dba64beSDimitry Andric       : Base(args...), m_py_obj(file), m_borrowed(borrowed) {
11539dba64beSDimitry Andric     assert(m_py_obj);
11549dba64beSDimitry Andric   }
11559dba64beSDimitry Andric 
11569dba64beSDimitry Andric   ~OwnedPythonFile() override {
11579dba64beSDimitry Andric     assert(m_py_obj);
11589dba64beSDimitry Andric     GIL takeGIL;
11599dba64beSDimitry Andric     Close();
11609dba64beSDimitry Andric     // we need to ensure the python object is released while we still
11619dba64beSDimitry Andric     // hold the GIL
11629dba64beSDimitry Andric     m_py_obj.Reset();
11639dba64beSDimitry Andric   }
11649dba64beSDimitry Andric 
11659dba64beSDimitry Andric   bool IsPythonSideValid() const {
11669dba64beSDimitry Andric     GIL takeGIL;
11679dba64beSDimitry Andric     auto closed = As<bool>(m_py_obj.GetAttribute("closed"));
11689dba64beSDimitry Andric     if (!closed) {
11699dba64beSDimitry Andric       llvm::consumeError(closed.takeError());
11709dba64beSDimitry Andric       return false;
11719dba64beSDimitry Andric     }
11729dba64beSDimitry Andric     return !closed.get();
11739dba64beSDimitry Andric   }
11749dba64beSDimitry Andric 
11759dba64beSDimitry Andric   bool IsValid() const override {
11769dba64beSDimitry Andric     return IsPythonSideValid() && Base::IsValid();
11779dba64beSDimitry Andric   }
11789dba64beSDimitry Andric 
11799dba64beSDimitry Andric   Status Close() override {
11809dba64beSDimitry Andric     assert(m_py_obj);
11819dba64beSDimitry Andric     Status py_error, base_error;
11829dba64beSDimitry Andric     GIL takeGIL;
11839dba64beSDimitry Andric     if (!m_borrowed) {
11849dba64beSDimitry Andric       auto r = m_py_obj.CallMethod("close");
11859dba64beSDimitry Andric       if (!r)
11869dba64beSDimitry Andric         py_error = Status(r.takeError());
11879dba64beSDimitry Andric     }
11889dba64beSDimitry Andric     base_error = Base::Close();
11899dba64beSDimitry Andric     if (py_error.Fail())
11909dba64beSDimitry Andric       return py_error;
11919dba64beSDimitry Andric     return base_error;
11929dba64beSDimitry Andric   };
11939dba64beSDimitry Andric 
11949dba64beSDimitry Andric   PyObject *GetPythonObject() const {
11959dba64beSDimitry Andric     assert(m_py_obj.IsValid());
11969dba64beSDimitry Andric     return m_py_obj.get();
11979dba64beSDimitry Andric   }
11989dba64beSDimitry Andric 
11999dba64beSDimitry Andric   static bool classof(const File *file) = delete;
12009dba64beSDimitry Andric 
12019dba64beSDimitry Andric protected:
12029dba64beSDimitry Andric   PythonFile m_py_obj;
12039dba64beSDimitry Andric   bool m_borrowed;
12049dba64beSDimitry Andric };
12059dba64beSDimitry Andric } // namespace
12069dba64beSDimitry Andric 
12079dba64beSDimitry Andric // A SimplePythonFile is a OwnedPythonFile that just does all I/O as
12089dba64beSDimitry Andric // a NativeFile
12099dba64beSDimitry Andric namespace {
12109dba64beSDimitry Andric class SimplePythonFile : public OwnedPythonFile<NativeFile> {
12119dba64beSDimitry Andric public:
12129dba64beSDimitry Andric   SimplePythonFile(const PythonFile &file, bool borrowed, int fd,
12139dba64beSDimitry Andric                    File::OpenOptions options)
12149dba64beSDimitry Andric       : OwnedPythonFile(file, borrowed, fd, options, false) {}
12159dba64beSDimitry Andric 
12169dba64beSDimitry Andric   static char ID;
12179dba64beSDimitry Andric   bool isA(const void *classID) const override {
12189dba64beSDimitry Andric     return classID == &ID || NativeFile::isA(classID);
12199dba64beSDimitry Andric   }
12209dba64beSDimitry Andric   static bool classof(const File *file) { return file->isA(&ID); }
12219dba64beSDimitry Andric };
12229dba64beSDimitry Andric char SimplePythonFile::ID = 0;
12239dba64beSDimitry Andric } // namespace
12249dba64beSDimitry Andric 
12259dba64beSDimitry Andric #if PY_MAJOR_VERSION >= 3
12269dba64beSDimitry Andric 
12279dba64beSDimitry Andric namespace {
12289dba64beSDimitry Andric class PythonBuffer {
12299dba64beSDimitry Andric public:
12309dba64beSDimitry Andric   PythonBuffer &operator=(const PythonBuffer &) = delete;
12319dba64beSDimitry Andric   PythonBuffer(const PythonBuffer &) = delete;
12329dba64beSDimitry Andric 
12339dba64beSDimitry Andric   static Expected<PythonBuffer> Create(PythonObject &obj,
12349dba64beSDimitry Andric                                        int flags = PyBUF_SIMPLE) {
12359dba64beSDimitry Andric     Py_buffer py_buffer = {};
12369dba64beSDimitry Andric     PyObject_GetBuffer(obj.get(), &py_buffer, flags);
12379dba64beSDimitry Andric     if (!py_buffer.obj)
12389dba64beSDimitry Andric       return llvm::make_error<PythonException>();
12399dba64beSDimitry Andric     return PythonBuffer(py_buffer);
12409dba64beSDimitry Andric   }
12419dba64beSDimitry Andric 
12429dba64beSDimitry Andric   PythonBuffer(PythonBuffer &&other) {
12439dba64beSDimitry Andric     m_buffer = other.m_buffer;
12449dba64beSDimitry Andric     other.m_buffer.obj = nullptr;
12459dba64beSDimitry Andric   }
12469dba64beSDimitry Andric 
12479dba64beSDimitry Andric   ~PythonBuffer() {
12489dba64beSDimitry Andric     if (m_buffer.obj)
12499dba64beSDimitry Andric       PyBuffer_Release(&m_buffer);
12509dba64beSDimitry Andric   }
12519dba64beSDimitry Andric 
12529dba64beSDimitry Andric   Py_buffer &get() { return m_buffer; }
12539dba64beSDimitry Andric 
12549dba64beSDimitry Andric private:
12559dba64beSDimitry Andric   // takes ownership of the buffer.
12569dba64beSDimitry Andric   PythonBuffer(const Py_buffer &py_buffer) : m_buffer(py_buffer) {}
12579dba64beSDimitry Andric   Py_buffer m_buffer;
12589dba64beSDimitry Andric };
12599dba64beSDimitry Andric } // namespace
12609dba64beSDimitry Andric 
12619dba64beSDimitry Andric // Shared methods between TextPythonFile and BinaryPythonFile
12629dba64beSDimitry Andric namespace {
12639dba64beSDimitry Andric class PythonIOFile : public OwnedPythonFile<File> {
12649dba64beSDimitry Andric public:
12659dba64beSDimitry Andric   PythonIOFile(const PythonFile &file, bool borrowed)
12669dba64beSDimitry Andric       : OwnedPythonFile(file, borrowed) {}
12679dba64beSDimitry Andric 
12689dba64beSDimitry Andric   ~PythonIOFile() override { Close(); }
12699dba64beSDimitry Andric 
12709dba64beSDimitry Andric   bool IsValid() const override { return IsPythonSideValid(); }
12719dba64beSDimitry Andric 
12729dba64beSDimitry Andric   Status Close() override {
12739dba64beSDimitry Andric     assert(m_py_obj);
12749dba64beSDimitry Andric     GIL takeGIL;
12759dba64beSDimitry Andric     if (m_borrowed)
12769dba64beSDimitry Andric       return Flush();
12779dba64beSDimitry Andric     auto r = m_py_obj.CallMethod("close");
12789dba64beSDimitry Andric     if (!r)
12799dba64beSDimitry Andric       return Status(r.takeError());
12809dba64beSDimitry Andric     return Status();
12819dba64beSDimitry Andric   }
12829dba64beSDimitry Andric 
12839dba64beSDimitry Andric   Status Flush() override {
12849dba64beSDimitry Andric     GIL takeGIL;
12859dba64beSDimitry Andric     auto r = m_py_obj.CallMethod("flush");
12869dba64beSDimitry Andric     if (!r)
12879dba64beSDimitry Andric       return Status(r.takeError());
12889dba64beSDimitry Andric     return Status();
12899dba64beSDimitry Andric   }
12909dba64beSDimitry Andric 
12919dba64beSDimitry Andric   Expected<File::OpenOptions> GetOptions() const override {
12929dba64beSDimitry Andric     GIL takeGIL;
12939dba64beSDimitry Andric     return GetOptionsForPyObject(m_py_obj);
12949dba64beSDimitry Andric   }
12959dba64beSDimitry Andric 
12969dba64beSDimitry Andric   static char ID;
12979dba64beSDimitry Andric   bool isA(const void *classID) const override {
12989dba64beSDimitry Andric     return classID == &ID || File::isA(classID);
12999dba64beSDimitry Andric   }
13009dba64beSDimitry Andric   static bool classof(const File *file) { return file->isA(&ID); }
13019dba64beSDimitry Andric };
13029dba64beSDimitry Andric char PythonIOFile::ID = 0;
13039dba64beSDimitry Andric } // namespace
13049dba64beSDimitry Andric 
13059dba64beSDimitry Andric namespace {
13069dba64beSDimitry Andric class BinaryPythonFile : public PythonIOFile {
13079dba64beSDimitry Andric protected:
13089dba64beSDimitry Andric   int m_descriptor;
13099dba64beSDimitry Andric 
13109dba64beSDimitry Andric public:
13119dba64beSDimitry Andric   BinaryPythonFile(int fd, const PythonFile &file, bool borrowed)
13129dba64beSDimitry Andric       : PythonIOFile(file, borrowed),
13139dba64beSDimitry Andric         m_descriptor(File::DescriptorIsValid(fd) ? fd
13149dba64beSDimitry Andric                                                  : File::kInvalidDescriptor) {}
13159dba64beSDimitry Andric 
13169dba64beSDimitry Andric   int GetDescriptor() const override { return m_descriptor; }
13179dba64beSDimitry Andric 
13189dba64beSDimitry Andric   Status Write(const void *buf, size_t &num_bytes) override {
13199dba64beSDimitry Andric     GIL takeGIL;
13209dba64beSDimitry Andric     PyObject *pybuffer_p = PyMemoryView_FromMemory(
13219dba64beSDimitry Andric         const_cast<char *>((const char *)buf), num_bytes, PyBUF_READ);
13229dba64beSDimitry Andric     if (!pybuffer_p)
13239dba64beSDimitry Andric       return Status(llvm::make_error<PythonException>());
13249dba64beSDimitry Andric     auto pybuffer = Take<PythonObject>(pybuffer_p);
13259dba64beSDimitry Andric     num_bytes = 0;
13269dba64beSDimitry Andric     auto bytes_written = As<long long>(m_py_obj.CallMethod("write", pybuffer));
13279dba64beSDimitry Andric     if (!bytes_written)
13289dba64beSDimitry Andric       return Status(bytes_written.takeError());
13299dba64beSDimitry Andric     if (bytes_written.get() < 0)
13309dba64beSDimitry Andric       return Status(".write() method returned a negative number!");
13319dba64beSDimitry Andric     static_assert(sizeof(long long) >= sizeof(size_t), "overflow");
13329dba64beSDimitry Andric     num_bytes = bytes_written.get();
13339dba64beSDimitry Andric     return Status();
13349dba64beSDimitry Andric   }
13359dba64beSDimitry Andric 
13369dba64beSDimitry Andric   Status Read(void *buf, size_t &num_bytes) override {
13379dba64beSDimitry Andric     GIL takeGIL;
13389dba64beSDimitry Andric     static_assert(sizeof(long long) >= sizeof(size_t), "overflow");
13399dba64beSDimitry Andric     auto pybuffer_obj =
13409dba64beSDimitry Andric         m_py_obj.CallMethod("read", (unsigned long long)num_bytes);
13419dba64beSDimitry Andric     if (!pybuffer_obj)
13429dba64beSDimitry Andric       return Status(pybuffer_obj.takeError());
13439dba64beSDimitry Andric     num_bytes = 0;
13449dba64beSDimitry Andric     if (pybuffer_obj.get().IsNone()) {
13459dba64beSDimitry Andric       // EOF
13469dba64beSDimitry Andric       num_bytes = 0;
13479dba64beSDimitry Andric       return Status();
13489dba64beSDimitry Andric     }
13499dba64beSDimitry Andric     auto pybuffer = PythonBuffer::Create(pybuffer_obj.get());
13509dba64beSDimitry Andric     if (!pybuffer)
13519dba64beSDimitry Andric       return Status(pybuffer.takeError());
13529dba64beSDimitry Andric     memcpy(buf, pybuffer.get().get().buf, pybuffer.get().get().len);
13539dba64beSDimitry Andric     num_bytes = pybuffer.get().get().len;
13549dba64beSDimitry Andric     return Status();
13559dba64beSDimitry Andric   }
13569dba64beSDimitry Andric };
13579dba64beSDimitry Andric } // namespace
13589dba64beSDimitry Andric 
13599dba64beSDimitry Andric namespace {
13609dba64beSDimitry Andric class TextPythonFile : public PythonIOFile {
13619dba64beSDimitry Andric protected:
13629dba64beSDimitry Andric   int m_descriptor;
13639dba64beSDimitry Andric 
13649dba64beSDimitry Andric public:
13659dba64beSDimitry Andric   TextPythonFile(int fd, const PythonFile &file, bool borrowed)
13669dba64beSDimitry Andric       : PythonIOFile(file, borrowed),
13679dba64beSDimitry Andric         m_descriptor(File::DescriptorIsValid(fd) ? fd
13689dba64beSDimitry Andric                                                  : File::kInvalidDescriptor) {}
13699dba64beSDimitry Andric 
13709dba64beSDimitry Andric   int GetDescriptor() const override { return m_descriptor; }
13719dba64beSDimitry Andric 
13729dba64beSDimitry Andric   Status Write(const void *buf, size_t &num_bytes) override {
13739dba64beSDimitry Andric     GIL takeGIL;
13749dba64beSDimitry Andric     auto pystring =
13759dba64beSDimitry Andric         PythonString::FromUTF8(llvm::StringRef((const char *)buf, num_bytes));
13769dba64beSDimitry Andric     if (!pystring)
13779dba64beSDimitry Andric       return Status(pystring.takeError());
13789dba64beSDimitry Andric     num_bytes = 0;
13799dba64beSDimitry Andric     auto bytes_written =
13809dba64beSDimitry Andric         As<long long>(m_py_obj.CallMethod("write", pystring.get()));
13819dba64beSDimitry Andric     if (!bytes_written)
13829dba64beSDimitry Andric       return Status(bytes_written.takeError());
13839dba64beSDimitry Andric     if (bytes_written.get() < 0)
13849dba64beSDimitry Andric       return Status(".write() method returned a negative number!");
13859dba64beSDimitry Andric     static_assert(sizeof(long long) >= sizeof(size_t), "overflow");
13869dba64beSDimitry Andric     num_bytes = bytes_written.get();
13879dba64beSDimitry Andric     return Status();
13889dba64beSDimitry Andric   }
13899dba64beSDimitry Andric 
13909dba64beSDimitry Andric   Status Read(void *buf, size_t &num_bytes) override {
13919dba64beSDimitry Andric     GIL takeGIL;
13929dba64beSDimitry Andric     size_t num_chars = num_bytes / 6;
13939dba64beSDimitry Andric     size_t orig_num_bytes = num_bytes;
13949dba64beSDimitry Andric     num_bytes = 0;
13959dba64beSDimitry Andric     if (orig_num_bytes < 6) {
13969dba64beSDimitry Andric       return Status("can't read less than 6 bytes from a utf8 text stream");
13979dba64beSDimitry Andric     }
13989dba64beSDimitry Andric     auto pystring = As<PythonString>(
13999dba64beSDimitry Andric         m_py_obj.CallMethod("read", (unsigned long long)num_chars));
14009dba64beSDimitry Andric     if (!pystring)
14019dba64beSDimitry Andric       return Status(pystring.takeError());
14029dba64beSDimitry Andric     if (pystring.get().IsNone()) {
14039dba64beSDimitry Andric       // EOF
14049dba64beSDimitry Andric       return Status();
14059dba64beSDimitry Andric     }
14069dba64beSDimitry Andric     auto stringref = pystring.get().AsUTF8();
14079dba64beSDimitry Andric     if (!stringref)
14089dba64beSDimitry Andric       return Status(stringref.takeError());
14099dba64beSDimitry Andric     num_bytes = stringref.get().size();
14109dba64beSDimitry Andric     memcpy(buf, stringref.get().begin(), num_bytes);
14119dba64beSDimitry Andric     return Status();
14129dba64beSDimitry Andric   }
14139dba64beSDimitry Andric };
14149dba64beSDimitry Andric } // namespace
14159dba64beSDimitry Andric 
14169dba64beSDimitry Andric #endif
14179dba64beSDimitry Andric 
14189dba64beSDimitry Andric llvm::Expected<FileSP> PythonFile::ConvertToFile(bool borrowed) {
14199dba64beSDimitry Andric   if (!IsValid())
14209dba64beSDimitry Andric     return llvm::createStringError(llvm::inconvertibleErrorCode(),
14219dba64beSDimitry Andric                                    "invalid PythonFile");
14229dba64beSDimitry Andric 
14239dba64beSDimitry Andric   int fd = PyObject_AsFileDescriptor(m_py_obj);
14249dba64beSDimitry Andric   if (fd < 0) {
14259dba64beSDimitry Andric     PyErr_Clear();
14269dba64beSDimitry Andric     return ConvertToFileForcingUseOfScriptingIOMethods(borrowed);
14279dba64beSDimitry Andric   }
14289dba64beSDimitry Andric   auto options = GetOptionsForPyObject(*this);
14299dba64beSDimitry Andric   if (!options)
14309dba64beSDimitry Andric     return options.takeError();
14319dba64beSDimitry Andric 
1432349cc55cSDimitry Andric   File::OpenOptions rw =
1433349cc55cSDimitry Andric       options.get() & (File::eOpenOptionReadOnly | File::eOpenOptionWriteOnly |
1434349cc55cSDimitry Andric                        File::eOpenOptionReadWrite);
1435349cc55cSDimitry Andric   if (rw == File::eOpenOptionWriteOnly || rw == File::eOpenOptionReadWrite) {
14369dba64beSDimitry Andric     // LLDB and python will not share I/O buffers.  We should probably
14379dba64beSDimitry Andric     // flush the python buffers now.
14389dba64beSDimitry Andric     auto r = CallMethod("flush");
14399dba64beSDimitry Andric     if (!r)
14409dba64beSDimitry Andric       return r.takeError();
1441480093f4SDimitry Andric   }
14429dba64beSDimitry Andric 
14439dba64beSDimitry Andric   FileSP file_sp;
14449dba64beSDimitry Andric   if (borrowed) {
14459dba64beSDimitry Andric     // In this case we we don't need to retain the python
14469dba64beSDimitry Andric     // object at all.
14479dba64beSDimitry Andric     file_sp = std::make_shared<NativeFile>(fd, options.get(), false);
14489dba64beSDimitry Andric   } else {
14499dba64beSDimitry Andric     file_sp = std::static_pointer_cast<File>(
14509dba64beSDimitry Andric         std::make_shared<SimplePythonFile>(*this, borrowed, fd, options.get()));
14519dba64beSDimitry Andric   }
14529dba64beSDimitry Andric   if (!file_sp->IsValid())
14539dba64beSDimitry Andric     return llvm::createStringError(llvm::inconvertibleErrorCode(),
14549dba64beSDimitry Andric                                    "invalid File");
14559dba64beSDimitry Andric 
14569dba64beSDimitry Andric   return file_sp;
14579dba64beSDimitry Andric }
14589dba64beSDimitry Andric 
14599dba64beSDimitry Andric llvm::Expected<FileSP>
14609dba64beSDimitry Andric PythonFile::ConvertToFileForcingUseOfScriptingIOMethods(bool borrowed) {
14619dba64beSDimitry Andric 
14629dba64beSDimitry Andric   assert(!PyErr_Occurred());
14639dba64beSDimitry Andric 
14649dba64beSDimitry Andric   if (!IsValid())
14659dba64beSDimitry Andric     return llvm::createStringError(llvm::inconvertibleErrorCode(),
14669dba64beSDimitry Andric                                    "invalid PythonFile");
14679dba64beSDimitry Andric 
14689dba64beSDimitry Andric #if PY_MAJOR_VERSION < 3
14699dba64beSDimitry Andric 
14709dba64beSDimitry Andric   return llvm::createStringError(llvm::inconvertibleErrorCode(),
14719dba64beSDimitry Andric                                  "not supported on python 2");
14729dba64beSDimitry Andric 
14739dba64beSDimitry Andric #else
14749dba64beSDimitry Andric 
14759dba64beSDimitry Andric   int fd = PyObject_AsFileDescriptor(m_py_obj);
14769dba64beSDimitry Andric   if (fd < 0) {
14779dba64beSDimitry Andric     PyErr_Clear();
14789dba64beSDimitry Andric     fd = File::kInvalidDescriptor;
14799dba64beSDimitry Andric   }
14809dba64beSDimitry Andric 
14819dba64beSDimitry Andric   auto io_module = PythonModule::Import("io");
14829dba64beSDimitry Andric   if (!io_module)
14839dba64beSDimitry Andric     return io_module.takeError();
14849dba64beSDimitry Andric   auto textIOBase = io_module.get().Get("TextIOBase");
14859dba64beSDimitry Andric   if (!textIOBase)
14869dba64beSDimitry Andric     return textIOBase.takeError();
14879dba64beSDimitry Andric   auto rawIOBase = io_module.get().Get("RawIOBase");
14889dba64beSDimitry Andric   if (!rawIOBase)
14899dba64beSDimitry Andric     return rawIOBase.takeError();
14909dba64beSDimitry Andric   auto bufferedIOBase = io_module.get().Get("BufferedIOBase");
14919dba64beSDimitry Andric   if (!bufferedIOBase)
14929dba64beSDimitry Andric     return bufferedIOBase.takeError();
14939dba64beSDimitry Andric 
14949dba64beSDimitry Andric   FileSP file_sp;
14959dba64beSDimitry Andric 
14969dba64beSDimitry Andric   auto isTextIO = IsInstance(textIOBase.get());
14979dba64beSDimitry Andric   if (!isTextIO)
14989dba64beSDimitry Andric     return isTextIO.takeError();
14999dba64beSDimitry Andric   if (isTextIO.get())
15009dba64beSDimitry Andric     file_sp = std::static_pointer_cast<File>(
15019dba64beSDimitry Andric         std::make_shared<TextPythonFile>(fd, *this, borrowed));
15029dba64beSDimitry Andric 
15039dba64beSDimitry Andric   auto isRawIO = IsInstance(rawIOBase.get());
15049dba64beSDimitry Andric   if (!isRawIO)
15059dba64beSDimitry Andric     return isRawIO.takeError();
15069dba64beSDimitry Andric   auto isBufferedIO = IsInstance(bufferedIOBase.get());
15079dba64beSDimitry Andric   if (!isBufferedIO)
15089dba64beSDimitry Andric     return isBufferedIO.takeError();
15099dba64beSDimitry Andric 
15109dba64beSDimitry Andric   if (isRawIO.get() || isBufferedIO.get()) {
15119dba64beSDimitry Andric     file_sp = std::static_pointer_cast<File>(
15129dba64beSDimitry Andric         std::make_shared<BinaryPythonFile>(fd, *this, borrowed));
15139dba64beSDimitry Andric   }
15149dba64beSDimitry Andric 
15159dba64beSDimitry Andric   if (!file_sp)
15169dba64beSDimitry Andric     return llvm::createStringError(llvm::inconvertibleErrorCode(),
15179dba64beSDimitry Andric                                    "python file is neither text nor binary");
15189dba64beSDimitry Andric 
15199dba64beSDimitry Andric   if (!file_sp->IsValid())
15209dba64beSDimitry Andric     return llvm::createStringError(llvm::inconvertibleErrorCode(),
15219dba64beSDimitry Andric                                    "invalid File");
15229dba64beSDimitry Andric 
15239dba64beSDimitry Andric   return file_sp;
15249dba64beSDimitry Andric 
15259dba64beSDimitry Andric #endif
15269dba64beSDimitry Andric }
15279dba64beSDimitry Andric 
15289dba64beSDimitry Andric Expected<PythonFile> PythonFile::FromFile(File &file, const char *mode) {
15299dba64beSDimitry Andric   if (!file.IsValid())
15309dba64beSDimitry Andric     return llvm::createStringError(llvm::inconvertibleErrorCode(),
15319dba64beSDimitry Andric                                    "invalid file");
15329dba64beSDimitry Andric 
15339dba64beSDimitry Andric   if (auto *simple = llvm::dyn_cast<SimplePythonFile>(&file))
15349dba64beSDimitry Andric     return Retain<PythonFile>(simple->GetPythonObject());
15359dba64beSDimitry Andric #if PY_MAJOR_VERSION >= 3
15369dba64beSDimitry Andric   if (auto *pythonio = llvm::dyn_cast<PythonIOFile>(&file))
15379dba64beSDimitry Andric     return Retain<PythonFile>(pythonio->GetPythonObject());
15389dba64beSDimitry Andric #endif
15399dba64beSDimitry Andric 
15409dba64beSDimitry Andric   if (!mode) {
15419dba64beSDimitry Andric     auto m = file.GetOpenMode();
15429dba64beSDimitry Andric     if (!m)
15439dba64beSDimitry Andric       return m.takeError();
15449dba64beSDimitry Andric     mode = m.get();
15459dba64beSDimitry Andric   }
15469dba64beSDimitry Andric 
15479dba64beSDimitry Andric   PyObject *file_obj;
15489dba64beSDimitry Andric #if PY_MAJOR_VERSION >= 3
15499dba64beSDimitry Andric   file_obj = PyFile_FromFd(file.GetDescriptor(), nullptr, mode, -1, nullptr,
1550480093f4SDimitry Andric                            "ignore", nullptr, /*closefd=*/0);
1551*0b57cec5SDimitry Andric #else
1552480093f4SDimitry Andric   // I'd like to pass ::fflush here if the file is writable,  so that
1553480093f4SDimitry Andric   // when the python side destructs the file object it will be flushed.
1554480093f4SDimitry Andric   // However, this would be dangerous.    It can cause fflush to be called
1555480093f4SDimitry Andric   // after fclose if the python program keeps a reference to the file after
1556480093f4SDimitry Andric   // the original lldb_private::File has been destructed.
1557480093f4SDimitry Andric   //
1558480093f4SDimitry Andric   // It's all well and good to ask a python program not to use a closed file
1559480093f4SDimitry Andric   // but asking a python program to make sure objects get released in a
1560480093f4SDimitry Andric   // particular order is not safe.
1561480093f4SDimitry Andric   //
1562480093f4SDimitry Andric   // The tradeoff here is that if a python 2 program wants to make sure this
1563480093f4SDimitry Andric   // file gets flushed, they'll have to do it explicitly or wait untill the
1564480093f4SDimitry Andric   // original lldb File itself gets flushed.
1565480093f4SDimitry Andric   file_obj = PyFile_FromFile(file.GetStream(), py2_const_cast(""),
1566480093f4SDimitry Andric                              py2_const_cast(mode), [](FILE *) { return 0; });
1567*0b57cec5SDimitry Andric #endif
15689dba64beSDimitry Andric 
15699dba64beSDimitry Andric   if (!file_obj)
15709dba64beSDimitry Andric     return exception();
15719dba64beSDimitry Andric 
15729dba64beSDimitry Andric   return Take<PythonFile>(file_obj);
1573*0b57cec5SDimitry Andric }
1574*0b57cec5SDimitry Andric 
15759dba64beSDimitry Andric Error PythonScript::Init() {
15769dba64beSDimitry Andric   if (function.IsValid())
15779dba64beSDimitry Andric     return Error::success();
1578*0b57cec5SDimitry Andric 
15799dba64beSDimitry Andric   PythonDictionary globals(PyInitialValue::Empty);
15809dba64beSDimitry Andric   auto builtins = PythonModule::BuiltinsModule();
15819dba64beSDimitry Andric   if (Error error = globals.SetItem("__builtins__", builtins))
15829dba64beSDimitry Andric     return error;
15839dba64beSDimitry Andric   PyObject *o =
15849dba64beSDimitry Andric       PyRun_String(script, Py_file_input, globals.get(), globals.get());
15859dba64beSDimitry Andric   if (!o)
15869dba64beSDimitry Andric     return exception();
15879dba64beSDimitry Andric   Take<PythonObject>(o);
15889dba64beSDimitry Andric   auto f = As<PythonCallable>(globals.GetItem("main"));
15899dba64beSDimitry Andric   if (!f)
15909dba64beSDimitry Andric     return f.takeError();
15919dba64beSDimitry Andric   function = std::move(f.get());
15929dba64beSDimitry Andric 
15939dba64beSDimitry Andric   return Error::success();
1594*0b57cec5SDimitry Andric }
1595*0b57cec5SDimitry Andric 
15969dba64beSDimitry Andric llvm::Expected<PythonObject>
15979dba64beSDimitry Andric python::runStringOneLine(const llvm::Twine &string,
15989dba64beSDimitry Andric                          const PythonDictionary &globals,
15999dba64beSDimitry Andric                          const PythonDictionary &locals) {
16009dba64beSDimitry Andric   if (!globals.IsValid() || !locals.IsValid())
16019dba64beSDimitry Andric     return nullDeref();
1602*0b57cec5SDimitry Andric 
16039dba64beSDimitry Andric   PyObject *code =
16049dba64beSDimitry Andric       Py_CompileString(NullTerminated(string), "<string>", Py_eval_input);
16059dba64beSDimitry Andric   if (!code) {
16069dba64beSDimitry Andric     PyErr_Clear();
16079dba64beSDimitry Andric     code =
16089dba64beSDimitry Andric         Py_CompileString(NullTerminated(string), "<string>", Py_single_input);
16099dba64beSDimitry Andric   }
16109dba64beSDimitry Andric   if (!code)
16119dba64beSDimitry Andric     return exception();
16129dba64beSDimitry Andric   auto code_ref = Take<PythonObject>(code);
16139dba64beSDimitry Andric 
16149dba64beSDimitry Andric #if PY_MAJOR_VERSION < 3
16159dba64beSDimitry Andric   PyObject *result =
16169dba64beSDimitry Andric       PyEval_EvalCode((PyCodeObject *)code, globals.get(), locals.get());
16179dba64beSDimitry Andric #else
16189dba64beSDimitry Andric   PyObject *result = PyEval_EvalCode(code, globals.get(), locals.get());
16199dba64beSDimitry Andric #endif
16209dba64beSDimitry Andric 
16219dba64beSDimitry Andric   if (!result)
16229dba64beSDimitry Andric     return exception();
16239dba64beSDimitry Andric 
16249dba64beSDimitry Andric   return Take<PythonObject>(result);
16259dba64beSDimitry Andric }
16269dba64beSDimitry Andric 
16279dba64beSDimitry Andric llvm::Expected<PythonObject>
16289dba64beSDimitry Andric python::runStringMultiLine(const llvm::Twine &string,
16299dba64beSDimitry Andric                            const PythonDictionary &globals,
16309dba64beSDimitry Andric                            const PythonDictionary &locals) {
16319dba64beSDimitry Andric   if (!globals.IsValid() || !locals.IsValid())
16329dba64beSDimitry Andric     return nullDeref();
16339dba64beSDimitry Andric   PyObject *result = PyRun_String(NullTerminated(string), Py_file_input,
16349dba64beSDimitry Andric                                   globals.get(), locals.get());
16359dba64beSDimitry Andric   if (!result)
16369dba64beSDimitry Andric     return exception();
16379dba64beSDimitry Andric   return Take<PythonObject>(result);
1638*0b57cec5SDimitry Andric }
1639*0b57cec5SDimitry Andric 
1640*0b57cec5SDimitry Andric #endif
1641