1bcadb5a3SPavel Labath //===-- PythonDataObjects.cpp -----------------------------------*- C++ -*-===//
22c1f46dcSZachary Turner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
62c1f46dcSZachary Turner //
72c1f46dcSZachary Turner //===----------------------------------------------------------------------===//
82c1f46dcSZachary Turner 
9d68983e3SPavel Labath #ifdef LLDB_DISABLE_PYTHON
10d68983e3SPavel Labath 
11d68983e3SPavel Labath // Python is disabled in this build
12d68983e3SPavel Labath 
13d68983e3SPavel Labath #else
14d68983e3SPavel Labath 
152c1f46dcSZachary Turner #include "PythonDataObjects.h"
162c1f46dcSZachary Turner #include "ScriptInterpreterPython.h"
172c1f46dcSZachary Turner 
182c1f46dcSZachary Turner #include "lldb/Host/File.h"
19190fadcdSZachary Turner #include "lldb/Host/FileSystem.h"
202c1f46dcSZachary Turner #include "lldb/Interpreter/ScriptInterpreter.h"
21085328eeSLawrence D'Anna #include "lldb/Utility/Log.h"
22bf9a7730SZachary Turner #include "lldb/Utility/Stream.h"
232c1f46dcSZachary Turner 
249a6c7572SJonas Devlieghere #include "llvm/ADT/StringSwitch.h"
25d9b553ecSLawrence D'Anna #include "llvm/Support/Casting.h"
26190fadcdSZachary Turner #include "llvm/Support/ConvertUTF.h"
272819136fSMichal Gorny #include "llvm/Support/Errno.h"
28190fadcdSZachary Turner 
292c1f46dcSZachary Turner #include <stdio.h>
302c1f46dcSZachary Turner 
312c1f46dcSZachary Turner using namespace lldb_private;
322c1f46dcSZachary Turner using namespace lldb;
33085328eeSLawrence D'Anna using namespace lldb_private::python;
34c86a6acaSLawrence D'Anna using llvm::cantFail;
35085328eeSLawrence D'Anna using llvm::Error;
36085328eeSLawrence D'Anna using llvm::Expected;
37722b6189SLawrence D'Anna using llvm::Twine;
38085328eeSLawrence D'Anna 
39085328eeSLawrence D'Anna template <> Expected<bool> python::As<bool>(Expected<PythonObject> &&obj) {
40085328eeSLawrence D'Anna   if (!obj)
41085328eeSLawrence D'Anna     return obj.takeError();
42085328eeSLawrence D'Anna   return obj.get().IsTrue();
43085328eeSLawrence D'Anna }
44085328eeSLawrence D'Anna 
45085328eeSLawrence D'Anna template <>
46085328eeSLawrence D'Anna Expected<long long> python::As<long long>(Expected<PythonObject> &&obj) {
47085328eeSLawrence D'Anna   if (!obj)
48085328eeSLawrence D'Anna     return obj.takeError();
49085328eeSLawrence D'Anna   return obj.get().AsLongLong();
50085328eeSLawrence D'Anna }
512c1f46dcSZachary Turner 
52c86a6acaSLawrence D'Anna template <>
53c86a6acaSLawrence D'Anna Expected<std::string> python::As<std::string>(Expected<PythonObject> &&obj) {
54c86a6acaSLawrence D'Anna   if (!obj)
55c86a6acaSLawrence D'Anna     return obj.takeError();
56c86a6acaSLawrence D'Anna   PyObject *str_obj = PyObject_Str(obj.get().get());
57c86a6acaSLawrence D'Anna   if (!obj)
58c86a6acaSLawrence D'Anna     return llvm::make_error<PythonException>();
59c86a6acaSLawrence D'Anna   auto str = Take<PythonString>(str_obj);
60c86a6acaSLawrence D'Anna   auto utf8 = str.AsUTF8();
61c86a6acaSLawrence D'Anna   if (!utf8)
62c86a6acaSLawrence D'Anna     return utf8.takeError();
63c86a6acaSLawrence D'Anna   return utf8.get();
64c86a6acaSLawrence D'Anna }
65c86a6acaSLawrence D'Anna 
662783d817SJonas Devlieghere void StructuredPythonObject::Serialize(llvm::json::OStream &s) const {
672783d817SJonas Devlieghere   s.value(llvm::formatv("Python Obj: {0:X}", GetValue()).str());
682c1f46dcSZachary Turner }
692c1f46dcSZachary Turner 
702c1f46dcSZachary Turner // PythonObject
712c1f46dcSZachary Turner 
72b9c1b51eSKate Stone void PythonObject::Dump(Stream &strm) const {
73b9c1b51eSKate Stone   if (m_py_obj) {
742819136fSMichal Gorny     FILE *file = llvm::sys::RetryAfterSignal(nullptr, ::tmpfile);
75b9c1b51eSKate Stone     if (file) {
762c1f46dcSZachary Turner       ::PyObject_Print(m_py_obj, file, 0);
772c1f46dcSZachary Turner       const long length = ftell(file);
78b9c1b51eSKate Stone       if (length) {
792c1f46dcSZachary Turner         ::rewind(file);
802c1f46dcSZachary Turner         std::vector<char> file_contents(length, '\0');
81b9c1b51eSKate Stone         const size_t length_read =
82b9c1b51eSKate Stone             ::fread(file_contents.data(), 1, file_contents.size(), file);
832c1f46dcSZachary Turner         if (length_read > 0)
842c1f46dcSZachary Turner           strm.Write(file_contents.data(), length_read);
852c1f46dcSZachary Turner       }
862c1f46dcSZachary Turner       ::fclose(file);
872c1f46dcSZachary Turner     }
88b9c1b51eSKate Stone   } else
892c1f46dcSZachary Turner     strm.PutCString("NULL");
902c1f46dcSZachary Turner }
912c1f46dcSZachary Turner 
92b9c1b51eSKate Stone PyObjectType PythonObject::GetObjectType() const {
93f8b22f8fSZachary Turner   if (!IsAllocated())
942c1f46dcSZachary Turner     return PyObjectType::None;
952c1f46dcSZachary Turner 
967841efbbSZachary Turner   if (PythonModule::Check(m_py_obj))
977841efbbSZachary Turner     return PyObjectType::Module;
9818426935SZachary Turner   if (PythonList::Check(m_py_obj))
992c1f46dcSZachary Turner     return PyObjectType::List;
100a1405147SZachary Turner   if (PythonTuple::Check(m_py_obj))
101a1405147SZachary Turner     return PyObjectType::Tuple;
10218426935SZachary Turner   if (PythonDictionary::Check(m_py_obj))
1032c1f46dcSZachary Turner     return PyObjectType::Dictionary;
10418426935SZachary Turner   if (PythonString::Check(m_py_obj))
10522c8efcdSZachary Turner     return PyObjectType::String;
1065a72c02bSZachary Turner #if PY_MAJOR_VERSION >= 3
1075a72c02bSZachary Turner   if (PythonBytes::Check(m_py_obj))
1085a72c02bSZachary Turner     return PyObjectType::Bytes;
1095a72c02bSZachary Turner #endif
110f9d6d204SZachary Turner   if (PythonByteArray::Check(m_py_obj))
111f9d6d204SZachary Turner     return PyObjectType::ByteArray;
112b81d715cSTatyana Krasnukha   if (PythonBoolean::Check(m_py_obj))
113b81d715cSTatyana Krasnukha     return PyObjectType::Boolean;
11418426935SZachary Turner   if (PythonInteger::Check(m_py_obj))
11522c8efcdSZachary Turner     return PyObjectType::Integer;
1169c40264fSZachary Turner   if (PythonFile::Check(m_py_obj))
1179c40264fSZachary Turner     return PyObjectType::File;
118a1405147SZachary Turner   if (PythonCallable::Check(m_py_obj))
119a1405147SZachary Turner     return PyObjectType::Callable;
1202c1f46dcSZachary Turner   return PyObjectType::Unknown;
1212c1f46dcSZachary Turner }
1222c1f46dcSZachary Turner 
123b9c1b51eSKate Stone PythonString PythonObject::Repr() const {
1242c1f46dcSZachary Turner   if (!m_py_obj)
1252c1f46dcSZachary Turner     return PythonString();
1262c1f46dcSZachary Turner   PyObject *repr = PyObject_Repr(m_py_obj);
1272c1f46dcSZachary Turner   if (!repr)
1282c1f46dcSZachary Turner     return PythonString();
129f8b22f8fSZachary Turner   return PythonString(PyRefType::Owned, repr);
1302c1f46dcSZachary Turner }
1312c1f46dcSZachary Turner 
132b9c1b51eSKate Stone PythonString PythonObject::Str() const {
1332c1f46dcSZachary Turner   if (!m_py_obj)
1342c1f46dcSZachary Turner     return PythonString();
1352c1f46dcSZachary Turner   PyObject *str = PyObject_Str(m_py_obj);
1362c1f46dcSZachary Turner   if (!str)
1372c1f46dcSZachary Turner     return PythonString();
138f8b22f8fSZachary Turner   return PythonString(PyRefType::Owned, str);
1392c1f46dcSZachary Turner }
1402c1f46dcSZachary Turner 
1417841efbbSZachary Turner PythonObject
142b9c1b51eSKate Stone PythonObject::ResolveNameWithDictionary(llvm::StringRef name,
143b9c1b51eSKate Stone                                         const PythonDictionary &dict) {
144c712bac7SJonas Devlieghere   size_t dot_pos = name.find('.');
145a1405147SZachary Turner   llvm::StringRef piece = name.substr(0, dot_pos);
146a1405147SZachary Turner   PythonObject result = dict.GetItemForKey(PythonString(piece));
147b9c1b51eSKate Stone   if (dot_pos == llvm::StringRef::npos) {
148a1405147SZachary Turner     // There was no dot, we're done.
149a1405147SZachary Turner     return result;
150a1405147SZachary Turner   }
151a1405147SZachary Turner 
152a1405147SZachary Turner   // There was a dot.  The remaining portion of the name should be looked up in
153a1405147SZachary Turner   // the context of the object that was found in the dictionary.
154a1405147SZachary Turner   return result.ResolveName(name.substr(dot_pos + 1));
1557841efbbSZachary Turner }
1567841efbbSZachary Turner 
157b9c1b51eSKate Stone PythonObject PythonObject::ResolveName(llvm::StringRef name) const {
15805097246SAdrian Prantl   // Resolve the name in the context of the specified object.  If, for example,
15905097246SAdrian Prantl   // `this` refers to a PyModule, then this will look for `name` in this
16005097246SAdrian Prantl   // module.  If `this` refers to a PyType, then it will resolve `name` as an
16105097246SAdrian Prantl   // attribute of that type.  If `this` refers to an instance of an object,
16205097246SAdrian Prantl   // then it will resolve `name` as the value of the specified field.
1637841efbbSZachary Turner   //
1647841efbbSZachary Turner   // This function handles dotted names so that, for example, if `m_py_obj`
16505097246SAdrian Prantl   // refers to the `sys` module, and `name` == "path.append", then it will find
16605097246SAdrian Prantl   // the function `sys.path.append`.
1677841efbbSZachary Turner 
168c712bac7SJonas Devlieghere   size_t dot_pos = name.find('.');
169b9c1b51eSKate Stone   if (dot_pos == llvm::StringRef::npos) {
17005097246SAdrian Prantl     // No dots in the name, we should be able to find the value immediately as
17105097246SAdrian Prantl     // an attribute of `m_py_obj`.
1727841efbbSZachary Turner     return GetAttributeValue(name);
1737841efbbSZachary Turner   }
1747841efbbSZachary Turner 
175b9c1b51eSKate Stone   // Look up the first piece of the name, and resolve the rest as a child of
176b9c1b51eSKate Stone   // that.
1777841efbbSZachary Turner   PythonObject parent = ResolveName(name.substr(0, dot_pos));
1787841efbbSZachary Turner   if (!parent.IsAllocated())
1797841efbbSZachary Turner     return PythonObject();
1807841efbbSZachary Turner 
1817841efbbSZachary Turner   // Tail recursion.. should be optimized by the compiler
1827841efbbSZachary Turner   return parent.ResolveName(name.substr(dot_pos + 1));
1837841efbbSZachary Turner }
1847841efbbSZachary Turner 
185b9c1b51eSKate Stone bool PythonObject::HasAttribute(llvm::StringRef attr) const {
1869c40264fSZachary Turner   if (!IsValid())
1879c40264fSZachary Turner     return false;
1889c40264fSZachary Turner   PythonString py_attr(attr);
1899c40264fSZachary Turner   return !!PyObject_HasAttr(m_py_obj, py_attr.get());
1909c40264fSZachary Turner }
1919c40264fSZachary Turner 
192b9c1b51eSKate Stone PythonObject PythonObject::GetAttributeValue(llvm::StringRef attr) const {
1937d6d218eSZachary Turner   if (!IsValid())
1947d6d218eSZachary Turner     return PythonObject();
1957d6d218eSZachary Turner 
1967d6d218eSZachary Turner   PythonString py_attr(attr);
1977d6d218eSZachary Turner   if (!PyObject_HasAttr(m_py_obj, py_attr.get()))
1987d6d218eSZachary Turner     return PythonObject();
1997d6d218eSZachary Turner 
2007d6d218eSZachary Turner   return PythonObject(PyRefType::Owned,
2017d6d218eSZachary Turner                       PyObject_GetAttr(m_py_obj, py_attr.get()));
2027d6d218eSZachary Turner }
2037d6d218eSZachary Turner 
204b9c1b51eSKate Stone StructuredData::ObjectSP PythonObject::CreateStructuredObject() const {
205b9c1b51eSKate Stone   switch (GetObjectType()) {
2062c1f46dcSZachary Turner   case PyObjectType::Dictionary:
207b9c1b51eSKate Stone     return PythonDictionary(PyRefType::Borrowed, m_py_obj)
208b9c1b51eSKate Stone         .CreateStructuredDictionary();
209b81d715cSTatyana Krasnukha   case PyObjectType::Boolean:
210b81d715cSTatyana Krasnukha     return PythonBoolean(PyRefType::Borrowed, m_py_obj)
211b81d715cSTatyana Krasnukha         .CreateStructuredBoolean();
2122c1f46dcSZachary Turner   case PyObjectType::Integer:
213b9c1b51eSKate Stone     return PythonInteger(PyRefType::Borrowed, m_py_obj)
214b9c1b51eSKate Stone         .CreateStructuredInteger();
2152c1f46dcSZachary Turner   case PyObjectType::List:
216f8b22f8fSZachary Turner     return PythonList(PyRefType::Borrowed, m_py_obj).CreateStructuredArray();
2172c1f46dcSZachary Turner   case PyObjectType::String:
218f8b22f8fSZachary Turner     return PythonString(PyRefType::Borrowed, m_py_obj).CreateStructuredString();
2195a72c02bSZachary Turner   case PyObjectType::Bytes:
2205a72c02bSZachary Turner     return PythonBytes(PyRefType::Borrowed, m_py_obj).CreateStructuredString();
221f9d6d204SZachary Turner   case PyObjectType::ByteArray:
222b9c1b51eSKate Stone     return PythonByteArray(PyRefType::Borrowed, m_py_obj)
223b9c1b51eSKate Stone         .CreateStructuredString();
2242c1f46dcSZachary Turner   case PyObjectType::None:
2252c1f46dcSZachary Turner     return StructuredData::ObjectSP();
2262c1f46dcSZachary Turner   default:
2272c1f46dcSZachary Turner     return StructuredData::ObjectSP(new StructuredPythonObject(m_py_obj));
2282c1f46dcSZachary Turner   }
2292c1f46dcSZachary Turner }
2302c1f46dcSZachary Turner 
2312c1f46dcSZachary Turner // PythonString
2325a72c02bSZachary Turner 
233d3bd5b3dSLawrence D'Anna PythonBytes::PythonBytes(llvm::ArrayRef<uint8_t> bytes) { SetBytes(bytes); }
2345a72c02bSZachary Turner 
235d3bd5b3dSLawrence D'Anna PythonBytes::PythonBytes(const uint8_t *bytes, size_t length) {
2365a72c02bSZachary Turner   SetBytes(llvm::ArrayRef<uint8_t>(bytes, length));
2375a72c02bSZachary Turner }
2385a72c02bSZachary Turner 
239b9c1b51eSKate Stone bool PythonBytes::Check(PyObject *py_obj) {
2405a72c02bSZachary Turner   if (!py_obj)
2415a72c02bSZachary Turner     return false;
242a6682a41SJonas Devlieghere   return PyBytes_Check(py_obj);
2435a72c02bSZachary Turner }
2445a72c02bSZachary Turner 
245b9c1b51eSKate Stone llvm::ArrayRef<uint8_t> PythonBytes::GetBytes() const {
2465a72c02bSZachary Turner   if (!IsValid())
2475a72c02bSZachary Turner     return llvm::ArrayRef<uint8_t>();
2485a72c02bSZachary Turner 
2495a72c02bSZachary Turner   Py_ssize_t size;
2505a72c02bSZachary Turner   char *c;
2515a72c02bSZachary Turner 
2525a72c02bSZachary Turner   PyBytes_AsStringAndSize(m_py_obj, &c, &size);
2535a72c02bSZachary Turner   return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size);
2545a72c02bSZachary Turner }
2555a72c02bSZachary Turner 
256b9c1b51eSKate Stone size_t PythonBytes::GetSize() const {
2575a72c02bSZachary Turner   if (!IsValid())
2585a72c02bSZachary Turner     return 0;
2595a72c02bSZachary Turner   return PyBytes_Size(m_py_obj);
2605a72c02bSZachary Turner }
2615a72c02bSZachary Turner 
262b9c1b51eSKate Stone void PythonBytes::SetBytes(llvm::ArrayRef<uint8_t> bytes) {
2635a72c02bSZachary Turner   const char *data = reinterpret_cast<const char *>(bytes.data());
26404edd189SLawrence D'Anna   *this = Take<PythonBytes>(PyBytes_FromStringAndSize(data, bytes.size()));
2655a72c02bSZachary Turner }
2665a72c02bSZachary Turner 
267b9c1b51eSKate Stone StructuredData::StringSP PythonBytes::CreateStructuredString() const {
2685a72c02bSZachary Turner   StructuredData::StringSP result(new StructuredData::String);
2695a72c02bSZachary Turner   Py_ssize_t size;
2705a72c02bSZachary Turner   char *c;
2715a72c02bSZachary Turner   PyBytes_AsStringAndSize(m_py_obj, &c, &size);
2725a72c02bSZachary Turner   result->SetValue(std::string(c, size));
2735a72c02bSZachary Turner   return result;
2745a72c02bSZachary Turner }
2755a72c02bSZachary Turner 
276b9c1b51eSKate Stone PythonByteArray::PythonByteArray(llvm::ArrayRef<uint8_t> bytes)
277b9c1b51eSKate Stone     : PythonByteArray(bytes.data(), bytes.size()) {}
278f9d6d204SZachary Turner 
279b9c1b51eSKate Stone PythonByteArray::PythonByteArray(const uint8_t *bytes, size_t length) {
280f9d6d204SZachary Turner   const char *str = reinterpret_cast<const char *>(bytes);
281722b6189SLawrence D'Anna   *this = Take<PythonByteArray>(PyByteArray_FromStringAndSize(str, length));
282f9d6d204SZachary Turner }
283f9d6d204SZachary Turner 
284b9c1b51eSKate Stone bool PythonByteArray::Check(PyObject *py_obj) {
285f9d6d204SZachary Turner   if (!py_obj)
286f9d6d204SZachary Turner     return false;
287a6682a41SJonas Devlieghere   return PyByteArray_Check(py_obj);
288f9d6d204SZachary Turner }
289f9d6d204SZachary Turner 
290b9c1b51eSKate Stone llvm::ArrayRef<uint8_t> PythonByteArray::GetBytes() const {
291f9d6d204SZachary Turner   if (!IsValid())
292f9d6d204SZachary Turner     return llvm::ArrayRef<uint8_t>();
293f9d6d204SZachary Turner 
294f9d6d204SZachary Turner   char *c = PyByteArray_AsString(m_py_obj);
295f9d6d204SZachary Turner   size_t size = GetSize();
296f9d6d204SZachary Turner   return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size);
297f9d6d204SZachary Turner }
298f9d6d204SZachary Turner 
299b9c1b51eSKate Stone size_t PythonByteArray::GetSize() const {
300f9d6d204SZachary Turner   if (!IsValid())
301f9d6d204SZachary Turner     return 0;
302f9d6d204SZachary Turner 
303f9d6d204SZachary Turner   return PyByteArray_Size(m_py_obj);
304f9d6d204SZachary Turner }
305f9d6d204SZachary Turner 
306b9c1b51eSKate Stone StructuredData::StringSP PythonByteArray::CreateStructuredString() const {
307f9d6d204SZachary Turner   StructuredData::StringSP result(new StructuredData::String);
308f9d6d204SZachary Turner   llvm::ArrayRef<uint8_t> bytes = GetBytes();
309f9d6d204SZachary Turner   const char *str = reinterpret_cast<const char *>(bytes.data());
310f9d6d204SZachary Turner   result->SetValue(std::string(str, bytes.size()));
311f9d6d204SZachary Turner   return result;
312f9d6d204SZachary Turner }
313f9d6d204SZachary Turner 
3145a72c02bSZachary Turner // PythonString
3152c1f46dcSZachary Turner 
316085328eeSLawrence D'Anna Expected<PythonString> PythonString::FromUTF8(llvm::StringRef string) {
317085328eeSLawrence D'Anna #if PY_MAJOR_VERSION >= 3
318085328eeSLawrence D'Anna   PyObject *str = PyUnicode_FromStringAndSize(string.data(), string.size());
319085328eeSLawrence D'Anna #else
320085328eeSLawrence D'Anna   PyObject *str = PyString_FromStringAndSize(string.data(), string.size());
321085328eeSLawrence D'Anna #endif
322085328eeSLawrence D'Anna   if (!str)
323085328eeSLawrence D'Anna     return llvm::make_error<PythonException>();
324085328eeSLawrence D'Anna   return Take<PythonString>(str);
325085328eeSLawrence D'Anna }
326085328eeSLawrence D'Anna 
327d3bd5b3dSLawrence D'Anna PythonString::PythonString(llvm::StringRef string) { SetString(string); }
3282c1f46dcSZachary Turner 
329b9c1b51eSKate Stone bool PythonString::Check(PyObject *py_obj) {
33022c8efcdSZachary Turner   if (!py_obj)
33122c8efcdSZachary Turner     return false;
33218426935SZachary Turner 
3337d6d218eSZachary Turner   if (PyUnicode_Check(py_obj))
3347d6d218eSZachary Turner     return true;
3357d6d218eSZachary Turner #if PY_MAJOR_VERSION < 3
3367d6d218eSZachary Turner   if (PyString_Check(py_obj))
3377d6d218eSZachary Turner     return true;
33822c8efcdSZachary Turner #endif
3397d6d218eSZachary Turner   return false;
34022c8efcdSZachary Turner }
34122c8efcdSZachary Turner 
342d3bd5b3dSLawrence D'Anna void PythonString::Convert(PyRefType &type, PyObject *&py_obj) {
3437d6d218eSZachary Turner #if PY_MAJOR_VERSION < 3
3447d6d218eSZachary Turner   // In Python 2, Don't store PyUnicode objects directly, because we need
3457d6d218eSZachary Turner   // access to their underlying character buffers which Python 2 doesn't
3467d6d218eSZachary Turner   // provide.
347085328eeSLawrence D'Anna   if (PyUnicode_Check(py_obj)) {
348d3bd5b3dSLawrence D'Anna     PyObject *s = PyUnicode_AsUTF8String(py_obj);
349d3bd5b3dSLawrence D'Anna     if (s == nullptr) {
350085328eeSLawrence D'Anna       PyErr_Clear();
351d3bd5b3dSLawrence D'Anna       if (type == PyRefType::Owned)
352d3bd5b3dSLawrence D'Anna         Py_DECREF(py_obj);
353d3bd5b3dSLawrence D'Anna       return;
354d3bd5b3dSLawrence D'Anna     }
355d3bd5b3dSLawrence D'Anna     if (type == PyRefType::Owned)
356d3bd5b3dSLawrence D'Anna       Py_DECREF(py_obj);
357d3bd5b3dSLawrence D'Anna     else
358d3bd5b3dSLawrence D'Anna       type = PyRefType::Owned;
359d3bd5b3dSLawrence D'Anna     py_obj = s;
360085328eeSLawrence D'Anna   }
3617d6d218eSZachary Turner #endif
3622c1f46dcSZachary Turner }
3632c1f46dcSZachary Turner 
364b9c1b51eSKate Stone llvm::StringRef PythonString::GetString() const {
365085328eeSLawrence D'Anna   auto s = AsUTF8();
366085328eeSLawrence D'Anna   if (!s) {
367085328eeSLawrence D'Anna     llvm::consumeError(s.takeError());
368085328eeSLawrence D'Anna     return llvm::StringRef("");
369085328eeSLawrence D'Anna   }
370085328eeSLawrence D'Anna   return s.get();
371085328eeSLawrence D'Anna }
372085328eeSLawrence D'Anna 
373085328eeSLawrence D'Anna Expected<llvm::StringRef> PythonString::AsUTF8() const {
37418426935SZachary Turner   if (!IsValid())
375085328eeSLawrence D'Anna     return nullDeref();
37618426935SZachary Turner 
37722c8efcdSZachary Turner   Py_ssize_t size;
3785457b426SPavel Labath   const char *data;
37918426935SZachary Turner 
38018426935SZachary Turner #if PY_MAJOR_VERSION >= 3
3815457b426SPavel Labath   data = PyUnicode_AsUTF8AndSize(m_py_obj, &size);
38218426935SZachary Turner #else
383085328eeSLawrence D'Anna   char *c = NULL;
384085328eeSLawrence D'Anna   int r = PyString_AsStringAndSize(m_py_obj, &c, &size);
385085328eeSLawrence D'Anna   if (r < 0)
386085328eeSLawrence D'Anna     c = NULL;
3875457b426SPavel Labath   data = c;
38818426935SZachary Turner #endif
389085328eeSLawrence D'Anna 
390085328eeSLawrence D'Anna   if (!data)
391085328eeSLawrence D'Anna     return exception();
392085328eeSLawrence D'Anna 
3935457b426SPavel Labath   return llvm::StringRef(data, size);
39422c8efcdSZachary Turner }
3952c1f46dcSZachary Turner 
396b9c1b51eSKate Stone size_t PythonString::GetSize() const {
397b9c1b51eSKate Stone   if (IsValid()) {
39818426935SZachary Turner #if PY_MAJOR_VERSION >= 3
39918426935SZachary Turner     return PyUnicode_GetSize(m_py_obj);
40018426935SZachary Turner #else
40118426935SZachary Turner     return PyString_Size(m_py_obj);
40218426935SZachary Turner #endif
40318426935SZachary Turner   }
4042c1f46dcSZachary Turner   return 0;
4052c1f46dcSZachary Turner }
4062c1f46dcSZachary Turner 
407b9c1b51eSKate Stone void PythonString::SetString(llvm::StringRef string) {
408085328eeSLawrence D'Anna   auto s = FromUTF8(string);
409085328eeSLawrence D'Anna   if (!s) {
410085328eeSLawrence D'Anna     llvm::consumeError(s.takeError());
411085328eeSLawrence D'Anna     Reset();
412085328eeSLawrence D'Anna   } else {
41303819d1cSLawrence D'Anna     *this = std::move(s.get());
414085328eeSLawrence D'Anna   }
4152c1f46dcSZachary Turner }
4162c1f46dcSZachary Turner 
417b9c1b51eSKate Stone StructuredData::StringSP PythonString::CreateStructuredString() const {
4182c1f46dcSZachary Turner   StructuredData::StringSP result(new StructuredData::String);
4192c1f46dcSZachary Turner   result->SetValue(GetString());
4202c1f46dcSZachary Turner   return result;
4212c1f46dcSZachary Turner }
4222c1f46dcSZachary Turner 
4232c1f46dcSZachary Turner // PythonInteger
4242c1f46dcSZachary Turner 
425d3bd5b3dSLawrence D'Anna PythonInteger::PythonInteger(int64_t value) { SetInteger(value); }
4262c1f46dcSZachary Turner 
427b9c1b51eSKate Stone bool PythonInteger::Check(PyObject *py_obj) {
42822c8efcdSZachary Turner   if (!py_obj)
42922c8efcdSZachary Turner     return false;
43022c8efcdSZachary Turner 
43122c8efcdSZachary Turner #if PY_MAJOR_VERSION >= 3
43205097246SAdrian Prantl   // Python 3 does not have PyInt_Check.  There is only one type of integral
43305097246SAdrian Prantl   // value, long.
43422c8efcdSZachary Turner   return PyLong_Check(py_obj);
43522c8efcdSZachary Turner #else
43622c8efcdSZachary Turner   return PyLong_Check(py_obj) || PyInt_Check(py_obj);
43722c8efcdSZachary Turner #endif
4382c1f46dcSZachary Turner }
4392c1f46dcSZachary Turner 
440d3bd5b3dSLawrence D'Anna void PythonInteger::Convert(PyRefType &type, PyObject *&py_obj) {
44122c8efcdSZachary Turner #if PY_MAJOR_VERSION < 3
44205097246SAdrian Prantl   // Always store this as a PyLong, which makes interoperability between Python
44305097246SAdrian Prantl   // 2.x and Python 3.x easier.  This is only necessary in 2.x, since 3.x
44405097246SAdrian Prantl   // doesn't even have a PyInt.
445b9c1b51eSKate Stone   if (PyInt_Check(py_obj)) {
446f8b22f8fSZachary Turner     // Since we converted the original object to a different type, the new
44705097246SAdrian Prantl     // object is an owned object regardless of the ownership semantics
44805097246SAdrian Prantl     // requested by the user.
449d3bd5b3dSLawrence D'Anna     long long value = PyInt_AsLong(py_obj);
450d3bd5b3dSLawrence D'Anna     PyObject *l = nullptr;
451d3bd5b3dSLawrence D'Anna     if (!PyErr_Occurred())
452d3bd5b3dSLawrence D'Anna       l = PyLong_FromLongLong(value);
453d3bd5b3dSLawrence D'Anna     if (l == nullptr) {
454d3bd5b3dSLawrence D'Anna       PyErr_Clear();
455d3bd5b3dSLawrence D'Anna       if (type == PyRefType::Owned)
456d3bd5b3dSLawrence D'Anna         Py_DECREF(py_obj);
457d3bd5b3dSLawrence D'Anna       return;
458d3bd5b3dSLawrence D'Anna     }
459d3bd5b3dSLawrence D'Anna     if (type == PyRefType::Owned)
460d3bd5b3dSLawrence D'Anna       Py_DECREF(py_obj);
461d3bd5b3dSLawrence D'Anna     else
462d3bd5b3dSLawrence D'Anna       type = PyRefType::Owned;
463d3bd5b3dSLawrence D'Anna     py_obj = l;
46422c8efcdSZachary Turner   }
46522c8efcdSZachary Turner #endif
4662c1f46dcSZachary Turner }
4672c1f46dcSZachary Turner 
468b9c1b51eSKate Stone int64_t PythonInteger::GetInteger() const {
469b9c1b51eSKate Stone   if (m_py_obj) {
470b9c1b51eSKate Stone     assert(PyLong_Check(m_py_obj) &&
471b9c1b51eSKate Stone            "PythonInteger::GetInteger has a PyObject that isn't a PyLong");
47222c8efcdSZachary Turner 
473008ec446SGreg Clayton     int overflow = 0;
474008ec446SGreg Clayton     int64_t result = PyLong_AsLongLongAndOverflow(m_py_obj, &overflow);
475b9c1b51eSKate Stone     if (overflow != 0) {
47605097246SAdrian Prantl       // We got an integer that overflows, like 18446744072853913392L we can't
47705097246SAdrian Prantl       // use PyLong_AsLongLong() as it will return 0xffffffffffffffff. If we
47805097246SAdrian Prantl       // use the unsigned long long it will work as expected.
479008ec446SGreg Clayton       const uint64_t uval = PyLong_AsUnsignedLongLong(m_py_obj);
4804f730dc7SIlia K       result = static_cast<int64_t>(uval);
481008ec446SGreg Clayton     }
482008ec446SGreg Clayton     return result;
4832c1f46dcSZachary Turner   }
4842c1f46dcSZachary Turner   return UINT64_MAX;
4852c1f46dcSZachary Turner }
4862c1f46dcSZachary Turner 
487b9c1b51eSKate Stone void PythonInteger::SetInteger(int64_t value) {
48804edd189SLawrence D'Anna   *this = Take<PythonInteger>(PyLong_FromLongLong(value));
4892c1f46dcSZachary Turner }
4902c1f46dcSZachary Turner 
491b9c1b51eSKate Stone StructuredData::IntegerSP PythonInteger::CreateStructuredInteger() const {
4922c1f46dcSZachary Turner   StructuredData::IntegerSP result(new StructuredData::Integer);
4932c1f46dcSZachary Turner   result->SetValue(GetInteger());
4942c1f46dcSZachary Turner   return result;
4952c1f46dcSZachary Turner }
4962c1f46dcSZachary Turner 
497b81d715cSTatyana Krasnukha // PythonBoolean
498b81d715cSTatyana Krasnukha 
499b81d715cSTatyana Krasnukha PythonBoolean::PythonBoolean(bool value) {
500b81d715cSTatyana Krasnukha   SetValue(value);
501b81d715cSTatyana Krasnukha }
502b81d715cSTatyana Krasnukha 
503b81d715cSTatyana Krasnukha bool PythonBoolean::Check(PyObject *py_obj) {
504b81d715cSTatyana Krasnukha   return py_obj ? PyBool_Check(py_obj) : false;
505b81d715cSTatyana Krasnukha }
506b81d715cSTatyana Krasnukha 
507b81d715cSTatyana Krasnukha bool PythonBoolean::GetValue() const {
508b81d715cSTatyana Krasnukha   return m_py_obj ? PyObject_IsTrue(m_py_obj) : false;
509b81d715cSTatyana Krasnukha }
510b81d715cSTatyana Krasnukha 
511b81d715cSTatyana Krasnukha void PythonBoolean::SetValue(bool value) {
51204edd189SLawrence D'Anna   *this = Take<PythonBoolean>(PyBool_FromLong(value));
513b81d715cSTatyana Krasnukha }
514b81d715cSTatyana Krasnukha 
515b81d715cSTatyana Krasnukha StructuredData::BooleanSP PythonBoolean::CreateStructuredBoolean() const {
516b81d715cSTatyana Krasnukha   StructuredData::BooleanSP result(new StructuredData::Boolean);
517b81d715cSTatyana Krasnukha   result->SetValue(GetValue());
518b81d715cSTatyana Krasnukha   return result;
519b81d715cSTatyana Krasnukha }
520b81d715cSTatyana Krasnukha 
5212c1f46dcSZachary Turner // PythonList
5222c1f46dcSZachary Turner 
523d3bd5b3dSLawrence D'Anna PythonList::PythonList(PyInitialValue value) {
524f8b22f8fSZachary Turner   if (value == PyInitialValue::Empty)
525722b6189SLawrence D'Anna     *this = Take<PythonList>(PyList_New(0));
5262c1f46dcSZachary Turner }
5272c1f46dcSZachary Turner 
528d3bd5b3dSLawrence D'Anna PythonList::PythonList(int list_size) {
529722b6189SLawrence D'Anna   *this = Take<PythonList>(PyList_New(list_size));
53087f47729SZachary Turner }
53187f47729SZachary Turner 
532b9c1b51eSKate Stone bool PythonList::Check(PyObject *py_obj) {
53322c8efcdSZachary Turner   if (!py_obj)
53422c8efcdSZachary Turner     return false;
53522c8efcdSZachary Turner   return PyList_Check(py_obj);
53622c8efcdSZachary Turner }
53722c8efcdSZachary Turner 
538b9c1b51eSKate Stone uint32_t PythonList::GetSize() const {
539f8b22f8fSZachary Turner   if (IsValid())
5402c1f46dcSZachary Turner     return PyList_GET_SIZE(m_py_obj);
5412c1f46dcSZachary Turner   return 0;
5422c1f46dcSZachary Turner }
5432c1f46dcSZachary Turner 
544b9c1b51eSKate Stone PythonObject PythonList::GetItemAtIndex(uint32_t index) const {
545f8b22f8fSZachary Turner   if (IsValid())
546f8b22f8fSZachary Turner     return PythonObject(PyRefType::Borrowed, PyList_GetItem(m_py_obj, index));
5472c1f46dcSZachary Turner   return PythonObject();
5482c1f46dcSZachary Turner }
5492c1f46dcSZachary Turner 
550b9c1b51eSKate Stone void PythonList::SetItemAtIndex(uint32_t index, const PythonObject &object) {
551b9c1b51eSKate Stone   if (IsAllocated() && object.IsValid()) {
552f8b22f8fSZachary Turner     // PyList_SetItem is documented to "steal" a reference, so we need to
553f8b22f8fSZachary Turner     // convert it to an owned reference by incrementing it.
554f8b22f8fSZachary Turner     Py_INCREF(object.get());
5552c1f46dcSZachary Turner     PyList_SetItem(m_py_obj, index, object.get());
5562c1f46dcSZachary Turner   }
557f8b22f8fSZachary Turner }
5582c1f46dcSZachary Turner 
559b9c1b51eSKate Stone void PythonList::AppendItem(const PythonObject &object) {
560b9c1b51eSKate Stone   if (IsAllocated() && object.IsValid()) {
561f8b22f8fSZachary Turner     // `PyList_Append` does *not* steal a reference, so do not call `Py_INCREF`
562f8b22f8fSZachary Turner     // here like we do with `PyList_SetItem`.
5632c1f46dcSZachary Turner     PyList_Append(m_py_obj, object.get());
5642c1f46dcSZachary Turner   }
565f8b22f8fSZachary Turner }
5662c1f46dcSZachary Turner 
567b9c1b51eSKate Stone StructuredData::ArraySP PythonList::CreateStructuredArray() const {
5682c1f46dcSZachary Turner   StructuredData::ArraySP result(new StructuredData::Array);
5692c1f46dcSZachary Turner   uint32_t count = GetSize();
570b9c1b51eSKate Stone   for (uint32_t i = 0; i < count; ++i) {
5712c1f46dcSZachary Turner     PythonObject obj = GetItemAtIndex(i);
5722c1f46dcSZachary Turner     result->AddItem(obj.CreateStructuredObject());
5732c1f46dcSZachary Turner   }
5742c1f46dcSZachary Turner   return result;
5752c1f46dcSZachary Turner }
5762c1f46dcSZachary Turner 
577a1405147SZachary Turner // PythonTuple
578a1405147SZachary Turner 
579d3bd5b3dSLawrence D'Anna PythonTuple::PythonTuple(PyInitialValue value) {
580a1405147SZachary Turner   if (value == PyInitialValue::Empty)
581722b6189SLawrence D'Anna     *this = Take<PythonTuple>(PyTuple_New(0));
582a1405147SZachary Turner }
583a1405147SZachary Turner 
584d3bd5b3dSLawrence D'Anna PythonTuple::PythonTuple(int tuple_size) {
585722b6189SLawrence D'Anna   *this = Take<PythonTuple>(PyTuple_New(tuple_size));
586a1405147SZachary Turner }
587a1405147SZachary Turner 
588b9c1b51eSKate Stone PythonTuple::PythonTuple(std::initializer_list<PythonObject> objects) {
589a1405147SZachary Turner   m_py_obj = PyTuple_New(objects.size());
590a1405147SZachary Turner 
591a1405147SZachary Turner   uint32_t idx = 0;
592b9c1b51eSKate Stone   for (auto object : objects) {
593a1405147SZachary Turner     if (object.IsValid())
594a1405147SZachary Turner       SetItemAtIndex(idx, object);
595a1405147SZachary Turner     idx++;
596a1405147SZachary Turner   }
597a1405147SZachary Turner }
598a1405147SZachary Turner 
599b9c1b51eSKate Stone PythonTuple::PythonTuple(std::initializer_list<PyObject *> objects) {
600a1405147SZachary Turner   m_py_obj = PyTuple_New(objects.size());
601a1405147SZachary Turner 
602a1405147SZachary Turner   uint32_t idx = 0;
603b9c1b51eSKate Stone   for (auto py_object : objects) {
604a1405147SZachary Turner     PythonObject object(PyRefType::Borrowed, py_object);
605a1405147SZachary Turner     if (object.IsValid())
606a1405147SZachary Turner       SetItemAtIndex(idx, object);
607a1405147SZachary Turner     idx++;
608a1405147SZachary Turner   }
609a1405147SZachary Turner }
610a1405147SZachary Turner 
611b9c1b51eSKate Stone bool PythonTuple::Check(PyObject *py_obj) {
612a1405147SZachary Turner   if (!py_obj)
613a1405147SZachary Turner     return false;
614a1405147SZachary Turner   return PyTuple_Check(py_obj);
615a1405147SZachary Turner }
616a1405147SZachary Turner 
617b9c1b51eSKate Stone uint32_t PythonTuple::GetSize() const {
618a1405147SZachary Turner   if (IsValid())
619a1405147SZachary Turner     return PyTuple_GET_SIZE(m_py_obj);
620a1405147SZachary Turner   return 0;
621a1405147SZachary Turner }
622a1405147SZachary Turner 
623b9c1b51eSKate Stone PythonObject PythonTuple::GetItemAtIndex(uint32_t index) const {
624a1405147SZachary Turner   if (IsValid())
625a1405147SZachary Turner     return PythonObject(PyRefType::Borrowed, PyTuple_GetItem(m_py_obj, index));
626a1405147SZachary Turner   return PythonObject();
627a1405147SZachary Turner }
628a1405147SZachary Turner 
629b9c1b51eSKate Stone void PythonTuple::SetItemAtIndex(uint32_t index, const PythonObject &object) {
630b9c1b51eSKate Stone   if (IsAllocated() && object.IsValid()) {
631a1405147SZachary Turner     // PyTuple_SetItem is documented to "steal" a reference, so we need to
632a1405147SZachary Turner     // convert it to an owned reference by incrementing it.
633a1405147SZachary Turner     Py_INCREF(object.get());
634a1405147SZachary Turner     PyTuple_SetItem(m_py_obj, index, object.get());
635a1405147SZachary Turner   }
636a1405147SZachary Turner }
637a1405147SZachary Turner 
638b9c1b51eSKate Stone StructuredData::ArraySP PythonTuple::CreateStructuredArray() const {
639a1405147SZachary Turner   StructuredData::ArraySP result(new StructuredData::Array);
640a1405147SZachary Turner   uint32_t count = GetSize();
641b9c1b51eSKate Stone   for (uint32_t i = 0; i < count; ++i) {
642a1405147SZachary Turner     PythonObject obj = GetItemAtIndex(i);
643a1405147SZachary Turner     result->AddItem(obj.CreateStructuredObject());
644a1405147SZachary Turner   }
645a1405147SZachary Turner   return result;
646a1405147SZachary Turner }
647a1405147SZachary Turner 
6482c1f46dcSZachary Turner // PythonDictionary
6492c1f46dcSZachary Turner 
650d3bd5b3dSLawrence D'Anna PythonDictionary::PythonDictionary(PyInitialValue value) {
651f8b22f8fSZachary Turner   if (value == PyInitialValue::Empty)
652722b6189SLawrence D'Anna     *this = Take<PythonDictionary>(PyDict_New());
6532c1f46dcSZachary Turner }
6542c1f46dcSZachary Turner 
655b9c1b51eSKate Stone bool PythonDictionary::Check(PyObject *py_obj) {
65622c8efcdSZachary Turner   if (!py_obj)
65722c8efcdSZachary Turner     return false;
65822c8efcdSZachary Turner 
65922c8efcdSZachary Turner   return PyDict_Check(py_obj);
66022c8efcdSZachary Turner }
66122c8efcdSZachary Turner 
662b9c1b51eSKate Stone uint32_t PythonDictionary::GetSize() const {
663f8b22f8fSZachary Turner   if (IsValid())
6642c1f46dcSZachary Turner     return PyDict_Size(m_py_obj);
6652c1f46dcSZachary Turner   return 0;
6662c1f46dcSZachary Turner }
6672c1f46dcSZachary Turner 
668b9c1b51eSKate Stone PythonList PythonDictionary::GetKeys() const {
669f8b22f8fSZachary Turner   if (IsValid())
670f8b22f8fSZachary Turner     return PythonList(PyRefType::Owned, PyDict_Keys(m_py_obj));
671f8b22f8fSZachary Turner   return PythonList(PyInitialValue::Invalid);
6722c1f46dcSZachary Turner }
6732c1f46dcSZachary Turner 
674b9c1b51eSKate Stone PythonObject PythonDictionary::GetItemForKey(const PythonObject &key) const {
675c86a6acaSLawrence D'Anna   auto item = GetItem(key);
676c86a6acaSLawrence D'Anna   if (!item) {
677c86a6acaSLawrence D'Anna     llvm::consumeError(item.takeError());
6782c1f46dcSZachary Turner     return PythonObject();
6792c1f46dcSZachary Turner   }
680c86a6acaSLawrence D'Anna   return std::move(item.get());
681c86a6acaSLawrence D'Anna }
682c86a6acaSLawrence D'Anna 
683c86a6acaSLawrence D'Anna Expected<PythonObject>
684c86a6acaSLawrence D'Anna PythonDictionary::GetItem(const PythonObject &key) const {
685c86a6acaSLawrence D'Anna   if (!IsValid())
686c86a6acaSLawrence D'Anna     return nullDeref();
687c86a6acaSLawrence D'Anna #if PY_MAJOR_VERSION >= 3
688c86a6acaSLawrence D'Anna   PyObject *o = PyDict_GetItemWithError(m_py_obj, key.get());
689c86a6acaSLawrence D'Anna   if (PyErr_Occurred())
690c86a6acaSLawrence D'Anna     return exception();
691c86a6acaSLawrence D'Anna #else
692c86a6acaSLawrence D'Anna   PyObject *o = PyDict_GetItem(m_py_obj, key.get());
693c86a6acaSLawrence D'Anna #endif
694c86a6acaSLawrence D'Anna   if (!o)
695c86a6acaSLawrence D'Anna     return keyError();
696c86a6acaSLawrence D'Anna   return Retain<PythonObject>(o);
697c86a6acaSLawrence D'Anna }
698c86a6acaSLawrence D'Anna 
699722b6189SLawrence D'Anna Expected<PythonObject> PythonDictionary::GetItem(const Twine &key) const {
700c86a6acaSLawrence D'Anna   if (!IsValid())
701c86a6acaSLawrence D'Anna     return nullDeref();
702722b6189SLawrence D'Anna   PyObject *o = PyDict_GetItemString(m_py_obj, NullTerminated(key));
703c86a6acaSLawrence D'Anna   if (PyErr_Occurred())
704c86a6acaSLawrence D'Anna     return exception();
705c86a6acaSLawrence D'Anna   if (!o)
706c86a6acaSLawrence D'Anna     return keyError();
707c86a6acaSLawrence D'Anna   return Retain<PythonObject>(o);
708c86a6acaSLawrence D'Anna }
709c86a6acaSLawrence D'Anna 
710c86a6acaSLawrence D'Anna Error PythonDictionary::SetItem(const PythonObject &key,
711c86a6acaSLawrence D'Anna                                 const PythonObject &value) const {
712c86a6acaSLawrence D'Anna   if (!IsValid() || !value.IsValid())
713c86a6acaSLawrence D'Anna     return nullDeref();
714c86a6acaSLawrence D'Anna   int r = PyDict_SetItem(m_py_obj, key.get(), value.get());
715c86a6acaSLawrence D'Anna   if (r < 0)
716c86a6acaSLawrence D'Anna     return exception();
717c86a6acaSLawrence D'Anna   return Error::success();
718c86a6acaSLawrence D'Anna }
719c86a6acaSLawrence D'Anna 
720722b6189SLawrence D'Anna Error PythonDictionary::SetItem(const Twine &key,
721c86a6acaSLawrence D'Anna                                 const PythonObject &value) const {
722c86a6acaSLawrence D'Anna   if (!IsValid() || !value.IsValid())
723c86a6acaSLawrence D'Anna     return nullDeref();
724722b6189SLawrence D'Anna   int r = PyDict_SetItemString(m_py_obj, NullTerminated(key), value.get());
725c86a6acaSLawrence D'Anna   if (r < 0)
726c86a6acaSLawrence D'Anna     return exception();
727c86a6acaSLawrence D'Anna   return Error::success();
728c86a6acaSLawrence D'Anna }
7292c1f46dcSZachary Turner 
730b9c1b51eSKate Stone void PythonDictionary::SetItemForKey(const PythonObject &key,
731b9c1b51eSKate Stone                                      const PythonObject &value) {
732c86a6acaSLawrence D'Anna   Error error = SetItem(key, value);
733c86a6acaSLawrence D'Anna   if (error)
734c86a6acaSLawrence D'Anna     llvm::consumeError(std::move(error));
7352c1f46dcSZachary Turner }
7362c1f46dcSZachary Turner 
7372c1f46dcSZachary Turner StructuredData::DictionarySP
738b9c1b51eSKate Stone PythonDictionary::CreateStructuredDictionary() const {
7392c1f46dcSZachary Turner   StructuredData::DictionarySP result(new StructuredData::Dictionary);
7402c1f46dcSZachary Turner   PythonList keys(GetKeys());
7412c1f46dcSZachary Turner   uint32_t num_keys = keys.GetSize();
742b9c1b51eSKate Stone   for (uint32_t i = 0; i < num_keys; ++i) {
7432c1f46dcSZachary Turner     PythonObject key = keys.GetItemAtIndex(i);
7442c1f46dcSZachary Turner     PythonObject value = GetItemForKey(key);
7452c1f46dcSZachary Turner     StructuredData::ObjectSP structured_value = value.CreateStructuredObject();
746f8b22f8fSZachary Turner     result->AddItem(key.Str().GetString(), structured_value);
7472c1f46dcSZachary Turner   }
7482c1f46dcSZachary Turner   return result;
7492c1f46dcSZachary Turner }
7502c1f46dcSZachary Turner 
751b9c1b51eSKate Stone PythonModule PythonModule::BuiltinsModule() {
752a1405147SZachary Turner #if PY_MAJOR_VERSION >= 3
753a1405147SZachary Turner   return AddModule("builtins");
754a1405147SZachary Turner #else
755a1405147SZachary Turner   return AddModule("__builtin__");
756a1405147SZachary Turner #endif
757a1405147SZachary Turner }
758a1405147SZachary Turner 
759b9c1b51eSKate Stone PythonModule PythonModule::MainModule() { return AddModule("__main__"); }
760a1405147SZachary Turner 
761b9c1b51eSKate Stone PythonModule PythonModule::AddModule(llvm::StringRef module) {
762a1405147SZachary Turner   std::string str = module.str();
763a1405147SZachary Turner   return PythonModule(PyRefType::Borrowed, PyImport_AddModule(str.c_str()));
7647841efbbSZachary Turner }
7657841efbbSZachary Turner 
766722b6189SLawrence D'Anna Expected<PythonModule> PythonModule::Import(const Twine &name) {
767722b6189SLawrence D'Anna   PyObject *mod = PyImport_ImportModule(NullTerminated(name));
768085328eeSLawrence D'Anna   if (!mod)
769085328eeSLawrence D'Anna     return exception();
770085328eeSLawrence D'Anna   return Take<PythonModule>(mod);
771085328eeSLawrence D'Anna }
772085328eeSLawrence D'Anna 
773722b6189SLawrence D'Anna Expected<PythonObject> PythonModule::Get(const Twine &name) {
774085328eeSLawrence D'Anna   if (!IsValid())
775085328eeSLawrence D'Anna     return nullDeref();
776085328eeSLawrence D'Anna   PyObject *dict = PyModule_GetDict(m_py_obj);
777085328eeSLawrence D'Anna   if (!dict)
778085328eeSLawrence D'Anna     return exception();
779722b6189SLawrence D'Anna   PyObject *item = PyDict_GetItemString(dict, NullTerminated(name));
780085328eeSLawrence D'Anna   if (!item)
781085328eeSLawrence D'Anna     return exception();
782085328eeSLawrence D'Anna   return Retain<PythonObject>(item);
7832419f1d5SZachary Turner }
7842419f1d5SZachary Turner 
785b9c1b51eSKate Stone bool PythonModule::Check(PyObject *py_obj) {
7867841efbbSZachary Turner   if (!py_obj)
7877841efbbSZachary Turner     return false;
7887841efbbSZachary Turner 
7897841efbbSZachary Turner   return PyModule_Check(py_obj);
7907841efbbSZachary Turner }
7917841efbbSZachary Turner 
792b9c1b51eSKate Stone PythonDictionary PythonModule::GetDictionary() const {
793722b6189SLawrence D'Anna   if (!IsValid())
794722b6189SLawrence D'Anna     return PythonDictionary();
795722b6189SLawrence D'Anna   return Retain<PythonDictionary>(PyModule_GetDict(m_py_obj));
7967841efbbSZachary Turner }
7977841efbbSZachary Turner 
798b9c1b51eSKate Stone bool PythonCallable::Check(PyObject *py_obj) {
799a1405147SZachary Turner   if (!py_obj)
800a1405147SZachary Turner     return false;
801a1405147SZachary Turner 
802a1405147SZachary Turner   return PyCallable_Check(py_obj);
803a1405147SZachary Turner }
804a1405147SZachary Turner 
80527a14f19SJim Ingham PythonCallable::ArgInfo PythonCallable::GetNumInitArguments() const {
806c86a6acaSLawrence D'Anna   auto arginfo = GetInitArgInfo();
807c86a6acaSLawrence D'Anna   if (!arginfo) {
808c86a6acaSLawrence D'Anna     llvm::consumeError(arginfo.takeError());
809c86a6acaSLawrence D'Anna     return ArgInfo{};
81027a14f19SJim Ingham   }
811c86a6acaSLawrence D'Anna   return arginfo.get();
81227a14f19SJim Ingham }
81327a14f19SJim Ingham 
814c86a6acaSLawrence D'Anna Expected<PythonCallable::ArgInfo> PythonCallable::GetInitArgInfo() const {
815a1405147SZachary Turner   if (!IsValid())
816c86a6acaSLawrence D'Anna     return nullDeref();
817c86a6acaSLawrence D'Anna   auto init = As<PythonCallable>(GetAttribute("__init__"));
818c86a6acaSLawrence D'Anna   if (!init)
819c86a6acaSLawrence D'Anna     return init.takeError();
820c86a6acaSLawrence D'Anna   return init.get().GetArgInfo();
821c86a6acaSLawrence D'Anna }
822c86a6acaSLawrence D'Anna 
823c86a6acaSLawrence D'Anna #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3
824c86a6acaSLawrence D'Anna static const char get_arg_info_script[] = R"(
825c86a6acaSLawrence D'Anna from inspect import signature, Parameter, ismethod
826c86a6acaSLawrence D'Anna from collections import namedtuple
827c86a6acaSLawrence D'Anna ArgInfo = namedtuple('ArgInfo', ['count', 'has_varargs', 'is_bound_method'])
82804edd189SLawrence D'Anna def main(f):
829c86a6acaSLawrence D'Anna     count = 0
830c86a6acaSLawrence D'Anna     varargs = False
831c86a6acaSLawrence D'Anna     for parameter in signature(f).parameters.values():
832c86a6acaSLawrence D'Anna         kind = parameter.kind
833c86a6acaSLawrence D'Anna         if kind in (Parameter.POSITIONAL_ONLY,
834c86a6acaSLawrence D'Anna                     Parameter.POSITIONAL_OR_KEYWORD):
835c86a6acaSLawrence D'Anna             count += 1
836c86a6acaSLawrence D'Anna         elif kind == Parameter.VAR_POSITIONAL:
837c86a6acaSLawrence D'Anna             varargs = True
838c86a6acaSLawrence D'Anna         elif kind in (Parameter.KEYWORD_ONLY,
839c86a6acaSLawrence D'Anna                       Parameter.VAR_KEYWORD):
840c86a6acaSLawrence D'Anna             pass
841c86a6acaSLawrence D'Anna         else:
842c86a6acaSLawrence D'Anna             raise Exception(f'unknown parameter kind: {kind}')
843c86a6acaSLawrence D'Anna     return ArgInfo(count, varargs, ismethod(f))
844c86a6acaSLawrence D'Anna )";
845c86a6acaSLawrence D'Anna #endif
846c86a6acaSLawrence D'Anna 
847c86a6acaSLawrence D'Anna Expected<PythonCallable::ArgInfo> PythonCallable::GetArgInfo() const {
848c86a6acaSLawrence D'Anna   ArgInfo result = {};
849c86a6acaSLawrence D'Anna   if (!IsValid())
850c86a6acaSLawrence D'Anna     return nullDeref();
851c86a6acaSLawrence D'Anna 
852c86a6acaSLawrence D'Anna #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3
853c86a6acaSLawrence D'Anna 
85404edd189SLawrence D'Anna   // no need to synchronize access to this global, we already have the GIL
85504edd189SLawrence D'Anna   static PythonScript get_arg_info(get_arg_info_script);
85604edd189SLawrence D'Anna   Expected<PythonObject> pyarginfo = get_arg_info(*this);
857c86a6acaSLawrence D'Anna   if (!pyarginfo)
858c86a6acaSLawrence D'Anna     return pyarginfo.takeError();
859c86a6acaSLawrence D'Anna   result.count = cantFail(As<long long>(pyarginfo.get().GetAttribute("count")));
860c86a6acaSLawrence D'Anna   result.has_varargs =
861c86a6acaSLawrence D'Anna       cantFail(As<bool>(pyarginfo.get().GetAttribute("has_varargs")));
8622386537cSLawrence D'Anna   bool is_method =
863c86a6acaSLawrence D'Anna       cantFail(As<bool>(pyarginfo.get().GetAttribute("is_bound_method")));
8642386537cSLawrence D'Anna   result.max_positional_args =
8652386537cSLawrence D'Anna       result.has_varargs ? ArgInfo::UNBOUNDED : result.count;
866c86a6acaSLawrence D'Anna 
867c86a6acaSLawrence D'Anna   // FIXME emulate old broken behavior
8682386537cSLawrence D'Anna   if (is_method)
869c86a6acaSLawrence D'Anna     result.count++;
870c86a6acaSLawrence D'Anna 
871c86a6acaSLawrence D'Anna #else
8722386537cSLawrence D'Anna   bool is_bound_method = false;
873a1405147SZachary Turner   PyObject *py_func_obj = m_py_obj;
874b9c1b51eSKate Stone   if (PyMethod_Check(py_func_obj)) {
875a1405147SZachary Turner     py_func_obj = PyMethod_GET_FUNCTION(py_func_obj);
876a5d6765cSEnrico Granata     PythonObject im_self = GetAttributeValue("im_self");
877a5d6765cSEnrico Granata     if (im_self.IsValid() && !im_self.IsNone())
8782386537cSLawrence D'Anna       is_bound_method = true;
879b9c1b51eSKate Stone   } else {
880a5d6765cSEnrico Granata     // see if this is a callable object with an __call__ method
881b9c1b51eSKate Stone     if (!PyFunction_Check(py_func_obj)) {
882a5d6765cSEnrico Granata       PythonObject __call__ = GetAttributeValue("__call__");
883b9c1b51eSKate Stone       if (__call__.IsValid()) {
884a5d6765cSEnrico Granata         auto __callable__ = __call__.AsType<PythonCallable>();
885b9c1b51eSKate Stone         if (__callable__.IsValid()) {
886a5d6765cSEnrico Granata           py_func_obj = PyMethod_GET_FUNCTION(__callable__.get());
8872386537cSLawrence D'Anna           PythonObject im_self = __callable__.GetAttributeValue("im_self");
888a5d6765cSEnrico Granata           if (im_self.IsValid() && !im_self.IsNone())
8892386537cSLawrence D'Anna             is_bound_method = true;
890a5d6765cSEnrico Granata         }
891a5d6765cSEnrico Granata       }
892a5d6765cSEnrico Granata     }
893a5d6765cSEnrico Granata   }
894a1405147SZachary Turner 
895a1405147SZachary Turner   if (!py_func_obj)
896b58fb2f4SZachary Turner     return result;
897a1405147SZachary Turner 
898a1405147SZachary Turner   PyCodeObject *code = (PyCodeObject *)PyFunction_GET_CODE(py_func_obj);
899a1405147SZachary Turner   if (!code)
900b58fb2f4SZachary Turner     return result;
901a1405147SZachary Turner 
902b58fb2f4SZachary Turner   result.count = code->co_argcount;
903b58fb2f4SZachary Turner   result.has_varargs = !!(code->co_flags & CO_VARARGS);
9042386537cSLawrence D'Anna   result.max_positional_args = result.has_varargs
9052386537cSLawrence D'Anna                                    ? ArgInfo::UNBOUNDED
9062386537cSLawrence D'Anna                                    : (result.count - (int)is_bound_method);
907c86a6acaSLawrence D'Anna 
908c86a6acaSLawrence D'Anna #endif
909c86a6acaSLawrence D'Anna 
910b58fb2f4SZachary Turner   return result;
911b58fb2f4SZachary Turner }
912b58fb2f4SZachary Turner 
9132386537cSLawrence D'Anna constexpr unsigned
9142386537cSLawrence D'Anna     PythonCallable::ArgInfo::UNBOUNDED; // FIXME delete after c++17
9152386537cSLawrence D'Anna 
916c86a6acaSLawrence D'Anna PythonCallable::ArgInfo PythonCallable::GetNumArguments() const {
917c86a6acaSLawrence D'Anna   auto arginfo = GetArgInfo();
918c86a6acaSLawrence D'Anna   if (!arginfo) {
919c86a6acaSLawrence D'Anna     llvm::consumeError(arginfo.takeError());
920c86a6acaSLawrence D'Anna     return ArgInfo{};
921c86a6acaSLawrence D'Anna   }
922c86a6acaSLawrence D'Anna   return arginfo.get();
923c86a6acaSLawrence D'Anna }
924c86a6acaSLawrence D'Anna 
925b9c1b51eSKate Stone PythonObject PythonCallable::operator()() {
926b9c1b51eSKate Stone   return PythonObject(PyRefType::Owned, PyObject_CallObject(m_py_obj, nullptr));
927a1405147SZachary Turner }
928a1405147SZachary Turner 
929b9c1b51eSKate Stone PythonObject PythonCallable::
930b9c1b51eSKate Stone operator()(std::initializer_list<PyObject *> args) {
931a1405147SZachary Turner   PythonTuple arg_tuple(args);
932a1405147SZachary Turner   return PythonObject(PyRefType::Owned,
933a1405147SZachary Turner                       PyObject_CallObject(m_py_obj, arg_tuple.get()));
934a1405147SZachary Turner }
935a1405147SZachary Turner 
936b9c1b51eSKate Stone PythonObject PythonCallable::
937b9c1b51eSKate Stone operator()(std::initializer_list<PythonObject> args) {
938a1405147SZachary Turner   PythonTuple arg_tuple(args);
939a1405147SZachary Turner   return PythonObject(PyRefType::Owned,
940a1405147SZachary Turner                       PyObject_CallObject(m_py_obj, arg_tuple.get()));
941a1405147SZachary Turner }
942a1405147SZachary Turner 
943b9c1b51eSKate Stone bool PythonFile::Check(PyObject *py_obj) {
94496898eb6SLawrence D'Anna   if (!py_obj)
94596898eb6SLawrence D'Anna     return false;
9469c40264fSZachary Turner #if PY_MAJOR_VERSION < 3
94723502721SJason Molenda   return PyFile_Check(py_obj);
94823502721SJason Molenda #else
9499c40264fSZachary Turner   // In Python 3, there is no `PyFile_Check`, and in fact PyFile is not even a
9509c40264fSZachary Turner   // first-class object type anymore.  `PyFile_FromFd` is just a thin wrapper
95105097246SAdrian Prantl   // over `io.open()`, which returns some object derived from `io.IOBase`. As a
95205097246SAdrian Prantl   // result, the only way to detect a file in Python 3 is to check whether it
95321b8a8aeSLawrence D'Anna   // inherits from `io.IOBase`.
95421b8a8aeSLawrence D'Anna   auto io_module = PythonModule::Import("io");
95521b8a8aeSLawrence D'Anna   if (!io_module) {
95621b8a8aeSLawrence D'Anna     llvm::consumeError(io_module.takeError());
9579c40264fSZachary Turner     return false;
95821b8a8aeSLawrence D'Anna   }
95921b8a8aeSLawrence D'Anna   auto iobase = io_module.get().Get("IOBase");
96021b8a8aeSLawrence D'Anna   if (!iobase) {
96121b8a8aeSLawrence D'Anna     llvm::consumeError(iobase.takeError());
9629c40264fSZachary Turner     return false;
96321b8a8aeSLawrence D'Anna   }
96421b8a8aeSLawrence D'Anna   int r = PyObject_IsInstance(py_obj, iobase.get().get());
96521b8a8aeSLawrence D'Anna   if (r < 0) {
96621b8a8aeSLawrence D'Anna     llvm::consumeError(exception()); // clear the exception and log it.
96721b8a8aeSLawrence D'Anna     return false;
96821b8a8aeSLawrence D'Anna   }
96921b8a8aeSLawrence D'Anna   return !!r;
97023502721SJason Molenda #endif
9719c40264fSZachary Turner }
9729c40264fSZachary Turner 
97321b8a8aeSLawrence D'Anna namespace {
97421b8a8aeSLawrence D'Anna class GIL {
97521b8a8aeSLawrence D'Anna public:
97621b8a8aeSLawrence D'Anna   GIL() {
97721b8a8aeSLawrence D'Anna     m_state = PyGILState_Ensure();
97821b8a8aeSLawrence D'Anna     assert(!PyErr_Occurred());
97921b8a8aeSLawrence D'Anna   }
98021b8a8aeSLawrence D'Anna   ~GIL() { PyGILState_Release(m_state); }
98121b8a8aeSLawrence D'Anna 
98221b8a8aeSLawrence D'Anna protected:
98321b8a8aeSLawrence D'Anna   PyGILState_STATE m_state;
98421b8a8aeSLawrence D'Anna };
98521b8a8aeSLawrence D'Anna } // namespace
98621b8a8aeSLawrence D'Anna 
987085328eeSLawrence D'Anna const char *PythonException::toCString() const {
988085328eeSLawrence D'Anna   if (!m_repr_bytes)
989085328eeSLawrence D'Anna     return "unknown exception";
990085328eeSLawrence D'Anna   return PyBytes_AS_STRING(m_repr_bytes);
991085328eeSLawrence D'Anna }
992085328eeSLawrence D'Anna 
993085328eeSLawrence D'Anna PythonException::PythonException(const char *caller) {
994085328eeSLawrence D'Anna   assert(PyErr_Occurred());
995085328eeSLawrence D'Anna   m_exception_type = m_exception = m_traceback = m_repr_bytes = NULL;
996085328eeSLawrence D'Anna   PyErr_Fetch(&m_exception_type, &m_exception, &m_traceback);
997085328eeSLawrence D'Anna   PyErr_NormalizeException(&m_exception_type, &m_exception, &m_traceback);
998085328eeSLawrence D'Anna   PyErr_Clear();
999085328eeSLawrence D'Anna   if (m_exception) {
1000085328eeSLawrence D'Anna     PyObject *repr = PyObject_Repr(m_exception);
1001085328eeSLawrence D'Anna     if (repr) {
1002085328eeSLawrence D'Anna       m_repr_bytes = PyUnicode_AsEncodedString(repr, "utf-8", nullptr);
1003085328eeSLawrence D'Anna       if (!m_repr_bytes) {
1004085328eeSLawrence D'Anna         PyErr_Clear();
1005085328eeSLawrence D'Anna       }
1006085328eeSLawrence D'Anna       Py_XDECREF(repr);
1007085328eeSLawrence D'Anna     } else {
1008085328eeSLawrence D'Anna       PyErr_Clear();
1009085328eeSLawrence D'Anna     }
1010085328eeSLawrence D'Anna   }
1011085328eeSLawrence D'Anna   Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT);
1012085328eeSLawrence D'Anna   if (caller)
1013085328eeSLawrence D'Anna     LLDB_LOGF(log, "%s failed with exception: %s", caller, toCString());
1014085328eeSLawrence D'Anna   else
1015085328eeSLawrence D'Anna     LLDB_LOGF(log, "python exception: %s", toCString());
1016085328eeSLawrence D'Anna }
1017085328eeSLawrence D'Anna void PythonException::Restore() {
1018085328eeSLawrence D'Anna   if (m_exception_type && m_exception) {
1019085328eeSLawrence D'Anna     PyErr_Restore(m_exception_type, m_exception, m_traceback);
1020085328eeSLawrence D'Anna   } else {
1021085328eeSLawrence D'Anna     PyErr_SetString(PyExc_Exception, toCString());
1022085328eeSLawrence D'Anna   }
1023085328eeSLawrence D'Anna   m_exception_type = m_exception = m_traceback = NULL;
1024085328eeSLawrence D'Anna }
1025085328eeSLawrence D'Anna 
1026085328eeSLawrence D'Anna PythonException::~PythonException() {
1027085328eeSLawrence D'Anna   Py_XDECREF(m_exception_type);
1028085328eeSLawrence D'Anna   Py_XDECREF(m_exception);
1029085328eeSLawrence D'Anna   Py_XDECREF(m_traceback);
1030085328eeSLawrence D'Anna   Py_XDECREF(m_repr_bytes);
1031085328eeSLawrence D'Anna }
1032085328eeSLawrence D'Anna 
1033085328eeSLawrence D'Anna void PythonException::log(llvm::raw_ostream &OS) const { OS << toCString(); }
1034085328eeSLawrence D'Anna 
1035085328eeSLawrence D'Anna std::error_code PythonException::convertToErrorCode() const {
1036085328eeSLawrence D'Anna   return llvm::inconvertibleErrorCode();
1037085328eeSLawrence D'Anna }
1038085328eeSLawrence D'Anna 
103904edd189SLawrence D'Anna bool PythonException::Matches(PyObject *exc) const {
104004edd189SLawrence D'Anna   return PyErr_GivenExceptionMatches(m_exception_type, exc);
104104edd189SLawrence D'Anna }
104204edd189SLawrence D'Anna 
104304edd189SLawrence D'Anna const char read_exception_script[] = R"(
104404edd189SLawrence D'Anna import sys
104504edd189SLawrence D'Anna from traceback import print_exception
104604edd189SLawrence D'Anna if sys.version_info.major < 3:
104704edd189SLawrence D'Anna   from StringIO import StringIO
104804edd189SLawrence D'Anna else:
104904edd189SLawrence D'Anna   from io import StringIO
105004edd189SLawrence D'Anna def main(exc_type, exc_value, tb):
105104edd189SLawrence D'Anna   f = StringIO()
105204edd189SLawrence D'Anna   print_exception(exc_type, exc_value, tb, file=f)
105304edd189SLawrence D'Anna   return f.getvalue()
105404edd189SLawrence D'Anna )";
105504edd189SLawrence D'Anna 
105604edd189SLawrence D'Anna std::string PythonException::ReadBacktrace() const {
105704edd189SLawrence D'Anna 
105804edd189SLawrence D'Anna   if (!m_traceback)
105904edd189SLawrence D'Anna     return toCString();
106004edd189SLawrence D'Anna 
106104edd189SLawrence D'Anna   // no need to synchronize access to this global, we already have the GIL
106204edd189SLawrence D'Anna   static PythonScript read_exception(read_exception_script);
106304edd189SLawrence D'Anna 
106404edd189SLawrence D'Anna   Expected<std::string> backtrace = As<std::string>(
106504edd189SLawrence D'Anna       read_exception(m_exception_type, m_exception, m_traceback));
106604edd189SLawrence D'Anna 
106704edd189SLawrence D'Anna   if (!backtrace) {
106804edd189SLawrence D'Anna     std::string message =
106904edd189SLawrence D'Anna         std::string(toCString()) + "\n" +
107004edd189SLawrence D'Anna         "Traceback unavailble, an error occurred while reading it:\n";
107104edd189SLawrence D'Anna     return (message + llvm::toString(backtrace.takeError()));
107204edd189SLawrence D'Anna   }
107304edd189SLawrence D'Anna 
107404edd189SLawrence D'Anna   return std::move(backtrace.get());
107504edd189SLawrence D'Anna }
107604edd189SLawrence D'Anna 
1077085328eeSLawrence D'Anna char PythonException::ID = 0;
1078085328eeSLawrence D'Anna 
107962c9fe42SLawrence D'Anna llvm::Expected<File::OpenOptions>
108062c9fe42SLawrence D'Anna GetOptionsForPyObject(const PythonObject &obj) {
108121b8a8aeSLawrence D'Anna #if PY_MAJOR_VERSION >= 3
108262c9fe42SLawrence D'Anna   auto options = File::OpenOptions(0);
108321b8a8aeSLawrence D'Anna   auto readable = As<bool>(obj.CallMethod("readable"));
108421b8a8aeSLawrence D'Anna   if (!readable)
108521b8a8aeSLawrence D'Anna     return readable.takeError();
108621b8a8aeSLawrence D'Anna   auto writable = As<bool>(obj.CallMethod("writable"));
108721b8a8aeSLawrence D'Anna   if (!writable)
108821b8a8aeSLawrence D'Anna     return writable.takeError();
108921b8a8aeSLawrence D'Anna   if (readable.get())
109021b8a8aeSLawrence D'Anna     options |= File::eOpenOptionRead;
109121b8a8aeSLawrence D'Anna   if (writable.get())
109221b8a8aeSLawrence D'Anna     options |= File::eOpenOptionWrite;
109362c9fe42SLawrence D'Anna   return options;
109421b8a8aeSLawrence D'Anna #else
109521b8a8aeSLawrence D'Anna   PythonString py_mode = obj.GetAttributeValue("mode").AsType<PythonString>();
109662c9fe42SLawrence D'Anna   return File::GetOptionsFromMode(py_mode.GetString());
109721b8a8aeSLawrence D'Anna #endif
109821b8a8aeSLawrence D'Anna }
109921b8a8aeSLawrence D'Anna 
110021b8a8aeSLawrence D'Anna // Base class template for python files.   All it knows how to do
110121b8a8aeSLawrence D'Anna // is hold a reference to the python object and close or flush it
110221b8a8aeSLawrence D'Anna // when the File is closed.
110321b8a8aeSLawrence D'Anna namespace {
110421b8a8aeSLawrence D'Anna template <typename Base> class OwnedPythonFile : public Base {
110521b8a8aeSLawrence D'Anna public:
110621b8a8aeSLawrence D'Anna   template <typename... Args>
110721b8a8aeSLawrence D'Anna   OwnedPythonFile(const PythonFile &file, bool borrowed, Args... args)
110821b8a8aeSLawrence D'Anna       : Base(args...), m_py_obj(file), m_borrowed(borrowed) {
110921b8a8aeSLawrence D'Anna     assert(m_py_obj);
111021b8a8aeSLawrence D'Anna   }
111121b8a8aeSLawrence D'Anna 
111221b8a8aeSLawrence D'Anna   ~OwnedPythonFile() override {
111321b8a8aeSLawrence D'Anna     assert(m_py_obj);
111421b8a8aeSLawrence D'Anna     GIL takeGIL;
111521b8a8aeSLawrence D'Anna     Close();
1116722b6189SLawrence D'Anna     // we need to ensure the python object is released while we still
1117722b6189SLawrence D'Anna     // hold the GIL
111821b8a8aeSLawrence D'Anna     m_py_obj.Reset();
111921b8a8aeSLawrence D'Anna   }
112021b8a8aeSLawrence D'Anna 
112121b8a8aeSLawrence D'Anna   bool IsPythonSideValid() const {
112221b8a8aeSLawrence D'Anna     GIL takeGIL;
112321b8a8aeSLawrence D'Anna     auto closed = As<bool>(m_py_obj.GetAttribute("closed"));
112421b8a8aeSLawrence D'Anna     if (!closed) {
112521b8a8aeSLawrence D'Anna       llvm::consumeError(closed.takeError());
112621b8a8aeSLawrence D'Anna       return false;
112721b8a8aeSLawrence D'Anna     }
112821b8a8aeSLawrence D'Anna     return !closed.get();
112921b8a8aeSLawrence D'Anna   }
113021b8a8aeSLawrence D'Anna 
113121b8a8aeSLawrence D'Anna   bool IsValid() const override {
113221b8a8aeSLawrence D'Anna     return IsPythonSideValid() && Base::IsValid();
113321b8a8aeSLawrence D'Anna   }
113421b8a8aeSLawrence D'Anna 
113521b8a8aeSLawrence D'Anna   Status Close() override {
113621b8a8aeSLawrence D'Anna     assert(m_py_obj);
113721b8a8aeSLawrence D'Anna     Status py_error, base_error;
113821b8a8aeSLawrence D'Anna     GIL takeGIL;
113921b8a8aeSLawrence D'Anna     if (!m_borrowed) {
114021b8a8aeSLawrence D'Anna       auto r = m_py_obj.CallMethod("close");
114121b8a8aeSLawrence D'Anna       if (!r)
114221b8a8aeSLawrence D'Anna         py_error = Status(r.takeError());
114321b8a8aeSLawrence D'Anna     }
114421b8a8aeSLawrence D'Anna     base_error = Base::Close();
114521b8a8aeSLawrence D'Anna     if (py_error.Fail())
114621b8a8aeSLawrence D'Anna       return py_error;
114721b8a8aeSLawrence D'Anna     return base_error;
114821b8a8aeSLawrence D'Anna   };
114921b8a8aeSLawrence D'Anna 
1150d9b553ecSLawrence D'Anna   PyObject *GetPythonObject() const {
1151d9b553ecSLawrence D'Anna     assert(m_py_obj.IsValid());
1152d9b553ecSLawrence D'Anna     return m_py_obj.get();
1153d9b553ecSLawrence D'Anna   }
1154d9b553ecSLawrence D'Anna 
1155d9b553ecSLawrence D'Anna   static bool classof(const File *file) = delete;
1156d9b553ecSLawrence D'Anna 
115721b8a8aeSLawrence D'Anna protected:
115821b8a8aeSLawrence D'Anna   PythonFile m_py_obj;
115921b8a8aeSLawrence D'Anna   bool m_borrowed;
116021b8a8aeSLawrence D'Anna };
116121b8a8aeSLawrence D'Anna } // namespace
116221b8a8aeSLawrence D'Anna 
116321b8a8aeSLawrence D'Anna // A SimplePythonFile is a OwnedPythonFile that just does all I/O as
116421b8a8aeSLawrence D'Anna // a NativeFile
116521b8a8aeSLawrence D'Anna namespace {
116621b8a8aeSLawrence D'Anna class SimplePythonFile : public OwnedPythonFile<NativeFile> {
116721b8a8aeSLawrence D'Anna public:
116821b8a8aeSLawrence D'Anna   SimplePythonFile(const PythonFile &file, bool borrowed, int fd,
116962c9fe42SLawrence D'Anna                    File::OpenOptions options)
117021b8a8aeSLawrence D'Anna       : OwnedPythonFile(file, borrowed, fd, options, false) {}
1171d9b553ecSLawrence D'Anna 
1172d9b553ecSLawrence D'Anna   static char ID;
1173d9b553ecSLawrence D'Anna   bool isA(const void *classID) const override {
1174d9b553ecSLawrence D'Anna     return classID == &ID || NativeFile::isA(classID);
1175d9b553ecSLawrence D'Anna   }
1176d9b553ecSLawrence D'Anna   static bool classof(const File *file) { return file->isA(&ID); }
117721b8a8aeSLawrence D'Anna };
1178d9b553ecSLawrence D'Anna char SimplePythonFile::ID = 0;
117921b8a8aeSLawrence D'Anna } // namespace
118021b8a8aeSLawrence D'Anna 
118121b8a8aeSLawrence D'Anna #if PY_MAJOR_VERSION >= 3
118221b8a8aeSLawrence D'Anna 
118321b8a8aeSLawrence D'Anna namespace {
118421b8a8aeSLawrence D'Anna class PythonBuffer {
118521b8a8aeSLawrence D'Anna public:
118621b8a8aeSLawrence D'Anna   PythonBuffer &operator=(const PythonBuffer &) = delete;
118721b8a8aeSLawrence D'Anna   PythonBuffer(const PythonBuffer &) = delete;
118821b8a8aeSLawrence D'Anna 
118921b8a8aeSLawrence D'Anna   static Expected<PythonBuffer> Create(PythonObject &obj,
119021b8a8aeSLawrence D'Anna                                        int flags = PyBUF_SIMPLE) {
119121b8a8aeSLawrence D'Anna     Py_buffer py_buffer = {};
119221b8a8aeSLawrence D'Anna     PyObject_GetBuffer(obj.get(), &py_buffer, flags);
119321b8a8aeSLawrence D'Anna     if (!py_buffer.obj)
119421b8a8aeSLawrence D'Anna       return llvm::make_error<PythonException>();
119521b8a8aeSLawrence D'Anna     return PythonBuffer(py_buffer);
119621b8a8aeSLawrence D'Anna   }
119721b8a8aeSLawrence D'Anna 
119821b8a8aeSLawrence D'Anna   PythonBuffer(PythonBuffer &&other) {
119921b8a8aeSLawrence D'Anna     m_buffer = other.m_buffer;
120021b8a8aeSLawrence D'Anna     other.m_buffer.obj = nullptr;
120121b8a8aeSLawrence D'Anna   }
120221b8a8aeSLawrence D'Anna 
120321b8a8aeSLawrence D'Anna   ~PythonBuffer() {
120421b8a8aeSLawrence D'Anna     if (m_buffer.obj)
120521b8a8aeSLawrence D'Anna       PyBuffer_Release(&m_buffer);
120621b8a8aeSLawrence D'Anna   }
120721b8a8aeSLawrence D'Anna 
120821b8a8aeSLawrence D'Anna   Py_buffer &get() { return m_buffer; }
120921b8a8aeSLawrence D'Anna 
121021b8a8aeSLawrence D'Anna private:
121121b8a8aeSLawrence D'Anna   // takes ownership of the buffer.
121221b8a8aeSLawrence D'Anna   PythonBuffer(const Py_buffer &py_buffer) : m_buffer(py_buffer) {}
121321b8a8aeSLawrence D'Anna   Py_buffer m_buffer;
121421b8a8aeSLawrence D'Anna };
121521b8a8aeSLawrence D'Anna } // namespace
121621b8a8aeSLawrence D'Anna 
121721b8a8aeSLawrence D'Anna // Shared methods between TextPythonFile and BinaryPythonFile
121821b8a8aeSLawrence D'Anna namespace {
121921b8a8aeSLawrence D'Anna class PythonIOFile : public OwnedPythonFile<File> {
122021b8a8aeSLawrence D'Anna public:
122121b8a8aeSLawrence D'Anna   PythonIOFile(const PythonFile &file, bool borrowed)
122221b8a8aeSLawrence D'Anna       : OwnedPythonFile(file, borrowed) {}
122321b8a8aeSLawrence D'Anna 
122421b8a8aeSLawrence D'Anna   ~PythonIOFile() override { Close(); }
122521b8a8aeSLawrence D'Anna 
122621b8a8aeSLawrence D'Anna   bool IsValid() const override { return IsPythonSideValid(); }
122721b8a8aeSLawrence D'Anna 
122821b8a8aeSLawrence D'Anna   Status Close() override {
122921b8a8aeSLawrence D'Anna     assert(m_py_obj);
123021b8a8aeSLawrence D'Anna     GIL takeGIL;
123121b8a8aeSLawrence D'Anna     if (m_borrowed)
123221b8a8aeSLawrence D'Anna       return Flush();
123321b8a8aeSLawrence D'Anna     auto r = m_py_obj.CallMethod("close");
123421b8a8aeSLawrence D'Anna     if (!r)
123521b8a8aeSLawrence D'Anna       return Status(r.takeError());
123621b8a8aeSLawrence D'Anna     return Status();
123721b8a8aeSLawrence D'Anna   }
123821b8a8aeSLawrence D'Anna 
123921b8a8aeSLawrence D'Anna   Status Flush() override {
124021b8a8aeSLawrence D'Anna     GIL takeGIL;
124121b8a8aeSLawrence D'Anna     auto r = m_py_obj.CallMethod("flush");
124221b8a8aeSLawrence D'Anna     if (!r)
124321b8a8aeSLawrence D'Anna       return Status(r.takeError());
124421b8a8aeSLawrence D'Anna     return Status();
124521b8a8aeSLawrence D'Anna   }
124621b8a8aeSLawrence D'Anna 
1247d9b553ecSLawrence D'Anna   Expected<File::OpenOptions> GetOptions() const override {
1248d9b553ecSLawrence D'Anna     GIL takeGIL;
1249d9b553ecSLawrence D'Anna     return GetOptionsForPyObject(m_py_obj);
1250d9b553ecSLawrence D'Anna   }
1251d9b553ecSLawrence D'Anna 
1252d9b553ecSLawrence D'Anna   static char ID;
1253d9b553ecSLawrence D'Anna   bool isA(const void *classID) const override {
1254d9b553ecSLawrence D'Anna     return classID == &ID || File::isA(classID);
1255d9b553ecSLawrence D'Anna   }
1256d9b553ecSLawrence D'Anna   static bool classof(const File *file) { return file->isA(&ID); }
125721b8a8aeSLawrence D'Anna };
1258d9b553ecSLawrence D'Anna char PythonIOFile::ID = 0;
125921b8a8aeSLawrence D'Anna } // namespace
126021b8a8aeSLawrence D'Anna 
126121b8a8aeSLawrence D'Anna namespace {
126221b8a8aeSLawrence D'Anna class BinaryPythonFile : public PythonIOFile {
126321b8a8aeSLawrence D'Anna protected:
126421b8a8aeSLawrence D'Anna   int m_descriptor;
126521b8a8aeSLawrence D'Anna 
126621b8a8aeSLawrence D'Anna public:
126721b8a8aeSLawrence D'Anna   BinaryPythonFile(int fd, const PythonFile &file, bool borrowed)
126821b8a8aeSLawrence D'Anna       : PythonIOFile(file, borrowed),
126921b8a8aeSLawrence D'Anna         m_descriptor(File::DescriptorIsValid(fd) ? fd
127021b8a8aeSLawrence D'Anna                                                  : File::kInvalidDescriptor) {}
127121b8a8aeSLawrence D'Anna 
127221b8a8aeSLawrence D'Anna   int GetDescriptor() const override { return m_descriptor; }
127321b8a8aeSLawrence D'Anna 
127421b8a8aeSLawrence D'Anna   Status Write(const void *buf, size_t &num_bytes) override {
127521b8a8aeSLawrence D'Anna     GIL takeGIL;
127621b8a8aeSLawrence D'Anna     PyObject *pybuffer_p = PyMemoryView_FromMemory(
127721b8a8aeSLawrence D'Anna         const_cast<char *>((const char *)buf), num_bytes, PyBUF_READ);
127821b8a8aeSLawrence D'Anna     if (!pybuffer_p)
127921b8a8aeSLawrence D'Anna       return Status(llvm::make_error<PythonException>());
128021b8a8aeSLawrence D'Anna     auto pybuffer = Take<PythonObject>(pybuffer_p);
128121b8a8aeSLawrence D'Anna     num_bytes = 0;
128221b8a8aeSLawrence D'Anna     auto bytes_written = As<long long>(m_py_obj.CallMethod("write", pybuffer));
128321b8a8aeSLawrence D'Anna     if (!bytes_written)
128421b8a8aeSLawrence D'Anna       return Status(bytes_written.takeError());
128521b8a8aeSLawrence D'Anna     if (bytes_written.get() < 0)
128621b8a8aeSLawrence D'Anna       return Status(".write() method returned a negative number!");
128721b8a8aeSLawrence D'Anna     static_assert(sizeof(long long) >= sizeof(size_t), "overflow");
128821b8a8aeSLawrence D'Anna     num_bytes = bytes_written.get();
128921b8a8aeSLawrence D'Anna     return Status();
129021b8a8aeSLawrence D'Anna   }
129121b8a8aeSLawrence D'Anna 
129221b8a8aeSLawrence D'Anna   Status Read(void *buf, size_t &num_bytes) override {
129321b8a8aeSLawrence D'Anna     GIL takeGIL;
129421b8a8aeSLawrence D'Anna     static_assert(sizeof(long long) >= sizeof(size_t), "overflow");
129521b8a8aeSLawrence D'Anna     auto pybuffer_obj =
129621b8a8aeSLawrence D'Anna         m_py_obj.CallMethod("read", (unsigned long long)num_bytes);
129721b8a8aeSLawrence D'Anna     if (!pybuffer_obj)
129821b8a8aeSLawrence D'Anna       return Status(pybuffer_obj.takeError());
129921b8a8aeSLawrence D'Anna     num_bytes = 0;
130021b8a8aeSLawrence D'Anna     if (pybuffer_obj.get().IsNone()) {
130121b8a8aeSLawrence D'Anna       // EOF
130221b8a8aeSLawrence D'Anna       num_bytes = 0;
130321b8a8aeSLawrence D'Anna       return Status();
130421b8a8aeSLawrence D'Anna     }
130521b8a8aeSLawrence D'Anna     auto pybuffer = PythonBuffer::Create(pybuffer_obj.get());
130621b8a8aeSLawrence D'Anna     if (!pybuffer)
130721b8a8aeSLawrence D'Anna       return Status(pybuffer.takeError());
130821b8a8aeSLawrence D'Anna     memcpy(buf, pybuffer.get().get().buf, pybuffer.get().get().len);
130921b8a8aeSLawrence D'Anna     num_bytes = pybuffer.get().get().len;
131021b8a8aeSLawrence D'Anna     return Status();
131121b8a8aeSLawrence D'Anna   }
131221b8a8aeSLawrence D'Anna };
131321b8a8aeSLawrence D'Anna } // namespace
131421b8a8aeSLawrence D'Anna 
131521b8a8aeSLawrence D'Anna namespace {
131621b8a8aeSLawrence D'Anna class TextPythonFile : public PythonIOFile {
131721b8a8aeSLawrence D'Anna protected:
131821b8a8aeSLawrence D'Anna   int m_descriptor;
131921b8a8aeSLawrence D'Anna 
132021b8a8aeSLawrence D'Anna public:
132121b8a8aeSLawrence D'Anna   TextPythonFile(int fd, const PythonFile &file, bool borrowed)
132221b8a8aeSLawrence D'Anna       : PythonIOFile(file, borrowed),
132321b8a8aeSLawrence D'Anna         m_descriptor(File::DescriptorIsValid(fd) ? fd
132421b8a8aeSLawrence D'Anna                                                  : File::kInvalidDescriptor) {}
132521b8a8aeSLawrence D'Anna 
132621b8a8aeSLawrence D'Anna   int GetDescriptor() const override { return m_descriptor; }
132721b8a8aeSLawrence D'Anna 
132821b8a8aeSLawrence D'Anna   Status Write(const void *buf, size_t &num_bytes) override {
132921b8a8aeSLawrence D'Anna     GIL takeGIL;
133021b8a8aeSLawrence D'Anna     auto pystring =
133121b8a8aeSLawrence D'Anna         PythonString::FromUTF8(llvm::StringRef((const char *)buf, num_bytes));
133221b8a8aeSLawrence D'Anna     if (!pystring)
133321b8a8aeSLawrence D'Anna       return Status(pystring.takeError());
133421b8a8aeSLawrence D'Anna     num_bytes = 0;
133521b8a8aeSLawrence D'Anna     auto bytes_written =
133621b8a8aeSLawrence D'Anna         As<long long>(m_py_obj.CallMethod("write", pystring.get()));
133721b8a8aeSLawrence D'Anna     if (!bytes_written)
133821b8a8aeSLawrence D'Anna       return Status(bytes_written.takeError());
133921b8a8aeSLawrence D'Anna     if (bytes_written.get() < 0)
134021b8a8aeSLawrence D'Anna       return Status(".write() method returned a negative number!");
134121b8a8aeSLawrence D'Anna     static_assert(sizeof(long long) >= sizeof(size_t), "overflow");
134221b8a8aeSLawrence D'Anna     num_bytes = bytes_written.get();
134321b8a8aeSLawrence D'Anna     return Status();
134421b8a8aeSLawrence D'Anna   }
134521b8a8aeSLawrence D'Anna 
134621b8a8aeSLawrence D'Anna   Status Read(void *buf, size_t &num_bytes) override {
134721b8a8aeSLawrence D'Anna     GIL takeGIL;
134821b8a8aeSLawrence D'Anna     size_t num_chars = num_bytes / 6;
134921b8a8aeSLawrence D'Anna     size_t orig_num_bytes = num_bytes;
135021b8a8aeSLawrence D'Anna     num_bytes = 0;
135121b8a8aeSLawrence D'Anna     if (orig_num_bytes < 6) {
135221b8a8aeSLawrence D'Anna       return Status("can't read less than 6 bytes from a utf8 text stream");
135321b8a8aeSLawrence D'Anna     }
135421b8a8aeSLawrence D'Anna     auto pystring = As<PythonString>(
135521b8a8aeSLawrence D'Anna         m_py_obj.CallMethod("read", (unsigned long long)num_chars));
135621b8a8aeSLawrence D'Anna     if (!pystring)
135721b8a8aeSLawrence D'Anna       return Status(pystring.takeError());
135821b8a8aeSLawrence D'Anna     if (pystring.get().IsNone()) {
135921b8a8aeSLawrence D'Anna       // EOF
136021b8a8aeSLawrence D'Anna       return Status();
136121b8a8aeSLawrence D'Anna     }
136221b8a8aeSLawrence D'Anna     auto stringref = pystring.get().AsUTF8();
136321b8a8aeSLawrence D'Anna     if (!stringref)
136421b8a8aeSLawrence D'Anna       return Status(stringref.takeError());
136521b8a8aeSLawrence D'Anna     num_bytes = stringref.get().size();
136621b8a8aeSLawrence D'Anna     memcpy(buf, stringref.get().begin(), num_bytes);
136721b8a8aeSLawrence D'Anna     return Status();
136821b8a8aeSLawrence D'Anna   }
136921b8a8aeSLawrence D'Anna };
137021b8a8aeSLawrence D'Anna } // namespace
137121b8a8aeSLawrence D'Anna 
137221b8a8aeSLawrence D'Anna #endif
137321b8a8aeSLawrence D'Anna 
137421b8a8aeSLawrence D'Anna llvm::Expected<FileSP> PythonFile::ConvertToFile(bool borrowed) {
137521b8a8aeSLawrence D'Anna   if (!IsValid())
137621b8a8aeSLawrence D'Anna     return llvm::createStringError(llvm::inconvertibleErrorCode(),
137721b8a8aeSLawrence D'Anna                                    "invalid PythonFile");
137821b8a8aeSLawrence D'Anna 
137921b8a8aeSLawrence D'Anna   int fd = PyObject_AsFileDescriptor(m_py_obj);
138021b8a8aeSLawrence D'Anna   if (fd < 0) {
138121b8a8aeSLawrence D'Anna     PyErr_Clear();
138221b8a8aeSLawrence D'Anna     return ConvertToFileForcingUseOfScriptingIOMethods(borrowed);
138321b8a8aeSLawrence D'Anna   }
138421b8a8aeSLawrence D'Anna   auto options = GetOptionsForPyObject(*this);
138521b8a8aeSLawrence D'Anna   if (!options)
138621b8a8aeSLawrence D'Anna     return options.takeError();
138721b8a8aeSLawrence D'Anna 
1388*267cc329SMichal Gorny   if (options.get() & File::eOpenOptionWrite) {
138921b8a8aeSLawrence D'Anna     // LLDB and python will not share I/O buffers.  We should probably
139021b8a8aeSLawrence D'Anna     // flush the python buffers now.
139121b8a8aeSLawrence D'Anna     auto r = CallMethod("flush");
139221b8a8aeSLawrence D'Anna     if (!r)
139321b8a8aeSLawrence D'Anna       return r.takeError();
1394*267cc329SMichal Gorny   }
139521b8a8aeSLawrence D'Anna 
139621b8a8aeSLawrence D'Anna   FileSP file_sp;
139721b8a8aeSLawrence D'Anna   if (borrowed) {
139821b8a8aeSLawrence D'Anna     // In this case we we don't need to retain the python
139921b8a8aeSLawrence D'Anna     // object at all.
140021b8a8aeSLawrence D'Anna     file_sp = std::make_shared<NativeFile>(fd, options.get(), false);
140121b8a8aeSLawrence D'Anna   } else {
140221b8a8aeSLawrence D'Anna     file_sp = std::static_pointer_cast<File>(
140321b8a8aeSLawrence D'Anna         std::make_shared<SimplePythonFile>(*this, borrowed, fd, options.get()));
140421b8a8aeSLawrence D'Anna   }
140521b8a8aeSLawrence D'Anna   if (!file_sp->IsValid())
140621b8a8aeSLawrence D'Anna     return llvm::createStringError(llvm::inconvertibleErrorCode(),
140721b8a8aeSLawrence D'Anna                                    "invalid File");
140821b8a8aeSLawrence D'Anna 
140921b8a8aeSLawrence D'Anna   return file_sp;
141021b8a8aeSLawrence D'Anna }
141121b8a8aeSLawrence D'Anna 
141221b8a8aeSLawrence D'Anna llvm::Expected<FileSP>
141321b8a8aeSLawrence D'Anna PythonFile::ConvertToFileForcingUseOfScriptingIOMethods(bool borrowed) {
141421b8a8aeSLawrence D'Anna 
141521b8a8aeSLawrence D'Anna   assert(!PyErr_Occurred());
141621b8a8aeSLawrence D'Anna 
141721b8a8aeSLawrence D'Anna   if (!IsValid())
141821b8a8aeSLawrence D'Anna     return llvm::createStringError(llvm::inconvertibleErrorCode(),
141921b8a8aeSLawrence D'Anna                                    "invalid PythonFile");
142021b8a8aeSLawrence D'Anna 
142121b8a8aeSLawrence D'Anna #if PY_MAJOR_VERSION < 3
142221b8a8aeSLawrence D'Anna 
142321b8a8aeSLawrence D'Anna   return llvm::createStringError(llvm::inconvertibleErrorCode(),
142421b8a8aeSLawrence D'Anna                                  "not supported on python 2");
142521b8a8aeSLawrence D'Anna 
142621b8a8aeSLawrence D'Anna #else
142721b8a8aeSLawrence D'Anna 
142821b8a8aeSLawrence D'Anna   int fd = PyObject_AsFileDescriptor(m_py_obj);
142921b8a8aeSLawrence D'Anna   if (fd < 0) {
143021b8a8aeSLawrence D'Anna     PyErr_Clear();
143121b8a8aeSLawrence D'Anna     fd = File::kInvalidDescriptor;
143221b8a8aeSLawrence D'Anna   }
143321b8a8aeSLawrence D'Anna 
143421b8a8aeSLawrence D'Anna   auto io_module = PythonModule::Import("io");
143521b8a8aeSLawrence D'Anna   if (!io_module)
143621b8a8aeSLawrence D'Anna     return io_module.takeError();
143721b8a8aeSLawrence D'Anna   auto textIOBase = io_module.get().Get("TextIOBase");
143821b8a8aeSLawrence D'Anna   if (!textIOBase)
143921b8a8aeSLawrence D'Anna     return textIOBase.takeError();
144021b8a8aeSLawrence D'Anna   auto rawIOBase = io_module.get().Get("RawIOBase");
144121b8a8aeSLawrence D'Anna   if (!rawIOBase)
144221b8a8aeSLawrence D'Anna     return rawIOBase.takeError();
144321b8a8aeSLawrence D'Anna   auto bufferedIOBase = io_module.get().Get("BufferedIOBase");
144421b8a8aeSLawrence D'Anna   if (!bufferedIOBase)
144521b8a8aeSLawrence D'Anna     return bufferedIOBase.takeError();
144621b8a8aeSLawrence D'Anna 
144721b8a8aeSLawrence D'Anna   FileSP file_sp;
144821b8a8aeSLawrence D'Anna 
144921b8a8aeSLawrence D'Anna   auto isTextIO = IsInstance(textIOBase.get());
145021b8a8aeSLawrence D'Anna   if (!isTextIO)
145121b8a8aeSLawrence D'Anna     return isTextIO.takeError();
145221b8a8aeSLawrence D'Anna   if (isTextIO.get())
145321b8a8aeSLawrence D'Anna     file_sp = std::static_pointer_cast<File>(
145421b8a8aeSLawrence D'Anna         std::make_shared<TextPythonFile>(fd, *this, borrowed));
145521b8a8aeSLawrence D'Anna 
145621b8a8aeSLawrence D'Anna   auto isRawIO = IsInstance(rawIOBase.get());
145721b8a8aeSLawrence D'Anna   if (!isRawIO)
145821b8a8aeSLawrence D'Anna     return isRawIO.takeError();
145921b8a8aeSLawrence D'Anna   auto isBufferedIO = IsInstance(bufferedIOBase.get());
146021b8a8aeSLawrence D'Anna   if (!isBufferedIO)
146121b8a8aeSLawrence D'Anna     return isBufferedIO.takeError();
146221b8a8aeSLawrence D'Anna 
146321b8a8aeSLawrence D'Anna   if (isRawIO.get() || isBufferedIO.get()) {
146421b8a8aeSLawrence D'Anna     file_sp = std::static_pointer_cast<File>(
146521b8a8aeSLawrence D'Anna         std::make_shared<BinaryPythonFile>(fd, *this, borrowed));
146621b8a8aeSLawrence D'Anna   }
146721b8a8aeSLawrence D'Anna 
146821b8a8aeSLawrence D'Anna   if (!file_sp)
146921b8a8aeSLawrence D'Anna     return llvm::createStringError(llvm::inconvertibleErrorCode(),
147021b8a8aeSLawrence D'Anna                                    "python file is neither text nor binary");
147121b8a8aeSLawrence D'Anna 
147221b8a8aeSLawrence D'Anna   if (!file_sp->IsValid())
147321b8a8aeSLawrence D'Anna     return llvm::createStringError(llvm::inconvertibleErrorCode(),
147421b8a8aeSLawrence D'Anna                                    "invalid File");
147521b8a8aeSLawrence D'Anna 
147621b8a8aeSLawrence D'Anna   return file_sp;
147721b8a8aeSLawrence D'Anna 
147821b8a8aeSLawrence D'Anna #endif
147921b8a8aeSLawrence D'Anna }
148021b8a8aeSLawrence D'Anna 
1481d9b553ecSLawrence D'Anna Expected<PythonFile> PythonFile::FromFile(File &file, const char *mode) {
1482d9b553ecSLawrence D'Anna   if (!file.IsValid())
1483d9b553ecSLawrence D'Anna     return llvm::createStringError(llvm::inconvertibleErrorCode(),
1484d9b553ecSLawrence D'Anna                                    "invalid file");
1485d9b553ecSLawrence D'Anna 
1486d9b553ecSLawrence D'Anna   if (auto *simple = llvm::dyn_cast<SimplePythonFile>(&file))
1487d9b553ecSLawrence D'Anna     return Retain<PythonFile>(simple->GetPythonObject());
1488d9b553ecSLawrence D'Anna #if PY_MAJOR_VERSION >= 3
1489d9b553ecSLawrence D'Anna   if (auto *pythonio = llvm::dyn_cast<PythonIOFile>(&file))
1490d9b553ecSLawrence D'Anna     return Retain<PythonFile>(pythonio->GetPythonObject());
1491d9b553ecSLawrence D'Anna #endif
1492d9b553ecSLawrence D'Anna 
1493d9b553ecSLawrence D'Anna   if (!mode) {
1494d9b553ecSLawrence D'Anna     auto m = file.GetOpenMode();
1495d9b553ecSLawrence D'Anna     if (!m)
1496d9b553ecSLawrence D'Anna       return m.takeError();
1497d9b553ecSLawrence D'Anna     mode = m.get();
1498d9b553ecSLawrence D'Anna   }
1499d9b553ecSLawrence D'Anna 
1500d9b553ecSLawrence D'Anna   PyObject *file_obj;
1501d9b553ecSLawrence D'Anna #if PY_MAJOR_VERSION >= 3
1502d9b553ecSLawrence D'Anna   file_obj = PyFile_FromFd(file.GetDescriptor(), nullptr, mode, -1, nullptr,
1503d9b553ecSLawrence D'Anna                            "ignore", nullptr, 0);
1504d9b553ecSLawrence D'Anna #else
1505d9b553ecSLawrence D'Anna   // Read through the Python source, doesn't seem to modify these strings
1506d9b553ecSLawrence D'Anna   char *cmode = const_cast<char *>(mode);
1507d9b553ecSLawrence D'Anna   // We pass ::flush instead of ::fclose here so we borrow the FILE* --
1508d9b553ecSLawrence D'Anna   // the lldb_private::File still owns it.
1509d9b553ecSLawrence D'Anna   file_obj =
1510d9b553ecSLawrence D'Anna       PyFile_FromFile(file.GetStream(), const_cast<char *>(""), cmode, ::fflush);
1511d9b553ecSLawrence D'Anna #endif
1512d9b553ecSLawrence D'Anna 
1513d9b553ecSLawrence D'Anna   if (!file_obj)
1514d9b553ecSLawrence D'Anna     return exception();
1515d9b553ecSLawrence D'Anna 
1516d9b553ecSLawrence D'Anna   return Take<PythonFile>(file_obj);
1517d9b553ecSLawrence D'Anna }
1518d9b553ecSLawrence D'Anna 
151904edd189SLawrence D'Anna Error PythonScript::Init() {
152004edd189SLawrence D'Anna   if (function.IsValid())
152104edd189SLawrence D'Anna     return Error::success();
152204edd189SLawrence D'Anna 
152304edd189SLawrence D'Anna   PythonDictionary globals(PyInitialValue::Empty);
152404edd189SLawrence D'Anna   auto builtins = PythonModule::BuiltinsModule();
152504edd189SLawrence D'Anna   if (Error error = globals.SetItem("__builtins__", builtins))
152604edd189SLawrence D'Anna     return error;
152704edd189SLawrence D'Anna   PyObject *o =
152804edd189SLawrence D'Anna       PyRun_String(script, Py_file_input, globals.get(), globals.get());
152904edd189SLawrence D'Anna   if (!o)
153004edd189SLawrence D'Anna     return exception();
153104edd189SLawrence D'Anna   Take<PythonObject>(o);
153204edd189SLawrence D'Anna   auto f = As<PythonCallable>(globals.GetItem("main"));
153304edd189SLawrence D'Anna   if (!f)
153404edd189SLawrence D'Anna     return f.takeError();
153504edd189SLawrence D'Anna   function = std::move(f.get());
153604edd189SLawrence D'Anna 
153704edd189SLawrence D'Anna   return Error::success();
153804edd189SLawrence D'Anna }
153904edd189SLawrence D'Anna 
154004edd189SLawrence D'Anna llvm::Expected<PythonObject>
154104edd189SLawrence D'Anna python::runStringOneLine(const llvm::Twine &string,
154204edd189SLawrence D'Anna                          const PythonDictionary &globals,
154304edd189SLawrence D'Anna                          const PythonDictionary &locals) {
154404edd189SLawrence D'Anna   if (!globals.IsValid() || !locals.IsValid())
154504edd189SLawrence D'Anna     return nullDeref();
154604edd189SLawrence D'Anna 
154704edd189SLawrence D'Anna   PyObject *code =
154804edd189SLawrence D'Anna       Py_CompileString(NullTerminated(string), "<string>", Py_eval_input);
154904edd189SLawrence D'Anna   if (!code) {
155004edd189SLawrence D'Anna     PyErr_Clear();
155104edd189SLawrence D'Anna     code =
155204edd189SLawrence D'Anna         Py_CompileString(NullTerminated(string), "<string>", Py_single_input);
155304edd189SLawrence D'Anna   }
155404edd189SLawrence D'Anna   if (!code)
155504edd189SLawrence D'Anna     return exception();
155604edd189SLawrence D'Anna   auto code_ref = Take<PythonObject>(code);
155704edd189SLawrence D'Anna 
155804edd189SLawrence D'Anna #if PY_MAJOR_VERSION < 3
155904edd189SLawrence D'Anna   PyObject *result =
156004edd189SLawrence D'Anna       PyEval_EvalCode((PyCodeObject *)code, globals.get(), locals.get());
156104edd189SLawrence D'Anna #else
156204edd189SLawrence D'Anna   PyObject *result = PyEval_EvalCode(code, globals.get(), locals.get());
156304edd189SLawrence D'Anna #endif
156404edd189SLawrence D'Anna 
156504edd189SLawrence D'Anna   if (!result)
156604edd189SLawrence D'Anna     return exception();
156704edd189SLawrence D'Anna 
156804edd189SLawrence D'Anna   return Take<PythonObject>(result);
156904edd189SLawrence D'Anna }
157004edd189SLawrence D'Anna 
157104edd189SLawrence D'Anna llvm::Expected<PythonObject>
157204edd189SLawrence D'Anna python::runStringMultiLine(const llvm::Twine &string,
157304edd189SLawrence D'Anna                            const PythonDictionary &globals,
157404edd189SLawrence D'Anna                            const PythonDictionary &locals) {
157504edd189SLawrence D'Anna   if (!globals.IsValid() || !locals.IsValid())
157604edd189SLawrence D'Anna     return nullDeref();
157704edd189SLawrence D'Anna   PyObject *result = PyRun_String(NullTerminated(string), Py_file_input,
157804edd189SLawrence D'Anna                                   globals.get(), locals.get());
157904edd189SLawrence D'Anna   if (!result)
158004edd189SLawrence D'Anna     return exception();
158104edd189SLawrence D'Anna   return Take<PythonObject>(result);
158204edd189SLawrence D'Anna }
158304edd189SLawrence D'Anna 
1584d68983e3SPavel Labath #endif
1585