180814287SRaphael Isemann //===-- PythonDataObjects.cpp ---------------------------------------------===// 22c1f46dcSZachary Turner // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 62c1f46dcSZachary Turner // 72c1f46dcSZachary Turner //===----------------------------------------------------------------------===// 82c1f46dcSZachary Turner 959998b7bSJonas Devlieghere #include "lldb/Host/Config.h" 10d68983e3SPavel Labath 114e26cf2cSJonas Devlieghere #if LLDB_ENABLE_PYTHON 12d68983e3SPavel Labath 132c1f46dcSZachary Turner #include "PythonDataObjects.h" 142c1f46dcSZachary Turner #include "ScriptInterpreterPython.h" 152c1f46dcSZachary Turner 162c1f46dcSZachary Turner #include "lldb/Host/File.h" 17190fadcdSZachary Turner #include "lldb/Host/FileSystem.h" 182c1f46dcSZachary Turner #include "lldb/Interpreter/ScriptInterpreter.h" 19085328eeSLawrence D'Anna #include "lldb/Utility/Log.h" 20bf9a7730SZachary Turner #include "lldb/Utility/Stream.h" 212c1f46dcSZachary Turner 229a6c7572SJonas Devlieghere #include "llvm/ADT/StringSwitch.h" 23d9b553ecSLawrence D'Anna #include "llvm/Support/Casting.h" 24190fadcdSZachary Turner #include "llvm/Support/ConvertUTF.h" 252819136fSMichal Gorny #include "llvm/Support/Errno.h" 26190fadcdSZachary Turner 272c1f46dcSZachary Turner #include <stdio.h> 282c1f46dcSZachary Turner 292c1f46dcSZachary Turner using namespace lldb_private; 302c1f46dcSZachary Turner using namespace lldb; 31085328eeSLawrence D'Anna using namespace lldb_private::python; 32c86a6acaSLawrence D'Anna using llvm::cantFail; 33085328eeSLawrence D'Anna using llvm::Error; 34085328eeSLawrence D'Anna using llvm::Expected; 35722b6189SLawrence D'Anna using llvm::Twine; 36085328eeSLawrence D'Anna 37085328eeSLawrence D'Anna template <> Expected<bool> python::As<bool>(Expected<PythonObject> &&obj) { 38085328eeSLawrence D'Anna if (!obj) 39085328eeSLawrence D'Anna return obj.takeError(); 40085328eeSLawrence D'Anna return obj.get().IsTrue(); 41085328eeSLawrence D'Anna } 42085328eeSLawrence D'Anna 43085328eeSLawrence D'Anna template <> 44085328eeSLawrence D'Anna Expected<long long> python::As<long long>(Expected<PythonObject> &&obj) { 45085328eeSLawrence D'Anna if (!obj) 46085328eeSLawrence D'Anna return obj.takeError(); 47*52712d3fSLawrence D'Anna return obj->AsLongLong(); 48*52712d3fSLawrence D'Anna } 49*52712d3fSLawrence D'Anna 50*52712d3fSLawrence D'Anna template <> 51*52712d3fSLawrence D'Anna Expected<unsigned long long> 52*52712d3fSLawrence D'Anna python::As<unsigned long long>(Expected<PythonObject> &&obj) { 53*52712d3fSLawrence D'Anna if (!obj) 54*52712d3fSLawrence D'Anna return obj.takeError(); 55*52712d3fSLawrence D'Anna return obj->AsUnsignedLongLong(); 56085328eeSLawrence D'Anna } 572c1f46dcSZachary Turner 58c86a6acaSLawrence D'Anna template <> 59c86a6acaSLawrence D'Anna Expected<std::string> python::As<std::string>(Expected<PythonObject> &&obj) { 60c86a6acaSLawrence D'Anna if (!obj) 61c86a6acaSLawrence D'Anna return obj.takeError(); 62c86a6acaSLawrence D'Anna PyObject *str_obj = PyObject_Str(obj.get().get()); 63c86a6acaSLawrence D'Anna if (!obj) 64c86a6acaSLawrence D'Anna return llvm::make_error<PythonException>(); 65c86a6acaSLawrence D'Anna auto str = Take<PythonString>(str_obj); 66c86a6acaSLawrence D'Anna auto utf8 = str.AsUTF8(); 67c86a6acaSLawrence D'Anna if (!utf8) 68c86a6acaSLawrence D'Anna return utf8.takeError(); 6919580c37SBenjamin Kramer return std::string(utf8.get()); 70c86a6acaSLawrence D'Anna } 71c86a6acaSLawrence D'Anna 72*52712d3fSLawrence D'Anna Expected<long long> PythonObject::AsLongLong() const { 73*52712d3fSLawrence D'Anna if (!m_py_obj) 74*52712d3fSLawrence D'Anna return nullDeref(); 75*52712d3fSLawrence D'Anna #if PY_MAJOR_VERSION < 3 76*52712d3fSLawrence D'Anna if (!PyLong_Check(m_py_obj)) { 77*52712d3fSLawrence D'Anna PythonInteger i(PyRefType::Borrowed, m_py_obj); 78*52712d3fSLawrence D'Anna return i.AsLongLong(); 79*52712d3fSLawrence D'Anna } 80*52712d3fSLawrence D'Anna #endif 81*52712d3fSLawrence D'Anna assert(!PyErr_Occurred()); 82*52712d3fSLawrence D'Anna long long r = PyLong_AsLongLong(m_py_obj); 83*52712d3fSLawrence D'Anna if (PyErr_Occurred()) 84*52712d3fSLawrence D'Anna return exception(); 85*52712d3fSLawrence D'Anna return r; 86*52712d3fSLawrence D'Anna } 87*52712d3fSLawrence D'Anna 88*52712d3fSLawrence D'Anna Expected<long long> PythonObject::AsUnsignedLongLong() const { 89*52712d3fSLawrence D'Anna if (!m_py_obj) 90*52712d3fSLawrence D'Anna return nullDeref(); 91*52712d3fSLawrence D'Anna #if PY_MAJOR_VERSION < 3 92*52712d3fSLawrence D'Anna if (!PyLong_Check(m_py_obj)) { 93*52712d3fSLawrence D'Anna PythonInteger i(PyRefType::Borrowed, m_py_obj); 94*52712d3fSLawrence D'Anna return i.AsUnsignedLongLong(); 95*52712d3fSLawrence D'Anna } 96*52712d3fSLawrence D'Anna #endif 97*52712d3fSLawrence D'Anna assert(!PyErr_Occurred()); 98*52712d3fSLawrence D'Anna long long r = PyLong_AsUnsignedLongLong(m_py_obj); 99*52712d3fSLawrence D'Anna if (PyErr_Occurred()) 100*52712d3fSLawrence D'Anna return exception(); 101*52712d3fSLawrence D'Anna return r; 102*52712d3fSLawrence D'Anna } 103*52712d3fSLawrence D'Anna 104*52712d3fSLawrence D'Anna // wraps on overflow, instead of raising an error. 105*52712d3fSLawrence D'Anna Expected<unsigned long long> PythonObject::AsModuloUnsignedLongLong() const { 106*52712d3fSLawrence D'Anna if (!m_py_obj) 107*52712d3fSLawrence D'Anna return nullDeref(); 108*52712d3fSLawrence D'Anna #if PY_MAJOR_VERSION < 3 109*52712d3fSLawrence D'Anna if (!PyLong_Check(m_py_obj)) { 110*52712d3fSLawrence D'Anna PythonInteger i(PyRefType::Borrowed, m_py_obj); 111*52712d3fSLawrence D'Anna return i.AsModuloUnsignedLongLong(); 112*52712d3fSLawrence D'Anna } 113*52712d3fSLawrence D'Anna #endif 114*52712d3fSLawrence D'Anna assert(!PyErr_Occurred()); 115*52712d3fSLawrence D'Anna unsigned long long r = PyLong_AsUnsignedLongLongMask(m_py_obj); 116*52712d3fSLawrence D'Anna if (PyErr_Occurred()) 117*52712d3fSLawrence D'Anna return exception(); 118*52712d3fSLawrence D'Anna return r; 119*52712d3fSLawrence D'Anna } 120*52712d3fSLawrence D'Anna 1212783d817SJonas Devlieghere void StructuredPythonObject::Serialize(llvm::json::OStream &s) const { 1222783d817SJonas Devlieghere s.value(llvm::formatv("Python Obj: {0:X}", GetValue()).str()); 1232c1f46dcSZachary Turner } 1242c1f46dcSZachary Turner 1252c1f46dcSZachary Turner // PythonObject 1262c1f46dcSZachary Turner 127b9c1b51eSKate Stone void PythonObject::Dump(Stream &strm) const { 128b9c1b51eSKate Stone if (m_py_obj) { 1292819136fSMichal Gorny FILE *file = llvm::sys::RetryAfterSignal(nullptr, ::tmpfile); 130b9c1b51eSKate Stone if (file) { 1312c1f46dcSZachary Turner ::PyObject_Print(m_py_obj, file, 0); 1322c1f46dcSZachary Turner const long length = ftell(file); 133b9c1b51eSKate Stone if (length) { 1342c1f46dcSZachary Turner ::rewind(file); 1352c1f46dcSZachary Turner std::vector<char> file_contents(length, '\0'); 136b9c1b51eSKate Stone const size_t length_read = 137b9c1b51eSKate Stone ::fread(file_contents.data(), 1, file_contents.size(), file); 1382c1f46dcSZachary Turner if (length_read > 0) 1392c1f46dcSZachary Turner strm.Write(file_contents.data(), length_read); 1402c1f46dcSZachary Turner } 1412c1f46dcSZachary Turner ::fclose(file); 1422c1f46dcSZachary Turner } 143b9c1b51eSKate Stone } else 1442c1f46dcSZachary Turner strm.PutCString("NULL"); 1452c1f46dcSZachary Turner } 1462c1f46dcSZachary Turner 147b9c1b51eSKate Stone PyObjectType PythonObject::GetObjectType() const { 148f8b22f8fSZachary Turner if (!IsAllocated()) 1492c1f46dcSZachary Turner return PyObjectType::None; 1502c1f46dcSZachary Turner 1517841efbbSZachary Turner if (PythonModule::Check(m_py_obj)) 1527841efbbSZachary Turner return PyObjectType::Module; 15318426935SZachary Turner if (PythonList::Check(m_py_obj)) 1542c1f46dcSZachary Turner return PyObjectType::List; 155a1405147SZachary Turner if (PythonTuple::Check(m_py_obj)) 156a1405147SZachary Turner return PyObjectType::Tuple; 15718426935SZachary Turner if (PythonDictionary::Check(m_py_obj)) 1582c1f46dcSZachary Turner return PyObjectType::Dictionary; 15918426935SZachary Turner if (PythonString::Check(m_py_obj)) 16022c8efcdSZachary Turner return PyObjectType::String; 1615a72c02bSZachary Turner #if PY_MAJOR_VERSION >= 3 1625a72c02bSZachary Turner if (PythonBytes::Check(m_py_obj)) 1635a72c02bSZachary Turner return PyObjectType::Bytes; 1645a72c02bSZachary Turner #endif 165f9d6d204SZachary Turner if (PythonByteArray::Check(m_py_obj)) 166f9d6d204SZachary Turner return PyObjectType::ByteArray; 167b81d715cSTatyana Krasnukha if (PythonBoolean::Check(m_py_obj)) 168b81d715cSTatyana Krasnukha return PyObjectType::Boolean; 16918426935SZachary Turner if (PythonInteger::Check(m_py_obj)) 17022c8efcdSZachary Turner return PyObjectType::Integer; 1719c40264fSZachary Turner if (PythonFile::Check(m_py_obj)) 1729c40264fSZachary Turner return PyObjectType::File; 173a1405147SZachary Turner if (PythonCallable::Check(m_py_obj)) 174a1405147SZachary Turner return PyObjectType::Callable; 1752c1f46dcSZachary Turner return PyObjectType::Unknown; 1762c1f46dcSZachary Turner } 1772c1f46dcSZachary Turner 178b9c1b51eSKate Stone PythonString PythonObject::Repr() const { 1792c1f46dcSZachary Turner if (!m_py_obj) 1802c1f46dcSZachary Turner return PythonString(); 1812c1f46dcSZachary Turner PyObject *repr = PyObject_Repr(m_py_obj); 1822c1f46dcSZachary Turner if (!repr) 1832c1f46dcSZachary Turner return PythonString(); 184f8b22f8fSZachary Turner return PythonString(PyRefType::Owned, repr); 1852c1f46dcSZachary Turner } 1862c1f46dcSZachary Turner 187b9c1b51eSKate Stone PythonString PythonObject::Str() const { 1882c1f46dcSZachary Turner if (!m_py_obj) 1892c1f46dcSZachary Turner return PythonString(); 1902c1f46dcSZachary Turner PyObject *str = PyObject_Str(m_py_obj); 1912c1f46dcSZachary Turner if (!str) 1922c1f46dcSZachary Turner return PythonString(); 193f8b22f8fSZachary Turner return PythonString(PyRefType::Owned, str); 1942c1f46dcSZachary Turner } 1952c1f46dcSZachary Turner 1967841efbbSZachary Turner PythonObject 197b9c1b51eSKate Stone PythonObject::ResolveNameWithDictionary(llvm::StringRef name, 198b9c1b51eSKate Stone const PythonDictionary &dict) { 199c712bac7SJonas Devlieghere size_t dot_pos = name.find('.'); 200a1405147SZachary Turner llvm::StringRef piece = name.substr(0, dot_pos); 201a1405147SZachary Turner PythonObject result = dict.GetItemForKey(PythonString(piece)); 202b9c1b51eSKate Stone if (dot_pos == llvm::StringRef::npos) { 203a1405147SZachary Turner // There was no dot, we're done. 204a1405147SZachary Turner return result; 205a1405147SZachary Turner } 206a1405147SZachary Turner 207a1405147SZachary Turner // There was a dot. The remaining portion of the name should be looked up in 208a1405147SZachary Turner // the context of the object that was found in the dictionary. 209a1405147SZachary Turner return result.ResolveName(name.substr(dot_pos + 1)); 2107841efbbSZachary Turner } 2117841efbbSZachary Turner 212b9c1b51eSKate Stone PythonObject PythonObject::ResolveName(llvm::StringRef name) const { 21305097246SAdrian Prantl // Resolve the name in the context of the specified object. If, for example, 21405097246SAdrian Prantl // `this` refers to a PyModule, then this will look for `name` in this 21505097246SAdrian Prantl // module. If `this` refers to a PyType, then it will resolve `name` as an 21605097246SAdrian Prantl // attribute of that type. If `this` refers to an instance of an object, 21705097246SAdrian Prantl // then it will resolve `name` as the value of the specified field. 2187841efbbSZachary Turner // 2197841efbbSZachary Turner // This function handles dotted names so that, for example, if `m_py_obj` 22005097246SAdrian Prantl // refers to the `sys` module, and `name` == "path.append", then it will find 22105097246SAdrian Prantl // the function `sys.path.append`. 2227841efbbSZachary Turner 223c712bac7SJonas Devlieghere size_t dot_pos = name.find('.'); 224b9c1b51eSKate Stone if (dot_pos == llvm::StringRef::npos) { 22505097246SAdrian Prantl // No dots in the name, we should be able to find the value immediately as 22605097246SAdrian Prantl // an attribute of `m_py_obj`. 2277841efbbSZachary Turner return GetAttributeValue(name); 2287841efbbSZachary Turner } 2297841efbbSZachary Turner 230b9c1b51eSKate Stone // Look up the first piece of the name, and resolve the rest as a child of 231b9c1b51eSKate Stone // that. 2327841efbbSZachary Turner PythonObject parent = ResolveName(name.substr(0, dot_pos)); 2337841efbbSZachary Turner if (!parent.IsAllocated()) 2347841efbbSZachary Turner return PythonObject(); 2357841efbbSZachary Turner 2367841efbbSZachary Turner // Tail recursion.. should be optimized by the compiler 2377841efbbSZachary Turner return parent.ResolveName(name.substr(dot_pos + 1)); 2387841efbbSZachary Turner } 2397841efbbSZachary Turner 240b9c1b51eSKate Stone bool PythonObject::HasAttribute(llvm::StringRef attr) const { 2419c40264fSZachary Turner if (!IsValid()) 2429c40264fSZachary Turner return false; 2439c40264fSZachary Turner PythonString py_attr(attr); 2449c40264fSZachary Turner return !!PyObject_HasAttr(m_py_obj, py_attr.get()); 2459c40264fSZachary Turner } 2469c40264fSZachary Turner 247b9c1b51eSKate Stone PythonObject PythonObject::GetAttributeValue(llvm::StringRef attr) const { 2487d6d218eSZachary Turner if (!IsValid()) 2497d6d218eSZachary Turner return PythonObject(); 2507d6d218eSZachary Turner 2517d6d218eSZachary Turner PythonString py_attr(attr); 2527d6d218eSZachary Turner if (!PyObject_HasAttr(m_py_obj, py_attr.get())) 2537d6d218eSZachary Turner return PythonObject(); 2547d6d218eSZachary Turner 2557d6d218eSZachary Turner return PythonObject(PyRefType::Owned, 2567d6d218eSZachary Turner PyObject_GetAttr(m_py_obj, py_attr.get())); 2577d6d218eSZachary Turner } 2587d6d218eSZachary Turner 259b9c1b51eSKate Stone StructuredData::ObjectSP PythonObject::CreateStructuredObject() const { 260b9c1b51eSKate Stone switch (GetObjectType()) { 2612c1f46dcSZachary Turner case PyObjectType::Dictionary: 262b9c1b51eSKate Stone return PythonDictionary(PyRefType::Borrowed, m_py_obj) 263b9c1b51eSKate Stone .CreateStructuredDictionary(); 264b81d715cSTatyana Krasnukha case PyObjectType::Boolean: 265b81d715cSTatyana Krasnukha return PythonBoolean(PyRefType::Borrowed, m_py_obj) 266b81d715cSTatyana Krasnukha .CreateStructuredBoolean(); 2672c1f46dcSZachary Turner case PyObjectType::Integer: 268b9c1b51eSKate Stone return PythonInteger(PyRefType::Borrowed, m_py_obj) 269b9c1b51eSKate Stone .CreateStructuredInteger(); 2702c1f46dcSZachary Turner case PyObjectType::List: 271f8b22f8fSZachary Turner return PythonList(PyRefType::Borrowed, m_py_obj).CreateStructuredArray(); 2722c1f46dcSZachary Turner case PyObjectType::String: 273f8b22f8fSZachary Turner return PythonString(PyRefType::Borrowed, m_py_obj).CreateStructuredString(); 2745a72c02bSZachary Turner case PyObjectType::Bytes: 2755a72c02bSZachary Turner return PythonBytes(PyRefType::Borrowed, m_py_obj).CreateStructuredString(); 276f9d6d204SZachary Turner case PyObjectType::ByteArray: 277b9c1b51eSKate Stone return PythonByteArray(PyRefType::Borrowed, m_py_obj) 278b9c1b51eSKate Stone .CreateStructuredString(); 2792c1f46dcSZachary Turner case PyObjectType::None: 2802c1f46dcSZachary Turner return StructuredData::ObjectSP(); 2812c1f46dcSZachary Turner default: 2822c1f46dcSZachary Turner return StructuredData::ObjectSP(new StructuredPythonObject(m_py_obj)); 2832c1f46dcSZachary Turner } 2842c1f46dcSZachary Turner } 2852c1f46dcSZachary Turner 2862c1f46dcSZachary Turner // PythonString 2875a72c02bSZachary Turner 288d3bd5b3dSLawrence D'Anna PythonBytes::PythonBytes(llvm::ArrayRef<uint8_t> bytes) { SetBytes(bytes); } 2895a72c02bSZachary Turner 290d3bd5b3dSLawrence D'Anna PythonBytes::PythonBytes(const uint8_t *bytes, size_t length) { 2915a72c02bSZachary Turner SetBytes(llvm::ArrayRef<uint8_t>(bytes, length)); 2925a72c02bSZachary Turner } 2935a72c02bSZachary Turner 294b9c1b51eSKate Stone bool PythonBytes::Check(PyObject *py_obj) { 2955a72c02bSZachary Turner if (!py_obj) 2965a72c02bSZachary Turner return false; 297a6682a41SJonas Devlieghere return PyBytes_Check(py_obj); 2985a72c02bSZachary Turner } 2995a72c02bSZachary Turner 300b9c1b51eSKate Stone llvm::ArrayRef<uint8_t> PythonBytes::GetBytes() const { 3015a72c02bSZachary Turner if (!IsValid()) 3025a72c02bSZachary Turner return llvm::ArrayRef<uint8_t>(); 3035a72c02bSZachary Turner 3045a72c02bSZachary Turner Py_ssize_t size; 3055a72c02bSZachary Turner char *c; 3065a72c02bSZachary Turner 3075a72c02bSZachary Turner PyBytes_AsStringAndSize(m_py_obj, &c, &size); 3085a72c02bSZachary Turner return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size); 3095a72c02bSZachary Turner } 3105a72c02bSZachary Turner 311b9c1b51eSKate Stone size_t PythonBytes::GetSize() const { 3125a72c02bSZachary Turner if (!IsValid()) 3135a72c02bSZachary Turner return 0; 3145a72c02bSZachary Turner return PyBytes_Size(m_py_obj); 3155a72c02bSZachary Turner } 3165a72c02bSZachary Turner 317b9c1b51eSKate Stone void PythonBytes::SetBytes(llvm::ArrayRef<uint8_t> bytes) { 3185a72c02bSZachary Turner const char *data = reinterpret_cast<const char *>(bytes.data()); 31904edd189SLawrence D'Anna *this = Take<PythonBytes>(PyBytes_FromStringAndSize(data, bytes.size())); 3205a72c02bSZachary Turner } 3215a72c02bSZachary Turner 322b9c1b51eSKate Stone StructuredData::StringSP PythonBytes::CreateStructuredString() const { 3235a72c02bSZachary Turner StructuredData::StringSP result(new StructuredData::String); 3245a72c02bSZachary Turner Py_ssize_t size; 3255a72c02bSZachary Turner char *c; 3265a72c02bSZachary Turner PyBytes_AsStringAndSize(m_py_obj, &c, &size); 3275a72c02bSZachary Turner result->SetValue(std::string(c, size)); 3285a72c02bSZachary Turner return result; 3295a72c02bSZachary Turner } 3305a72c02bSZachary Turner 331b9c1b51eSKate Stone PythonByteArray::PythonByteArray(llvm::ArrayRef<uint8_t> bytes) 332b9c1b51eSKate Stone : PythonByteArray(bytes.data(), bytes.size()) {} 333f9d6d204SZachary Turner 334b9c1b51eSKate Stone PythonByteArray::PythonByteArray(const uint8_t *bytes, size_t length) { 335f9d6d204SZachary Turner const char *str = reinterpret_cast<const char *>(bytes); 336722b6189SLawrence D'Anna *this = Take<PythonByteArray>(PyByteArray_FromStringAndSize(str, length)); 337f9d6d204SZachary Turner } 338f9d6d204SZachary Turner 339b9c1b51eSKate Stone bool PythonByteArray::Check(PyObject *py_obj) { 340f9d6d204SZachary Turner if (!py_obj) 341f9d6d204SZachary Turner return false; 342a6682a41SJonas Devlieghere return PyByteArray_Check(py_obj); 343f9d6d204SZachary Turner } 344f9d6d204SZachary Turner 345b9c1b51eSKate Stone llvm::ArrayRef<uint8_t> PythonByteArray::GetBytes() const { 346f9d6d204SZachary Turner if (!IsValid()) 347f9d6d204SZachary Turner return llvm::ArrayRef<uint8_t>(); 348f9d6d204SZachary Turner 349f9d6d204SZachary Turner char *c = PyByteArray_AsString(m_py_obj); 350f9d6d204SZachary Turner size_t size = GetSize(); 351f9d6d204SZachary Turner return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size); 352f9d6d204SZachary Turner } 353f9d6d204SZachary Turner 354b9c1b51eSKate Stone size_t PythonByteArray::GetSize() const { 355f9d6d204SZachary Turner if (!IsValid()) 356f9d6d204SZachary Turner return 0; 357f9d6d204SZachary Turner 358f9d6d204SZachary Turner return PyByteArray_Size(m_py_obj); 359f9d6d204SZachary Turner } 360f9d6d204SZachary Turner 361b9c1b51eSKate Stone StructuredData::StringSP PythonByteArray::CreateStructuredString() const { 362f9d6d204SZachary Turner StructuredData::StringSP result(new StructuredData::String); 363f9d6d204SZachary Turner llvm::ArrayRef<uint8_t> bytes = GetBytes(); 364f9d6d204SZachary Turner const char *str = reinterpret_cast<const char *>(bytes.data()); 365f9d6d204SZachary Turner result->SetValue(std::string(str, bytes.size())); 366f9d6d204SZachary Turner return result; 367f9d6d204SZachary Turner } 368f9d6d204SZachary Turner 3695a72c02bSZachary Turner // PythonString 3702c1f46dcSZachary Turner 371085328eeSLawrence D'Anna Expected<PythonString> PythonString::FromUTF8(llvm::StringRef string) { 372085328eeSLawrence D'Anna #if PY_MAJOR_VERSION >= 3 373085328eeSLawrence D'Anna PyObject *str = PyUnicode_FromStringAndSize(string.data(), string.size()); 374085328eeSLawrence D'Anna #else 375085328eeSLawrence D'Anna PyObject *str = PyString_FromStringAndSize(string.data(), string.size()); 376085328eeSLawrence D'Anna #endif 377085328eeSLawrence D'Anna if (!str) 378085328eeSLawrence D'Anna return llvm::make_error<PythonException>(); 379085328eeSLawrence D'Anna return Take<PythonString>(str); 380085328eeSLawrence D'Anna } 381085328eeSLawrence D'Anna 382d3bd5b3dSLawrence D'Anna PythonString::PythonString(llvm::StringRef string) { SetString(string); } 3832c1f46dcSZachary Turner 384b9c1b51eSKate Stone bool PythonString::Check(PyObject *py_obj) { 38522c8efcdSZachary Turner if (!py_obj) 38622c8efcdSZachary Turner return false; 38718426935SZachary Turner 3887d6d218eSZachary Turner if (PyUnicode_Check(py_obj)) 3897d6d218eSZachary Turner return true; 3907d6d218eSZachary Turner #if PY_MAJOR_VERSION < 3 3917d6d218eSZachary Turner if (PyString_Check(py_obj)) 3927d6d218eSZachary Turner return true; 39322c8efcdSZachary Turner #endif 3947d6d218eSZachary Turner return false; 39522c8efcdSZachary Turner } 39622c8efcdSZachary Turner 397d3bd5b3dSLawrence D'Anna void PythonString::Convert(PyRefType &type, PyObject *&py_obj) { 3987d6d218eSZachary Turner #if PY_MAJOR_VERSION < 3 3997d6d218eSZachary Turner // In Python 2, Don't store PyUnicode objects directly, because we need 4007d6d218eSZachary Turner // access to their underlying character buffers which Python 2 doesn't 4017d6d218eSZachary Turner // provide. 402085328eeSLawrence D'Anna if (PyUnicode_Check(py_obj)) { 403d3bd5b3dSLawrence D'Anna PyObject *s = PyUnicode_AsUTF8String(py_obj); 404d3bd5b3dSLawrence D'Anna if (s == nullptr) { 405085328eeSLawrence D'Anna PyErr_Clear(); 406d3bd5b3dSLawrence D'Anna if (type == PyRefType::Owned) 407d3bd5b3dSLawrence D'Anna Py_DECREF(py_obj); 408d3bd5b3dSLawrence D'Anna return; 409d3bd5b3dSLawrence D'Anna } 410d3bd5b3dSLawrence D'Anna if (type == PyRefType::Owned) 411d3bd5b3dSLawrence D'Anna Py_DECREF(py_obj); 412d3bd5b3dSLawrence D'Anna else 413d3bd5b3dSLawrence D'Anna type = PyRefType::Owned; 414d3bd5b3dSLawrence D'Anna py_obj = s; 415085328eeSLawrence D'Anna } 4167d6d218eSZachary Turner #endif 4172c1f46dcSZachary Turner } 4182c1f46dcSZachary Turner 419b9c1b51eSKate Stone llvm::StringRef PythonString::GetString() const { 420085328eeSLawrence D'Anna auto s = AsUTF8(); 421085328eeSLawrence D'Anna if (!s) { 422085328eeSLawrence D'Anna llvm::consumeError(s.takeError()); 423085328eeSLawrence D'Anna return llvm::StringRef(""); 424085328eeSLawrence D'Anna } 425085328eeSLawrence D'Anna return s.get(); 426085328eeSLawrence D'Anna } 427085328eeSLawrence D'Anna 428085328eeSLawrence D'Anna Expected<llvm::StringRef> PythonString::AsUTF8() const { 42918426935SZachary Turner if (!IsValid()) 430085328eeSLawrence D'Anna return nullDeref(); 43118426935SZachary Turner 43222c8efcdSZachary Turner Py_ssize_t size; 4335457b426SPavel Labath const char *data; 43418426935SZachary Turner 43518426935SZachary Turner #if PY_MAJOR_VERSION >= 3 4365457b426SPavel Labath data = PyUnicode_AsUTF8AndSize(m_py_obj, &size); 43718426935SZachary Turner #else 438085328eeSLawrence D'Anna char *c = NULL; 439085328eeSLawrence D'Anna int r = PyString_AsStringAndSize(m_py_obj, &c, &size); 440085328eeSLawrence D'Anna if (r < 0) 441085328eeSLawrence D'Anna c = NULL; 4425457b426SPavel Labath data = c; 44318426935SZachary Turner #endif 444085328eeSLawrence D'Anna 445085328eeSLawrence D'Anna if (!data) 446085328eeSLawrence D'Anna return exception(); 447085328eeSLawrence D'Anna 4485457b426SPavel Labath return llvm::StringRef(data, size); 44922c8efcdSZachary Turner } 4502c1f46dcSZachary Turner 451b9c1b51eSKate Stone size_t PythonString::GetSize() const { 452b9c1b51eSKate Stone if (IsValid()) { 45318426935SZachary Turner #if PY_MAJOR_VERSION >= 3 45418426935SZachary Turner return PyUnicode_GetSize(m_py_obj); 45518426935SZachary Turner #else 45618426935SZachary Turner return PyString_Size(m_py_obj); 45718426935SZachary Turner #endif 45818426935SZachary Turner } 4592c1f46dcSZachary Turner return 0; 4602c1f46dcSZachary Turner } 4612c1f46dcSZachary Turner 462b9c1b51eSKate Stone void PythonString::SetString(llvm::StringRef string) { 463085328eeSLawrence D'Anna auto s = FromUTF8(string); 464085328eeSLawrence D'Anna if (!s) { 465085328eeSLawrence D'Anna llvm::consumeError(s.takeError()); 466085328eeSLawrence D'Anna Reset(); 467085328eeSLawrence D'Anna } else { 46803819d1cSLawrence D'Anna *this = std::move(s.get()); 469085328eeSLawrence D'Anna } 4702c1f46dcSZachary Turner } 4712c1f46dcSZachary Turner 472b9c1b51eSKate Stone StructuredData::StringSP PythonString::CreateStructuredString() const { 4732c1f46dcSZachary Turner StructuredData::StringSP result(new StructuredData::String); 4742c1f46dcSZachary Turner result->SetValue(GetString()); 4752c1f46dcSZachary Turner return result; 4762c1f46dcSZachary Turner } 4772c1f46dcSZachary Turner 4782c1f46dcSZachary Turner // PythonInteger 4792c1f46dcSZachary Turner 480d3bd5b3dSLawrence D'Anna PythonInteger::PythonInteger(int64_t value) { SetInteger(value); } 4812c1f46dcSZachary Turner 482b9c1b51eSKate Stone bool PythonInteger::Check(PyObject *py_obj) { 48322c8efcdSZachary Turner if (!py_obj) 48422c8efcdSZachary Turner return false; 48522c8efcdSZachary Turner 48622c8efcdSZachary Turner #if PY_MAJOR_VERSION >= 3 48705097246SAdrian Prantl // Python 3 does not have PyInt_Check. There is only one type of integral 48805097246SAdrian Prantl // value, long. 48922c8efcdSZachary Turner return PyLong_Check(py_obj); 49022c8efcdSZachary Turner #else 49122c8efcdSZachary Turner return PyLong_Check(py_obj) || PyInt_Check(py_obj); 49222c8efcdSZachary Turner #endif 4932c1f46dcSZachary Turner } 4942c1f46dcSZachary Turner 495d3bd5b3dSLawrence D'Anna void PythonInteger::Convert(PyRefType &type, PyObject *&py_obj) { 49622c8efcdSZachary Turner #if PY_MAJOR_VERSION < 3 49705097246SAdrian Prantl // Always store this as a PyLong, which makes interoperability between Python 49805097246SAdrian Prantl // 2.x and Python 3.x easier. This is only necessary in 2.x, since 3.x 49905097246SAdrian Prantl // doesn't even have a PyInt. 500b9c1b51eSKate Stone if (PyInt_Check(py_obj)) { 501f8b22f8fSZachary Turner // Since we converted the original object to a different type, the new 50205097246SAdrian Prantl // object is an owned object regardless of the ownership semantics 50305097246SAdrian Prantl // requested by the user. 504d3bd5b3dSLawrence D'Anna long long value = PyInt_AsLong(py_obj); 505d3bd5b3dSLawrence D'Anna PyObject *l = nullptr; 506d3bd5b3dSLawrence D'Anna if (!PyErr_Occurred()) 507d3bd5b3dSLawrence D'Anna l = PyLong_FromLongLong(value); 508d3bd5b3dSLawrence D'Anna if (l == nullptr) { 509d3bd5b3dSLawrence D'Anna PyErr_Clear(); 510d3bd5b3dSLawrence D'Anna if (type == PyRefType::Owned) 511d3bd5b3dSLawrence D'Anna Py_DECREF(py_obj); 512d3bd5b3dSLawrence D'Anna return; 513d3bd5b3dSLawrence D'Anna } 514d3bd5b3dSLawrence D'Anna if (type == PyRefType::Owned) 515d3bd5b3dSLawrence D'Anna Py_DECREF(py_obj); 516d3bd5b3dSLawrence D'Anna else 517d3bd5b3dSLawrence D'Anna type = PyRefType::Owned; 518d3bd5b3dSLawrence D'Anna py_obj = l; 51922c8efcdSZachary Turner } 52022c8efcdSZachary Turner #endif 5212c1f46dcSZachary Turner } 5222c1f46dcSZachary Turner 523b9c1b51eSKate Stone void PythonInteger::SetInteger(int64_t value) { 52404edd189SLawrence D'Anna *this = Take<PythonInteger>(PyLong_FromLongLong(value)); 5252c1f46dcSZachary Turner } 5262c1f46dcSZachary Turner 527b9c1b51eSKate Stone StructuredData::IntegerSP PythonInteger::CreateStructuredInteger() const { 5282c1f46dcSZachary Turner StructuredData::IntegerSP result(new StructuredData::Integer); 529*52712d3fSLawrence D'Anna // FIXME this is really not ideal. Errors are silently converted to 0 530*52712d3fSLawrence D'Anna // and overflows are silently wrapped. But we'd need larger changes 531*52712d3fSLawrence D'Anna // to StructuredData to fix it, so that's how it is for now. 532*52712d3fSLawrence D'Anna llvm::Expected<unsigned long long> value = AsModuloUnsignedLongLong(); 533*52712d3fSLawrence D'Anna if (!value) { 534*52712d3fSLawrence D'Anna llvm::consumeError(value.takeError()); 535*52712d3fSLawrence D'Anna result->SetValue(0); 536*52712d3fSLawrence D'Anna } else { 537*52712d3fSLawrence D'Anna result->SetValue(value.get()); 538*52712d3fSLawrence D'Anna } 5392c1f46dcSZachary Turner return result; 5402c1f46dcSZachary Turner } 5412c1f46dcSZachary Turner 542b81d715cSTatyana Krasnukha // PythonBoolean 543b81d715cSTatyana Krasnukha 544b81d715cSTatyana Krasnukha PythonBoolean::PythonBoolean(bool value) { 545b81d715cSTatyana Krasnukha SetValue(value); 546b81d715cSTatyana Krasnukha } 547b81d715cSTatyana Krasnukha 548b81d715cSTatyana Krasnukha bool PythonBoolean::Check(PyObject *py_obj) { 549b81d715cSTatyana Krasnukha return py_obj ? PyBool_Check(py_obj) : false; 550b81d715cSTatyana Krasnukha } 551b81d715cSTatyana Krasnukha 552b81d715cSTatyana Krasnukha bool PythonBoolean::GetValue() const { 553b81d715cSTatyana Krasnukha return m_py_obj ? PyObject_IsTrue(m_py_obj) : false; 554b81d715cSTatyana Krasnukha } 555b81d715cSTatyana Krasnukha 556b81d715cSTatyana Krasnukha void PythonBoolean::SetValue(bool value) { 55704edd189SLawrence D'Anna *this = Take<PythonBoolean>(PyBool_FromLong(value)); 558b81d715cSTatyana Krasnukha } 559b81d715cSTatyana Krasnukha 560b81d715cSTatyana Krasnukha StructuredData::BooleanSP PythonBoolean::CreateStructuredBoolean() const { 561b81d715cSTatyana Krasnukha StructuredData::BooleanSP result(new StructuredData::Boolean); 562b81d715cSTatyana Krasnukha result->SetValue(GetValue()); 563b81d715cSTatyana Krasnukha return result; 564b81d715cSTatyana Krasnukha } 565b81d715cSTatyana Krasnukha 5662c1f46dcSZachary Turner // PythonList 5672c1f46dcSZachary Turner 568d3bd5b3dSLawrence D'Anna PythonList::PythonList(PyInitialValue value) { 569f8b22f8fSZachary Turner if (value == PyInitialValue::Empty) 570722b6189SLawrence D'Anna *this = Take<PythonList>(PyList_New(0)); 5712c1f46dcSZachary Turner } 5722c1f46dcSZachary Turner 573d3bd5b3dSLawrence D'Anna PythonList::PythonList(int list_size) { 574722b6189SLawrence D'Anna *this = Take<PythonList>(PyList_New(list_size)); 57587f47729SZachary Turner } 57687f47729SZachary Turner 577b9c1b51eSKate Stone bool PythonList::Check(PyObject *py_obj) { 57822c8efcdSZachary Turner if (!py_obj) 57922c8efcdSZachary Turner return false; 58022c8efcdSZachary Turner return PyList_Check(py_obj); 58122c8efcdSZachary Turner } 58222c8efcdSZachary Turner 583b9c1b51eSKate Stone uint32_t PythonList::GetSize() const { 584f8b22f8fSZachary Turner if (IsValid()) 5852c1f46dcSZachary Turner return PyList_GET_SIZE(m_py_obj); 5862c1f46dcSZachary Turner return 0; 5872c1f46dcSZachary Turner } 5882c1f46dcSZachary Turner 589b9c1b51eSKate Stone PythonObject PythonList::GetItemAtIndex(uint32_t index) const { 590f8b22f8fSZachary Turner if (IsValid()) 591f8b22f8fSZachary Turner return PythonObject(PyRefType::Borrowed, PyList_GetItem(m_py_obj, index)); 5922c1f46dcSZachary Turner return PythonObject(); 5932c1f46dcSZachary Turner } 5942c1f46dcSZachary Turner 595b9c1b51eSKate Stone void PythonList::SetItemAtIndex(uint32_t index, const PythonObject &object) { 596b9c1b51eSKate Stone if (IsAllocated() && object.IsValid()) { 597f8b22f8fSZachary Turner // PyList_SetItem is documented to "steal" a reference, so we need to 598f8b22f8fSZachary Turner // convert it to an owned reference by incrementing it. 599f8b22f8fSZachary Turner Py_INCREF(object.get()); 6002c1f46dcSZachary Turner PyList_SetItem(m_py_obj, index, object.get()); 6012c1f46dcSZachary Turner } 602f8b22f8fSZachary Turner } 6032c1f46dcSZachary Turner 604b9c1b51eSKate Stone void PythonList::AppendItem(const PythonObject &object) { 605b9c1b51eSKate Stone if (IsAllocated() && object.IsValid()) { 606f8b22f8fSZachary Turner // `PyList_Append` does *not* steal a reference, so do not call `Py_INCREF` 607f8b22f8fSZachary Turner // here like we do with `PyList_SetItem`. 6082c1f46dcSZachary Turner PyList_Append(m_py_obj, object.get()); 6092c1f46dcSZachary Turner } 610f8b22f8fSZachary Turner } 6112c1f46dcSZachary Turner 612b9c1b51eSKate Stone StructuredData::ArraySP PythonList::CreateStructuredArray() const { 6132c1f46dcSZachary Turner StructuredData::ArraySP result(new StructuredData::Array); 6142c1f46dcSZachary Turner uint32_t count = GetSize(); 615b9c1b51eSKate Stone for (uint32_t i = 0; i < count; ++i) { 6162c1f46dcSZachary Turner PythonObject obj = GetItemAtIndex(i); 6172c1f46dcSZachary Turner result->AddItem(obj.CreateStructuredObject()); 6182c1f46dcSZachary Turner } 6192c1f46dcSZachary Turner return result; 6202c1f46dcSZachary Turner } 6212c1f46dcSZachary Turner 622a1405147SZachary Turner // PythonTuple 623a1405147SZachary Turner 624d3bd5b3dSLawrence D'Anna PythonTuple::PythonTuple(PyInitialValue value) { 625a1405147SZachary Turner if (value == PyInitialValue::Empty) 626722b6189SLawrence D'Anna *this = Take<PythonTuple>(PyTuple_New(0)); 627a1405147SZachary Turner } 628a1405147SZachary Turner 629d3bd5b3dSLawrence D'Anna PythonTuple::PythonTuple(int tuple_size) { 630722b6189SLawrence D'Anna *this = Take<PythonTuple>(PyTuple_New(tuple_size)); 631a1405147SZachary Turner } 632a1405147SZachary Turner 633b9c1b51eSKate Stone PythonTuple::PythonTuple(std::initializer_list<PythonObject> objects) { 634a1405147SZachary Turner m_py_obj = PyTuple_New(objects.size()); 635a1405147SZachary Turner 636a1405147SZachary Turner uint32_t idx = 0; 637b9c1b51eSKate Stone for (auto object : objects) { 638a1405147SZachary Turner if (object.IsValid()) 639a1405147SZachary Turner SetItemAtIndex(idx, object); 640a1405147SZachary Turner idx++; 641a1405147SZachary Turner } 642a1405147SZachary Turner } 643a1405147SZachary Turner 644b9c1b51eSKate Stone PythonTuple::PythonTuple(std::initializer_list<PyObject *> objects) { 645a1405147SZachary Turner m_py_obj = PyTuple_New(objects.size()); 646a1405147SZachary Turner 647a1405147SZachary Turner uint32_t idx = 0; 648b9c1b51eSKate Stone for (auto py_object : objects) { 649a1405147SZachary Turner PythonObject object(PyRefType::Borrowed, py_object); 650a1405147SZachary Turner if (object.IsValid()) 651a1405147SZachary Turner SetItemAtIndex(idx, object); 652a1405147SZachary Turner idx++; 653a1405147SZachary Turner } 654a1405147SZachary Turner } 655a1405147SZachary Turner 656b9c1b51eSKate Stone bool PythonTuple::Check(PyObject *py_obj) { 657a1405147SZachary Turner if (!py_obj) 658a1405147SZachary Turner return false; 659a1405147SZachary Turner return PyTuple_Check(py_obj); 660a1405147SZachary Turner } 661a1405147SZachary Turner 662b9c1b51eSKate Stone uint32_t PythonTuple::GetSize() const { 663a1405147SZachary Turner if (IsValid()) 664a1405147SZachary Turner return PyTuple_GET_SIZE(m_py_obj); 665a1405147SZachary Turner return 0; 666a1405147SZachary Turner } 667a1405147SZachary Turner 668b9c1b51eSKate Stone PythonObject PythonTuple::GetItemAtIndex(uint32_t index) const { 669a1405147SZachary Turner if (IsValid()) 670a1405147SZachary Turner return PythonObject(PyRefType::Borrowed, PyTuple_GetItem(m_py_obj, index)); 671a1405147SZachary Turner return PythonObject(); 672a1405147SZachary Turner } 673a1405147SZachary Turner 674b9c1b51eSKate Stone void PythonTuple::SetItemAtIndex(uint32_t index, const PythonObject &object) { 675b9c1b51eSKate Stone if (IsAllocated() && object.IsValid()) { 676a1405147SZachary Turner // PyTuple_SetItem is documented to "steal" a reference, so we need to 677a1405147SZachary Turner // convert it to an owned reference by incrementing it. 678a1405147SZachary Turner Py_INCREF(object.get()); 679a1405147SZachary Turner PyTuple_SetItem(m_py_obj, index, object.get()); 680a1405147SZachary Turner } 681a1405147SZachary Turner } 682a1405147SZachary Turner 683b9c1b51eSKate Stone StructuredData::ArraySP PythonTuple::CreateStructuredArray() const { 684a1405147SZachary Turner StructuredData::ArraySP result(new StructuredData::Array); 685a1405147SZachary Turner uint32_t count = GetSize(); 686b9c1b51eSKate Stone for (uint32_t i = 0; i < count; ++i) { 687a1405147SZachary Turner PythonObject obj = GetItemAtIndex(i); 688a1405147SZachary Turner result->AddItem(obj.CreateStructuredObject()); 689a1405147SZachary Turner } 690a1405147SZachary Turner return result; 691a1405147SZachary Turner } 692a1405147SZachary Turner 6932c1f46dcSZachary Turner // PythonDictionary 6942c1f46dcSZachary Turner 695d3bd5b3dSLawrence D'Anna PythonDictionary::PythonDictionary(PyInitialValue value) { 696f8b22f8fSZachary Turner if (value == PyInitialValue::Empty) 697722b6189SLawrence D'Anna *this = Take<PythonDictionary>(PyDict_New()); 6982c1f46dcSZachary Turner } 6992c1f46dcSZachary Turner 700b9c1b51eSKate Stone bool PythonDictionary::Check(PyObject *py_obj) { 70122c8efcdSZachary Turner if (!py_obj) 70222c8efcdSZachary Turner return false; 70322c8efcdSZachary Turner 70422c8efcdSZachary Turner return PyDict_Check(py_obj); 70522c8efcdSZachary Turner } 70622c8efcdSZachary Turner 707b9c1b51eSKate Stone uint32_t PythonDictionary::GetSize() const { 708f8b22f8fSZachary Turner if (IsValid()) 7092c1f46dcSZachary Turner return PyDict_Size(m_py_obj); 7102c1f46dcSZachary Turner return 0; 7112c1f46dcSZachary Turner } 7122c1f46dcSZachary Turner 713b9c1b51eSKate Stone PythonList PythonDictionary::GetKeys() const { 714f8b22f8fSZachary Turner if (IsValid()) 715f8b22f8fSZachary Turner return PythonList(PyRefType::Owned, PyDict_Keys(m_py_obj)); 716f8b22f8fSZachary Turner return PythonList(PyInitialValue::Invalid); 7172c1f46dcSZachary Turner } 7182c1f46dcSZachary Turner 719b9c1b51eSKate Stone PythonObject PythonDictionary::GetItemForKey(const PythonObject &key) const { 720c86a6acaSLawrence D'Anna auto item = GetItem(key); 721c86a6acaSLawrence D'Anna if (!item) { 722c86a6acaSLawrence D'Anna llvm::consumeError(item.takeError()); 7232c1f46dcSZachary Turner return PythonObject(); 7242c1f46dcSZachary Turner } 725c86a6acaSLawrence D'Anna return std::move(item.get()); 726c86a6acaSLawrence D'Anna } 727c86a6acaSLawrence D'Anna 728c86a6acaSLawrence D'Anna Expected<PythonObject> 729c86a6acaSLawrence D'Anna PythonDictionary::GetItem(const PythonObject &key) const { 730c86a6acaSLawrence D'Anna if (!IsValid()) 731c86a6acaSLawrence D'Anna return nullDeref(); 732c86a6acaSLawrence D'Anna #if PY_MAJOR_VERSION >= 3 733c86a6acaSLawrence D'Anna PyObject *o = PyDict_GetItemWithError(m_py_obj, key.get()); 734c86a6acaSLawrence D'Anna if (PyErr_Occurred()) 735c86a6acaSLawrence D'Anna return exception(); 736c86a6acaSLawrence D'Anna #else 737c86a6acaSLawrence D'Anna PyObject *o = PyDict_GetItem(m_py_obj, key.get()); 738c86a6acaSLawrence D'Anna #endif 739c86a6acaSLawrence D'Anna if (!o) 740c86a6acaSLawrence D'Anna return keyError(); 741c86a6acaSLawrence D'Anna return Retain<PythonObject>(o); 742c86a6acaSLawrence D'Anna } 743c86a6acaSLawrence D'Anna 744722b6189SLawrence D'Anna Expected<PythonObject> PythonDictionary::GetItem(const Twine &key) const { 745c86a6acaSLawrence D'Anna if (!IsValid()) 746c86a6acaSLawrence D'Anna return nullDeref(); 747722b6189SLawrence D'Anna PyObject *o = PyDict_GetItemString(m_py_obj, NullTerminated(key)); 748c86a6acaSLawrence D'Anna if (PyErr_Occurred()) 749c86a6acaSLawrence D'Anna return exception(); 750c86a6acaSLawrence D'Anna if (!o) 751c86a6acaSLawrence D'Anna return keyError(); 752c86a6acaSLawrence D'Anna return Retain<PythonObject>(o); 753c86a6acaSLawrence D'Anna } 754c86a6acaSLawrence D'Anna 755c86a6acaSLawrence D'Anna Error PythonDictionary::SetItem(const PythonObject &key, 756c86a6acaSLawrence D'Anna const PythonObject &value) const { 757c86a6acaSLawrence D'Anna if (!IsValid() || !value.IsValid()) 758c86a6acaSLawrence D'Anna return nullDeref(); 759c86a6acaSLawrence D'Anna int r = PyDict_SetItem(m_py_obj, key.get(), value.get()); 760c86a6acaSLawrence D'Anna if (r < 0) 761c86a6acaSLawrence D'Anna return exception(); 762c86a6acaSLawrence D'Anna return Error::success(); 763c86a6acaSLawrence D'Anna } 764c86a6acaSLawrence D'Anna 765722b6189SLawrence D'Anna Error PythonDictionary::SetItem(const Twine &key, 766c86a6acaSLawrence D'Anna const PythonObject &value) const { 767c86a6acaSLawrence D'Anna if (!IsValid() || !value.IsValid()) 768c86a6acaSLawrence D'Anna return nullDeref(); 769722b6189SLawrence D'Anna int r = PyDict_SetItemString(m_py_obj, NullTerminated(key), value.get()); 770c86a6acaSLawrence D'Anna if (r < 0) 771c86a6acaSLawrence D'Anna return exception(); 772c86a6acaSLawrence D'Anna return Error::success(); 773c86a6acaSLawrence D'Anna } 7742c1f46dcSZachary Turner 775b9c1b51eSKate Stone void PythonDictionary::SetItemForKey(const PythonObject &key, 776b9c1b51eSKate Stone const PythonObject &value) { 777c86a6acaSLawrence D'Anna Error error = SetItem(key, value); 778c86a6acaSLawrence D'Anna if (error) 779c86a6acaSLawrence D'Anna llvm::consumeError(std::move(error)); 7802c1f46dcSZachary Turner } 7812c1f46dcSZachary Turner 7822c1f46dcSZachary Turner StructuredData::DictionarySP 783b9c1b51eSKate Stone PythonDictionary::CreateStructuredDictionary() const { 7842c1f46dcSZachary Turner StructuredData::DictionarySP result(new StructuredData::Dictionary); 7852c1f46dcSZachary Turner PythonList keys(GetKeys()); 7862c1f46dcSZachary Turner uint32_t num_keys = keys.GetSize(); 787b9c1b51eSKate Stone for (uint32_t i = 0; i < num_keys; ++i) { 7882c1f46dcSZachary Turner PythonObject key = keys.GetItemAtIndex(i); 7892c1f46dcSZachary Turner PythonObject value = GetItemForKey(key); 7902c1f46dcSZachary Turner StructuredData::ObjectSP structured_value = value.CreateStructuredObject(); 791f8b22f8fSZachary Turner result->AddItem(key.Str().GetString(), structured_value); 7922c1f46dcSZachary Turner } 7932c1f46dcSZachary Turner return result; 7942c1f46dcSZachary Turner } 7952c1f46dcSZachary Turner 796b9c1b51eSKate Stone PythonModule PythonModule::BuiltinsModule() { 797a1405147SZachary Turner #if PY_MAJOR_VERSION >= 3 798a1405147SZachary Turner return AddModule("builtins"); 799a1405147SZachary Turner #else 800a1405147SZachary Turner return AddModule("__builtin__"); 801a1405147SZachary Turner #endif 802a1405147SZachary Turner } 803a1405147SZachary Turner 804b9c1b51eSKate Stone PythonModule PythonModule::MainModule() { return AddModule("__main__"); } 805a1405147SZachary Turner 806b9c1b51eSKate Stone PythonModule PythonModule::AddModule(llvm::StringRef module) { 807a1405147SZachary Turner std::string str = module.str(); 808a1405147SZachary Turner return PythonModule(PyRefType::Borrowed, PyImport_AddModule(str.c_str())); 8097841efbbSZachary Turner } 8107841efbbSZachary Turner 811722b6189SLawrence D'Anna Expected<PythonModule> PythonModule::Import(const Twine &name) { 812722b6189SLawrence D'Anna PyObject *mod = PyImport_ImportModule(NullTerminated(name)); 813085328eeSLawrence D'Anna if (!mod) 814085328eeSLawrence D'Anna return exception(); 815085328eeSLawrence D'Anna return Take<PythonModule>(mod); 816085328eeSLawrence D'Anna } 817085328eeSLawrence D'Anna 818722b6189SLawrence D'Anna Expected<PythonObject> PythonModule::Get(const Twine &name) { 819085328eeSLawrence D'Anna if (!IsValid()) 820085328eeSLawrence D'Anna return nullDeref(); 821085328eeSLawrence D'Anna PyObject *dict = PyModule_GetDict(m_py_obj); 822085328eeSLawrence D'Anna if (!dict) 823085328eeSLawrence D'Anna return exception(); 824722b6189SLawrence D'Anna PyObject *item = PyDict_GetItemString(dict, NullTerminated(name)); 825085328eeSLawrence D'Anna if (!item) 826085328eeSLawrence D'Anna return exception(); 827085328eeSLawrence D'Anna return Retain<PythonObject>(item); 8282419f1d5SZachary Turner } 8292419f1d5SZachary Turner 830b9c1b51eSKate Stone bool PythonModule::Check(PyObject *py_obj) { 8317841efbbSZachary Turner if (!py_obj) 8327841efbbSZachary Turner return false; 8337841efbbSZachary Turner 8347841efbbSZachary Turner return PyModule_Check(py_obj); 8357841efbbSZachary Turner } 8367841efbbSZachary Turner 837b9c1b51eSKate Stone PythonDictionary PythonModule::GetDictionary() const { 838722b6189SLawrence D'Anna if (!IsValid()) 839722b6189SLawrence D'Anna return PythonDictionary(); 840722b6189SLawrence D'Anna return Retain<PythonDictionary>(PyModule_GetDict(m_py_obj)); 8417841efbbSZachary Turner } 8427841efbbSZachary Turner 843b9c1b51eSKate Stone bool PythonCallable::Check(PyObject *py_obj) { 844a1405147SZachary Turner if (!py_obj) 845a1405147SZachary Turner return false; 846a1405147SZachary Turner 847a1405147SZachary Turner return PyCallable_Check(py_obj); 848a1405147SZachary Turner } 849a1405147SZachary Turner 850c86a6acaSLawrence D'Anna #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3 851c86a6acaSLawrence D'Anna static const char get_arg_info_script[] = R"( 852c86a6acaSLawrence D'Anna from inspect import signature, Parameter, ismethod 853c86a6acaSLawrence D'Anna from collections import namedtuple 854adbf64ccSLawrence D'Anna ArgInfo = namedtuple('ArgInfo', ['count', 'has_varargs']) 85504edd189SLawrence D'Anna def main(f): 856c86a6acaSLawrence D'Anna count = 0 857c86a6acaSLawrence D'Anna varargs = False 858c86a6acaSLawrence D'Anna for parameter in signature(f).parameters.values(): 859c86a6acaSLawrence D'Anna kind = parameter.kind 860c86a6acaSLawrence D'Anna if kind in (Parameter.POSITIONAL_ONLY, 861c86a6acaSLawrence D'Anna Parameter.POSITIONAL_OR_KEYWORD): 862c86a6acaSLawrence D'Anna count += 1 863c86a6acaSLawrence D'Anna elif kind == Parameter.VAR_POSITIONAL: 864c86a6acaSLawrence D'Anna varargs = True 865c86a6acaSLawrence D'Anna elif kind in (Parameter.KEYWORD_ONLY, 866c86a6acaSLawrence D'Anna Parameter.VAR_KEYWORD): 867c86a6acaSLawrence D'Anna pass 868c86a6acaSLawrence D'Anna else: 869c86a6acaSLawrence D'Anna raise Exception(f'unknown parameter kind: {kind}') 870adbf64ccSLawrence D'Anna return ArgInfo(count, varargs) 871c86a6acaSLawrence D'Anna )"; 872c86a6acaSLawrence D'Anna #endif 873c86a6acaSLawrence D'Anna 874c86a6acaSLawrence D'Anna Expected<PythonCallable::ArgInfo> PythonCallable::GetArgInfo() const { 875c86a6acaSLawrence D'Anna ArgInfo result = {}; 876c86a6acaSLawrence D'Anna if (!IsValid()) 877c86a6acaSLawrence D'Anna return nullDeref(); 878c86a6acaSLawrence D'Anna 879c86a6acaSLawrence D'Anna #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3 880c86a6acaSLawrence D'Anna 88104edd189SLawrence D'Anna // no need to synchronize access to this global, we already have the GIL 88204edd189SLawrence D'Anna static PythonScript get_arg_info(get_arg_info_script); 88304edd189SLawrence D'Anna Expected<PythonObject> pyarginfo = get_arg_info(*this); 884c86a6acaSLawrence D'Anna if (!pyarginfo) 885c86a6acaSLawrence D'Anna return pyarginfo.takeError(); 886adbf64ccSLawrence D'Anna long long count = 887adbf64ccSLawrence D'Anna cantFail(As<long long>(pyarginfo.get().GetAttribute("count"))); 888adbf64ccSLawrence D'Anna bool has_varargs = 889c86a6acaSLawrence D'Anna cantFail(As<bool>(pyarginfo.get().GetAttribute("has_varargs"))); 890adbf64ccSLawrence D'Anna result.max_positional_args = has_varargs ? ArgInfo::UNBOUNDED : count; 891c86a6acaSLawrence D'Anna 892c86a6acaSLawrence D'Anna #else 893adbf64ccSLawrence D'Anna PyObject *py_func_obj; 8942386537cSLawrence D'Anna bool is_bound_method = false; 895adbf64ccSLawrence D'Anna bool is_class = false; 896adbf64ccSLawrence D'Anna 897adbf64ccSLawrence D'Anna if (PyType_Check(m_py_obj) || PyClass_Check(m_py_obj)) { 898adbf64ccSLawrence D'Anna auto init = GetAttribute("__init__"); 899adbf64ccSLawrence D'Anna if (!init) 900adbf64ccSLawrence D'Anna return init.takeError(); 901adbf64ccSLawrence D'Anna py_func_obj = init.get().get(); 902adbf64ccSLawrence D'Anna is_class = true; 903adbf64ccSLawrence D'Anna } else { 904adbf64ccSLawrence D'Anna py_func_obj = m_py_obj; 905adbf64ccSLawrence D'Anna } 906adbf64ccSLawrence D'Anna 907b9c1b51eSKate Stone if (PyMethod_Check(py_func_obj)) { 908a1405147SZachary Turner py_func_obj = PyMethod_GET_FUNCTION(py_func_obj); 909a5d6765cSEnrico Granata PythonObject im_self = GetAttributeValue("im_self"); 910a5d6765cSEnrico Granata if (im_self.IsValid() && !im_self.IsNone()) 9112386537cSLawrence D'Anna is_bound_method = true; 912b9c1b51eSKate Stone } else { 913a5d6765cSEnrico Granata // see if this is a callable object with an __call__ method 914b9c1b51eSKate Stone if (!PyFunction_Check(py_func_obj)) { 915a5d6765cSEnrico Granata PythonObject __call__ = GetAttributeValue("__call__"); 916b9c1b51eSKate Stone if (__call__.IsValid()) { 917a5d6765cSEnrico Granata auto __callable__ = __call__.AsType<PythonCallable>(); 918b9c1b51eSKate Stone if (__callable__.IsValid()) { 919a5d6765cSEnrico Granata py_func_obj = PyMethod_GET_FUNCTION(__callable__.get()); 9202386537cSLawrence D'Anna PythonObject im_self = __callable__.GetAttributeValue("im_self"); 921a5d6765cSEnrico Granata if (im_self.IsValid() && !im_self.IsNone()) 9222386537cSLawrence D'Anna is_bound_method = true; 923a5d6765cSEnrico Granata } 924a5d6765cSEnrico Granata } 925a5d6765cSEnrico Granata } 926a5d6765cSEnrico Granata } 927a1405147SZachary Turner 928a1405147SZachary Turner if (!py_func_obj) 929b58fb2f4SZachary Turner return result; 930a1405147SZachary Turner 931a1405147SZachary Turner PyCodeObject *code = (PyCodeObject *)PyFunction_GET_CODE(py_func_obj); 932a1405147SZachary Turner if (!code) 933b58fb2f4SZachary Turner return result; 934a1405147SZachary Turner 935adbf64ccSLawrence D'Anna auto count = code->co_argcount; 936adbf64ccSLawrence D'Anna bool has_varargs = !!(code->co_flags & CO_VARARGS); 937adbf64ccSLawrence D'Anna result.max_positional_args = 938adbf64ccSLawrence D'Anna has_varargs ? ArgInfo::UNBOUNDED 939adbf64ccSLawrence D'Anna : (count - (int)is_bound_method) - (int)is_class; 940c86a6acaSLawrence D'Anna 941c86a6acaSLawrence D'Anna #endif 942c86a6acaSLawrence D'Anna 943b58fb2f4SZachary Turner return result; 944b58fb2f4SZachary Turner } 945b58fb2f4SZachary Turner 9462386537cSLawrence D'Anna constexpr unsigned 9472386537cSLawrence D'Anna PythonCallable::ArgInfo::UNBOUNDED; // FIXME delete after c++17 9482386537cSLawrence D'Anna 949b9c1b51eSKate Stone PythonObject PythonCallable::operator()() { 950b9c1b51eSKate Stone return PythonObject(PyRefType::Owned, PyObject_CallObject(m_py_obj, nullptr)); 951a1405147SZachary Turner } 952a1405147SZachary Turner 953b9c1b51eSKate Stone PythonObject PythonCallable:: 954b9c1b51eSKate Stone operator()(std::initializer_list<PyObject *> args) { 955a1405147SZachary Turner PythonTuple arg_tuple(args); 956a1405147SZachary Turner return PythonObject(PyRefType::Owned, 957a1405147SZachary Turner PyObject_CallObject(m_py_obj, arg_tuple.get())); 958a1405147SZachary Turner } 959a1405147SZachary Turner 960b9c1b51eSKate Stone PythonObject PythonCallable:: 961b9c1b51eSKate Stone operator()(std::initializer_list<PythonObject> args) { 962a1405147SZachary Turner PythonTuple arg_tuple(args); 963a1405147SZachary Turner return PythonObject(PyRefType::Owned, 964a1405147SZachary Turner PyObject_CallObject(m_py_obj, arg_tuple.get())); 965a1405147SZachary Turner } 966a1405147SZachary Turner 967b9c1b51eSKate Stone bool PythonFile::Check(PyObject *py_obj) { 96896898eb6SLawrence D'Anna if (!py_obj) 96996898eb6SLawrence D'Anna return false; 9709c40264fSZachary Turner #if PY_MAJOR_VERSION < 3 97123502721SJason Molenda return PyFile_Check(py_obj); 97223502721SJason Molenda #else 9739c40264fSZachary Turner // In Python 3, there is no `PyFile_Check`, and in fact PyFile is not even a 9749c40264fSZachary Turner // first-class object type anymore. `PyFile_FromFd` is just a thin wrapper 97505097246SAdrian Prantl // over `io.open()`, which returns some object derived from `io.IOBase`. As a 97605097246SAdrian Prantl // result, the only way to detect a file in Python 3 is to check whether it 97721b8a8aeSLawrence D'Anna // inherits from `io.IOBase`. 97821b8a8aeSLawrence D'Anna auto io_module = PythonModule::Import("io"); 97921b8a8aeSLawrence D'Anna if (!io_module) { 98021b8a8aeSLawrence D'Anna llvm::consumeError(io_module.takeError()); 9819c40264fSZachary Turner return false; 98221b8a8aeSLawrence D'Anna } 98321b8a8aeSLawrence D'Anna auto iobase = io_module.get().Get("IOBase"); 98421b8a8aeSLawrence D'Anna if (!iobase) { 98521b8a8aeSLawrence D'Anna llvm::consumeError(iobase.takeError()); 9869c40264fSZachary Turner return false; 98721b8a8aeSLawrence D'Anna } 98821b8a8aeSLawrence D'Anna int r = PyObject_IsInstance(py_obj, iobase.get().get()); 98921b8a8aeSLawrence D'Anna if (r < 0) { 99021b8a8aeSLawrence D'Anna llvm::consumeError(exception()); // clear the exception and log it. 99121b8a8aeSLawrence D'Anna return false; 99221b8a8aeSLawrence D'Anna } 99321b8a8aeSLawrence D'Anna return !!r; 99423502721SJason Molenda #endif 9959c40264fSZachary Turner } 9969c40264fSZachary Turner 99721b8a8aeSLawrence D'Anna namespace { 99821b8a8aeSLawrence D'Anna class GIL { 99921b8a8aeSLawrence D'Anna public: 100021b8a8aeSLawrence D'Anna GIL() { 100121b8a8aeSLawrence D'Anna m_state = PyGILState_Ensure(); 100221b8a8aeSLawrence D'Anna assert(!PyErr_Occurred()); 100321b8a8aeSLawrence D'Anna } 100421b8a8aeSLawrence D'Anna ~GIL() { PyGILState_Release(m_state); } 100521b8a8aeSLawrence D'Anna 100621b8a8aeSLawrence D'Anna protected: 100721b8a8aeSLawrence D'Anna PyGILState_STATE m_state; 100821b8a8aeSLawrence D'Anna }; 100921b8a8aeSLawrence D'Anna } // namespace 101021b8a8aeSLawrence D'Anna 1011085328eeSLawrence D'Anna const char *PythonException::toCString() const { 1012085328eeSLawrence D'Anna if (!m_repr_bytes) 1013085328eeSLawrence D'Anna return "unknown exception"; 1014085328eeSLawrence D'Anna return PyBytes_AS_STRING(m_repr_bytes); 1015085328eeSLawrence D'Anna } 1016085328eeSLawrence D'Anna 1017085328eeSLawrence D'Anna PythonException::PythonException(const char *caller) { 1018085328eeSLawrence D'Anna assert(PyErr_Occurred()); 1019085328eeSLawrence D'Anna m_exception_type = m_exception = m_traceback = m_repr_bytes = NULL; 1020085328eeSLawrence D'Anna PyErr_Fetch(&m_exception_type, &m_exception, &m_traceback); 1021085328eeSLawrence D'Anna PyErr_NormalizeException(&m_exception_type, &m_exception, &m_traceback); 1022085328eeSLawrence D'Anna PyErr_Clear(); 1023085328eeSLawrence D'Anna if (m_exception) { 1024085328eeSLawrence D'Anna PyObject *repr = PyObject_Repr(m_exception); 1025085328eeSLawrence D'Anna if (repr) { 1026085328eeSLawrence D'Anna m_repr_bytes = PyUnicode_AsEncodedString(repr, "utf-8", nullptr); 1027085328eeSLawrence D'Anna if (!m_repr_bytes) { 1028085328eeSLawrence D'Anna PyErr_Clear(); 1029085328eeSLawrence D'Anna } 1030085328eeSLawrence D'Anna Py_XDECREF(repr); 1031085328eeSLawrence D'Anna } else { 1032085328eeSLawrence D'Anna PyErr_Clear(); 1033085328eeSLawrence D'Anna } 1034085328eeSLawrence D'Anna } 1035085328eeSLawrence D'Anna Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT); 1036085328eeSLawrence D'Anna if (caller) 1037085328eeSLawrence D'Anna LLDB_LOGF(log, "%s failed with exception: %s", caller, toCString()); 1038085328eeSLawrence D'Anna else 1039085328eeSLawrence D'Anna LLDB_LOGF(log, "python exception: %s", toCString()); 1040085328eeSLawrence D'Anna } 1041085328eeSLawrence D'Anna void PythonException::Restore() { 1042085328eeSLawrence D'Anna if (m_exception_type && m_exception) { 1043085328eeSLawrence D'Anna PyErr_Restore(m_exception_type, m_exception, m_traceback); 1044085328eeSLawrence D'Anna } else { 1045085328eeSLawrence D'Anna PyErr_SetString(PyExc_Exception, toCString()); 1046085328eeSLawrence D'Anna } 1047085328eeSLawrence D'Anna m_exception_type = m_exception = m_traceback = NULL; 1048085328eeSLawrence D'Anna } 1049085328eeSLawrence D'Anna 1050085328eeSLawrence D'Anna PythonException::~PythonException() { 1051085328eeSLawrence D'Anna Py_XDECREF(m_exception_type); 1052085328eeSLawrence D'Anna Py_XDECREF(m_exception); 1053085328eeSLawrence D'Anna Py_XDECREF(m_traceback); 1054085328eeSLawrence D'Anna Py_XDECREF(m_repr_bytes); 1055085328eeSLawrence D'Anna } 1056085328eeSLawrence D'Anna 1057085328eeSLawrence D'Anna void PythonException::log(llvm::raw_ostream &OS) const { OS << toCString(); } 1058085328eeSLawrence D'Anna 1059085328eeSLawrence D'Anna std::error_code PythonException::convertToErrorCode() const { 1060085328eeSLawrence D'Anna return llvm::inconvertibleErrorCode(); 1061085328eeSLawrence D'Anna } 1062085328eeSLawrence D'Anna 106304edd189SLawrence D'Anna bool PythonException::Matches(PyObject *exc) const { 106404edd189SLawrence D'Anna return PyErr_GivenExceptionMatches(m_exception_type, exc); 106504edd189SLawrence D'Anna } 106604edd189SLawrence D'Anna 106704edd189SLawrence D'Anna const char read_exception_script[] = R"( 106804edd189SLawrence D'Anna import sys 106904edd189SLawrence D'Anna from traceback import print_exception 107004edd189SLawrence D'Anna if sys.version_info.major < 3: 107104edd189SLawrence D'Anna from StringIO import StringIO 107204edd189SLawrence D'Anna else: 107304edd189SLawrence D'Anna from io import StringIO 107404edd189SLawrence D'Anna def main(exc_type, exc_value, tb): 107504edd189SLawrence D'Anna f = StringIO() 107604edd189SLawrence D'Anna print_exception(exc_type, exc_value, tb, file=f) 107704edd189SLawrence D'Anna return f.getvalue() 107804edd189SLawrence D'Anna )"; 107904edd189SLawrence D'Anna 108004edd189SLawrence D'Anna std::string PythonException::ReadBacktrace() const { 108104edd189SLawrence D'Anna 108204edd189SLawrence D'Anna if (!m_traceback) 108304edd189SLawrence D'Anna return toCString(); 108404edd189SLawrence D'Anna 108504edd189SLawrence D'Anna // no need to synchronize access to this global, we already have the GIL 108604edd189SLawrence D'Anna static PythonScript read_exception(read_exception_script); 108704edd189SLawrence D'Anna 108804edd189SLawrence D'Anna Expected<std::string> backtrace = As<std::string>( 108904edd189SLawrence D'Anna read_exception(m_exception_type, m_exception, m_traceback)); 109004edd189SLawrence D'Anna 109104edd189SLawrence D'Anna if (!backtrace) { 109204edd189SLawrence D'Anna std::string message = 109304edd189SLawrence D'Anna std::string(toCString()) + "\n" + 1094e9264b74SKazuaki Ishizaki "Traceback unavailable, an error occurred while reading it:\n"; 109504edd189SLawrence D'Anna return (message + llvm::toString(backtrace.takeError())); 109604edd189SLawrence D'Anna } 109704edd189SLawrence D'Anna 109804edd189SLawrence D'Anna return std::move(backtrace.get()); 109904edd189SLawrence D'Anna } 110004edd189SLawrence D'Anna 1101085328eeSLawrence D'Anna char PythonException::ID = 0; 1102085328eeSLawrence D'Anna 110362c9fe42SLawrence D'Anna llvm::Expected<File::OpenOptions> 110462c9fe42SLawrence D'Anna GetOptionsForPyObject(const PythonObject &obj) { 110521b8a8aeSLawrence D'Anna #if PY_MAJOR_VERSION >= 3 110662c9fe42SLawrence D'Anna auto options = File::OpenOptions(0); 110721b8a8aeSLawrence D'Anna auto readable = As<bool>(obj.CallMethod("readable")); 110821b8a8aeSLawrence D'Anna if (!readable) 110921b8a8aeSLawrence D'Anna return readable.takeError(); 111021b8a8aeSLawrence D'Anna auto writable = As<bool>(obj.CallMethod("writable")); 111121b8a8aeSLawrence D'Anna if (!writable) 111221b8a8aeSLawrence D'Anna return writable.takeError(); 111321b8a8aeSLawrence D'Anna if (readable.get()) 111421b8a8aeSLawrence D'Anna options |= File::eOpenOptionRead; 111521b8a8aeSLawrence D'Anna if (writable.get()) 111621b8a8aeSLawrence D'Anna options |= File::eOpenOptionWrite; 111762c9fe42SLawrence D'Anna return options; 111821b8a8aeSLawrence D'Anna #else 111921b8a8aeSLawrence D'Anna PythonString py_mode = obj.GetAttributeValue("mode").AsType<PythonString>(); 112062c9fe42SLawrence D'Anna return File::GetOptionsFromMode(py_mode.GetString()); 112121b8a8aeSLawrence D'Anna #endif 112221b8a8aeSLawrence D'Anna } 112321b8a8aeSLawrence D'Anna 112421b8a8aeSLawrence D'Anna // Base class template for python files. All it knows how to do 112521b8a8aeSLawrence D'Anna // is hold a reference to the python object and close or flush it 112621b8a8aeSLawrence D'Anna // when the File is closed. 112721b8a8aeSLawrence D'Anna namespace { 112821b8a8aeSLawrence D'Anna template <typename Base> class OwnedPythonFile : public Base { 112921b8a8aeSLawrence D'Anna public: 113021b8a8aeSLawrence D'Anna template <typename... Args> 113121b8a8aeSLawrence D'Anna OwnedPythonFile(const PythonFile &file, bool borrowed, Args... args) 113221b8a8aeSLawrence D'Anna : Base(args...), m_py_obj(file), m_borrowed(borrowed) { 113321b8a8aeSLawrence D'Anna assert(m_py_obj); 113421b8a8aeSLawrence D'Anna } 113521b8a8aeSLawrence D'Anna 113621b8a8aeSLawrence D'Anna ~OwnedPythonFile() override { 113721b8a8aeSLawrence D'Anna assert(m_py_obj); 113821b8a8aeSLawrence D'Anna GIL takeGIL; 113921b8a8aeSLawrence D'Anna Close(); 1140722b6189SLawrence D'Anna // we need to ensure the python object is released while we still 1141722b6189SLawrence D'Anna // hold the GIL 114221b8a8aeSLawrence D'Anna m_py_obj.Reset(); 114321b8a8aeSLawrence D'Anna } 114421b8a8aeSLawrence D'Anna 114521b8a8aeSLawrence D'Anna bool IsPythonSideValid() const { 114621b8a8aeSLawrence D'Anna GIL takeGIL; 114721b8a8aeSLawrence D'Anna auto closed = As<bool>(m_py_obj.GetAttribute("closed")); 114821b8a8aeSLawrence D'Anna if (!closed) { 114921b8a8aeSLawrence D'Anna llvm::consumeError(closed.takeError()); 115021b8a8aeSLawrence D'Anna return false; 115121b8a8aeSLawrence D'Anna } 115221b8a8aeSLawrence D'Anna return !closed.get(); 115321b8a8aeSLawrence D'Anna } 115421b8a8aeSLawrence D'Anna 115521b8a8aeSLawrence D'Anna bool IsValid() const override { 115621b8a8aeSLawrence D'Anna return IsPythonSideValid() && Base::IsValid(); 115721b8a8aeSLawrence D'Anna } 115821b8a8aeSLawrence D'Anna 115921b8a8aeSLawrence D'Anna Status Close() override { 116021b8a8aeSLawrence D'Anna assert(m_py_obj); 116121b8a8aeSLawrence D'Anna Status py_error, base_error; 116221b8a8aeSLawrence D'Anna GIL takeGIL; 116321b8a8aeSLawrence D'Anna if (!m_borrowed) { 116421b8a8aeSLawrence D'Anna auto r = m_py_obj.CallMethod("close"); 116521b8a8aeSLawrence D'Anna if (!r) 116621b8a8aeSLawrence D'Anna py_error = Status(r.takeError()); 116721b8a8aeSLawrence D'Anna } 116821b8a8aeSLawrence D'Anna base_error = Base::Close(); 116921b8a8aeSLawrence D'Anna if (py_error.Fail()) 117021b8a8aeSLawrence D'Anna return py_error; 117121b8a8aeSLawrence D'Anna return base_error; 117221b8a8aeSLawrence D'Anna }; 117321b8a8aeSLawrence D'Anna 1174d9b553ecSLawrence D'Anna PyObject *GetPythonObject() const { 1175d9b553ecSLawrence D'Anna assert(m_py_obj.IsValid()); 1176d9b553ecSLawrence D'Anna return m_py_obj.get(); 1177d9b553ecSLawrence D'Anna } 1178d9b553ecSLawrence D'Anna 1179d9b553ecSLawrence D'Anna static bool classof(const File *file) = delete; 1180d9b553ecSLawrence D'Anna 118121b8a8aeSLawrence D'Anna protected: 118221b8a8aeSLawrence D'Anna PythonFile m_py_obj; 118321b8a8aeSLawrence D'Anna bool m_borrowed; 118421b8a8aeSLawrence D'Anna }; 118521b8a8aeSLawrence D'Anna } // namespace 118621b8a8aeSLawrence D'Anna 118721b8a8aeSLawrence D'Anna // A SimplePythonFile is a OwnedPythonFile that just does all I/O as 118821b8a8aeSLawrence D'Anna // a NativeFile 118921b8a8aeSLawrence D'Anna namespace { 119021b8a8aeSLawrence D'Anna class SimplePythonFile : public OwnedPythonFile<NativeFile> { 119121b8a8aeSLawrence D'Anna public: 119221b8a8aeSLawrence D'Anna SimplePythonFile(const PythonFile &file, bool borrowed, int fd, 119362c9fe42SLawrence D'Anna File::OpenOptions options) 119421b8a8aeSLawrence D'Anna : OwnedPythonFile(file, borrowed, fd, options, false) {} 1195d9b553ecSLawrence D'Anna 1196d9b553ecSLawrence D'Anna static char ID; 1197d9b553ecSLawrence D'Anna bool isA(const void *classID) const override { 1198d9b553ecSLawrence D'Anna return classID == &ID || NativeFile::isA(classID); 1199d9b553ecSLawrence D'Anna } 1200d9b553ecSLawrence D'Anna static bool classof(const File *file) { return file->isA(&ID); } 120121b8a8aeSLawrence D'Anna }; 1202d9b553ecSLawrence D'Anna char SimplePythonFile::ID = 0; 120321b8a8aeSLawrence D'Anna } // namespace 120421b8a8aeSLawrence D'Anna 120521b8a8aeSLawrence D'Anna #if PY_MAJOR_VERSION >= 3 120621b8a8aeSLawrence D'Anna 120721b8a8aeSLawrence D'Anna namespace { 120821b8a8aeSLawrence D'Anna class PythonBuffer { 120921b8a8aeSLawrence D'Anna public: 121021b8a8aeSLawrence D'Anna PythonBuffer &operator=(const PythonBuffer &) = delete; 121121b8a8aeSLawrence D'Anna PythonBuffer(const PythonBuffer &) = delete; 121221b8a8aeSLawrence D'Anna 121321b8a8aeSLawrence D'Anna static Expected<PythonBuffer> Create(PythonObject &obj, 121421b8a8aeSLawrence D'Anna int flags = PyBUF_SIMPLE) { 121521b8a8aeSLawrence D'Anna Py_buffer py_buffer = {}; 121621b8a8aeSLawrence D'Anna PyObject_GetBuffer(obj.get(), &py_buffer, flags); 121721b8a8aeSLawrence D'Anna if (!py_buffer.obj) 121821b8a8aeSLawrence D'Anna return llvm::make_error<PythonException>(); 121921b8a8aeSLawrence D'Anna return PythonBuffer(py_buffer); 122021b8a8aeSLawrence D'Anna } 122121b8a8aeSLawrence D'Anna 122221b8a8aeSLawrence D'Anna PythonBuffer(PythonBuffer &&other) { 122321b8a8aeSLawrence D'Anna m_buffer = other.m_buffer; 122421b8a8aeSLawrence D'Anna other.m_buffer.obj = nullptr; 122521b8a8aeSLawrence D'Anna } 122621b8a8aeSLawrence D'Anna 122721b8a8aeSLawrence D'Anna ~PythonBuffer() { 122821b8a8aeSLawrence D'Anna if (m_buffer.obj) 122921b8a8aeSLawrence D'Anna PyBuffer_Release(&m_buffer); 123021b8a8aeSLawrence D'Anna } 123121b8a8aeSLawrence D'Anna 123221b8a8aeSLawrence D'Anna Py_buffer &get() { return m_buffer; } 123321b8a8aeSLawrence D'Anna 123421b8a8aeSLawrence D'Anna private: 123521b8a8aeSLawrence D'Anna // takes ownership of the buffer. 123621b8a8aeSLawrence D'Anna PythonBuffer(const Py_buffer &py_buffer) : m_buffer(py_buffer) {} 123721b8a8aeSLawrence D'Anna Py_buffer m_buffer; 123821b8a8aeSLawrence D'Anna }; 123921b8a8aeSLawrence D'Anna } // namespace 124021b8a8aeSLawrence D'Anna 124121b8a8aeSLawrence D'Anna // Shared methods between TextPythonFile and BinaryPythonFile 124221b8a8aeSLawrence D'Anna namespace { 124321b8a8aeSLawrence D'Anna class PythonIOFile : public OwnedPythonFile<File> { 124421b8a8aeSLawrence D'Anna public: 124521b8a8aeSLawrence D'Anna PythonIOFile(const PythonFile &file, bool borrowed) 124621b8a8aeSLawrence D'Anna : OwnedPythonFile(file, borrowed) {} 124721b8a8aeSLawrence D'Anna 124821b8a8aeSLawrence D'Anna ~PythonIOFile() override { Close(); } 124921b8a8aeSLawrence D'Anna 125021b8a8aeSLawrence D'Anna bool IsValid() const override { return IsPythonSideValid(); } 125121b8a8aeSLawrence D'Anna 125221b8a8aeSLawrence D'Anna Status Close() override { 125321b8a8aeSLawrence D'Anna assert(m_py_obj); 125421b8a8aeSLawrence D'Anna GIL takeGIL; 125521b8a8aeSLawrence D'Anna if (m_borrowed) 125621b8a8aeSLawrence D'Anna return Flush(); 125721b8a8aeSLawrence D'Anna auto r = m_py_obj.CallMethod("close"); 125821b8a8aeSLawrence D'Anna if (!r) 125921b8a8aeSLawrence D'Anna return Status(r.takeError()); 126021b8a8aeSLawrence D'Anna return Status(); 126121b8a8aeSLawrence D'Anna } 126221b8a8aeSLawrence D'Anna 126321b8a8aeSLawrence D'Anna Status Flush() override { 126421b8a8aeSLawrence D'Anna GIL takeGIL; 126521b8a8aeSLawrence D'Anna auto r = m_py_obj.CallMethod("flush"); 126621b8a8aeSLawrence D'Anna if (!r) 126721b8a8aeSLawrence D'Anna return Status(r.takeError()); 126821b8a8aeSLawrence D'Anna return Status(); 126921b8a8aeSLawrence D'Anna } 127021b8a8aeSLawrence D'Anna 1271d9b553ecSLawrence D'Anna Expected<File::OpenOptions> GetOptions() const override { 1272d9b553ecSLawrence D'Anna GIL takeGIL; 1273d9b553ecSLawrence D'Anna return GetOptionsForPyObject(m_py_obj); 1274d9b553ecSLawrence D'Anna } 1275d9b553ecSLawrence D'Anna 1276d9b553ecSLawrence D'Anna static char ID; 1277d9b553ecSLawrence D'Anna bool isA(const void *classID) const override { 1278d9b553ecSLawrence D'Anna return classID == &ID || File::isA(classID); 1279d9b553ecSLawrence D'Anna } 1280d9b553ecSLawrence D'Anna static bool classof(const File *file) { return file->isA(&ID); } 128121b8a8aeSLawrence D'Anna }; 1282d9b553ecSLawrence D'Anna char PythonIOFile::ID = 0; 128321b8a8aeSLawrence D'Anna } // namespace 128421b8a8aeSLawrence D'Anna 128521b8a8aeSLawrence D'Anna namespace { 128621b8a8aeSLawrence D'Anna class BinaryPythonFile : public PythonIOFile { 128721b8a8aeSLawrence D'Anna protected: 128821b8a8aeSLawrence D'Anna int m_descriptor; 128921b8a8aeSLawrence D'Anna 129021b8a8aeSLawrence D'Anna public: 129121b8a8aeSLawrence D'Anna BinaryPythonFile(int fd, const PythonFile &file, bool borrowed) 129221b8a8aeSLawrence D'Anna : PythonIOFile(file, borrowed), 129321b8a8aeSLawrence D'Anna m_descriptor(File::DescriptorIsValid(fd) ? fd 129421b8a8aeSLawrence D'Anna : File::kInvalidDescriptor) {} 129521b8a8aeSLawrence D'Anna 129621b8a8aeSLawrence D'Anna int GetDescriptor() const override { return m_descriptor; } 129721b8a8aeSLawrence D'Anna 129821b8a8aeSLawrence D'Anna Status Write(const void *buf, size_t &num_bytes) override { 129921b8a8aeSLawrence D'Anna GIL takeGIL; 130021b8a8aeSLawrence D'Anna PyObject *pybuffer_p = PyMemoryView_FromMemory( 130121b8a8aeSLawrence D'Anna const_cast<char *>((const char *)buf), num_bytes, PyBUF_READ); 130221b8a8aeSLawrence D'Anna if (!pybuffer_p) 130321b8a8aeSLawrence D'Anna return Status(llvm::make_error<PythonException>()); 130421b8a8aeSLawrence D'Anna auto pybuffer = Take<PythonObject>(pybuffer_p); 130521b8a8aeSLawrence D'Anna num_bytes = 0; 130621b8a8aeSLawrence D'Anna auto bytes_written = As<long long>(m_py_obj.CallMethod("write", pybuffer)); 130721b8a8aeSLawrence D'Anna if (!bytes_written) 130821b8a8aeSLawrence D'Anna return Status(bytes_written.takeError()); 130921b8a8aeSLawrence D'Anna if (bytes_written.get() < 0) 131021b8a8aeSLawrence D'Anna return Status(".write() method returned a negative number!"); 131121b8a8aeSLawrence D'Anna static_assert(sizeof(long long) >= sizeof(size_t), "overflow"); 131221b8a8aeSLawrence D'Anna num_bytes = bytes_written.get(); 131321b8a8aeSLawrence D'Anna return Status(); 131421b8a8aeSLawrence D'Anna } 131521b8a8aeSLawrence D'Anna 131621b8a8aeSLawrence D'Anna Status Read(void *buf, size_t &num_bytes) override { 131721b8a8aeSLawrence D'Anna GIL takeGIL; 131821b8a8aeSLawrence D'Anna static_assert(sizeof(long long) >= sizeof(size_t), "overflow"); 131921b8a8aeSLawrence D'Anna auto pybuffer_obj = 132021b8a8aeSLawrence D'Anna m_py_obj.CallMethod("read", (unsigned long long)num_bytes); 132121b8a8aeSLawrence D'Anna if (!pybuffer_obj) 132221b8a8aeSLawrence D'Anna return Status(pybuffer_obj.takeError()); 132321b8a8aeSLawrence D'Anna num_bytes = 0; 132421b8a8aeSLawrence D'Anna if (pybuffer_obj.get().IsNone()) { 132521b8a8aeSLawrence D'Anna // EOF 132621b8a8aeSLawrence D'Anna num_bytes = 0; 132721b8a8aeSLawrence D'Anna return Status(); 132821b8a8aeSLawrence D'Anna } 132921b8a8aeSLawrence D'Anna auto pybuffer = PythonBuffer::Create(pybuffer_obj.get()); 133021b8a8aeSLawrence D'Anna if (!pybuffer) 133121b8a8aeSLawrence D'Anna return Status(pybuffer.takeError()); 133221b8a8aeSLawrence D'Anna memcpy(buf, pybuffer.get().get().buf, pybuffer.get().get().len); 133321b8a8aeSLawrence D'Anna num_bytes = pybuffer.get().get().len; 133421b8a8aeSLawrence D'Anna return Status(); 133521b8a8aeSLawrence D'Anna } 133621b8a8aeSLawrence D'Anna }; 133721b8a8aeSLawrence D'Anna } // namespace 133821b8a8aeSLawrence D'Anna 133921b8a8aeSLawrence D'Anna namespace { 134021b8a8aeSLawrence D'Anna class TextPythonFile : public PythonIOFile { 134121b8a8aeSLawrence D'Anna protected: 134221b8a8aeSLawrence D'Anna int m_descriptor; 134321b8a8aeSLawrence D'Anna 134421b8a8aeSLawrence D'Anna public: 134521b8a8aeSLawrence D'Anna TextPythonFile(int fd, const PythonFile &file, bool borrowed) 134621b8a8aeSLawrence D'Anna : PythonIOFile(file, borrowed), 134721b8a8aeSLawrence D'Anna m_descriptor(File::DescriptorIsValid(fd) ? fd 134821b8a8aeSLawrence D'Anna : File::kInvalidDescriptor) {} 134921b8a8aeSLawrence D'Anna 135021b8a8aeSLawrence D'Anna int GetDescriptor() const override { return m_descriptor; } 135121b8a8aeSLawrence D'Anna 135221b8a8aeSLawrence D'Anna Status Write(const void *buf, size_t &num_bytes) override { 135321b8a8aeSLawrence D'Anna GIL takeGIL; 135421b8a8aeSLawrence D'Anna auto pystring = 135521b8a8aeSLawrence D'Anna PythonString::FromUTF8(llvm::StringRef((const char *)buf, num_bytes)); 135621b8a8aeSLawrence D'Anna if (!pystring) 135721b8a8aeSLawrence D'Anna return Status(pystring.takeError()); 135821b8a8aeSLawrence D'Anna num_bytes = 0; 135921b8a8aeSLawrence D'Anna auto bytes_written = 136021b8a8aeSLawrence D'Anna As<long long>(m_py_obj.CallMethod("write", pystring.get())); 136121b8a8aeSLawrence D'Anna if (!bytes_written) 136221b8a8aeSLawrence D'Anna return Status(bytes_written.takeError()); 136321b8a8aeSLawrence D'Anna if (bytes_written.get() < 0) 136421b8a8aeSLawrence D'Anna return Status(".write() method returned a negative number!"); 136521b8a8aeSLawrence D'Anna static_assert(sizeof(long long) >= sizeof(size_t), "overflow"); 136621b8a8aeSLawrence D'Anna num_bytes = bytes_written.get(); 136721b8a8aeSLawrence D'Anna return Status(); 136821b8a8aeSLawrence D'Anna } 136921b8a8aeSLawrence D'Anna 137021b8a8aeSLawrence D'Anna Status Read(void *buf, size_t &num_bytes) override { 137121b8a8aeSLawrence D'Anna GIL takeGIL; 137221b8a8aeSLawrence D'Anna size_t num_chars = num_bytes / 6; 137321b8a8aeSLawrence D'Anna size_t orig_num_bytes = num_bytes; 137421b8a8aeSLawrence D'Anna num_bytes = 0; 137521b8a8aeSLawrence D'Anna if (orig_num_bytes < 6) { 137621b8a8aeSLawrence D'Anna return Status("can't read less than 6 bytes from a utf8 text stream"); 137721b8a8aeSLawrence D'Anna } 137821b8a8aeSLawrence D'Anna auto pystring = As<PythonString>( 137921b8a8aeSLawrence D'Anna m_py_obj.CallMethod("read", (unsigned long long)num_chars)); 138021b8a8aeSLawrence D'Anna if (!pystring) 138121b8a8aeSLawrence D'Anna return Status(pystring.takeError()); 138221b8a8aeSLawrence D'Anna if (pystring.get().IsNone()) { 138321b8a8aeSLawrence D'Anna // EOF 138421b8a8aeSLawrence D'Anna return Status(); 138521b8a8aeSLawrence D'Anna } 138621b8a8aeSLawrence D'Anna auto stringref = pystring.get().AsUTF8(); 138721b8a8aeSLawrence D'Anna if (!stringref) 138821b8a8aeSLawrence D'Anna return Status(stringref.takeError()); 138921b8a8aeSLawrence D'Anna num_bytes = stringref.get().size(); 139021b8a8aeSLawrence D'Anna memcpy(buf, stringref.get().begin(), num_bytes); 139121b8a8aeSLawrence D'Anna return Status(); 139221b8a8aeSLawrence D'Anna } 139321b8a8aeSLawrence D'Anna }; 139421b8a8aeSLawrence D'Anna } // namespace 139521b8a8aeSLawrence D'Anna 139621b8a8aeSLawrence D'Anna #endif 139721b8a8aeSLawrence D'Anna 139821b8a8aeSLawrence D'Anna llvm::Expected<FileSP> PythonFile::ConvertToFile(bool borrowed) { 139921b8a8aeSLawrence D'Anna if (!IsValid()) 140021b8a8aeSLawrence D'Anna return llvm::createStringError(llvm::inconvertibleErrorCode(), 140121b8a8aeSLawrence D'Anna "invalid PythonFile"); 140221b8a8aeSLawrence D'Anna 140321b8a8aeSLawrence D'Anna int fd = PyObject_AsFileDescriptor(m_py_obj); 140421b8a8aeSLawrence D'Anna if (fd < 0) { 140521b8a8aeSLawrence D'Anna PyErr_Clear(); 140621b8a8aeSLawrence D'Anna return ConvertToFileForcingUseOfScriptingIOMethods(borrowed); 140721b8a8aeSLawrence D'Anna } 140821b8a8aeSLawrence D'Anna auto options = GetOptionsForPyObject(*this); 140921b8a8aeSLawrence D'Anna if (!options) 141021b8a8aeSLawrence D'Anna return options.takeError(); 141121b8a8aeSLawrence D'Anna 1412267cc329SMichal Gorny if (options.get() & File::eOpenOptionWrite) { 141321b8a8aeSLawrence D'Anna // LLDB and python will not share I/O buffers. We should probably 141421b8a8aeSLawrence D'Anna // flush the python buffers now. 141521b8a8aeSLawrence D'Anna auto r = CallMethod("flush"); 141621b8a8aeSLawrence D'Anna if (!r) 141721b8a8aeSLawrence D'Anna return r.takeError(); 1418267cc329SMichal Gorny } 141921b8a8aeSLawrence D'Anna 142021b8a8aeSLawrence D'Anna FileSP file_sp; 142121b8a8aeSLawrence D'Anna if (borrowed) { 142221b8a8aeSLawrence D'Anna // In this case we we don't need to retain the python 142321b8a8aeSLawrence D'Anna // object at all. 142421b8a8aeSLawrence D'Anna file_sp = std::make_shared<NativeFile>(fd, options.get(), false); 142521b8a8aeSLawrence D'Anna } else { 142621b8a8aeSLawrence D'Anna file_sp = std::static_pointer_cast<File>( 142721b8a8aeSLawrence D'Anna std::make_shared<SimplePythonFile>(*this, borrowed, fd, options.get())); 142821b8a8aeSLawrence D'Anna } 142921b8a8aeSLawrence D'Anna if (!file_sp->IsValid()) 143021b8a8aeSLawrence D'Anna return llvm::createStringError(llvm::inconvertibleErrorCode(), 143121b8a8aeSLawrence D'Anna "invalid File"); 143221b8a8aeSLawrence D'Anna 143321b8a8aeSLawrence D'Anna return file_sp; 143421b8a8aeSLawrence D'Anna } 143521b8a8aeSLawrence D'Anna 143621b8a8aeSLawrence D'Anna llvm::Expected<FileSP> 143721b8a8aeSLawrence D'Anna PythonFile::ConvertToFileForcingUseOfScriptingIOMethods(bool borrowed) { 143821b8a8aeSLawrence D'Anna 143921b8a8aeSLawrence D'Anna assert(!PyErr_Occurred()); 144021b8a8aeSLawrence D'Anna 144121b8a8aeSLawrence D'Anna if (!IsValid()) 144221b8a8aeSLawrence D'Anna return llvm::createStringError(llvm::inconvertibleErrorCode(), 144321b8a8aeSLawrence D'Anna "invalid PythonFile"); 144421b8a8aeSLawrence D'Anna 144521b8a8aeSLawrence D'Anna #if PY_MAJOR_VERSION < 3 144621b8a8aeSLawrence D'Anna 144721b8a8aeSLawrence D'Anna return llvm::createStringError(llvm::inconvertibleErrorCode(), 144821b8a8aeSLawrence D'Anna "not supported on python 2"); 144921b8a8aeSLawrence D'Anna 145021b8a8aeSLawrence D'Anna #else 145121b8a8aeSLawrence D'Anna 145221b8a8aeSLawrence D'Anna int fd = PyObject_AsFileDescriptor(m_py_obj); 145321b8a8aeSLawrence D'Anna if (fd < 0) { 145421b8a8aeSLawrence D'Anna PyErr_Clear(); 145521b8a8aeSLawrence D'Anna fd = File::kInvalidDescriptor; 145621b8a8aeSLawrence D'Anna } 145721b8a8aeSLawrence D'Anna 145821b8a8aeSLawrence D'Anna auto io_module = PythonModule::Import("io"); 145921b8a8aeSLawrence D'Anna if (!io_module) 146021b8a8aeSLawrence D'Anna return io_module.takeError(); 146121b8a8aeSLawrence D'Anna auto textIOBase = io_module.get().Get("TextIOBase"); 146221b8a8aeSLawrence D'Anna if (!textIOBase) 146321b8a8aeSLawrence D'Anna return textIOBase.takeError(); 146421b8a8aeSLawrence D'Anna auto rawIOBase = io_module.get().Get("RawIOBase"); 146521b8a8aeSLawrence D'Anna if (!rawIOBase) 146621b8a8aeSLawrence D'Anna return rawIOBase.takeError(); 146721b8a8aeSLawrence D'Anna auto bufferedIOBase = io_module.get().Get("BufferedIOBase"); 146821b8a8aeSLawrence D'Anna if (!bufferedIOBase) 146921b8a8aeSLawrence D'Anna return bufferedIOBase.takeError(); 147021b8a8aeSLawrence D'Anna 147121b8a8aeSLawrence D'Anna FileSP file_sp; 147221b8a8aeSLawrence D'Anna 147321b8a8aeSLawrence D'Anna auto isTextIO = IsInstance(textIOBase.get()); 147421b8a8aeSLawrence D'Anna if (!isTextIO) 147521b8a8aeSLawrence D'Anna return isTextIO.takeError(); 147621b8a8aeSLawrence D'Anna if (isTextIO.get()) 147721b8a8aeSLawrence D'Anna file_sp = std::static_pointer_cast<File>( 147821b8a8aeSLawrence D'Anna std::make_shared<TextPythonFile>(fd, *this, borrowed)); 147921b8a8aeSLawrence D'Anna 148021b8a8aeSLawrence D'Anna auto isRawIO = IsInstance(rawIOBase.get()); 148121b8a8aeSLawrence D'Anna if (!isRawIO) 148221b8a8aeSLawrence D'Anna return isRawIO.takeError(); 148321b8a8aeSLawrence D'Anna auto isBufferedIO = IsInstance(bufferedIOBase.get()); 148421b8a8aeSLawrence D'Anna if (!isBufferedIO) 148521b8a8aeSLawrence D'Anna return isBufferedIO.takeError(); 148621b8a8aeSLawrence D'Anna 148721b8a8aeSLawrence D'Anna if (isRawIO.get() || isBufferedIO.get()) { 148821b8a8aeSLawrence D'Anna file_sp = std::static_pointer_cast<File>( 148921b8a8aeSLawrence D'Anna std::make_shared<BinaryPythonFile>(fd, *this, borrowed)); 149021b8a8aeSLawrence D'Anna } 149121b8a8aeSLawrence D'Anna 149221b8a8aeSLawrence D'Anna if (!file_sp) 149321b8a8aeSLawrence D'Anna return llvm::createStringError(llvm::inconvertibleErrorCode(), 149421b8a8aeSLawrence D'Anna "python file is neither text nor binary"); 149521b8a8aeSLawrence D'Anna 149621b8a8aeSLawrence D'Anna if (!file_sp->IsValid()) 149721b8a8aeSLawrence D'Anna return llvm::createStringError(llvm::inconvertibleErrorCode(), 149821b8a8aeSLawrence D'Anna "invalid File"); 149921b8a8aeSLawrence D'Anna 150021b8a8aeSLawrence D'Anna return file_sp; 150121b8a8aeSLawrence D'Anna 150221b8a8aeSLawrence D'Anna #endif 150321b8a8aeSLawrence D'Anna } 150421b8a8aeSLawrence D'Anna 1505d9b553ecSLawrence D'Anna Expected<PythonFile> PythonFile::FromFile(File &file, const char *mode) { 1506d9b553ecSLawrence D'Anna if (!file.IsValid()) 1507d9b553ecSLawrence D'Anna return llvm::createStringError(llvm::inconvertibleErrorCode(), 1508d9b553ecSLawrence D'Anna "invalid file"); 1509d9b553ecSLawrence D'Anna 1510d9b553ecSLawrence D'Anna if (auto *simple = llvm::dyn_cast<SimplePythonFile>(&file)) 1511d9b553ecSLawrence D'Anna return Retain<PythonFile>(simple->GetPythonObject()); 1512d9b553ecSLawrence D'Anna #if PY_MAJOR_VERSION >= 3 1513d9b553ecSLawrence D'Anna if (auto *pythonio = llvm::dyn_cast<PythonIOFile>(&file)) 1514d9b553ecSLawrence D'Anna return Retain<PythonFile>(pythonio->GetPythonObject()); 1515d9b553ecSLawrence D'Anna #endif 1516d9b553ecSLawrence D'Anna 1517d9b553ecSLawrence D'Anna if (!mode) { 1518d9b553ecSLawrence D'Anna auto m = file.GetOpenMode(); 1519d9b553ecSLawrence D'Anna if (!m) 1520d9b553ecSLawrence D'Anna return m.takeError(); 1521d9b553ecSLawrence D'Anna mode = m.get(); 1522d9b553ecSLawrence D'Anna } 1523d9b553ecSLawrence D'Anna 1524d9b553ecSLawrence D'Anna PyObject *file_obj; 1525d9b553ecSLawrence D'Anna #if PY_MAJOR_VERSION >= 3 1526d9b553ecSLawrence D'Anna file_obj = PyFile_FromFd(file.GetDescriptor(), nullptr, mode, -1, nullptr, 15273071ebf7SLawrence D'Anna "ignore", nullptr, /*closefd=*/0); 1528d9b553ecSLawrence D'Anna #else 15293071ebf7SLawrence D'Anna // I'd like to pass ::fflush here if the file is writable, so that 15303071ebf7SLawrence D'Anna // when the python side destructs the file object it will be flushed. 15313071ebf7SLawrence D'Anna // However, this would be dangerous. It can cause fflush to be called 15323071ebf7SLawrence D'Anna // after fclose if the python program keeps a reference to the file after 15333071ebf7SLawrence D'Anna // the original lldb_private::File has been destructed. 15343071ebf7SLawrence D'Anna // 15353071ebf7SLawrence D'Anna // It's all well and good to ask a python program not to use a closed file 15363071ebf7SLawrence D'Anna // but asking a python program to make sure objects get released in a 15373071ebf7SLawrence D'Anna // particular order is not safe. 15383071ebf7SLawrence D'Anna // 15393071ebf7SLawrence D'Anna // The tradeoff here is that if a python 2 program wants to make sure this 15403071ebf7SLawrence D'Anna // file gets flushed, they'll have to do it explicitly or wait untill the 15413071ebf7SLawrence D'Anna // original lldb File itself gets flushed. 15426a93a12aSLawrence D'Anna file_obj = PyFile_FromFile(file.GetStream(), py2_const_cast(""), 15433071ebf7SLawrence D'Anna py2_const_cast(mode), [](FILE *) { return 0; }); 1544d9b553ecSLawrence D'Anna #endif 1545d9b553ecSLawrence D'Anna 1546d9b553ecSLawrence D'Anna if (!file_obj) 1547d9b553ecSLawrence D'Anna return exception(); 1548d9b553ecSLawrence D'Anna 1549d9b553ecSLawrence D'Anna return Take<PythonFile>(file_obj); 1550d9b553ecSLawrence D'Anna } 1551d9b553ecSLawrence D'Anna 155204edd189SLawrence D'Anna Error PythonScript::Init() { 155304edd189SLawrence D'Anna if (function.IsValid()) 155404edd189SLawrence D'Anna return Error::success(); 155504edd189SLawrence D'Anna 155604edd189SLawrence D'Anna PythonDictionary globals(PyInitialValue::Empty); 155704edd189SLawrence D'Anna auto builtins = PythonModule::BuiltinsModule(); 155804edd189SLawrence D'Anna if (Error error = globals.SetItem("__builtins__", builtins)) 155904edd189SLawrence D'Anna return error; 156004edd189SLawrence D'Anna PyObject *o = 156104edd189SLawrence D'Anna PyRun_String(script, Py_file_input, globals.get(), globals.get()); 156204edd189SLawrence D'Anna if (!o) 156304edd189SLawrence D'Anna return exception(); 156404edd189SLawrence D'Anna Take<PythonObject>(o); 156504edd189SLawrence D'Anna auto f = As<PythonCallable>(globals.GetItem("main")); 156604edd189SLawrence D'Anna if (!f) 156704edd189SLawrence D'Anna return f.takeError(); 156804edd189SLawrence D'Anna function = std::move(f.get()); 156904edd189SLawrence D'Anna 157004edd189SLawrence D'Anna return Error::success(); 157104edd189SLawrence D'Anna } 157204edd189SLawrence D'Anna 157304edd189SLawrence D'Anna llvm::Expected<PythonObject> 157404edd189SLawrence D'Anna python::runStringOneLine(const llvm::Twine &string, 157504edd189SLawrence D'Anna const PythonDictionary &globals, 157604edd189SLawrence D'Anna const PythonDictionary &locals) { 157704edd189SLawrence D'Anna if (!globals.IsValid() || !locals.IsValid()) 157804edd189SLawrence D'Anna return nullDeref(); 157904edd189SLawrence D'Anna 158004edd189SLawrence D'Anna PyObject *code = 158104edd189SLawrence D'Anna Py_CompileString(NullTerminated(string), "<string>", Py_eval_input); 158204edd189SLawrence D'Anna if (!code) { 158304edd189SLawrence D'Anna PyErr_Clear(); 158404edd189SLawrence D'Anna code = 158504edd189SLawrence D'Anna Py_CompileString(NullTerminated(string), "<string>", Py_single_input); 158604edd189SLawrence D'Anna } 158704edd189SLawrence D'Anna if (!code) 158804edd189SLawrence D'Anna return exception(); 158904edd189SLawrence D'Anna auto code_ref = Take<PythonObject>(code); 159004edd189SLawrence D'Anna 159104edd189SLawrence D'Anna #if PY_MAJOR_VERSION < 3 159204edd189SLawrence D'Anna PyObject *result = 159304edd189SLawrence D'Anna PyEval_EvalCode((PyCodeObject *)code, globals.get(), locals.get()); 159404edd189SLawrence D'Anna #else 159504edd189SLawrence D'Anna PyObject *result = PyEval_EvalCode(code, globals.get(), locals.get()); 159604edd189SLawrence D'Anna #endif 159704edd189SLawrence D'Anna 159804edd189SLawrence D'Anna if (!result) 159904edd189SLawrence D'Anna return exception(); 160004edd189SLawrence D'Anna 160104edd189SLawrence D'Anna return Take<PythonObject>(result); 160204edd189SLawrence D'Anna } 160304edd189SLawrence D'Anna 160404edd189SLawrence D'Anna llvm::Expected<PythonObject> 160504edd189SLawrence D'Anna python::runStringMultiLine(const llvm::Twine &string, 160604edd189SLawrence D'Anna const PythonDictionary &globals, 160704edd189SLawrence D'Anna const PythonDictionary &locals) { 160804edd189SLawrence D'Anna if (!globals.IsValid() || !locals.IsValid()) 160904edd189SLawrence D'Anna return nullDeref(); 161004edd189SLawrence D'Anna PyObject *result = PyRun_String(NullTerminated(string), Py_file_input, 161104edd189SLawrence D'Anna globals.get(), locals.get()); 161204edd189SLawrence D'Anna if (!result) 161304edd189SLawrence D'Anna return exception(); 161404edd189SLawrence D'Anna return Take<PythonObject>(result); 161504edd189SLawrence D'Anna } 161604edd189SLawrence D'Anna 1617d68983e3SPavel Labath #endif 1618