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; 34085328eeSLawrence D'Anna using llvm::Error; 35085328eeSLawrence D'Anna using llvm::Expected; 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(); 47085328eeSLawrence D'Anna return obj.get().AsLongLong(); 48085328eeSLawrence D'Anna } 492c1f46dcSZachary Turner 502783d817SJonas Devlieghere void StructuredPythonObject::Serialize(llvm::json::OStream &s) const { 512783d817SJonas Devlieghere s.value(llvm::formatv("Python Obj: {0:X}", GetValue()).str()); 522c1f46dcSZachary Turner } 532c1f46dcSZachary Turner 542c1f46dcSZachary Turner // PythonObject 552c1f46dcSZachary Turner 56b9c1b51eSKate Stone void PythonObject::Dump(Stream &strm) const { 57b9c1b51eSKate Stone if (m_py_obj) { 582819136fSMichal Gorny FILE *file = llvm::sys::RetryAfterSignal(nullptr, ::tmpfile); 59b9c1b51eSKate Stone if (file) { 602c1f46dcSZachary Turner ::PyObject_Print(m_py_obj, file, 0); 612c1f46dcSZachary Turner const long length = ftell(file); 62b9c1b51eSKate Stone if (length) { 632c1f46dcSZachary Turner ::rewind(file); 642c1f46dcSZachary Turner std::vector<char> file_contents(length, '\0'); 65b9c1b51eSKate Stone const size_t length_read = 66b9c1b51eSKate Stone ::fread(file_contents.data(), 1, file_contents.size(), file); 672c1f46dcSZachary Turner if (length_read > 0) 682c1f46dcSZachary Turner strm.Write(file_contents.data(), length_read); 692c1f46dcSZachary Turner } 702c1f46dcSZachary Turner ::fclose(file); 712c1f46dcSZachary Turner } 72b9c1b51eSKate Stone } else 732c1f46dcSZachary Turner strm.PutCString("NULL"); 742c1f46dcSZachary Turner } 752c1f46dcSZachary Turner 76b9c1b51eSKate Stone PyObjectType PythonObject::GetObjectType() const { 77f8b22f8fSZachary Turner if (!IsAllocated()) 782c1f46dcSZachary Turner return PyObjectType::None; 792c1f46dcSZachary Turner 807841efbbSZachary Turner if (PythonModule::Check(m_py_obj)) 817841efbbSZachary Turner return PyObjectType::Module; 8218426935SZachary Turner if (PythonList::Check(m_py_obj)) 832c1f46dcSZachary Turner return PyObjectType::List; 84a1405147SZachary Turner if (PythonTuple::Check(m_py_obj)) 85a1405147SZachary Turner return PyObjectType::Tuple; 8618426935SZachary Turner if (PythonDictionary::Check(m_py_obj)) 872c1f46dcSZachary Turner return PyObjectType::Dictionary; 8818426935SZachary Turner if (PythonString::Check(m_py_obj)) 8922c8efcdSZachary Turner return PyObjectType::String; 905a72c02bSZachary Turner #if PY_MAJOR_VERSION >= 3 915a72c02bSZachary Turner if (PythonBytes::Check(m_py_obj)) 925a72c02bSZachary Turner return PyObjectType::Bytes; 935a72c02bSZachary Turner #endif 94f9d6d204SZachary Turner if (PythonByteArray::Check(m_py_obj)) 95f9d6d204SZachary Turner return PyObjectType::ByteArray; 96b81d715cSTatyana Krasnukha if (PythonBoolean::Check(m_py_obj)) 97b81d715cSTatyana Krasnukha return PyObjectType::Boolean; 9818426935SZachary Turner if (PythonInteger::Check(m_py_obj)) 9922c8efcdSZachary Turner return PyObjectType::Integer; 1009c40264fSZachary Turner if (PythonFile::Check(m_py_obj)) 1019c40264fSZachary Turner return PyObjectType::File; 102a1405147SZachary Turner if (PythonCallable::Check(m_py_obj)) 103a1405147SZachary Turner return PyObjectType::Callable; 1042c1f46dcSZachary Turner return PyObjectType::Unknown; 1052c1f46dcSZachary Turner } 1062c1f46dcSZachary Turner 107b9c1b51eSKate Stone PythonString PythonObject::Repr() const { 1082c1f46dcSZachary Turner if (!m_py_obj) 1092c1f46dcSZachary Turner return PythonString(); 1102c1f46dcSZachary Turner PyObject *repr = PyObject_Repr(m_py_obj); 1112c1f46dcSZachary Turner if (!repr) 1122c1f46dcSZachary Turner return PythonString(); 113f8b22f8fSZachary Turner return PythonString(PyRefType::Owned, repr); 1142c1f46dcSZachary Turner } 1152c1f46dcSZachary Turner 116b9c1b51eSKate Stone PythonString PythonObject::Str() const { 1172c1f46dcSZachary Turner if (!m_py_obj) 1182c1f46dcSZachary Turner return PythonString(); 1192c1f46dcSZachary Turner PyObject *str = PyObject_Str(m_py_obj); 1202c1f46dcSZachary Turner if (!str) 1212c1f46dcSZachary Turner return PythonString(); 122f8b22f8fSZachary Turner return PythonString(PyRefType::Owned, str); 1232c1f46dcSZachary Turner } 1242c1f46dcSZachary Turner 1257841efbbSZachary Turner PythonObject 126b9c1b51eSKate Stone PythonObject::ResolveNameWithDictionary(llvm::StringRef name, 127b9c1b51eSKate Stone const PythonDictionary &dict) { 128c712bac7SJonas Devlieghere size_t dot_pos = name.find('.'); 129a1405147SZachary Turner llvm::StringRef piece = name.substr(0, dot_pos); 130a1405147SZachary Turner PythonObject result = dict.GetItemForKey(PythonString(piece)); 131b9c1b51eSKate Stone if (dot_pos == llvm::StringRef::npos) { 132a1405147SZachary Turner // There was no dot, we're done. 133a1405147SZachary Turner return result; 134a1405147SZachary Turner } 135a1405147SZachary Turner 136a1405147SZachary Turner // There was a dot. The remaining portion of the name should be looked up in 137a1405147SZachary Turner // the context of the object that was found in the dictionary. 138a1405147SZachary Turner return result.ResolveName(name.substr(dot_pos + 1)); 1397841efbbSZachary Turner } 1407841efbbSZachary Turner 141b9c1b51eSKate Stone PythonObject PythonObject::ResolveName(llvm::StringRef name) const { 14205097246SAdrian Prantl // Resolve the name in the context of the specified object. If, for example, 14305097246SAdrian Prantl // `this` refers to a PyModule, then this will look for `name` in this 14405097246SAdrian Prantl // module. If `this` refers to a PyType, then it will resolve `name` as an 14505097246SAdrian Prantl // attribute of that type. If `this` refers to an instance of an object, 14605097246SAdrian Prantl // then it will resolve `name` as the value of the specified field. 1477841efbbSZachary Turner // 1487841efbbSZachary Turner // This function handles dotted names so that, for example, if `m_py_obj` 14905097246SAdrian Prantl // refers to the `sys` module, and `name` == "path.append", then it will find 15005097246SAdrian Prantl // the function `sys.path.append`. 1517841efbbSZachary Turner 152c712bac7SJonas Devlieghere size_t dot_pos = name.find('.'); 153b9c1b51eSKate Stone if (dot_pos == llvm::StringRef::npos) { 15405097246SAdrian Prantl // No dots in the name, we should be able to find the value immediately as 15505097246SAdrian Prantl // an attribute of `m_py_obj`. 1567841efbbSZachary Turner return GetAttributeValue(name); 1577841efbbSZachary Turner } 1587841efbbSZachary Turner 159b9c1b51eSKate Stone // Look up the first piece of the name, and resolve the rest as a child of 160b9c1b51eSKate Stone // that. 1617841efbbSZachary Turner PythonObject parent = ResolveName(name.substr(0, dot_pos)); 1627841efbbSZachary Turner if (!parent.IsAllocated()) 1637841efbbSZachary Turner return PythonObject(); 1647841efbbSZachary Turner 1657841efbbSZachary Turner // Tail recursion.. should be optimized by the compiler 1667841efbbSZachary Turner return parent.ResolveName(name.substr(dot_pos + 1)); 1677841efbbSZachary Turner } 1687841efbbSZachary Turner 169b9c1b51eSKate Stone bool PythonObject::HasAttribute(llvm::StringRef attr) const { 1709c40264fSZachary Turner if (!IsValid()) 1719c40264fSZachary Turner return false; 1729c40264fSZachary Turner PythonString py_attr(attr); 1739c40264fSZachary Turner return !!PyObject_HasAttr(m_py_obj, py_attr.get()); 1749c40264fSZachary Turner } 1759c40264fSZachary Turner 176b9c1b51eSKate Stone PythonObject PythonObject::GetAttributeValue(llvm::StringRef attr) const { 1777d6d218eSZachary Turner if (!IsValid()) 1787d6d218eSZachary Turner return PythonObject(); 1797d6d218eSZachary Turner 1807d6d218eSZachary Turner PythonString py_attr(attr); 1817d6d218eSZachary Turner if (!PyObject_HasAttr(m_py_obj, py_attr.get())) 1827d6d218eSZachary Turner return PythonObject(); 1837d6d218eSZachary Turner 1847d6d218eSZachary Turner return PythonObject(PyRefType::Owned, 1857d6d218eSZachary Turner PyObject_GetAttr(m_py_obj, py_attr.get())); 1867d6d218eSZachary Turner } 1877d6d218eSZachary Turner 188b9c1b51eSKate Stone StructuredData::ObjectSP PythonObject::CreateStructuredObject() const { 189b9c1b51eSKate Stone switch (GetObjectType()) { 1902c1f46dcSZachary Turner case PyObjectType::Dictionary: 191b9c1b51eSKate Stone return PythonDictionary(PyRefType::Borrowed, m_py_obj) 192b9c1b51eSKate Stone .CreateStructuredDictionary(); 193b81d715cSTatyana Krasnukha case PyObjectType::Boolean: 194b81d715cSTatyana Krasnukha return PythonBoolean(PyRefType::Borrowed, m_py_obj) 195b81d715cSTatyana Krasnukha .CreateStructuredBoolean(); 1962c1f46dcSZachary Turner case PyObjectType::Integer: 197b9c1b51eSKate Stone return PythonInteger(PyRefType::Borrowed, m_py_obj) 198b9c1b51eSKate Stone .CreateStructuredInteger(); 1992c1f46dcSZachary Turner case PyObjectType::List: 200f8b22f8fSZachary Turner return PythonList(PyRefType::Borrowed, m_py_obj).CreateStructuredArray(); 2012c1f46dcSZachary Turner case PyObjectType::String: 202f8b22f8fSZachary Turner return PythonString(PyRefType::Borrowed, m_py_obj).CreateStructuredString(); 2035a72c02bSZachary Turner case PyObjectType::Bytes: 2045a72c02bSZachary Turner return PythonBytes(PyRefType::Borrowed, m_py_obj).CreateStructuredString(); 205f9d6d204SZachary Turner case PyObjectType::ByteArray: 206b9c1b51eSKate Stone return PythonByteArray(PyRefType::Borrowed, m_py_obj) 207b9c1b51eSKate Stone .CreateStructuredString(); 2082c1f46dcSZachary Turner case PyObjectType::None: 2092c1f46dcSZachary Turner return StructuredData::ObjectSP(); 2102c1f46dcSZachary Turner default: 2112c1f46dcSZachary Turner return StructuredData::ObjectSP(new StructuredPythonObject(m_py_obj)); 2122c1f46dcSZachary Turner } 2132c1f46dcSZachary Turner } 2142c1f46dcSZachary Turner 2152c1f46dcSZachary Turner // PythonString 2165a72c02bSZachary Turner 217*d3bd5b3dSLawrence D'Anna PythonBytes::PythonBytes(llvm::ArrayRef<uint8_t> bytes) { SetBytes(bytes); } 2185a72c02bSZachary Turner 219*d3bd5b3dSLawrence D'Anna PythonBytes::PythonBytes(const uint8_t *bytes, size_t length) { 2205a72c02bSZachary Turner SetBytes(llvm::ArrayRef<uint8_t>(bytes, length)); 2215a72c02bSZachary Turner } 2225a72c02bSZachary Turner 223b9c1b51eSKate Stone bool PythonBytes::Check(PyObject *py_obj) { 2245a72c02bSZachary Turner if (!py_obj) 2255a72c02bSZachary Turner return false; 226a6682a41SJonas Devlieghere return PyBytes_Check(py_obj); 2275a72c02bSZachary Turner } 2285a72c02bSZachary Turner 229b9c1b51eSKate Stone llvm::ArrayRef<uint8_t> PythonBytes::GetBytes() const { 2305a72c02bSZachary Turner if (!IsValid()) 2315a72c02bSZachary Turner return llvm::ArrayRef<uint8_t>(); 2325a72c02bSZachary Turner 2335a72c02bSZachary Turner Py_ssize_t size; 2345a72c02bSZachary Turner char *c; 2355a72c02bSZachary Turner 2365a72c02bSZachary Turner PyBytes_AsStringAndSize(m_py_obj, &c, &size); 2375a72c02bSZachary Turner return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size); 2385a72c02bSZachary Turner } 2395a72c02bSZachary Turner 240b9c1b51eSKate Stone size_t PythonBytes::GetSize() const { 2415a72c02bSZachary Turner if (!IsValid()) 2425a72c02bSZachary Turner return 0; 2435a72c02bSZachary Turner return PyBytes_Size(m_py_obj); 2445a72c02bSZachary Turner } 2455a72c02bSZachary Turner 246b9c1b51eSKate Stone void PythonBytes::SetBytes(llvm::ArrayRef<uint8_t> bytes) { 2475a72c02bSZachary Turner const char *data = reinterpret_cast<const char *>(bytes.data()); 2485a72c02bSZachary Turner PyObject *py_bytes = PyBytes_FromStringAndSize(data, bytes.size()); 2495a72c02bSZachary Turner PythonObject::Reset(PyRefType::Owned, py_bytes); 2505a72c02bSZachary Turner } 2515a72c02bSZachary Turner 252b9c1b51eSKate Stone StructuredData::StringSP PythonBytes::CreateStructuredString() const { 2535a72c02bSZachary Turner StructuredData::StringSP result(new StructuredData::String); 2545a72c02bSZachary Turner Py_ssize_t size; 2555a72c02bSZachary Turner char *c; 2565a72c02bSZachary Turner PyBytes_AsStringAndSize(m_py_obj, &c, &size); 2575a72c02bSZachary Turner result->SetValue(std::string(c, size)); 2585a72c02bSZachary Turner return result; 2595a72c02bSZachary Turner } 2605a72c02bSZachary Turner 261b9c1b51eSKate Stone PythonByteArray::PythonByteArray(llvm::ArrayRef<uint8_t> bytes) 262b9c1b51eSKate Stone : PythonByteArray(bytes.data(), bytes.size()) {} 263f9d6d204SZachary Turner 264b9c1b51eSKate Stone PythonByteArray::PythonByteArray(const uint8_t *bytes, size_t length) { 265f9d6d204SZachary Turner const char *str = reinterpret_cast<const char *>(bytes); 266f9d6d204SZachary Turner Reset(PyRefType::Owned, PyByteArray_FromStringAndSize(str, length)); 267f9d6d204SZachary Turner } 268f9d6d204SZachary Turner 269b9c1b51eSKate Stone bool PythonByteArray::Check(PyObject *py_obj) { 270f9d6d204SZachary Turner if (!py_obj) 271f9d6d204SZachary Turner return false; 272a6682a41SJonas Devlieghere return PyByteArray_Check(py_obj); 273f9d6d204SZachary Turner } 274f9d6d204SZachary Turner 275b9c1b51eSKate Stone llvm::ArrayRef<uint8_t> PythonByteArray::GetBytes() const { 276f9d6d204SZachary Turner if (!IsValid()) 277f9d6d204SZachary Turner return llvm::ArrayRef<uint8_t>(); 278f9d6d204SZachary Turner 279f9d6d204SZachary Turner char *c = PyByteArray_AsString(m_py_obj); 280f9d6d204SZachary Turner size_t size = GetSize(); 281f9d6d204SZachary Turner return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size); 282f9d6d204SZachary Turner } 283f9d6d204SZachary Turner 284b9c1b51eSKate Stone size_t PythonByteArray::GetSize() const { 285f9d6d204SZachary Turner if (!IsValid()) 286f9d6d204SZachary Turner return 0; 287f9d6d204SZachary Turner 288f9d6d204SZachary Turner return PyByteArray_Size(m_py_obj); 289f9d6d204SZachary Turner } 290f9d6d204SZachary Turner 291b9c1b51eSKate Stone StructuredData::StringSP PythonByteArray::CreateStructuredString() const { 292f9d6d204SZachary Turner StructuredData::StringSP result(new StructuredData::String); 293f9d6d204SZachary Turner llvm::ArrayRef<uint8_t> bytes = GetBytes(); 294f9d6d204SZachary Turner const char *str = reinterpret_cast<const char *>(bytes.data()); 295f9d6d204SZachary Turner result->SetValue(std::string(str, bytes.size())); 296f9d6d204SZachary Turner return result; 297f9d6d204SZachary Turner } 298f9d6d204SZachary Turner 2995a72c02bSZachary Turner // PythonString 3002c1f46dcSZachary Turner 301085328eeSLawrence D'Anna Expected<PythonString> PythonString::FromUTF8(llvm::StringRef string) { 302085328eeSLawrence D'Anna #if PY_MAJOR_VERSION >= 3 303085328eeSLawrence D'Anna PyObject *str = PyUnicode_FromStringAndSize(string.data(), string.size()); 304085328eeSLawrence D'Anna #else 305085328eeSLawrence D'Anna PyObject *str = PyString_FromStringAndSize(string.data(), string.size()); 306085328eeSLawrence D'Anna #endif 307085328eeSLawrence D'Anna if (!str) 308085328eeSLawrence D'Anna return llvm::make_error<PythonException>(); 309085328eeSLawrence D'Anna return Take<PythonString>(str); 310085328eeSLawrence D'Anna } 311085328eeSLawrence D'Anna 312*d3bd5b3dSLawrence D'Anna PythonString::PythonString(llvm::StringRef string) { SetString(string); } 3132c1f46dcSZachary Turner 314b9c1b51eSKate Stone bool PythonString::Check(PyObject *py_obj) { 31522c8efcdSZachary Turner if (!py_obj) 31622c8efcdSZachary Turner return false; 31718426935SZachary Turner 3187d6d218eSZachary Turner if (PyUnicode_Check(py_obj)) 3197d6d218eSZachary Turner return true; 3207d6d218eSZachary Turner #if PY_MAJOR_VERSION < 3 3217d6d218eSZachary Turner if (PyString_Check(py_obj)) 3227d6d218eSZachary Turner return true; 32322c8efcdSZachary Turner #endif 3247d6d218eSZachary Turner return false; 32522c8efcdSZachary Turner } 32622c8efcdSZachary Turner 327*d3bd5b3dSLawrence D'Anna void PythonString::Convert(PyRefType &type, PyObject *&py_obj) { 3287d6d218eSZachary Turner #if PY_MAJOR_VERSION < 3 3297d6d218eSZachary Turner // In Python 2, Don't store PyUnicode objects directly, because we need 3307d6d218eSZachary Turner // access to their underlying character buffers which Python 2 doesn't 3317d6d218eSZachary Turner // provide. 332085328eeSLawrence D'Anna if (PyUnicode_Check(py_obj)) { 333*d3bd5b3dSLawrence D'Anna PyObject *s = PyUnicode_AsUTF8String(py_obj); 334*d3bd5b3dSLawrence D'Anna if (s == nullptr) { 335085328eeSLawrence D'Anna PyErr_Clear(); 336*d3bd5b3dSLawrence D'Anna if (type == PyRefType::Owned) 337*d3bd5b3dSLawrence D'Anna Py_DECREF(py_obj); 338*d3bd5b3dSLawrence D'Anna return; 339*d3bd5b3dSLawrence D'Anna } 340*d3bd5b3dSLawrence D'Anna if (type == PyRefType::Owned) 341*d3bd5b3dSLawrence D'Anna Py_DECREF(py_obj); 342*d3bd5b3dSLawrence D'Anna else 343*d3bd5b3dSLawrence D'Anna type = PyRefType::Owned; 344*d3bd5b3dSLawrence D'Anna py_obj = s; 345085328eeSLawrence D'Anna } 3467d6d218eSZachary Turner #endif 3472c1f46dcSZachary Turner } 3482c1f46dcSZachary Turner 349b9c1b51eSKate Stone llvm::StringRef PythonString::GetString() const { 350085328eeSLawrence D'Anna auto s = AsUTF8(); 351085328eeSLawrence D'Anna if (!s) { 352085328eeSLawrence D'Anna llvm::consumeError(s.takeError()); 353085328eeSLawrence D'Anna return llvm::StringRef(""); 354085328eeSLawrence D'Anna } 355085328eeSLawrence D'Anna return s.get(); 356085328eeSLawrence D'Anna } 357085328eeSLawrence D'Anna 358085328eeSLawrence D'Anna Expected<llvm::StringRef> PythonString::AsUTF8() const { 35918426935SZachary Turner if (!IsValid()) 360085328eeSLawrence D'Anna return nullDeref(); 36118426935SZachary Turner 36222c8efcdSZachary Turner Py_ssize_t size; 3635457b426SPavel Labath const char *data; 36418426935SZachary Turner 36518426935SZachary Turner #if PY_MAJOR_VERSION >= 3 3665457b426SPavel Labath data = PyUnicode_AsUTF8AndSize(m_py_obj, &size); 36718426935SZachary Turner #else 368085328eeSLawrence D'Anna char *c = NULL; 369085328eeSLawrence D'Anna int r = PyString_AsStringAndSize(m_py_obj, &c, &size); 370085328eeSLawrence D'Anna if (r < 0) 371085328eeSLawrence D'Anna c = NULL; 3725457b426SPavel Labath data = c; 37318426935SZachary Turner #endif 374085328eeSLawrence D'Anna 375085328eeSLawrence D'Anna if (!data) 376085328eeSLawrence D'Anna return exception(); 377085328eeSLawrence D'Anna 3785457b426SPavel Labath return llvm::StringRef(data, size); 37922c8efcdSZachary Turner } 3802c1f46dcSZachary Turner 381b9c1b51eSKate Stone size_t PythonString::GetSize() const { 382b9c1b51eSKate Stone if (IsValid()) { 38318426935SZachary Turner #if PY_MAJOR_VERSION >= 3 38418426935SZachary Turner return PyUnicode_GetSize(m_py_obj); 38518426935SZachary Turner #else 38618426935SZachary Turner return PyString_Size(m_py_obj); 38718426935SZachary Turner #endif 38818426935SZachary Turner } 3892c1f46dcSZachary Turner return 0; 3902c1f46dcSZachary Turner } 3912c1f46dcSZachary Turner 392b9c1b51eSKate Stone void PythonString::SetString(llvm::StringRef string) { 393085328eeSLawrence D'Anna auto s = FromUTF8(string); 394085328eeSLawrence D'Anna if (!s) { 395085328eeSLawrence D'Anna llvm::consumeError(s.takeError()); 396085328eeSLawrence D'Anna Reset(); 397085328eeSLawrence D'Anna } else { 398085328eeSLawrence D'Anna PythonObject::Reset(std::move(s.get())); 399085328eeSLawrence D'Anna } 4002c1f46dcSZachary Turner } 4012c1f46dcSZachary Turner 402b9c1b51eSKate Stone StructuredData::StringSP PythonString::CreateStructuredString() const { 4032c1f46dcSZachary Turner StructuredData::StringSP result(new StructuredData::String); 4042c1f46dcSZachary Turner result->SetValue(GetString()); 4052c1f46dcSZachary Turner return result; 4062c1f46dcSZachary Turner } 4072c1f46dcSZachary Turner 4082c1f46dcSZachary Turner // PythonInteger 4092c1f46dcSZachary Turner 410*d3bd5b3dSLawrence D'Anna PythonInteger::PythonInteger(int64_t value) { SetInteger(value); } 4112c1f46dcSZachary Turner 412b9c1b51eSKate Stone bool PythonInteger::Check(PyObject *py_obj) { 41322c8efcdSZachary Turner if (!py_obj) 41422c8efcdSZachary Turner return false; 41522c8efcdSZachary Turner 41622c8efcdSZachary Turner #if PY_MAJOR_VERSION >= 3 41705097246SAdrian Prantl // Python 3 does not have PyInt_Check. There is only one type of integral 41805097246SAdrian Prantl // value, long. 41922c8efcdSZachary Turner return PyLong_Check(py_obj); 42022c8efcdSZachary Turner #else 42122c8efcdSZachary Turner return PyLong_Check(py_obj) || PyInt_Check(py_obj); 42222c8efcdSZachary Turner #endif 4232c1f46dcSZachary Turner } 4242c1f46dcSZachary Turner 425*d3bd5b3dSLawrence D'Anna void PythonInteger::Convert(PyRefType &type, PyObject *&py_obj) { 42622c8efcdSZachary Turner #if PY_MAJOR_VERSION < 3 42705097246SAdrian Prantl // Always store this as a PyLong, which makes interoperability between Python 42805097246SAdrian Prantl // 2.x and Python 3.x easier. This is only necessary in 2.x, since 3.x 42905097246SAdrian Prantl // doesn't even have a PyInt. 430b9c1b51eSKate Stone if (PyInt_Check(py_obj)) { 431f8b22f8fSZachary Turner // Since we converted the original object to a different type, the new 43205097246SAdrian Prantl // object is an owned object regardless of the ownership semantics 43305097246SAdrian Prantl // requested by the user. 434*d3bd5b3dSLawrence D'Anna long long value = PyInt_AsLong(py_obj); 435*d3bd5b3dSLawrence D'Anna PyObject *l = nullptr; 436*d3bd5b3dSLawrence D'Anna if (!PyErr_Occurred()) 437*d3bd5b3dSLawrence D'Anna l = PyLong_FromLongLong(value); 438*d3bd5b3dSLawrence D'Anna if (l == nullptr) { 439*d3bd5b3dSLawrence D'Anna PyErr_Clear(); 440*d3bd5b3dSLawrence D'Anna if (type == PyRefType::Owned) 441*d3bd5b3dSLawrence D'Anna Py_DECREF(py_obj); 442*d3bd5b3dSLawrence D'Anna return; 443*d3bd5b3dSLawrence D'Anna } 444*d3bd5b3dSLawrence D'Anna if (type == PyRefType::Owned) 445*d3bd5b3dSLawrence D'Anna Py_DECREF(py_obj); 446*d3bd5b3dSLawrence D'Anna else 447*d3bd5b3dSLawrence D'Anna type = PyRefType::Owned; 448*d3bd5b3dSLawrence D'Anna py_obj = l; 44922c8efcdSZachary Turner } 45022c8efcdSZachary Turner #endif 4512c1f46dcSZachary Turner } 4522c1f46dcSZachary Turner 453b9c1b51eSKate Stone int64_t PythonInteger::GetInteger() const { 454b9c1b51eSKate Stone if (m_py_obj) { 455b9c1b51eSKate Stone assert(PyLong_Check(m_py_obj) && 456b9c1b51eSKate Stone "PythonInteger::GetInteger has a PyObject that isn't a PyLong"); 45722c8efcdSZachary Turner 458008ec446SGreg Clayton int overflow = 0; 459008ec446SGreg Clayton int64_t result = PyLong_AsLongLongAndOverflow(m_py_obj, &overflow); 460b9c1b51eSKate Stone if (overflow != 0) { 46105097246SAdrian Prantl // We got an integer that overflows, like 18446744072853913392L we can't 46205097246SAdrian Prantl // use PyLong_AsLongLong() as it will return 0xffffffffffffffff. If we 46305097246SAdrian Prantl // use the unsigned long long it will work as expected. 464008ec446SGreg Clayton const uint64_t uval = PyLong_AsUnsignedLongLong(m_py_obj); 4654f730dc7SIlia K result = static_cast<int64_t>(uval); 466008ec446SGreg Clayton } 467008ec446SGreg Clayton return result; 4682c1f46dcSZachary Turner } 4692c1f46dcSZachary Turner return UINT64_MAX; 4702c1f46dcSZachary Turner } 4712c1f46dcSZachary Turner 472b9c1b51eSKate Stone void PythonInteger::SetInteger(int64_t value) { 473f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Owned, PyLong_FromLongLong(value)); 4742c1f46dcSZachary Turner } 4752c1f46dcSZachary Turner 476b9c1b51eSKate Stone StructuredData::IntegerSP PythonInteger::CreateStructuredInteger() const { 4772c1f46dcSZachary Turner StructuredData::IntegerSP result(new StructuredData::Integer); 4782c1f46dcSZachary Turner result->SetValue(GetInteger()); 4792c1f46dcSZachary Turner return result; 4802c1f46dcSZachary Turner } 4812c1f46dcSZachary Turner 482b81d715cSTatyana Krasnukha // PythonBoolean 483b81d715cSTatyana Krasnukha 484b81d715cSTatyana Krasnukha PythonBoolean::PythonBoolean(bool value) { 485b81d715cSTatyana Krasnukha SetValue(value); 486b81d715cSTatyana Krasnukha } 487b81d715cSTatyana Krasnukha 488b81d715cSTatyana Krasnukha bool PythonBoolean::Check(PyObject *py_obj) { 489b81d715cSTatyana Krasnukha return py_obj ? PyBool_Check(py_obj) : false; 490b81d715cSTatyana Krasnukha } 491b81d715cSTatyana Krasnukha 492b81d715cSTatyana Krasnukha bool PythonBoolean::GetValue() const { 493b81d715cSTatyana Krasnukha return m_py_obj ? PyObject_IsTrue(m_py_obj) : false; 494b81d715cSTatyana Krasnukha } 495b81d715cSTatyana Krasnukha 496b81d715cSTatyana Krasnukha void PythonBoolean::SetValue(bool value) { 497b81d715cSTatyana Krasnukha PythonObject::Reset(PyRefType::Owned, PyBool_FromLong(value)); 498b81d715cSTatyana Krasnukha } 499b81d715cSTatyana Krasnukha 500b81d715cSTatyana Krasnukha StructuredData::BooleanSP PythonBoolean::CreateStructuredBoolean() const { 501b81d715cSTatyana Krasnukha StructuredData::BooleanSP result(new StructuredData::Boolean); 502b81d715cSTatyana Krasnukha result->SetValue(GetValue()); 503b81d715cSTatyana Krasnukha return result; 504b81d715cSTatyana Krasnukha } 505b81d715cSTatyana Krasnukha 5062c1f46dcSZachary Turner // PythonList 5072c1f46dcSZachary Turner 508*d3bd5b3dSLawrence D'Anna PythonList::PythonList(PyInitialValue value) { 509f8b22f8fSZachary Turner if (value == PyInitialValue::Empty) 510f8b22f8fSZachary Turner Reset(PyRefType::Owned, PyList_New(0)); 5112c1f46dcSZachary Turner } 5122c1f46dcSZachary Turner 513*d3bd5b3dSLawrence D'Anna PythonList::PythonList(int list_size) { 51487f47729SZachary Turner Reset(PyRefType::Owned, PyList_New(list_size)); 51587f47729SZachary Turner } 51687f47729SZachary Turner 517b9c1b51eSKate Stone bool PythonList::Check(PyObject *py_obj) { 51822c8efcdSZachary Turner if (!py_obj) 51922c8efcdSZachary Turner return false; 52022c8efcdSZachary Turner return PyList_Check(py_obj); 52122c8efcdSZachary Turner } 52222c8efcdSZachary Turner 523b9c1b51eSKate Stone uint32_t PythonList::GetSize() const { 524f8b22f8fSZachary Turner if (IsValid()) 5252c1f46dcSZachary Turner return PyList_GET_SIZE(m_py_obj); 5262c1f46dcSZachary Turner return 0; 5272c1f46dcSZachary Turner } 5282c1f46dcSZachary Turner 529b9c1b51eSKate Stone PythonObject PythonList::GetItemAtIndex(uint32_t index) const { 530f8b22f8fSZachary Turner if (IsValid()) 531f8b22f8fSZachary Turner return PythonObject(PyRefType::Borrowed, PyList_GetItem(m_py_obj, index)); 5322c1f46dcSZachary Turner return PythonObject(); 5332c1f46dcSZachary Turner } 5342c1f46dcSZachary Turner 535b9c1b51eSKate Stone void PythonList::SetItemAtIndex(uint32_t index, const PythonObject &object) { 536b9c1b51eSKate Stone if (IsAllocated() && object.IsValid()) { 537f8b22f8fSZachary Turner // PyList_SetItem is documented to "steal" a reference, so we need to 538f8b22f8fSZachary Turner // convert it to an owned reference by incrementing it. 539f8b22f8fSZachary Turner Py_INCREF(object.get()); 5402c1f46dcSZachary Turner PyList_SetItem(m_py_obj, index, object.get()); 5412c1f46dcSZachary Turner } 542f8b22f8fSZachary Turner } 5432c1f46dcSZachary Turner 544b9c1b51eSKate Stone void PythonList::AppendItem(const PythonObject &object) { 545b9c1b51eSKate Stone if (IsAllocated() && object.IsValid()) { 546f8b22f8fSZachary Turner // `PyList_Append` does *not* steal a reference, so do not call `Py_INCREF` 547f8b22f8fSZachary Turner // here like we do with `PyList_SetItem`. 5482c1f46dcSZachary Turner PyList_Append(m_py_obj, object.get()); 5492c1f46dcSZachary Turner } 550f8b22f8fSZachary Turner } 5512c1f46dcSZachary Turner 552b9c1b51eSKate Stone StructuredData::ArraySP PythonList::CreateStructuredArray() const { 5532c1f46dcSZachary Turner StructuredData::ArraySP result(new StructuredData::Array); 5542c1f46dcSZachary Turner uint32_t count = GetSize(); 555b9c1b51eSKate Stone for (uint32_t i = 0; i < count; ++i) { 5562c1f46dcSZachary Turner PythonObject obj = GetItemAtIndex(i); 5572c1f46dcSZachary Turner result->AddItem(obj.CreateStructuredObject()); 5582c1f46dcSZachary Turner } 5592c1f46dcSZachary Turner return result; 5602c1f46dcSZachary Turner } 5612c1f46dcSZachary Turner 562a1405147SZachary Turner // PythonTuple 563a1405147SZachary Turner 564*d3bd5b3dSLawrence D'Anna PythonTuple::PythonTuple(PyInitialValue value) { 565a1405147SZachary Turner if (value == PyInitialValue::Empty) 566a1405147SZachary Turner Reset(PyRefType::Owned, PyTuple_New(0)); 567a1405147SZachary Turner } 568a1405147SZachary Turner 569*d3bd5b3dSLawrence D'Anna PythonTuple::PythonTuple(int tuple_size) { 570a1405147SZachary Turner Reset(PyRefType::Owned, PyTuple_New(tuple_size)); 571a1405147SZachary Turner } 572a1405147SZachary Turner 573b9c1b51eSKate Stone PythonTuple::PythonTuple(std::initializer_list<PythonObject> objects) { 574a1405147SZachary Turner m_py_obj = PyTuple_New(objects.size()); 575a1405147SZachary Turner 576a1405147SZachary Turner uint32_t idx = 0; 577b9c1b51eSKate Stone for (auto object : objects) { 578a1405147SZachary Turner if (object.IsValid()) 579a1405147SZachary Turner SetItemAtIndex(idx, object); 580a1405147SZachary Turner idx++; 581a1405147SZachary Turner } 582a1405147SZachary Turner } 583a1405147SZachary Turner 584b9c1b51eSKate Stone PythonTuple::PythonTuple(std::initializer_list<PyObject *> objects) { 585a1405147SZachary Turner m_py_obj = PyTuple_New(objects.size()); 586a1405147SZachary Turner 587a1405147SZachary Turner uint32_t idx = 0; 588b9c1b51eSKate Stone for (auto py_object : objects) { 589a1405147SZachary Turner PythonObject object(PyRefType::Borrowed, py_object); 590a1405147SZachary Turner if (object.IsValid()) 591a1405147SZachary Turner SetItemAtIndex(idx, object); 592a1405147SZachary Turner idx++; 593a1405147SZachary Turner } 594a1405147SZachary Turner } 595a1405147SZachary Turner 596b9c1b51eSKate Stone bool PythonTuple::Check(PyObject *py_obj) { 597a1405147SZachary Turner if (!py_obj) 598a1405147SZachary Turner return false; 599a1405147SZachary Turner return PyTuple_Check(py_obj); 600a1405147SZachary Turner } 601a1405147SZachary Turner 602b9c1b51eSKate Stone uint32_t PythonTuple::GetSize() const { 603a1405147SZachary Turner if (IsValid()) 604a1405147SZachary Turner return PyTuple_GET_SIZE(m_py_obj); 605a1405147SZachary Turner return 0; 606a1405147SZachary Turner } 607a1405147SZachary Turner 608b9c1b51eSKate Stone PythonObject PythonTuple::GetItemAtIndex(uint32_t index) const { 609a1405147SZachary Turner if (IsValid()) 610a1405147SZachary Turner return PythonObject(PyRefType::Borrowed, PyTuple_GetItem(m_py_obj, index)); 611a1405147SZachary Turner return PythonObject(); 612a1405147SZachary Turner } 613a1405147SZachary Turner 614b9c1b51eSKate Stone void PythonTuple::SetItemAtIndex(uint32_t index, const PythonObject &object) { 615b9c1b51eSKate Stone if (IsAllocated() && object.IsValid()) { 616a1405147SZachary Turner // PyTuple_SetItem is documented to "steal" a reference, so we need to 617a1405147SZachary Turner // convert it to an owned reference by incrementing it. 618a1405147SZachary Turner Py_INCREF(object.get()); 619a1405147SZachary Turner PyTuple_SetItem(m_py_obj, index, object.get()); 620a1405147SZachary Turner } 621a1405147SZachary Turner } 622a1405147SZachary Turner 623b9c1b51eSKate Stone StructuredData::ArraySP PythonTuple::CreateStructuredArray() const { 624a1405147SZachary Turner StructuredData::ArraySP result(new StructuredData::Array); 625a1405147SZachary Turner uint32_t count = GetSize(); 626b9c1b51eSKate Stone for (uint32_t i = 0; i < count; ++i) { 627a1405147SZachary Turner PythonObject obj = GetItemAtIndex(i); 628a1405147SZachary Turner result->AddItem(obj.CreateStructuredObject()); 629a1405147SZachary Turner } 630a1405147SZachary Turner return result; 631a1405147SZachary Turner } 632a1405147SZachary Turner 6332c1f46dcSZachary Turner // PythonDictionary 6342c1f46dcSZachary Turner 635*d3bd5b3dSLawrence D'Anna PythonDictionary::PythonDictionary(PyInitialValue value) { 636f8b22f8fSZachary Turner if (value == PyInitialValue::Empty) 637f8b22f8fSZachary Turner Reset(PyRefType::Owned, PyDict_New()); 6382c1f46dcSZachary Turner } 6392c1f46dcSZachary Turner 640b9c1b51eSKate Stone bool PythonDictionary::Check(PyObject *py_obj) { 64122c8efcdSZachary Turner if (!py_obj) 64222c8efcdSZachary Turner return false; 64322c8efcdSZachary Turner 64422c8efcdSZachary Turner return PyDict_Check(py_obj); 64522c8efcdSZachary Turner } 64622c8efcdSZachary Turner 647b9c1b51eSKate Stone uint32_t PythonDictionary::GetSize() const { 648f8b22f8fSZachary Turner if (IsValid()) 6492c1f46dcSZachary Turner return PyDict_Size(m_py_obj); 6502c1f46dcSZachary Turner return 0; 6512c1f46dcSZachary Turner } 6522c1f46dcSZachary Turner 653b9c1b51eSKate Stone PythonList PythonDictionary::GetKeys() const { 654f8b22f8fSZachary Turner if (IsValid()) 655f8b22f8fSZachary Turner return PythonList(PyRefType::Owned, PyDict_Keys(m_py_obj)); 656f8b22f8fSZachary Turner return PythonList(PyInitialValue::Invalid); 6572c1f46dcSZachary Turner } 6582c1f46dcSZachary Turner 659b9c1b51eSKate Stone PythonObject PythonDictionary::GetItemForKey(const PythonObject &key) const { 660f8b22f8fSZachary Turner if (IsAllocated() && key.IsValid()) 661b9c1b51eSKate Stone return PythonObject(PyRefType::Borrowed, 662b9c1b51eSKate Stone PyDict_GetItem(m_py_obj, key.get())); 6632c1f46dcSZachary Turner return PythonObject(); 6642c1f46dcSZachary Turner } 6652c1f46dcSZachary Turner 666b9c1b51eSKate Stone void PythonDictionary::SetItemForKey(const PythonObject &key, 667b9c1b51eSKate Stone const PythonObject &value) { 668f8b22f8fSZachary Turner if (IsAllocated() && key.IsValid() && value.IsValid()) 6692c1f46dcSZachary Turner PyDict_SetItem(m_py_obj, key.get(), value.get()); 6702c1f46dcSZachary Turner } 6712c1f46dcSZachary Turner 6722c1f46dcSZachary Turner StructuredData::DictionarySP 673b9c1b51eSKate Stone PythonDictionary::CreateStructuredDictionary() const { 6742c1f46dcSZachary Turner StructuredData::DictionarySP result(new StructuredData::Dictionary); 6752c1f46dcSZachary Turner PythonList keys(GetKeys()); 6762c1f46dcSZachary Turner uint32_t num_keys = keys.GetSize(); 677b9c1b51eSKate Stone for (uint32_t i = 0; i < num_keys; ++i) { 6782c1f46dcSZachary Turner PythonObject key = keys.GetItemAtIndex(i); 6792c1f46dcSZachary Turner PythonObject value = GetItemForKey(key); 6802c1f46dcSZachary Turner StructuredData::ObjectSP structured_value = value.CreateStructuredObject(); 681f8b22f8fSZachary Turner result->AddItem(key.Str().GetString(), structured_value); 6822c1f46dcSZachary Turner } 6832c1f46dcSZachary Turner return result; 6842c1f46dcSZachary Turner } 6852c1f46dcSZachary Turner 686b9c1b51eSKate Stone PythonModule PythonModule::BuiltinsModule() { 687a1405147SZachary Turner #if PY_MAJOR_VERSION >= 3 688a1405147SZachary Turner return AddModule("builtins"); 689a1405147SZachary Turner #else 690a1405147SZachary Turner return AddModule("__builtin__"); 691a1405147SZachary Turner #endif 692a1405147SZachary Turner } 693a1405147SZachary Turner 694b9c1b51eSKate Stone PythonModule PythonModule::MainModule() { return AddModule("__main__"); } 695a1405147SZachary Turner 696b9c1b51eSKate Stone PythonModule PythonModule::AddModule(llvm::StringRef module) { 697a1405147SZachary Turner std::string str = module.str(); 698a1405147SZachary Turner return PythonModule(PyRefType::Borrowed, PyImport_AddModule(str.c_str())); 6997841efbbSZachary Turner } 7007841efbbSZachary Turner 701085328eeSLawrence D'Anna Expected<PythonModule> PythonModule::Import(const char *name) { 702085328eeSLawrence D'Anna PyObject *mod = PyImport_ImportModule(name); 703085328eeSLawrence D'Anna if (!mod) 704085328eeSLawrence D'Anna return exception(); 705085328eeSLawrence D'Anna return Take<PythonModule>(mod); 706085328eeSLawrence D'Anna } 707085328eeSLawrence D'Anna 708085328eeSLawrence D'Anna Expected<PythonObject> PythonModule::Get(const char *name) { 709085328eeSLawrence D'Anna if (!IsValid()) 710085328eeSLawrence D'Anna return nullDeref(); 711085328eeSLawrence D'Anna PyObject *dict = PyModule_GetDict(m_py_obj); 712085328eeSLawrence D'Anna if (!dict) 713085328eeSLawrence D'Anna return exception(); 714085328eeSLawrence D'Anna PyObject *item = PyDict_GetItemString(dict, name); 715085328eeSLawrence D'Anna if (!item) 716085328eeSLawrence D'Anna return exception(); 717085328eeSLawrence D'Anna return Retain<PythonObject>(item); 7182419f1d5SZachary Turner } 7192419f1d5SZachary Turner 720b9c1b51eSKate Stone bool PythonModule::Check(PyObject *py_obj) { 7217841efbbSZachary Turner if (!py_obj) 7227841efbbSZachary Turner return false; 7237841efbbSZachary Turner 7247841efbbSZachary Turner return PyModule_Check(py_obj); 7257841efbbSZachary Turner } 7267841efbbSZachary Turner 727b9c1b51eSKate Stone PythonDictionary PythonModule::GetDictionary() const { 7287841efbbSZachary Turner return PythonDictionary(PyRefType::Borrowed, PyModule_GetDict(m_py_obj)); 7297841efbbSZachary Turner } 7307841efbbSZachary Turner 731b9c1b51eSKate Stone bool PythonCallable::Check(PyObject *py_obj) { 732a1405147SZachary Turner if (!py_obj) 733a1405147SZachary Turner return false; 734a1405147SZachary Turner 735a1405147SZachary Turner return PyCallable_Check(py_obj); 736a1405147SZachary Turner } 737a1405147SZachary Turner 73827a14f19SJim Ingham PythonCallable::ArgInfo PythonCallable::GetNumInitArguments() const { 73927a14f19SJim Ingham ArgInfo result = {0, false, false, false}; 74027a14f19SJim Ingham if (!IsValid()) 74127a14f19SJim Ingham return result; 74227a14f19SJim Ingham 74327a14f19SJim Ingham PythonObject __init__ = GetAttributeValue("__init__"); 74427a14f19SJim Ingham if (__init__.IsValid() ) { 74527a14f19SJim Ingham auto __init_callable__ = __init__.AsType<PythonCallable>(); 74627a14f19SJim Ingham if (__init_callable__.IsValid()) 74727a14f19SJim Ingham return __init_callable__.GetNumArguments(); 74827a14f19SJim Ingham } 74927a14f19SJim Ingham return result; 75027a14f19SJim Ingham } 75127a14f19SJim Ingham 752b9c1b51eSKate Stone PythonCallable::ArgInfo PythonCallable::GetNumArguments() const { 753a5d6765cSEnrico Granata ArgInfo result = {0, false, false, false}; 754a1405147SZachary Turner if (!IsValid()) 755b58fb2f4SZachary Turner return result; 756a1405147SZachary Turner 757a1405147SZachary Turner PyObject *py_func_obj = m_py_obj; 758b9c1b51eSKate Stone if (PyMethod_Check(py_func_obj)) { 759a1405147SZachary Turner py_func_obj = PyMethod_GET_FUNCTION(py_func_obj); 760a5d6765cSEnrico Granata PythonObject im_self = GetAttributeValue("im_self"); 761a5d6765cSEnrico Granata if (im_self.IsValid() && !im_self.IsNone()) 762a5d6765cSEnrico Granata result.is_bound_method = true; 763b9c1b51eSKate Stone } else { 764a5d6765cSEnrico Granata // see if this is a callable object with an __call__ method 765b9c1b51eSKate Stone if (!PyFunction_Check(py_func_obj)) { 766a5d6765cSEnrico Granata PythonObject __call__ = GetAttributeValue("__call__"); 767b9c1b51eSKate Stone if (__call__.IsValid()) { 768a5d6765cSEnrico Granata auto __callable__ = __call__.AsType<PythonCallable>(); 769b9c1b51eSKate Stone if (__callable__.IsValid()) { 770a5d6765cSEnrico Granata py_func_obj = PyMethod_GET_FUNCTION(__callable__.get()); 771a5d6765cSEnrico Granata PythonObject im_self = GetAttributeValue("im_self"); 772a5d6765cSEnrico Granata if (im_self.IsValid() && !im_self.IsNone()) 773a5d6765cSEnrico Granata result.is_bound_method = true; 774a5d6765cSEnrico Granata } 775a5d6765cSEnrico Granata } 776a5d6765cSEnrico Granata } 777a5d6765cSEnrico Granata } 778a1405147SZachary Turner 779a1405147SZachary Turner if (!py_func_obj) 780b58fb2f4SZachary Turner return result; 781a1405147SZachary Turner 782a1405147SZachary Turner PyCodeObject *code = (PyCodeObject *)PyFunction_GET_CODE(py_func_obj); 783a1405147SZachary Turner if (!code) 784b58fb2f4SZachary Turner return result; 785a1405147SZachary Turner 786b58fb2f4SZachary Turner result.count = code->co_argcount; 787b58fb2f4SZachary Turner result.has_varargs = !!(code->co_flags & CO_VARARGS); 788b58fb2f4SZachary Turner result.has_kwargs = !!(code->co_flags & CO_VARKEYWORDS); 789b58fb2f4SZachary Turner return result; 790b58fb2f4SZachary Turner } 791b58fb2f4SZachary Turner 792b9c1b51eSKate Stone PythonObject PythonCallable::operator()() { 793b9c1b51eSKate Stone return PythonObject(PyRefType::Owned, PyObject_CallObject(m_py_obj, nullptr)); 794a1405147SZachary Turner } 795a1405147SZachary Turner 796b9c1b51eSKate Stone PythonObject PythonCallable:: 797b9c1b51eSKate Stone operator()(std::initializer_list<PyObject *> args) { 798a1405147SZachary Turner PythonTuple arg_tuple(args); 799a1405147SZachary Turner return PythonObject(PyRefType::Owned, 800a1405147SZachary Turner PyObject_CallObject(m_py_obj, arg_tuple.get())); 801a1405147SZachary Turner } 802a1405147SZachary Turner 803b9c1b51eSKate Stone PythonObject PythonCallable:: 804b9c1b51eSKate Stone operator()(std::initializer_list<PythonObject> args) { 805a1405147SZachary Turner PythonTuple arg_tuple(args); 806a1405147SZachary Turner return PythonObject(PyRefType::Owned, 807a1405147SZachary Turner PyObject_CallObject(m_py_obj, arg_tuple.get())); 808a1405147SZachary Turner } 809a1405147SZachary Turner 810b9c1b51eSKate Stone bool PythonFile::Check(PyObject *py_obj) { 81196898eb6SLawrence D'Anna if (!py_obj) 81296898eb6SLawrence D'Anna return false; 8139c40264fSZachary Turner #if PY_MAJOR_VERSION < 3 81423502721SJason Molenda return PyFile_Check(py_obj); 81523502721SJason Molenda #else 8169c40264fSZachary Turner // In Python 3, there is no `PyFile_Check`, and in fact PyFile is not even a 8179c40264fSZachary Turner // first-class object type anymore. `PyFile_FromFd` is just a thin wrapper 81805097246SAdrian Prantl // over `io.open()`, which returns some object derived from `io.IOBase`. As a 81905097246SAdrian Prantl // result, the only way to detect a file in Python 3 is to check whether it 82021b8a8aeSLawrence D'Anna // inherits from `io.IOBase`. 82121b8a8aeSLawrence D'Anna auto io_module = PythonModule::Import("io"); 82221b8a8aeSLawrence D'Anna if (!io_module) { 82321b8a8aeSLawrence D'Anna llvm::consumeError(io_module.takeError()); 8249c40264fSZachary Turner return false; 82521b8a8aeSLawrence D'Anna } 82621b8a8aeSLawrence D'Anna auto iobase = io_module.get().Get("IOBase"); 82721b8a8aeSLawrence D'Anna if (!iobase) { 82821b8a8aeSLawrence D'Anna llvm::consumeError(iobase.takeError()); 8299c40264fSZachary Turner return false; 83021b8a8aeSLawrence D'Anna } 83121b8a8aeSLawrence D'Anna int r = PyObject_IsInstance(py_obj, iobase.get().get()); 83221b8a8aeSLawrence D'Anna if (r < 0) { 83321b8a8aeSLawrence D'Anna llvm::consumeError(exception()); // clear the exception and log it. 83421b8a8aeSLawrence D'Anna return false; 83521b8a8aeSLawrence D'Anna } 83621b8a8aeSLawrence D'Anna return !!r; 83723502721SJason Molenda #endif 8389c40264fSZachary Turner } 8399c40264fSZachary Turner 8402fce1137SLawrence D'Anna FileUP PythonFile::GetUnderlyingFile() const { 841eda01c31SZachary Turner if (!IsValid()) 8422fce1137SLawrence D'Anna return nullptr; 843eda01c31SZachary Turner 844eda01c31SZachary Turner // We don't own the file descriptor returned by this function, make sure the 845eda01c31SZachary Turner // File object knows about that. 846744959b9SEnrico Granata PythonString py_mode = GetAttributeValue("mode").AsType<PythonString>(); 84757504530SLawrence D'Anna auto options = File::GetOptionsFromMode(py_mode.GetString()); 84862c9fe42SLawrence D'Anna if (!options) { 84962c9fe42SLawrence D'Anna llvm::consumeError(options.takeError()); 85062c9fe42SLawrence D'Anna return nullptr; 85162c9fe42SLawrence D'Anna } 85262c9fe42SLawrence D'Anna auto file = std::unique_ptr<File>(new NativeFile( 85362c9fe42SLawrence D'Anna PyObject_AsFileDescriptor(m_py_obj), options.get(), false)); 8542fce1137SLawrence D'Anna if (!file->IsValid()) 8552fce1137SLawrence D'Anna return nullptr; 8562fce1137SLawrence D'Anna return file; 857eda01c31SZachary Turner } 858d68983e3SPavel Labath 85921b8a8aeSLawrence D'Anna namespace { 86021b8a8aeSLawrence D'Anna class GIL { 86121b8a8aeSLawrence D'Anna public: 86221b8a8aeSLawrence D'Anna GIL() { 86321b8a8aeSLawrence D'Anna m_state = PyGILState_Ensure(); 86421b8a8aeSLawrence D'Anna assert(!PyErr_Occurred()); 86521b8a8aeSLawrence D'Anna } 86621b8a8aeSLawrence D'Anna ~GIL() { PyGILState_Release(m_state); } 86721b8a8aeSLawrence D'Anna 86821b8a8aeSLawrence D'Anna protected: 86921b8a8aeSLawrence D'Anna PyGILState_STATE m_state; 87021b8a8aeSLawrence D'Anna }; 87121b8a8aeSLawrence D'Anna } // namespace 87221b8a8aeSLawrence D'Anna 873085328eeSLawrence D'Anna const char *PythonException::toCString() const { 874085328eeSLawrence D'Anna if (!m_repr_bytes) 875085328eeSLawrence D'Anna return "unknown exception"; 876085328eeSLawrence D'Anna return PyBytes_AS_STRING(m_repr_bytes); 877085328eeSLawrence D'Anna } 878085328eeSLawrence D'Anna 879085328eeSLawrence D'Anna PythonException::PythonException(const char *caller) { 880085328eeSLawrence D'Anna assert(PyErr_Occurred()); 881085328eeSLawrence D'Anna m_exception_type = m_exception = m_traceback = m_repr_bytes = NULL; 882085328eeSLawrence D'Anna PyErr_Fetch(&m_exception_type, &m_exception, &m_traceback); 883085328eeSLawrence D'Anna PyErr_NormalizeException(&m_exception_type, &m_exception, &m_traceback); 884085328eeSLawrence D'Anna PyErr_Clear(); 885085328eeSLawrence D'Anna if (m_exception) { 886085328eeSLawrence D'Anna PyObject *repr = PyObject_Repr(m_exception); 887085328eeSLawrence D'Anna if (repr) { 888085328eeSLawrence D'Anna m_repr_bytes = PyUnicode_AsEncodedString(repr, "utf-8", nullptr); 889085328eeSLawrence D'Anna if (!m_repr_bytes) { 890085328eeSLawrence D'Anna PyErr_Clear(); 891085328eeSLawrence D'Anna } 892085328eeSLawrence D'Anna Py_XDECREF(repr); 893085328eeSLawrence D'Anna } else { 894085328eeSLawrence D'Anna PyErr_Clear(); 895085328eeSLawrence D'Anna } 896085328eeSLawrence D'Anna } 897085328eeSLawrence D'Anna Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT); 898085328eeSLawrence D'Anna if (caller) 899085328eeSLawrence D'Anna LLDB_LOGF(log, "%s failed with exception: %s", caller, toCString()); 900085328eeSLawrence D'Anna else 901085328eeSLawrence D'Anna LLDB_LOGF(log, "python exception: %s", toCString()); 902085328eeSLawrence D'Anna } 903085328eeSLawrence D'Anna void PythonException::Restore() { 904085328eeSLawrence D'Anna if (m_exception_type && m_exception) { 905085328eeSLawrence D'Anna PyErr_Restore(m_exception_type, m_exception, m_traceback); 906085328eeSLawrence D'Anna } else { 907085328eeSLawrence D'Anna PyErr_SetString(PyExc_Exception, toCString()); 908085328eeSLawrence D'Anna } 909085328eeSLawrence D'Anna m_exception_type = m_exception = m_traceback = NULL; 910085328eeSLawrence D'Anna } 911085328eeSLawrence D'Anna 912085328eeSLawrence D'Anna PythonException::~PythonException() { 913085328eeSLawrence D'Anna Py_XDECREF(m_exception_type); 914085328eeSLawrence D'Anna Py_XDECREF(m_exception); 915085328eeSLawrence D'Anna Py_XDECREF(m_traceback); 916085328eeSLawrence D'Anna Py_XDECREF(m_repr_bytes); 917085328eeSLawrence D'Anna } 918085328eeSLawrence D'Anna 919085328eeSLawrence D'Anna void PythonException::log(llvm::raw_ostream &OS) const { OS << toCString(); } 920085328eeSLawrence D'Anna 921085328eeSLawrence D'Anna std::error_code PythonException::convertToErrorCode() const { 922085328eeSLawrence D'Anna return llvm::inconvertibleErrorCode(); 923085328eeSLawrence D'Anna } 924085328eeSLawrence D'Anna 925085328eeSLawrence D'Anna char PythonException::ID = 0; 926085328eeSLawrence D'Anna 92762c9fe42SLawrence D'Anna llvm::Expected<File::OpenOptions> 92862c9fe42SLawrence D'Anna GetOptionsForPyObject(const PythonObject &obj) { 92921b8a8aeSLawrence D'Anna #if PY_MAJOR_VERSION >= 3 93062c9fe42SLawrence D'Anna auto options = File::OpenOptions(0); 93121b8a8aeSLawrence D'Anna auto readable = As<bool>(obj.CallMethod("readable")); 93221b8a8aeSLawrence D'Anna if (!readable) 93321b8a8aeSLawrence D'Anna return readable.takeError(); 93421b8a8aeSLawrence D'Anna auto writable = As<bool>(obj.CallMethod("writable")); 93521b8a8aeSLawrence D'Anna if (!writable) 93621b8a8aeSLawrence D'Anna return writable.takeError(); 93721b8a8aeSLawrence D'Anna if (readable.get()) 93821b8a8aeSLawrence D'Anna options |= File::eOpenOptionRead; 93921b8a8aeSLawrence D'Anna if (writable.get()) 94021b8a8aeSLawrence D'Anna options |= File::eOpenOptionWrite; 94162c9fe42SLawrence D'Anna return options; 94221b8a8aeSLawrence D'Anna #else 94321b8a8aeSLawrence D'Anna PythonString py_mode = obj.GetAttributeValue("mode").AsType<PythonString>(); 94462c9fe42SLawrence D'Anna return File::GetOptionsFromMode(py_mode.GetString()); 94521b8a8aeSLawrence D'Anna #endif 94621b8a8aeSLawrence D'Anna } 94721b8a8aeSLawrence D'Anna 94821b8a8aeSLawrence D'Anna // Base class template for python files. All it knows how to do 94921b8a8aeSLawrence D'Anna // is hold a reference to the python object and close or flush it 95021b8a8aeSLawrence D'Anna // when the File is closed. 95121b8a8aeSLawrence D'Anna namespace { 95221b8a8aeSLawrence D'Anna template <typename Base> class OwnedPythonFile : public Base { 95321b8a8aeSLawrence D'Anna public: 95421b8a8aeSLawrence D'Anna template <typename... Args> 95521b8a8aeSLawrence D'Anna OwnedPythonFile(const PythonFile &file, bool borrowed, Args... args) 95621b8a8aeSLawrence D'Anna : Base(args...), m_py_obj(file), m_borrowed(borrowed) { 95721b8a8aeSLawrence D'Anna assert(m_py_obj); 95821b8a8aeSLawrence D'Anna } 95921b8a8aeSLawrence D'Anna 96021b8a8aeSLawrence D'Anna ~OwnedPythonFile() override { 96121b8a8aeSLawrence D'Anna assert(m_py_obj); 96221b8a8aeSLawrence D'Anna GIL takeGIL; 96321b8a8aeSLawrence D'Anna Close(); 96421b8a8aeSLawrence D'Anna m_py_obj.Reset(); 96521b8a8aeSLawrence D'Anna } 96621b8a8aeSLawrence D'Anna 96721b8a8aeSLawrence D'Anna bool IsPythonSideValid() const { 96821b8a8aeSLawrence D'Anna GIL takeGIL; 96921b8a8aeSLawrence D'Anna auto closed = As<bool>(m_py_obj.GetAttribute("closed")); 97021b8a8aeSLawrence D'Anna if (!closed) { 97121b8a8aeSLawrence D'Anna llvm::consumeError(closed.takeError()); 97221b8a8aeSLawrence D'Anna return false; 97321b8a8aeSLawrence D'Anna } 97421b8a8aeSLawrence D'Anna return !closed.get(); 97521b8a8aeSLawrence D'Anna } 97621b8a8aeSLawrence D'Anna 97721b8a8aeSLawrence D'Anna bool IsValid() const override { 97821b8a8aeSLawrence D'Anna return IsPythonSideValid() && Base::IsValid(); 97921b8a8aeSLawrence D'Anna } 98021b8a8aeSLawrence D'Anna 98121b8a8aeSLawrence D'Anna Status Close() override { 98221b8a8aeSLawrence D'Anna assert(m_py_obj); 98321b8a8aeSLawrence D'Anna Status py_error, base_error; 98421b8a8aeSLawrence D'Anna GIL takeGIL; 98521b8a8aeSLawrence D'Anna if (!m_borrowed) { 98621b8a8aeSLawrence D'Anna auto r = m_py_obj.CallMethod("close"); 98721b8a8aeSLawrence D'Anna if (!r) 98821b8a8aeSLawrence D'Anna py_error = Status(r.takeError()); 98921b8a8aeSLawrence D'Anna } 99021b8a8aeSLawrence D'Anna base_error = Base::Close(); 99121b8a8aeSLawrence D'Anna if (py_error.Fail()) 99221b8a8aeSLawrence D'Anna return py_error; 99321b8a8aeSLawrence D'Anna return base_error; 99421b8a8aeSLawrence D'Anna }; 99521b8a8aeSLawrence D'Anna 996d9b553ecSLawrence D'Anna PyObject *GetPythonObject() const { 997d9b553ecSLawrence D'Anna assert(m_py_obj.IsValid()); 998d9b553ecSLawrence D'Anna return m_py_obj.get(); 999d9b553ecSLawrence D'Anna } 1000d9b553ecSLawrence D'Anna 1001d9b553ecSLawrence D'Anna static bool classof(const File *file) = delete; 1002d9b553ecSLawrence D'Anna 100321b8a8aeSLawrence D'Anna protected: 100421b8a8aeSLawrence D'Anna PythonFile m_py_obj; 100521b8a8aeSLawrence D'Anna bool m_borrowed; 100621b8a8aeSLawrence D'Anna }; 100721b8a8aeSLawrence D'Anna } // namespace 100821b8a8aeSLawrence D'Anna 100921b8a8aeSLawrence D'Anna // A SimplePythonFile is a OwnedPythonFile that just does all I/O as 101021b8a8aeSLawrence D'Anna // a NativeFile 101121b8a8aeSLawrence D'Anna namespace { 101221b8a8aeSLawrence D'Anna class SimplePythonFile : public OwnedPythonFile<NativeFile> { 101321b8a8aeSLawrence D'Anna public: 101421b8a8aeSLawrence D'Anna SimplePythonFile(const PythonFile &file, bool borrowed, int fd, 101562c9fe42SLawrence D'Anna File::OpenOptions options) 101621b8a8aeSLawrence D'Anna : OwnedPythonFile(file, borrowed, fd, options, false) {} 1017d9b553ecSLawrence D'Anna 1018d9b553ecSLawrence D'Anna static char ID; 1019d9b553ecSLawrence D'Anna bool isA(const void *classID) const override { 1020d9b553ecSLawrence D'Anna return classID == &ID || NativeFile::isA(classID); 1021d9b553ecSLawrence D'Anna } 1022d9b553ecSLawrence D'Anna static bool classof(const File *file) { return file->isA(&ID); } 102321b8a8aeSLawrence D'Anna }; 1024d9b553ecSLawrence D'Anna char SimplePythonFile::ID = 0; 102521b8a8aeSLawrence D'Anna } // namespace 102621b8a8aeSLawrence D'Anna 102721b8a8aeSLawrence D'Anna #if PY_MAJOR_VERSION >= 3 102821b8a8aeSLawrence D'Anna 102921b8a8aeSLawrence D'Anna namespace { 103021b8a8aeSLawrence D'Anna class PythonBuffer { 103121b8a8aeSLawrence D'Anna public: 103221b8a8aeSLawrence D'Anna PythonBuffer &operator=(const PythonBuffer &) = delete; 103321b8a8aeSLawrence D'Anna PythonBuffer(const PythonBuffer &) = delete; 103421b8a8aeSLawrence D'Anna 103521b8a8aeSLawrence D'Anna static Expected<PythonBuffer> Create(PythonObject &obj, 103621b8a8aeSLawrence D'Anna int flags = PyBUF_SIMPLE) { 103721b8a8aeSLawrence D'Anna Py_buffer py_buffer = {}; 103821b8a8aeSLawrence D'Anna PyObject_GetBuffer(obj.get(), &py_buffer, flags); 103921b8a8aeSLawrence D'Anna if (!py_buffer.obj) 104021b8a8aeSLawrence D'Anna return llvm::make_error<PythonException>(); 104121b8a8aeSLawrence D'Anna return PythonBuffer(py_buffer); 104221b8a8aeSLawrence D'Anna } 104321b8a8aeSLawrence D'Anna 104421b8a8aeSLawrence D'Anna PythonBuffer(PythonBuffer &&other) { 104521b8a8aeSLawrence D'Anna m_buffer = other.m_buffer; 104621b8a8aeSLawrence D'Anna other.m_buffer.obj = nullptr; 104721b8a8aeSLawrence D'Anna } 104821b8a8aeSLawrence D'Anna 104921b8a8aeSLawrence D'Anna ~PythonBuffer() { 105021b8a8aeSLawrence D'Anna if (m_buffer.obj) 105121b8a8aeSLawrence D'Anna PyBuffer_Release(&m_buffer); 105221b8a8aeSLawrence D'Anna } 105321b8a8aeSLawrence D'Anna 105421b8a8aeSLawrence D'Anna Py_buffer &get() { return m_buffer; } 105521b8a8aeSLawrence D'Anna 105621b8a8aeSLawrence D'Anna private: 105721b8a8aeSLawrence D'Anna // takes ownership of the buffer. 105821b8a8aeSLawrence D'Anna PythonBuffer(const Py_buffer &py_buffer) : m_buffer(py_buffer) {} 105921b8a8aeSLawrence D'Anna Py_buffer m_buffer; 106021b8a8aeSLawrence D'Anna }; 106121b8a8aeSLawrence D'Anna } // namespace 106221b8a8aeSLawrence D'Anna 106321b8a8aeSLawrence D'Anna // Shared methods between TextPythonFile and BinaryPythonFile 106421b8a8aeSLawrence D'Anna namespace { 106521b8a8aeSLawrence D'Anna class PythonIOFile : public OwnedPythonFile<File> { 106621b8a8aeSLawrence D'Anna public: 106721b8a8aeSLawrence D'Anna PythonIOFile(const PythonFile &file, bool borrowed) 106821b8a8aeSLawrence D'Anna : OwnedPythonFile(file, borrowed) {} 106921b8a8aeSLawrence D'Anna 107021b8a8aeSLawrence D'Anna ~PythonIOFile() override { Close(); } 107121b8a8aeSLawrence D'Anna 107221b8a8aeSLawrence D'Anna bool IsValid() const override { return IsPythonSideValid(); } 107321b8a8aeSLawrence D'Anna 107421b8a8aeSLawrence D'Anna Status Close() override { 107521b8a8aeSLawrence D'Anna assert(m_py_obj); 107621b8a8aeSLawrence D'Anna GIL takeGIL; 107721b8a8aeSLawrence D'Anna if (m_borrowed) 107821b8a8aeSLawrence D'Anna return Flush(); 107921b8a8aeSLawrence D'Anna auto r = m_py_obj.CallMethod("close"); 108021b8a8aeSLawrence D'Anna if (!r) 108121b8a8aeSLawrence D'Anna return Status(r.takeError()); 108221b8a8aeSLawrence D'Anna return Status(); 108321b8a8aeSLawrence D'Anna } 108421b8a8aeSLawrence D'Anna 108521b8a8aeSLawrence D'Anna Status Flush() override { 108621b8a8aeSLawrence D'Anna GIL takeGIL; 108721b8a8aeSLawrence D'Anna auto r = m_py_obj.CallMethod("flush"); 108821b8a8aeSLawrence D'Anna if (!r) 108921b8a8aeSLawrence D'Anna return Status(r.takeError()); 109021b8a8aeSLawrence D'Anna return Status(); 109121b8a8aeSLawrence D'Anna } 109221b8a8aeSLawrence D'Anna 1093d9b553ecSLawrence D'Anna Expected<File::OpenOptions> GetOptions() const override { 1094d9b553ecSLawrence D'Anna GIL takeGIL; 1095d9b553ecSLawrence D'Anna return GetOptionsForPyObject(m_py_obj); 1096d9b553ecSLawrence D'Anna } 1097d9b553ecSLawrence D'Anna 1098d9b553ecSLawrence D'Anna static char ID; 1099d9b553ecSLawrence D'Anna bool isA(const void *classID) const override { 1100d9b553ecSLawrence D'Anna return classID == &ID || File::isA(classID); 1101d9b553ecSLawrence D'Anna } 1102d9b553ecSLawrence D'Anna static bool classof(const File *file) { return file->isA(&ID); } 110321b8a8aeSLawrence D'Anna }; 1104d9b553ecSLawrence D'Anna char PythonIOFile::ID = 0; 110521b8a8aeSLawrence D'Anna } // namespace 110621b8a8aeSLawrence D'Anna 110721b8a8aeSLawrence D'Anna namespace { 110821b8a8aeSLawrence D'Anna class BinaryPythonFile : public PythonIOFile { 110921b8a8aeSLawrence D'Anna protected: 111021b8a8aeSLawrence D'Anna int m_descriptor; 111121b8a8aeSLawrence D'Anna 111221b8a8aeSLawrence D'Anna public: 111321b8a8aeSLawrence D'Anna BinaryPythonFile(int fd, const PythonFile &file, bool borrowed) 111421b8a8aeSLawrence D'Anna : PythonIOFile(file, borrowed), 111521b8a8aeSLawrence D'Anna m_descriptor(File::DescriptorIsValid(fd) ? fd 111621b8a8aeSLawrence D'Anna : File::kInvalidDescriptor) {} 111721b8a8aeSLawrence D'Anna 111821b8a8aeSLawrence D'Anna int GetDescriptor() const override { return m_descriptor; } 111921b8a8aeSLawrence D'Anna 112021b8a8aeSLawrence D'Anna Status Write(const void *buf, size_t &num_bytes) override { 112121b8a8aeSLawrence D'Anna GIL takeGIL; 112221b8a8aeSLawrence D'Anna PyObject *pybuffer_p = PyMemoryView_FromMemory( 112321b8a8aeSLawrence D'Anna const_cast<char *>((const char *)buf), num_bytes, PyBUF_READ); 112421b8a8aeSLawrence D'Anna if (!pybuffer_p) 112521b8a8aeSLawrence D'Anna return Status(llvm::make_error<PythonException>()); 112621b8a8aeSLawrence D'Anna auto pybuffer = Take<PythonObject>(pybuffer_p); 112721b8a8aeSLawrence D'Anna num_bytes = 0; 112821b8a8aeSLawrence D'Anna auto bytes_written = As<long long>(m_py_obj.CallMethod("write", pybuffer)); 112921b8a8aeSLawrence D'Anna if (!bytes_written) 113021b8a8aeSLawrence D'Anna return Status(bytes_written.takeError()); 113121b8a8aeSLawrence D'Anna if (bytes_written.get() < 0) 113221b8a8aeSLawrence D'Anna return Status(".write() method returned a negative number!"); 113321b8a8aeSLawrence D'Anna static_assert(sizeof(long long) >= sizeof(size_t), "overflow"); 113421b8a8aeSLawrence D'Anna num_bytes = bytes_written.get(); 113521b8a8aeSLawrence D'Anna return Status(); 113621b8a8aeSLawrence D'Anna } 113721b8a8aeSLawrence D'Anna 113821b8a8aeSLawrence D'Anna Status Read(void *buf, size_t &num_bytes) override { 113921b8a8aeSLawrence D'Anna GIL takeGIL; 114021b8a8aeSLawrence D'Anna static_assert(sizeof(long long) >= sizeof(size_t), "overflow"); 114121b8a8aeSLawrence D'Anna auto pybuffer_obj = 114221b8a8aeSLawrence D'Anna m_py_obj.CallMethod("read", (unsigned long long)num_bytes); 114321b8a8aeSLawrence D'Anna if (!pybuffer_obj) 114421b8a8aeSLawrence D'Anna return Status(pybuffer_obj.takeError()); 114521b8a8aeSLawrence D'Anna num_bytes = 0; 114621b8a8aeSLawrence D'Anna if (pybuffer_obj.get().IsNone()) { 114721b8a8aeSLawrence D'Anna // EOF 114821b8a8aeSLawrence D'Anna num_bytes = 0; 114921b8a8aeSLawrence D'Anna return Status(); 115021b8a8aeSLawrence D'Anna } 115121b8a8aeSLawrence D'Anna auto pybuffer = PythonBuffer::Create(pybuffer_obj.get()); 115221b8a8aeSLawrence D'Anna if (!pybuffer) 115321b8a8aeSLawrence D'Anna return Status(pybuffer.takeError()); 115421b8a8aeSLawrence D'Anna memcpy(buf, pybuffer.get().get().buf, pybuffer.get().get().len); 115521b8a8aeSLawrence D'Anna num_bytes = pybuffer.get().get().len; 115621b8a8aeSLawrence D'Anna return Status(); 115721b8a8aeSLawrence D'Anna } 115821b8a8aeSLawrence D'Anna }; 115921b8a8aeSLawrence D'Anna } // namespace 116021b8a8aeSLawrence D'Anna 116121b8a8aeSLawrence D'Anna namespace { 116221b8a8aeSLawrence D'Anna class TextPythonFile : public PythonIOFile { 116321b8a8aeSLawrence D'Anna protected: 116421b8a8aeSLawrence D'Anna int m_descriptor; 116521b8a8aeSLawrence D'Anna 116621b8a8aeSLawrence D'Anna public: 116721b8a8aeSLawrence D'Anna TextPythonFile(int fd, const PythonFile &file, bool borrowed) 116821b8a8aeSLawrence D'Anna : PythonIOFile(file, borrowed), 116921b8a8aeSLawrence D'Anna m_descriptor(File::DescriptorIsValid(fd) ? fd 117021b8a8aeSLawrence D'Anna : File::kInvalidDescriptor) {} 117121b8a8aeSLawrence D'Anna 117221b8a8aeSLawrence D'Anna int GetDescriptor() const override { return m_descriptor; } 117321b8a8aeSLawrence D'Anna 117421b8a8aeSLawrence D'Anna Status Write(const void *buf, size_t &num_bytes) override { 117521b8a8aeSLawrence D'Anna GIL takeGIL; 117621b8a8aeSLawrence D'Anna auto pystring = 117721b8a8aeSLawrence D'Anna PythonString::FromUTF8(llvm::StringRef((const char *)buf, num_bytes)); 117821b8a8aeSLawrence D'Anna if (!pystring) 117921b8a8aeSLawrence D'Anna return Status(pystring.takeError()); 118021b8a8aeSLawrence D'Anna num_bytes = 0; 118121b8a8aeSLawrence D'Anna auto bytes_written = 118221b8a8aeSLawrence D'Anna As<long long>(m_py_obj.CallMethod("write", pystring.get())); 118321b8a8aeSLawrence D'Anna if (!bytes_written) 118421b8a8aeSLawrence D'Anna return Status(bytes_written.takeError()); 118521b8a8aeSLawrence D'Anna if (bytes_written.get() < 0) 118621b8a8aeSLawrence D'Anna return Status(".write() method returned a negative number!"); 118721b8a8aeSLawrence D'Anna static_assert(sizeof(long long) >= sizeof(size_t), "overflow"); 118821b8a8aeSLawrence D'Anna num_bytes = bytes_written.get(); 118921b8a8aeSLawrence D'Anna return Status(); 119021b8a8aeSLawrence D'Anna } 119121b8a8aeSLawrence D'Anna 119221b8a8aeSLawrence D'Anna Status Read(void *buf, size_t &num_bytes) override { 119321b8a8aeSLawrence D'Anna GIL takeGIL; 119421b8a8aeSLawrence D'Anna size_t num_chars = num_bytes / 6; 119521b8a8aeSLawrence D'Anna size_t orig_num_bytes = num_bytes; 119621b8a8aeSLawrence D'Anna num_bytes = 0; 119721b8a8aeSLawrence D'Anna if (orig_num_bytes < 6) { 119821b8a8aeSLawrence D'Anna return Status("can't read less than 6 bytes from a utf8 text stream"); 119921b8a8aeSLawrence D'Anna } 120021b8a8aeSLawrence D'Anna auto pystring = As<PythonString>( 120121b8a8aeSLawrence D'Anna m_py_obj.CallMethod("read", (unsigned long long)num_chars)); 120221b8a8aeSLawrence D'Anna if (!pystring) 120321b8a8aeSLawrence D'Anna return Status(pystring.takeError()); 120421b8a8aeSLawrence D'Anna if (pystring.get().IsNone()) { 120521b8a8aeSLawrence D'Anna // EOF 120621b8a8aeSLawrence D'Anna return Status(); 120721b8a8aeSLawrence D'Anna } 120821b8a8aeSLawrence D'Anna auto stringref = pystring.get().AsUTF8(); 120921b8a8aeSLawrence D'Anna if (!stringref) 121021b8a8aeSLawrence D'Anna return Status(stringref.takeError()); 121121b8a8aeSLawrence D'Anna num_bytes = stringref.get().size(); 121221b8a8aeSLawrence D'Anna memcpy(buf, stringref.get().begin(), num_bytes); 121321b8a8aeSLawrence D'Anna return Status(); 121421b8a8aeSLawrence D'Anna } 121521b8a8aeSLawrence D'Anna }; 121621b8a8aeSLawrence D'Anna } // namespace 121721b8a8aeSLawrence D'Anna 121821b8a8aeSLawrence D'Anna #endif 121921b8a8aeSLawrence D'Anna 122021b8a8aeSLawrence D'Anna llvm::Expected<FileSP> PythonFile::ConvertToFile(bool borrowed) { 122121b8a8aeSLawrence D'Anna if (!IsValid()) 122221b8a8aeSLawrence D'Anna return llvm::createStringError(llvm::inconvertibleErrorCode(), 122321b8a8aeSLawrence D'Anna "invalid PythonFile"); 122421b8a8aeSLawrence D'Anna 122521b8a8aeSLawrence D'Anna int fd = PyObject_AsFileDescriptor(m_py_obj); 122621b8a8aeSLawrence D'Anna if (fd < 0) { 122721b8a8aeSLawrence D'Anna PyErr_Clear(); 122821b8a8aeSLawrence D'Anna return ConvertToFileForcingUseOfScriptingIOMethods(borrowed); 122921b8a8aeSLawrence D'Anna } 123021b8a8aeSLawrence D'Anna auto options = GetOptionsForPyObject(*this); 123121b8a8aeSLawrence D'Anna if (!options) 123221b8a8aeSLawrence D'Anna return options.takeError(); 123321b8a8aeSLawrence D'Anna 123421b8a8aeSLawrence D'Anna // LLDB and python will not share I/O buffers. We should probably 123521b8a8aeSLawrence D'Anna // flush the python buffers now. 123621b8a8aeSLawrence D'Anna auto r = CallMethod("flush"); 123721b8a8aeSLawrence D'Anna if (!r) 123821b8a8aeSLawrence D'Anna return r.takeError(); 123921b8a8aeSLawrence D'Anna 124021b8a8aeSLawrence D'Anna FileSP file_sp; 124121b8a8aeSLawrence D'Anna if (borrowed) { 124221b8a8aeSLawrence D'Anna // In this case we we don't need to retain the python 124321b8a8aeSLawrence D'Anna // object at all. 124421b8a8aeSLawrence D'Anna file_sp = std::make_shared<NativeFile>(fd, options.get(), false); 124521b8a8aeSLawrence D'Anna } else { 124621b8a8aeSLawrence D'Anna file_sp = std::static_pointer_cast<File>( 124721b8a8aeSLawrence D'Anna std::make_shared<SimplePythonFile>(*this, borrowed, fd, options.get())); 124821b8a8aeSLawrence D'Anna } 124921b8a8aeSLawrence D'Anna if (!file_sp->IsValid()) 125021b8a8aeSLawrence D'Anna return llvm::createStringError(llvm::inconvertibleErrorCode(), 125121b8a8aeSLawrence D'Anna "invalid File"); 125221b8a8aeSLawrence D'Anna 125321b8a8aeSLawrence D'Anna return file_sp; 125421b8a8aeSLawrence D'Anna } 125521b8a8aeSLawrence D'Anna 125621b8a8aeSLawrence D'Anna llvm::Expected<FileSP> 125721b8a8aeSLawrence D'Anna PythonFile::ConvertToFileForcingUseOfScriptingIOMethods(bool borrowed) { 125821b8a8aeSLawrence D'Anna 125921b8a8aeSLawrence D'Anna assert(!PyErr_Occurred()); 126021b8a8aeSLawrence D'Anna 126121b8a8aeSLawrence D'Anna if (!IsValid()) 126221b8a8aeSLawrence D'Anna return llvm::createStringError(llvm::inconvertibleErrorCode(), 126321b8a8aeSLawrence D'Anna "invalid PythonFile"); 126421b8a8aeSLawrence D'Anna 126521b8a8aeSLawrence D'Anna #if PY_MAJOR_VERSION < 3 126621b8a8aeSLawrence D'Anna 126721b8a8aeSLawrence D'Anna return llvm::createStringError(llvm::inconvertibleErrorCode(), 126821b8a8aeSLawrence D'Anna "not supported on python 2"); 126921b8a8aeSLawrence D'Anna 127021b8a8aeSLawrence D'Anna #else 127121b8a8aeSLawrence D'Anna 127221b8a8aeSLawrence D'Anna int fd = PyObject_AsFileDescriptor(m_py_obj); 127321b8a8aeSLawrence D'Anna if (fd < 0) { 127421b8a8aeSLawrence D'Anna PyErr_Clear(); 127521b8a8aeSLawrence D'Anna fd = File::kInvalidDescriptor; 127621b8a8aeSLawrence D'Anna } 127721b8a8aeSLawrence D'Anna 127821b8a8aeSLawrence D'Anna auto io_module = PythonModule::Import("io"); 127921b8a8aeSLawrence D'Anna if (!io_module) 128021b8a8aeSLawrence D'Anna return io_module.takeError(); 128121b8a8aeSLawrence D'Anna auto textIOBase = io_module.get().Get("TextIOBase"); 128221b8a8aeSLawrence D'Anna if (!textIOBase) 128321b8a8aeSLawrence D'Anna return textIOBase.takeError(); 128421b8a8aeSLawrence D'Anna auto rawIOBase = io_module.get().Get("RawIOBase"); 128521b8a8aeSLawrence D'Anna if (!rawIOBase) 128621b8a8aeSLawrence D'Anna return rawIOBase.takeError(); 128721b8a8aeSLawrence D'Anna auto bufferedIOBase = io_module.get().Get("BufferedIOBase"); 128821b8a8aeSLawrence D'Anna if (!bufferedIOBase) 128921b8a8aeSLawrence D'Anna return bufferedIOBase.takeError(); 129021b8a8aeSLawrence D'Anna 129121b8a8aeSLawrence D'Anna FileSP file_sp; 129221b8a8aeSLawrence D'Anna 129321b8a8aeSLawrence D'Anna auto isTextIO = IsInstance(textIOBase.get()); 129421b8a8aeSLawrence D'Anna if (!isTextIO) 129521b8a8aeSLawrence D'Anna return isTextIO.takeError(); 129621b8a8aeSLawrence D'Anna if (isTextIO.get()) 129721b8a8aeSLawrence D'Anna file_sp = std::static_pointer_cast<File>( 129821b8a8aeSLawrence D'Anna std::make_shared<TextPythonFile>(fd, *this, borrowed)); 129921b8a8aeSLawrence D'Anna 130021b8a8aeSLawrence D'Anna auto isRawIO = IsInstance(rawIOBase.get()); 130121b8a8aeSLawrence D'Anna if (!isRawIO) 130221b8a8aeSLawrence D'Anna return isRawIO.takeError(); 130321b8a8aeSLawrence D'Anna auto isBufferedIO = IsInstance(bufferedIOBase.get()); 130421b8a8aeSLawrence D'Anna if (!isBufferedIO) 130521b8a8aeSLawrence D'Anna return isBufferedIO.takeError(); 130621b8a8aeSLawrence D'Anna 130721b8a8aeSLawrence D'Anna if (isRawIO.get() || isBufferedIO.get()) { 130821b8a8aeSLawrence D'Anna file_sp = std::static_pointer_cast<File>( 130921b8a8aeSLawrence D'Anna std::make_shared<BinaryPythonFile>(fd, *this, borrowed)); 131021b8a8aeSLawrence D'Anna } 131121b8a8aeSLawrence D'Anna 131221b8a8aeSLawrence D'Anna if (!file_sp) 131321b8a8aeSLawrence D'Anna return llvm::createStringError(llvm::inconvertibleErrorCode(), 131421b8a8aeSLawrence D'Anna "python file is neither text nor binary"); 131521b8a8aeSLawrence D'Anna 131621b8a8aeSLawrence D'Anna if (!file_sp->IsValid()) 131721b8a8aeSLawrence D'Anna return llvm::createStringError(llvm::inconvertibleErrorCode(), 131821b8a8aeSLawrence D'Anna "invalid File"); 131921b8a8aeSLawrence D'Anna 132021b8a8aeSLawrence D'Anna return file_sp; 132121b8a8aeSLawrence D'Anna 132221b8a8aeSLawrence D'Anna #endif 132321b8a8aeSLawrence D'Anna } 132421b8a8aeSLawrence D'Anna 1325d9b553ecSLawrence D'Anna Expected<PythonFile> PythonFile::FromFile(File &file, const char *mode) { 1326d9b553ecSLawrence D'Anna if (!file.IsValid()) 1327d9b553ecSLawrence D'Anna return llvm::createStringError(llvm::inconvertibleErrorCode(), 1328d9b553ecSLawrence D'Anna "invalid file"); 1329d9b553ecSLawrence D'Anna 1330d9b553ecSLawrence D'Anna if (auto *simple = llvm::dyn_cast<SimplePythonFile>(&file)) 1331d9b553ecSLawrence D'Anna return Retain<PythonFile>(simple->GetPythonObject()); 1332d9b553ecSLawrence D'Anna #if PY_MAJOR_VERSION >= 3 1333d9b553ecSLawrence D'Anna if (auto *pythonio = llvm::dyn_cast<PythonIOFile>(&file)) 1334d9b553ecSLawrence D'Anna return Retain<PythonFile>(pythonio->GetPythonObject()); 1335d9b553ecSLawrence D'Anna #endif 1336d9b553ecSLawrence D'Anna 1337d9b553ecSLawrence D'Anna if (!mode) { 1338d9b553ecSLawrence D'Anna auto m = file.GetOpenMode(); 1339d9b553ecSLawrence D'Anna if (!m) 1340d9b553ecSLawrence D'Anna return m.takeError(); 1341d9b553ecSLawrence D'Anna mode = m.get(); 1342d9b553ecSLawrence D'Anna } 1343d9b553ecSLawrence D'Anna 1344d9b553ecSLawrence D'Anna PyObject *file_obj; 1345d9b553ecSLawrence D'Anna #if PY_MAJOR_VERSION >= 3 1346d9b553ecSLawrence D'Anna file_obj = PyFile_FromFd(file.GetDescriptor(), nullptr, mode, -1, nullptr, 1347d9b553ecSLawrence D'Anna "ignore", nullptr, 0); 1348d9b553ecSLawrence D'Anna #else 1349d9b553ecSLawrence D'Anna // Read through the Python source, doesn't seem to modify these strings 1350d9b553ecSLawrence D'Anna char *cmode = const_cast<char *>(mode); 1351d9b553ecSLawrence D'Anna // We pass ::flush instead of ::fclose here so we borrow the FILE* -- 1352d9b553ecSLawrence D'Anna // the lldb_private::File still owns it. 1353d9b553ecSLawrence D'Anna file_obj = 1354d9b553ecSLawrence D'Anna PyFile_FromFile(file.GetStream(), const_cast<char *>(""), cmode, ::fflush); 1355d9b553ecSLawrence D'Anna #endif 1356d9b553ecSLawrence D'Anna 1357d9b553ecSLawrence D'Anna if (!file_obj) 1358d9b553ecSLawrence D'Anna return exception(); 1359d9b553ecSLawrence D'Anna 1360d9b553ecSLawrence D'Anna return Take<PythonFile>(file_obj); 1361d9b553ecSLawrence D'Anna } 1362d9b553ecSLawrence D'Anna 1363d68983e3SPavel Labath #endif 1364