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