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" 25*d9b553ecSLawrence 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 216b9c1b51eSKate Stone PythonBytes::PythonBytes() : PythonObject() {} 2175a72c02bSZachary Turner 218b9c1b51eSKate Stone PythonBytes::PythonBytes(llvm::ArrayRef<uint8_t> bytes) : PythonObject() { 2195a72c02bSZachary Turner SetBytes(bytes); 2205a72c02bSZachary Turner } 2215a72c02bSZachary Turner 222b9c1b51eSKate Stone PythonBytes::PythonBytes(const uint8_t *bytes, size_t length) : PythonObject() { 2235a72c02bSZachary Turner SetBytes(llvm::ArrayRef<uint8_t>(bytes, length)); 2245a72c02bSZachary Turner } 2255a72c02bSZachary Turner 226b9c1b51eSKate Stone PythonBytes::PythonBytes(PyRefType type, PyObject *py_obj) : PythonObject() { 2275a72c02bSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string 2285a72c02bSZachary Turner } 2295a72c02bSZachary Turner 230b9c1b51eSKate Stone PythonBytes::~PythonBytes() {} 2315a72c02bSZachary Turner 232b9c1b51eSKate Stone bool PythonBytes::Check(PyObject *py_obj) { 2335a72c02bSZachary Turner if (!py_obj) 2345a72c02bSZachary Turner return false; 235a6682a41SJonas Devlieghere return PyBytes_Check(py_obj); 2365a72c02bSZachary Turner } 2375a72c02bSZachary Turner 238b9c1b51eSKate Stone void PythonBytes::Reset(PyRefType type, PyObject *py_obj) { 23905097246SAdrian Prantl // Grab the desired reference type so that if we end up rejecting `py_obj` it 24005097246SAdrian Prantl // still gets decremented if necessary. 2415a72c02bSZachary Turner PythonObject result(type, py_obj); 2425a72c02bSZachary Turner 243b9c1b51eSKate Stone if (!PythonBytes::Check(py_obj)) { 2445a72c02bSZachary Turner PythonObject::Reset(); 2455a72c02bSZachary Turner return; 2465a72c02bSZachary Turner } 2475a72c02bSZachary Turner 248b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 24905097246SAdrian Prantl // overflow since it calls back into the virtual implementation. 2505a72c02bSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 2515a72c02bSZachary Turner } 2525a72c02bSZachary Turner 253b9c1b51eSKate Stone llvm::ArrayRef<uint8_t> PythonBytes::GetBytes() const { 2545a72c02bSZachary Turner if (!IsValid()) 2555a72c02bSZachary Turner return llvm::ArrayRef<uint8_t>(); 2565a72c02bSZachary Turner 2575a72c02bSZachary Turner Py_ssize_t size; 2585a72c02bSZachary Turner char *c; 2595a72c02bSZachary Turner 2605a72c02bSZachary Turner PyBytes_AsStringAndSize(m_py_obj, &c, &size); 2615a72c02bSZachary Turner return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size); 2625a72c02bSZachary Turner } 2635a72c02bSZachary Turner 264b9c1b51eSKate Stone size_t PythonBytes::GetSize() const { 2655a72c02bSZachary Turner if (!IsValid()) 2665a72c02bSZachary Turner return 0; 2675a72c02bSZachary Turner return PyBytes_Size(m_py_obj); 2685a72c02bSZachary Turner } 2695a72c02bSZachary Turner 270b9c1b51eSKate Stone void PythonBytes::SetBytes(llvm::ArrayRef<uint8_t> bytes) { 2715a72c02bSZachary Turner const char *data = reinterpret_cast<const char *>(bytes.data()); 2725a72c02bSZachary Turner PyObject *py_bytes = PyBytes_FromStringAndSize(data, bytes.size()); 2735a72c02bSZachary Turner PythonObject::Reset(PyRefType::Owned, py_bytes); 2745a72c02bSZachary Turner } 2755a72c02bSZachary Turner 276b9c1b51eSKate Stone StructuredData::StringSP PythonBytes::CreateStructuredString() const { 2775a72c02bSZachary Turner StructuredData::StringSP result(new StructuredData::String); 2785a72c02bSZachary Turner Py_ssize_t size; 2795a72c02bSZachary Turner char *c; 2805a72c02bSZachary Turner PyBytes_AsStringAndSize(m_py_obj, &c, &size); 2815a72c02bSZachary Turner result->SetValue(std::string(c, size)); 2825a72c02bSZachary Turner return result; 2835a72c02bSZachary Turner } 2845a72c02bSZachary Turner 285b9c1b51eSKate Stone PythonByteArray::PythonByteArray(llvm::ArrayRef<uint8_t> bytes) 286b9c1b51eSKate Stone : PythonByteArray(bytes.data(), bytes.size()) {} 287f9d6d204SZachary Turner 288b9c1b51eSKate Stone PythonByteArray::PythonByteArray(const uint8_t *bytes, size_t length) { 289f9d6d204SZachary Turner const char *str = reinterpret_cast<const char *>(bytes); 290f9d6d204SZachary Turner Reset(PyRefType::Owned, PyByteArray_FromStringAndSize(str, length)); 291f9d6d204SZachary Turner } 292f9d6d204SZachary Turner 293b9c1b51eSKate Stone PythonByteArray::PythonByteArray(PyRefType type, PyObject *o) { 294f9d6d204SZachary Turner Reset(type, o); 295f9d6d204SZachary Turner } 296f9d6d204SZachary Turner 297b9c1b51eSKate Stone PythonByteArray::PythonByteArray(const PythonBytes &object) 298b9c1b51eSKate Stone : PythonObject(object) {} 299f9d6d204SZachary Turner 300b9c1b51eSKate Stone PythonByteArray::~PythonByteArray() {} 301f9d6d204SZachary Turner 302b9c1b51eSKate Stone bool PythonByteArray::Check(PyObject *py_obj) { 303f9d6d204SZachary Turner if (!py_obj) 304f9d6d204SZachary Turner return false; 305a6682a41SJonas Devlieghere return PyByteArray_Check(py_obj); 306f9d6d204SZachary Turner } 307f9d6d204SZachary Turner 308b9c1b51eSKate Stone void PythonByteArray::Reset(PyRefType type, PyObject *py_obj) { 30905097246SAdrian Prantl // Grab the desired reference type so that if we end up rejecting `py_obj` it 31005097246SAdrian Prantl // still gets decremented if necessary. 311f9d6d204SZachary Turner PythonObject result(type, py_obj); 312f9d6d204SZachary Turner 313b9c1b51eSKate Stone if (!PythonByteArray::Check(py_obj)) { 314f9d6d204SZachary Turner PythonObject::Reset(); 315f9d6d204SZachary Turner return; 316f9d6d204SZachary Turner } 317f9d6d204SZachary Turner 318b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 31905097246SAdrian Prantl // overflow since it calls back into the virtual implementation. 320f9d6d204SZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 321f9d6d204SZachary Turner } 322f9d6d204SZachary Turner 323b9c1b51eSKate Stone llvm::ArrayRef<uint8_t> PythonByteArray::GetBytes() const { 324f9d6d204SZachary Turner if (!IsValid()) 325f9d6d204SZachary Turner return llvm::ArrayRef<uint8_t>(); 326f9d6d204SZachary Turner 327f9d6d204SZachary Turner char *c = PyByteArray_AsString(m_py_obj); 328f9d6d204SZachary Turner size_t size = GetSize(); 329f9d6d204SZachary Turner return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size); 330f9d6d204SZachary Turner } 331f9d6d204SZachary Turner 332b9c1b51eSKate Stone size_t PythonByteArray::GetSize() const { 333f9d6d204SZachary Turner if (!IsValid()) 334f9d6d204SZachary Turner return 0; 335f9d6d204SZachary Turner 336f9d6d204SZachary Turner return PyByteArray_Size(m_py_obj); 337f9d6d204SZachary Turner } 338f9d6d204SZachary Turner 339b9c1b51eSKate Stone StructuredData::StringSP PythonByteArray::CreateStructuredString() const { 340f9d6d204SZachary Turner StructuredData::StringSP result(new StructuredData::String); 341f9d6d204SZachary Turner llvm::ArrayRef<uint8_t> bytes = GetBytes(); 342f9d6d204SZachary Turner const char *str = reinterpret_cast<const char *>(bytes.data()); 343f9d6d204SZachary Turner result->SetValue(std::string(str, bytes.size())); 344f9d6d204SZachary Turner return result; 345f9d6d204SZachary Turner } 346f9d6d204SZachary Turner 3475a72c02bSZachary Turner // PythonString 3482c1f46dcSZachary Turner 349085328eeSLawrence D'Anna Expected<PythonString> PythonString::FromUTF8(llvm::StringRef string) { 350085328eeSLawrence D'Anna #if PY_MAJOR_VERSION >= 3 351085328eeSLawrence D'Anna PyObject *str = PyUnicode_FromStringAndSize(string.data(), string.size()); 352085328eeSLawrence D'Anna #else 353085328eeSLawrence D'Anna PyObject *str = PyString_FromStringAndSize(string.data(), string.size()); 354085328eeSLawrence D'Anna #endif 355085328eeSLawrence D'Anna if (!str) 356085328eeSLawrence D'Anna return llvm::make_error<PythonException>(); 357085328eeSLawrence D'Anna return Take<PythonString>(str); 358085328eeSLawrence D'Anna } 359085328eeSLawrence D'Anna 360b9c1b51eSKate Stone PythonString::PythonString(PyRefType type, PyObject *py_obj) : PythonObject() { 361f8b22f8fSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string 3622c1f46dcSZachary Turner } 3632c1f46dcSZachary Turner 364b9c1b51eSKate Stone PythonString::PythonString(llvm::StringRef string) : PythonObject() { 36522c8efcdSZachary Turner SetString(string); 3662c1f46dcSZachary Turner } 3672c1f46dcSZachary Turner 368b9c1b51eSKate Stone PythonString::PythonString() : PythonObject() {} 3692c1f46dcSZachary Turner 370b9c1b51eSKate Stone PythonString::~PythonString() {} 3712c1f46dcSZachary Turner 372b9c1b51eSKate Stone bool PythonString::Check(PyObject *py_obj) { 37322c8efcdSZachary Turner if (!py_obj) 37422c8efcdSZachary Turner return false; 37518426935SZachary Turner 3767d6d218eSZachary Turner if (PyUnicode_Check(py_obj)) 3777d6d218eSZachary Turner return true; 3787d6d218eSZachary Turner #if PY_MAJOR_VERSION < 3 3797d6d218eSZachary Turner if (PyString_Check(py_obj)) 3807d6d218eSZachary Turner return true; 38122c8efcdSZachary Turner #endif 3827d6d218eSZachary Turner return false; 38322c8efcdSZachary Turner } 38422c8efcdSZachary Turner 385b9c1b51eSKate Stone void PythonString::Reset(PyRefType type, PyObject *py_obj) { 38605097246SAdrian Prantl // Grab the desired reference type so that if we end up rejecting `py_obj` it 38705097246SAdrian Prantl // still gets decremented if necessary. 388f8b22f8fSZachary Turner PythonObject result(type, py_obj); 389f8b22f8fSZachary Turner 390b9c1b51eSKate Stone if (!PythonString::Check(py_obj)) { 391f8b22f8fSZachary Turner PythonObject::Reset(); 392f8b22f8fSZachary Turner return; 39322c8efcdSZachary Turner } 3947d6d218eSZachary Turner #if PY_MAJOR_VERSION < 3 3957d6d218eSZachary Turner // In Python 2, Don't store PyUnicode objects directly, because we need 3967d6d218eSZachary Turner // access to their underlying character buffers which Python 2 doesn't 3977d6d218eSZachary Turner // provide. 398085328eeSLawrence D'Anna if (PyUnicode_Check(py_obj)) { 399085328eeSLawrence D'Anna PyObject *s = PyUnicode_AsUTF8String(result.get()); 400085328eeSLawrence D'Anna if (s == NULL) 401085328eeSLawrence D'Anna PyErr_Clear(); 402085328eeSLawrence D'Anna result.Reset(PyRefType::Owned, s); 403085328eeSLawrence D'Anna } 4047d6d218eSZachary Turner #endif 405b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 40605097246SAdrian Prantl // overflow since it calls back into the virtual implementation. 407f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 4082c1f46dcSZachary Turner } 4092c1f46dcSZachary Turner 410b9c1b51eSKate Stone llvm::StringRef PythonString::GetString() const { 411085328eeSLawrence D'Anna auto s = AsUTF8(); 412085328eeSLawrence D'Anna if (!s) { 413085328eeSLawrence D'Anna llvm::consumeError(s.takeError()); 414085328eeSLawrence D'Anna return llvm::StringRef(""); 415085328eeSLawrence D'Anna } 416085328eeSLawrence D'Anna return s.get(); 417085328eeSLawrence D'Anna } 418085328eeSLawrence D'Anna 419085328eeSLawrence D'Anna Expected<llvm::StringRef> PythonString::AsUTF8() const { 42018426935SZachary Turner if (!IsValid()) 421085328eeSLawrence D'Anna return nullDeref(); 42218426935SZachary Turner 42322c8efcdSZachary Turner Py_ssize_t size; 4245457b426SPavel Labath const char *data; 42518426935SZachary Turner 42618426935SZachary Turner #if PY_MAJOR_VERSION >= 3 4275457b426SPavel Labath data = PyUnicode_AsUTF8AndSize(m_py_obj, &size); 42818426935SZachary Turner #else 429085328eeSLawrence D'Anna char *c = NULL; 430085328eeSLawrence D'Anna int r = PyString_AsStringAndSize(m_py_obj, &c, &size); 431085328eeSLawrence D'Anna if (r < 0) 432085328eeSLawrence D'Anna c = NULL; 4335457b426SPavel Labath data = c; 43418426935SZachary Turner #endif 435085328eeSLawrence D'Anna 436085328eeSLawrence D'Anna if (!data) 437085328eeSLawrence D'Anna return exception(); 438085328eeSLawrence D'Anna 4395457b426SPavel Labath return llvm::StringRef(data, size); 44022c8efcdSZachary Turner } 4412c1f46dcSZachary Turner 442b9c1b51eSKate Stone size_t PythonString::GetSize() const { 443b9c1b51eSKate Stone if (IsValid()) { 44418426935SZachary Turner #if PY_MAJOR_VERSION >= 3 44518426935SZachary Turner return PyUnicode_GetSize(m_py_obj); 44618426935SZachary Turner #else 44718426935SZachary Turner return PyString_Size(m_py_obj); 44818426935SZachary Turner #endif 44918426935SZachary Turner } 4502c1f46dcSZachary Turner return 0; 4512c1f46dcSZachary Turner } 4522c1f46dcSZachary Turner 453b9c1b51eSKate Stone void PythonString::SetString(llvm::StringRef string) { 454085328eeSLawrence D'Anna auto s = FromUTF8(string); 455085328eeSLawrence D'Anna if (!s) { 456085328eeSLawrence D'Anna llvm::consumeError(s.takeError()); 457085328eeSLawrence D'Anna Reset(); 458085328eeSLawrence D'Anna } else { 459085328eeSLawrence D'Anna PythonObject::Reset(std::move(s.get())); 460085328eeSLawrence D'Anna } 4612c1f46dcSZachary Turner } 4622c1f46dcSZachary Turner 463b9c1b51eSKate Stone StructuredData::StringSP PythonString::CreateStructuredString() const { 4642c1f46dcSZachary Turner StructuredData::StringSP result(new StructuredData::String); 4652c1f46dcSZachary Turner result->SetValue(GetString()); 4662c1f46dcSZachary Turner return result; 4672c1f46dcSZachary Turner } 4682c1f46dcSZachary Turner 4692c1f46dcSZachary Turner // PythonInteger 4702c1f46dcSZachary Turner 471b9c1b51eSKate Stone PythonInteger::PythonInteger() : PythonObject() {} 4727d6d218eSZachary Turner 473f8b22f8fSZachary Turner PythonInteger::PythonInteger(PyRefType type, PyObject *py_obj) 474b9c1b51eSKate Stone : PythonObject() { 475f8b22f8fSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a integer type 4762c1f46dcSZachary Turner } 4772c1f46dcSZachary Turner 478b9c1b51eSKate Stone PythonInteger::PythonInteger(int64_t value) : PythonObject() { 4792c1f46dcSZachary Turner SetInteger(value); 4802c1f46dcSZachary Turner } 4812c1f46dcSZachary Turner 482b9c1b51eSKate Stone PythonInteger::~PythonInteger() {} 4832c1f46dcSZachary Turner 484b9c1b51eSKate Stone bool PythonInteger::Check(PyObject *py_obj) { 48522c8efcdSZachary Turner if (!py_obj) 48622c8efcdSZachary Turner return false; 48722c8efcdSZachary Turner 48822c8efcdSZachary Turner #if PY_MAJOR_VERSION >= 3 48905097246SAdrian Prantl // Python 3 does not have PyInt_Check. There is only one type of integral 49005097246SAdrian Prantl // value, long. 49122c8efcdSZachary Turner return PyLong_Check(py_obj); 49222c8efcdSZachary Turner #else 49322c8efcdSZachary Turner return PyLong_Check(py_obj) || PyInt_Check(py_obj); 49422c8efcdSZachary Turner #endif 4952c1f46dcSZachary Turner } 4962c1f46dcSZachary Turner 497b9c1b51eSKate Stone void PythonInteger::Reset(PyRefType type, PyObject *py_obj) { 49805097246SAdrian Prantl // Grab the desired reference type so that if we end up rejecting `py_obj` it 49905097246SAdrian Prantl // still gets decremented if necessary. 500f8b22f8fSZachary Turner PythonObject result(type, py_obj); 501f8b22f8fSZachary Turner 502b9c1b51eSKate Stone if (!PythonInteger::Check(py_obj)) { 503f8b22f8fSZachary Turner PythonObject::Reset(); 504f8b22f8fSZachary Turner return; 50522c8efcdSZachary Turner } 50622c8efcdSZachary Turner 50722c8efcdSZachary Turner #if PY_MAJOR_VERSION < 3 50805097246SAdrian Prantl // Always store this as a PyLong, which makes interoperability between Python 50905097246SAdrian Prantl // 2.x and Python 3.x easier. This is only necessary in 2.x, since 3.x 51005097246SAdrian Prantl // doesn't even have a PyInt. 511b9c1b51eSKate Stone if (PyInt_Check(py_obj)) { 512f8b22f8fSZachary Turner // Since we converted the original object to a different type, the new 51305097246SAdrian Prantl // object is an owned object regardless of the ownership semantics 51405097246SAdrian Prantl // requested by the user. 515f8b22f8fSZachary Turner result.Reset(PyRefType::Owned, PyLong_FromLongLong(PyInt_AsLong(py_obj))); 51622c8efcdSZachary Turner } 51722c8efcdSZachary Turner #endif 51822c8efcdSZachary Turner 519b9c1b51eSKate Stone assert(PyLong_Check(result.get()) && 520b9c1b51eSKate Stone "Couldn't get a PyLong from this PyObject"); 52122c8efcdSZachary Turner 522b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 52305097246SAdrian Prantl // overflow since it calls back into the virtual implementation. 524f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 5252c1f46dcSZachary Turner } 5262c1f46dcSZachary Turner 527b9c1b51eSKate Stone int64_t PythonInteger::GetInteger() const { 528b9c1b51eSKate Stone if (m_py_obj) { 529b9c1b51eSKate Stone assert(PyLong_Check(m_py_obj) && 530b9c1b51eSKate Stone "PythonInteger::GetInteger has a PyObject that isn't a PyLong"); 53122c8efcdSZachary Turner 532008ec446SGreg Clayton int overflow = 0; 533008ec446SGreg Clayton int64_t result = PyLong_AsLongLongAndOverflow(m_py_obj, &overflow); 534b9c1b51eSKate Stone if (overflow != 0) { 53505097246SAdrian Prantl // We got an integer that overflows, like 18446744072853913392L we can't 53605097246SAdrian Prantl // use PyLong_AsLongLong() as it will return 0xffffffffffffffff. If we 53705097246SAdrian Prantl // use the unsigned long long it will work as expected. 538008ec446SGreg Clayton const uint64_t uval = PyLong_AsUnsignedLongLong(m_py_obj); 5394f730dc7SIlia K result = static_cast<int64_t>(uval); 540008ec446SGreg Clayton } 541008ec446SGreg Clayton return result; 5422c1f46dcSZachary Turner } 5432c1f46dcSZachary Turner return UINT64_MAX; 5442c1f46dcSZachary Turner } 5452c1f46dcSZachary Turner 546b9c1b51eSKate Stone void PythonInteger::SetInteger(int64_t value) { 547f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Owned, PyLong_FromLongLong(value)); 5482c1f46dcSZachary Turner } 5492c1f46dcSZachary Turner 550b9c1b51eSKate Stone StructuredData::IntegerSP PythonInteger::CreateStructuredInteger() const { 5512c1f46dcSZachary Turner StructuredData::IntegerSP result(new StructuredData::Integer); 5522c1f46dcSZachary Turner result->SetValue(GetInteger()); 5532c1f46dcSZachary Turner return result; 5542c1f46dcSZachary Turner } 5552c1f46dcSZachary Turner 556b81d715cSTatyana Krasnukha // PythonBoolean 557b81d715cSTatyana Krasnukha 558b81d715cSTatyana Krasnukha PythonBoolean::PythonBoolean(PyRefType type, PyObject *py_obj) 559b81d715cSTatyana Krasnukha : PythonObject() { 560b81d715cSTatyana Krasnukha Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a boolean type 561b81d715cSTatyana Krasnukha } 562b81d715cSTatyana Krasnukha 563b81d715cSTatyana Krasnukha PythonBoolean::PythonBoolean(bool value) { 564b81d715cSTatyana Krasnukha SetValue(value); 565b81d715cSTatyana Krasnukha } 566b81d715cSTatyana Krasnukha 567b81d715cSTatyana Krasnukha bool PythonBoolean::Check(PyObject *py_obj) { 568b81d715cSTatyana Krasnukha return py_obj ? PyBool_Check(py_obj) : false; 569b81d715cSTatyana Krasnukha } 570b81d715cSTatyana Krasnukha 571b81d715cSTatyana Krasnukha void PythonBoolean::Reset(PyRefType type, PyObject *py_obj) { 572b81d715cSTatyana Krasnukha // Grab the desired reference type so that if we end up rejecting `py_obj` it 573b81d715cSTatyana Krasnukha // still gets decremented if necessary. 574b81d715cSTatyana Krasnukha PythonObject result(type, py_obj); 575b81d715cSTatyana Krasnukha 576b81d715cSTatyana Krasnukha if (!PythonBoolean::Check(py_obj)) { 577b81d715cSTatyana Krasnukha PythonObject::Reset(); 578b81d715cSTatyana Krasnukha return; 579b81d715cSTatyana Krasnukha } 580b81d715cSTatyana Krasnukha 581b81d715cSTatyana Krasnukha // Calling PythonObject::Reset(const PythonObject&) will lead to stack 582b81d715cSTatyana Krasnukha // overflow since it calls back into the virtual implementation. 583b81d715cSTatyana Krasnukha PythonObject::Reset(PyRefType::Borrowed, result.get()); 584b81d715cSTatyana Krasnukha } 585b81d715cSTatyana Krasnukha 586b81d715cSTatyana Krasnukha bool PythonBoolean::GetValue() const { 587b81d715cSTatyana Krasnukha return m_py_obj ? PyObject_IsTrue(m_py_obj) : false; 588b81d715cSTatyana Krasnukha } 589b81d715cSTatyana Krasnukha 590b81d715cSTatyana Krasnukha void PythonBoolean::SetValue(bool value) { 591b81d715cSTatyana Krasnukha PythonObject::Reset(PyRefType::Owned, PyBool_FromLong(value)); 592b81d715cSTatyana Krasnukha } 593b81d715cSTatyana Krasnukha 594b81d715cSTatyana Krasnukha StructuredData::BooleanSP PythonBoolean::CreateStructuredBoolean() const { 595b81d715cSTatyana Krasnukha StructuredData::BooleanSP result(new StructuredData::Boolean); 596b81d715cSTatyana Krasnukha result->SetValue(GetValue()); 597b81d715cSTatyana Krasnukha return result; 598b81d715cSTatyana Krasnukha } 599b81d715cSTatyana Krasnukha 6002c1f46dcSZachary Turner // PythonList 6012c1f46dcSZachary Turner 602b9c1b51eSKate Stone PythonList::PythonList(PyInitialValue value) : PythonObject() { 603f8b22f8fSZachary Turner if (value == PyInitialValue::Empty) 604f8b22f8fSZachary Turner Reset(PyRefType::Owned, PyList_New(0)); 6052c1f46dcSZachary Turner } 6062c1f46dcSZachary Turner 607b9c1b51eSKate Stone PythonList::PythonList(int list_size) : PythonObject() { 60887f47729SZachary Turner Reset(PyRefType::Owned, PyList_New(list_size)); 60987f47729SZachary Turner } 61087f47729SZachary Turner 611b9c1b51eSKate Stone PythonList::PythonList(PyRefType type, PyObject *py_obj) : PythonObject() { 612f8b22f8fSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a list 6132c1f46dcSZachary Turner } 6142c1f46dcSZachary Turner 615b9c1b51eSKate Stone PythonList::~PythonList() {} 6162c1f46dcSZachary Turner 617b9c1b51eSKate Stone bool PythonList::Check(PyObject *py_obj) { 61822c8efcdSZachary Turner if (!py_obj) 61922c8efcdSZachary Turner return false; 62022c8efcdSZachary Turner return PyList_Check(py_obj); 62122c8efcdSZachary Turner } 62222c8efcdSZachary Turner 623b9c1b51eSKate Stone void PythonList::Reset(PyRefType type, PyObject *py_obj) { 62405097246SAdrian Prantl // Grab the desired reference type so that if we end up rejecting `py_obj` it 62505097246SAdrian Prantl // still gets decremented if necessary. 626f8b22f8fSZachary Turner PythonObject result(type, py_obj); 627f8b22f8fSZachary Turner 628b9c1b51eSKate Stone if (!PythonList::Check(py_obj)) { 629f8b22f8fSZachary Turner PythonObject::Reset(); 630f8b22f8fSZachary Turner return; 63122c8efcdSZachary Turner } 63222c8efcdSZachary Turner 633b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 63405097246SAdrian Prantl // overflow since it calls back into the virtual implementation. 635f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 6362c1f46dcSZachary Turner } 6372c1f46dcSZachary Turner 638b9c1b51eSKate Stone uint32_t PythonList::GetSize() const { 639f8b22f8fSZachary Turner if (IsValid()) 6402c1f46dcSZachary Turner return PyList_GET_SIZE(m_py_obj); 6412c1f46dcSZachary Turner return 0; 6422c1f46dcSZachary Turner } 6432c1f46dcSZachary Turner 644b9c1b51eSKate Stone PythonObject PythonList::GetItemAtIndex(uint32_t index) const { 645f8b22f8fSZachary Turner if (IsValid()) 646f8b22f8fSZachary Turner return PythonObject(PyRefType::Borrowed, PyList_GetItem(m_py_obj, index)); 6472c1f46dcSZachary Turner return PythonObject(); 6482c1f46dcSZachary Turner } 6492c1f46dcSZachary Turner 650b9c1b51eSKate Stone void PythonList::SetItemAtIndex(uint32_t index, const PythonObject &object) { 651b9c1b51eSKate Stone if (IsAllocated() && object.IsValid()) { 652f8b22f8fSZachary Turner // PyList_SetItem is documented to "steal" a reference, so we need to 653f8b22f8fSZachary Turner // convert it to an owned reference by incrementing it. 654f8b22f8fSZachary Turner Py_INCREF(object.get()); 6552c1f46dcSZachary Turner PyList_SetItem(m_py_obj, index, object.get()); 6562c1f46dcSZachary Turner } 657f8b22f8fSZachary Turner } 6582c1f46dcSZachary Turner 659b9c1b51eSKate Stone void PythonList::AppendItem(const PythonObject &object) { 660b9c1b51eSKate Stone if (IsAllocated() && object.IsValid()) { 661f8b22f8fSZachary Turner // `PyList_Append` does *not* steal a reference, so do not call `Py_INCREF` 662f8b22f8fSZachary Turner // here like we do with `PyList_SetItem`. 6632c1f46dcSZachary Turner PyList_Append(m_py_obj, object.get()); 6642c1f46dcSZachary Turner } 665f8b22f8fSZachary Turner } 6662c1f46dcSZachary Turner 667b9c1b51eSKate Stone StructuredData::ArraySP PythonList::CreateStructuredArray() const { 6682c1f46dcSZachary Turner StructuredData::ArraySP result(new StructuredData::Array); 6692c1f46dcSZachary Turner uint32_t count = GetSize(); 670b9c1b51eSKate Stone for (uint32_t i = 0; i < count; ++i) { 6712c1f46dcSZachary Turner PythonObject obj = GetItemAtIndex(i); 6722c1f46dcSZachary Turner result->AddItem(obj.CreateStructuredObject()); 6732c1f46dcSZachary Turner } 6742c1f46dcSZachary Turner return result; 6752c1f46dcSZachary Turner } 6762c1f46dcSZachary Turner 677a1405147SZachary Turner // PythonTuple 678a1405147SZachary Turner 679b9c1b51eSKate Stone PythonTuple::PythonTuple(PyInitialValue value) : PythonObject() { 680a1405147SZachary Turner if (value == PyInitialValue::Empty) 681a1405147SZachary Turner Reset(PyRefType::Owned, PyTuple_New(0)); 682a1405147SZachary Turner } 683a1405147SZachary Turner 684b9c1b51eSKate Stone PythonTuple::PythonTuple(int tuple_size) : PythonObject() { 685a1405147SZachary Turner Reset(PyRefType::Owned, PyTuple_New(tuple_size)); 686a1405147SZachary Turner } 687a1405147SZachary Turner 688b9c1b51eSKate Stone PythonTuple::PythonTuple(PyRefType type, PyObject *py_obj) : PythonObject() { 689a1405147SZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a tuple 690a1405147SZachary Turner } 691a1405147SZachary Turner 692b9c1b51eSKate Stone PythonTuple::PythonTuple(std::initializer_list<PythonObject> objects) { 693a1405147SZachary Turner m_py_obj = PyTuple_New(objects.size()); 694a1405147SZachary Turner 695a1405147SZachary Turner uint32_t idx = 0; 696b9c1b51eSKate Stone for (auto object : objects) { 697a1405147SZachary Turner if (object.IsValid()) 698a1405147SZachary Turner SetItemAtIndex(idx, object); 699a1405147SZachary Turner idx++; 700a1405147SZachary Turner } 701a1405147SZachary Turner } 702a1405147SZachary Turner 703b9c1b51eSKate Stone PythonTuple::PythonTuple(std::initializer_list<PyObject *> objects) { 704a1405147SZachary Turner m_py_obj = PyTuple_New(objects.size()); 705a1405147SZachary Turner 706a1405147SZachary Turner uint32_t idx = 0; 707b9c1b51eSKate Stone for (auto py_object : objects) { 708a1405147SZachary Turner PythonObject object(PyRefType::Borrowed, py_object); 709a1405147SZachary Turner if (object.IsValid()) 710a1405147SZachary Turner SetItemAtIndex(idx, object); 711a1405147SZachary Turner idx++; 712a1405147SZachary Turner } 713a1405147SZachary Turner } 714a1405147SZachary Turner 715b9c1b51eSKate Stone PythonTuple::~PythonTuple() {} 716a1405147SZachary Turner 717b9c1b51eSKate Stone bool PythonTuple::Check(PyObject *py_obj) { 718a1405147SZachary Turner if (!py_obj) 719a1405147SZachary Turner return false; 720a1405147SZachary Turner return PyTuple_Check(py_obj); 721a1405147SZachary Turner } 722a1405147SZachary Turner 723b9c1b51eSKate Stone void PythonTuple::Reset(PyRefType type, PyObject *py_obj) { 72405097246SAdrian Prantl // Grab the desired reference type so that if we end up rejecting `py_obj` it 72505097246SAdrian Prantl // still gets decremented if necessary. 726a1405147SZachary Turner PythonObject result(type, py_obj); 727a1405147SZachary Turner 728b9c1b51eSKate Stone if (!PythonTuple::Check(py_obj)) { 729a1405147SZachary Turner PythonObject::Reset(); 730a1405147SZachary Turner return; 731a1405147SZachary Turner } 732a1405147SZachary Turner 733b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 73405097246SAdrian Prantl // overflow since it calls back into the virtual implementation. 735a1405147SZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 736a1405147SZachary Turner } 737a1405147SZachary Turner 738b9c1b51eSKate Stone uint32_t PythonTuple::GetSize() const { 739a1405147SZachary Turner if (IsValid()) 740a1405147SZachary Turner return PyTuple_GET_SIZE(m_py_obj); 741a1405147SZachary Turner return 0; 742a1405147SZachary Turner } 743a1405147SZachary Turner 744b9c1b51eSKate Stone PythonObject PythonTuple::GetItemAtIndex(uint32_t index) const { 745a1405147SZachary Turner if (IsValid()) 746a1405147SZachary Turner return PythonObject(PyRefType::Borrowed, PyTuple_GetItem(m_py_obj, index)); 747a1405147SZachary Turner return PythonObject(); 748a1405147SZachary Turner } 749a1405147SZachary Turner 750b9c1b51eSKate Stone void PythonTuple::SetItemAtIndex(uint32_t index, const PythonObject &object) { 751b9c1b51eSKate Stone if (IsAllocated() && object.IsValid()) { 752a1405147SZachary Turner // PyTuple_SetItem is documented to "steal" a reference, so we need to 753a1405147SZachary Turner // convert it to an owned reference by incrementing it. 754a1405147SZachary Turner Py_INCREF(object.get()); 755a1405147SZachary Turner PyTuple_SetItem(m_py_obj, index, object.get()); 756a1405147SZachary Turner } 757a1405147SZachary Turner } 758a1405147SZachary Turner 759b9c1b51eSKate Stone StructuredData::ArraySP PythonTuple::CreateStructuredArray() const { 760a1405147SZachary Turner StructuredData::ArraySP result(new StructuredData::Array); 761a1405147SZachary Turner uint32_t count = GetSize(); 762b9c1b51eSKate Stone for (uint32_t i = 0; i < count; ++i) { 763a1405147SZachary Turner PythonObject obj = GetItemAtIndex(i); 764a1405147SZachary Turner result->AddItem(obj.CreateStructuredObject()); 765a1405147SZachary Turner } 766a1405147SZachary Turner return result; 767a1405147SZachary Turner } 768a1405147SZachary Turner 7692c1f46dcSZachary Turner // PythonDictionary 7702c1f46dcSZachary Turner 771b9c1b51eSKate Stone PythonDictionary::PythonDictionary(PyInitialValue value) : PythonObject() { 772f8b22f8fSZachary Turner if (value == PyInitialValue::Empty) 773f8b22f8fSZachary Turner Reset(PyRefType::Owned, PyDict_New()); 7742c1f46dcSZachary Turner } 7752c1f46dcSZachary Turner 776f8b22f8fSZachary Turner PythonDictionary::PythonDictionary(PyRefType type, PyObject *py_obj) 777b9c1b51eSKate Stone : PythonObject() { 778f8b22f8fSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a dictionary 7792c1f46dcSZachary Turner } 7802c1f46dcSZachary Turner 781b9c1b51eSKate Stone PythonDictionary::~PythonDictionary() {} 7822c1f46dcSZachary Turner 783b9c1b51eSKate Stone bool PythonDictionary::Check(PyObject *py_obj) { 78422c8efcdSZachary Turner if (!py_obj) 78522c8efcdSZachary Turner return false; 78622c8efcdSZachary Turner 78722c8efcdSZachary Turner return PyDict_Check(py_obj); 78822c8efcdSZachary Turner } 78922c8efcdSZachary Turner 790b9c1b51eSKate Stone void PythonDictionary::Reset(PyRefType type, PyObject *py_obj) { 79105097246SAdrian Prantl // Grab the desired reference type so that if we end up rejecting `py_obj` it 79205097246SAdrian Prantl // still gets decremented if necessary. 793f8b22f8fSZachary Turner PythonObject result(type, py_obj); 794f8b22f8fSZachary Turner 795b9c1b51eSKate Stone if (!PythonDictionary::Check(py_obj)) { 796f8b22f8fSZachary Turner PythonObject::Reset(); 797f8b22f8fSZachary Turner return; 79822c8efcdSZachary Turner } 79922c8efcdSZachary Turner 800b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 80105097246SAdrian Prantl // overflow since it calls back into the virtual implementation. 802f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 8032c1f46dcSZachary Turner } 8042c1f46dcSZachary Turner 805b9c1b51eSKate Stone uint32_t PythonDictionary::GetSize() const { 806f8b22f8fSZachary Turner if (IsValid()) 8072c1f46dcSZachary Turner return PyDict_Size(m_py_obj); 8082c1f46dcSZachary Turner return 0; 8092c1f46dcSZachary Turner } 8102c1f46dcSZachary Turner 811b9c1b51eSKate Stone PythonList PythonDictionary::GetKeys() const { 812f8b22f8fSZachary Turner if (IsValid()) 813f8b22f8fSZachary Turner return PythonList(PyRefType::Owned, PyDict_Keys(m_py_obj)); 814f8b22f8fSZachary Turner return PythonList(PyInitialValue::Invalid); 8152c1f46dcSZachary Turner } 8162c1f46dcSZachary Turner 817b9c1b51eSKate Stone PythonObject PythonDictionary::GetItemForKey(const PythonObject &key) const { 818f8b22f8fSZachary Turner if (IsAllocated() && key.IsValid()) 819b9c1b51eSKate Stone return PythonObject(PyRefType::Borrowed, 820b9c1b51eSKate Stone PyDict_GetItem(m_py_obj, key.get())); 8212c1f46dcSZachary Turner return PythonObject(); 8222c1f46dcSZachary Turner } 8232c1f46dcSZachary Turner 824b9c1b51eSKate Stone void PythonDictionary::SetItemForKey(const PythonObject &key, 825b9c1b51eSKate Stone const PythonObject &value) { 826f8b22f8fSZachary Turner if (IsAllocated() && key.IsValid() && value.IsValid()) 8272c1f46dcSZachary Turner PyDict_SetItem(m_py_obj, key.get(), value.get()); 8282c1f46dcSZachary Turner } 8292c1f46dcSZachary Turner 8302c1f46dcSZachary Turner StructuredData::DictionarySP 831b9c1b51eSKate Stone PythonDictionary::CreateStructuredDictionary() const { 8322c1f46dcSZachary Turner StructuredData::DictionarySP result(new StructuredData::Dictionary); 8332c1f46dcSZachary Turner PythonList keys(GetKeys()); 8342c1f46dcSZachary Turner uint32_t num_keys = keys.GetSize(); 835b9c1b51eSKate Stone for (uint32_t i = 0; i < num_keys; ++i) { 8362c1f46dcSZachary Turner PythonObject key = keys.GetItemAtIndex(i); 8372c1f46dcSZachary Turner PythonObject value = GetItemForKey(key); 8382c1f46dcSZachary Turner StructuredData::ObjectSP structured_value = value.CreateStructuredObject(); 839f8b22f8fSZachary Turner result->AddItem(key.Str().GetString(), structured_value); 8402c1f46dcSZachary Turner } 8412c1f46dcSZachary Turner return result; 8422c1f46dcSZachary Turner } 8432c1f46dcSZachary Turner 844b9c1b51eSKate Stone PythonModule::PythonModule() : PythonObject() {} 8457841efbbSZachary Turner 846b9c1b51eSKate Stone PythonModule::PythonModule(PyRefType type, PyObject *py_obj) { 8477841efbbSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a module 8487841efbbSZachary Turner } 8497841efbbSZachary Turner 850b9c1b51eSKate Stone PythonModule::~PythonModule() {} 8517841efbbSZachary Turner 852b9c1b51eSKate Stone PythonModule PythonModule::BuiltinsModule() { 853a1405147SZachary Turner #if PY_MAJOR_VERSION >= 3 854a1405147SZachary Turner return AddModule("builtins"); 855a1405147SZachary Turner #else 856a1405147SZachary Turner return AddModule("__builtin__"); 857a1405147SZachary Turner #endif 858a1405147SZachary Turner } 859a1405147SZachary Turner 860b9c1b51eSKate Stone PythonModule PythonModule::MainModule() { return AddModule("__main__"); } 861a1405147SZachary Turner 862b9c1b51eSKate Stone PythonModule PythonModule::AddModule(llvm::StringRef module) { 863a1405147SZachary Turner std::string str = module.str(); 864a1405147SZachary Turner return PythonModule(PyRefType::Borrowed, PyImport_AddModule(str.c_str())); 8657841efbbSZachary Turner } 8667841efbbSZachary Turner 867085328eeSLawrence D'Anna Expected<PythonModule> PythonModule::Import(const char *name) { 868085328eeSLawrence D'Anna PyObject *mod = PyImport_ImportModule(name); 869085328eeSLawrence D'Anna if (!mod) 870085328eeSLawrence D'Anna return exception(); 871085328eeSLawrence D'Anna return Take<PythonModule>(mod); 872085328eeSLawrence D'Anna } 873085328eeSLawrence D'Anna 874085328eeSLawrence D'Anna Expected<PythonObject> PythonModule::Get(const char *name) { 875085328eeSLawrence D'Anna if (!IsValid()) 876085328eeSLawrence D'Anna return nullDeref(); 877085328eeSLawrence D'Anna PyObject *dict = PyModule_GetDict(m_py_obj); 878085328eeSLawrence D'Anna if (!dict) 879085328eeSLawrence D'Anna return exception(); 880085328eeSLawrence D'Anna PyObject *item = PyDict_GetItemString(dict, name); 881085328eeSLawrence D'Anna if (!item) 882085328eeSLawrence D'Anna return exception(); 883085328eeSLawrence D'Anna return Retain<PythonObject>(item); 8842419f1d5SZachary Turner } 8852419f1d5SZachary Turner 886b9c1b51eSKate Stone bool PythonModule::Check(PyObject *py_obj) { 8877841efbbSZachary Turner if (!py_obj) 8887841efbbSZachary Turner return false; 8897841efbbSZachary Turner 8907841efbbSZachary Turner return PyModule_Check(py_obj); 8917841efbbSZachary Turner } 8927841efbbSZachary Turner 893b9c1b51eSKate Stone void PythonModule::Reset(PyRefType type, PyObject *py_obj) { 89405097246SAdrian Prantl // Grab the desired reference type so that if we end up rejecting `py_obj` it 89505097246SAdrian Prantl // still gets decremented if necessary. 8967841efbbSZachary Turner PythonObject result(type, py_obj); 8977841efbbSZachary Turner 898b9c1b51eSKate Stone if (!PythonModule::Check(py_obj)) { 8997841efbbSZachary Turner PythonObject::Reset(); 9007841efbbSZachary Turner return; 9017841efbbSZachary Turner } 9027841efbbSZachary Turner 903b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 90405097246SAdrian Prantl // overflow since it calls back into the virtual implementation. 9057841efbbSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 9067841efbbSZachary Turner } 9077841efbbSZachary Turner 908b9c1b51eSKate Stone PythonDictionary PythonModule::GetDictionary() const { 9097841efbbSZachary Turner return PythonDictionary(PyRefType::Borrowed, PyModule_GetDict(m_py_obj)); 9107841efbbSZachary Turner } 9117841efbbSZachary Turner 912b9c1b51eSKate Stone PythonCallable::PythonCallable() : PythonObject() {} 913a1405147SZachary Turner 914b9c1b51eSKate Stone PythonCallable::PythonCallable(PyRefType type, PyObject *py_obj) { 915a1405147SZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a callable 916a1405147SZachary Turner } 917a1405147SZachary Turner 918b9c1b51eSKate Stone PythonCallable::~PythonCallable() {} 919a1405147SZachary Turner 920b9c1b51eSKate Stone bool PythonCallable::Check(PyObject *py_obj) { 921a1405147SZachary Turner if (!py_obj) 922a1405147SZachary Turner return false; 923a1405147SZachary Turner 924a1405147SZachary Turner return PyCallable_Check(py_obj); 925a1405147SZachary Turner } 926a1405147SZachary Turner 927b9c1b51eSKate Stone void PythonCallable::Reset(PyRefType type, PyObject *py_obj) { 92805097246SAdrian Prantl // Grab the desired reference type so that if we end up rejecting `py_obj` it 92905097246SAdrian Prantl // still gets decremented if necessary. 930a1405147SZachary Turner PythonObject result(type, py_obj); 931a1405147SZachary Turner 932b9c1b51eSKate Stone if (!PythonCallable::Check(py_obj)) { 933a1405147SZachary Turner PythonObject::Reset(); 934a1405147SZachary Turner return; 935a1405147SZachary Turner } 936a1405147SZachary Turner 937b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 93805097246SAdrian Prantl // overflow since it calls back into the virtual implementation. 939a1405147SZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 940a1405147SZachary Turner } 941a1405147SZachary Turner 94227a14f19SJim Ingham PythonCallable::ArgInfo PythonCallable::GetNumInitArguments() const { 94327a14f19SJim Ingham ArgInfo result = {0, false, false, false}; 94427a14f19SJim Ingham if (!IsValid()) 94527a14f19SJim Ingham return result; 94627a14f19SJim Ingham 94727a14f19SJim Ingham PythonObject __init__ = GetAttributeValue("__init__"); 94827a14f19SJim Ingham if (__init__.IsValid() ) { 94927a14f19SJim Ingham auto __init_callable__ = __init__.AsType<PythonCallable>(); 95027a14f19SJim Ingham if (__init_callable__.IsValid()) 95127a14f19SJim Ingham return __init_callable__.GetNumArguments(); 95227a14f19SJim Ingham } 95327a14f19SJim Ingham return result; 95427a14f19SJim Ingham } 95527a14f19SJim Ingham 956b9c1b51eSKate Stone PythonCallable::ArgInfo PythonCallable::GetNumArguments() const { 957a5d6765cSEnrico Granata ArgInfo result = {0, false, false, false}; 958a1405147SZachary Turner if (!IsValid()) 959b58fb2f4SZachary Turner return result; 960a1405147SZachary Turner 961a1405147SZachary Turner PyObject *py_func_obj = m_py_obj; 962b9c1b51eSKate Stone if (PyMethod_Check(py_func_obj)) { 963a1405147SZachary Turner py_func_obj = PyMethod_GET_FUNCTION(py_func_obj); 964a5d6765cSEnrico Granata PythonObject im_self = GetAttributeValue("im_self"); 965a5d6765cSEnrico Granata if (im_self.IsValid() && !im_self.IsNone()) 966a5d6765cSEnrico Granata result.is_bound_method = true; 967b9c1b51eSKate Stone } else { 968a5d6765cSEnrico Granata // see if this is a callable object with an __call__ method 969b9c1b51eSKate Stone if (!PyFunction_Check(py_func_obj)) { 970a5d6765cSEnrico Granata PythonObject __call__ = GetAttributeValue("__call__"); 971b9c1b51eSKate Stone if (__call__.IsValid()) { 972a5d6765cSEnrico Granata auto __callable__ = __call__.AsType<PythonCallable>(); 973b9c1b51eSKate Stone if (__callable__.IsValid()) { 974a5d6765cSEnrico Granata py_func_obj = PyMethod_GET_FUNCTION(__callable__.get()); 975a5d6765cSEnrico Granata PythonObject im_self = GetAttributeValue("im_self"); 976a5d6765cSEnrico Granata if (im_self.IsValid() && !im_self.IsNone()) 977a5d6765cSEnrico Granata result.is_bound_method = true; 978a5d6765cSEnrico Granata } 979a5d6765cSEnrico Granata } 980a5d6765cSEnrico Granata } 981a5d6765cSEnrico Granata } 982a1405147SZachary Turner 983a1405147SZachary Turner if (!py_func_obj) 984b58fb2f4SZachary Turner return result; 985a1405147SZachary Turner 986a1405147SZachary Turner PyCodeObject *code = (PyCodeObject *)PyFunction_GET_CODE(py_func_obj); 987a1405147SZachary Turner if (!code) 988b58fb2f4SZachary Turner return result; 989a1405147SZachary Turner 990b58fb2f4SZachary Turner result.count = code->co_argcount; 991b58fb2f4SZachary Turner result.has_varargs = !!(code->co_flags & CO_VARARGS); 992b58fb2f4SZachary Turner result.has_kwargs = !!(code->co_flags & CO_VARKEYWORDS); 993b58fb2f4SZachary Turner return result; 994b58fb2f4SZachary Turner } 995b58fb2f4SZachary Turner 996b9c1b51eSKate Stone PythonObject PythonCallable::operator()() { 997b9c1b51eSKate Stone return PythonObject(PyRefType::Owned, PyObject_CallObject(m_py_obj, nullptr)); 998a1405147SZachary Turner } 999a1405147SZachary Turner 1000b9c1b51eSKate Stone PythonObject PythonCallable:: 1001b9c1b51eSKate Stone operator()(std::initializer_list<PyObject *> args) { 1002a1405147SZachary Turner PythonTuple arg_tuple(args); 1003a1405147SZachary Turner return PythonObject(PyRefType::Owned, 1004a1405147SZachary Turner PyObject_CallObject(m_py_obj, arg_tuple.get())); 1005a1405147SZachary Turner } 1006a1405147SZachary Turner 1007b9c1b51eSKate Stone PythonObject PythonCallable:: 1008b9c1b51eSKate Stone operator()(std::initializer_list<PythonObject> args) { 1009a1405147SZachary Turner PythonTuple arg_tuple(args); 1010a1405147SZachary Turner return PythonObject(PyRefType::Owned, 1011a1405147SZachary Turner PyObject_CallObject(m_py_obj, arg_tuple.get())); 1012a1405147SZachary Turner } 1013a1405147SZachary Turner 1014b9c1b51eSKate Stone PythonFile::PythonFile() : PythonObject() {} 101532064024SZachary Turner 1016b9c1b51eSKate Stone PythonFile::PythonFile(PyRefType type, PyObject *o) { Reset(type, o); } 10179c40264fSZachary Turner 1018b9c1b51eSKate Stone PythonFile::~PythonFile() {} 10199c40264fSZachary Turner 1020b9c1b51eSKate Stone bool PythonFile::Check(PyObject *py_obj) { 102196898eb6SLawrence D'Anna if (!py_obj) 102296898eb6SLawrence D'Anna return false; 10239c40264fSZachary Turner #if PY_MAJOR_VERSION < 3 102423502721SJason Molenda return PyFile_Check(py_obj); 102523502721SJason Molenda #else 10269c40264fSZachary Turner // In Python 3, there is no `PyFile_Check`, and in fact PyFile is not even a 10279c40264fSZachary Turner // first-class object type anymore. `PyFile_FromFd` is just a thin wrapper 102805097246SAdrian Prantl // over `io.open()`, which returns some object derived from `io.IOBase`. As a 102905097246SAdrian Prantl // result, the only way to detect a file in Python 3 is to check whether it 103021b8a8aeSLawrence D'Anna // inherits from `io.IOBase`. 103121b8a8aeSLawrence D'Anna auto io_module = PythonModule::Import("io"); 103221b8a8aeSLawrence D'Anna if (!io_module) { 103321b8a8aeSLawrence D'Anna llvm::consumeError(io_module.takeError()); 10349c40264fSZachary Turner return false; 103521b8a8aeSLawrence D'Anna } 103621b8a8aeSLawrence D'Anna auto iobase = io_module.get().Get("IOBase"); 103721b8a8aeSLawrence D'Anna if (!iobase) { 103821b8a8aeSLawrence D'Anna llvm::consumeError(iobase.takeError()); 10399c40264fSZachary Turner return false; 104021b8a8aeSLawrence D'Anna } 104121b8a8aeSLawrence D'Anna int r = PyObject_IsInstance(py_obj, iobase.get().get()); 104221b8a8aeSLawrence D'Anna if (r < 0) { 104321b8a8aeSLawrence D'Anna llvm::consumeError(exception()); // clear the exception and log it. 104421b8a8aeSLawrence D'Anna return false; 104521b8a8aeSLawrence D'Anna } 104621b8a8aeSLawrence D'Anna return !!r; 104723502721SJason Molenda #endif 10489c40264fSZachary Turner } 10499c40264fSZachary Turner 1050b9c1b51eSKate Stone void PythonFile::Reset(PyRefType type, PyObject *py_obj) { 105105097246SAdrian Prantl // Grab the desired reference type so that if we end up rejecting `py_obj` it 105205097246SAdrian Prantl // still gets decremented if necessary. 10539c40264fSZachary Turner PythonObject result(type, py_obj); 10549c40264fSZachary Turner 105523502721SJason Molenda if (!PythonFile::Check(py_obj)) { 10569c40264fSZachary Turner PythonObject::Reset(); 10579c40264fSZachary Turner return; 10589c40264fSZachary Turner } 10599c40264fSZachary Turner 10609c40264fSZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack 10619c40264fSZachary Turner // overflow since it calls back into the virtual implementation. 10629c40264fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 10639c40264fSZachary Turner } 10649c40264fSZachary Turner 10652fce1137SLawrence D'Anna FileUP PythonFile::GetUnderlyingFile() const { 1066eda01c31SZachary Turner if (!IsValid()) 10672fce1137SLawrence D'Anna return nullptr; 1068eda01c31SZachary Turner 1069eda01c31SZachary Turner // We don't own the file descriptor returned by this function, make sure the 1070eda01c31SZachary Turner // File object knows about that. 1071744959b9SEnrico Granata PythonString py_mode = GetAttributeValue("mode").AsType<PythonString>(); 107257504530SLawrence D'Anna auto options = File::GetOptionsFromMode(py_mode.GetString()); 107362c9fe42SLawrence D'Anna if (!options) { 107462c9fe42SLawrence D'Anna llvm::consumeError(options.takeError()); 107562c9fe42SLawrence D'Anna return nullptr; 107662c9fe42SLawrence D'Anna } 107762c9fe42SLawrence D'Anna auto file = std::unique_ptr<File>(new NativeFile( 107862c9fe42SLawrence D'Anna PyObject_AsFileDescriptor(m_py_obj), options.get(), false)); 10792fce1137SLawrence D'Anna if (!file->IsValid()) 10802fce1137SLawrence D'Anna return nullptr; 10812fce1137SLawrence D'Anna return file; 1082eda01c31SZachary Turner } 1083d68983e3SPavel Labath 108421b8a8aeSLawrence D'Anna namespace { 108521b8a8aeSLawrence D'Anna class GIL { 108621b8a8aeSLawrence D'Anna public: 108721b8a8aeSLawrence D'Anna GIL() { 108821b8a8aeSLawrence D'Anna m_state = PyGILState_Ensure(); 108921b8a8aeSLawrence D'Anna assert(!PyErr_Occurred()); 109021b8a8aeSLawrence D'Anna } 109121b8a8aeSLawrence D'Anna ~GIL() { PyGILState_Release(m_state); } 109221b8a8aeSLawrence D'Anna 109321b8a8aeSLawrence D'Anna protected: 109421b8a8aeSLawrence D'Anna PyGILState_STATE m_state; 109521b8a8aeSLawrence D'Anna }; 109621b8a8aeSLawrence D'Anna } // namespace 109721b8a8aeSLawrence D'Anna 1098085328eeSLawrence D'Anna const char *PythonException::toCString() const { 1099085328eeSLawrence D'Anna if (!m_repr_bytes) 1100085328eeSLawrence D'Anna return "unknown exception"; 1101085328eeSLawrence D'Anna return PyBytes_AS_STRING(m_repr_bytes); 1102085328eeSLawrence D'Anna } 1103085328eeSLawrence D'Anna 1104085328eeSLawrence D'Anna PythonException::PythonException(const char *caller) { 1105085328eeSLawrence D'Anna assert(PyErr_Occurred()); 1106085328eeSLawrence D'Anna m_exception_type = m_exception = m_traceback = m_repr_bytes = NULL; 1107085328eeSLawrence D'Anna PyErr_Fetch(&m_exception_type, &m_exception, &m_traceback); 1108085328eeSLawrence D'Anna PyErr_NormalizeException(&m_exception_type, &m_exception, &m_traceback); 1109085328eeSLawrence D'Anna PyErr_Clear(); 1110085328eeSLawrence D'Anna if (m_exception) { 1111085328eeSLawrence D'Anna PyObject *repr = PyObject_Repr(m_exception); 1112085328eeSLawrence D'Anna if (repr) { 1113085328eeSLawrence D'Anna m_repr_bytes = PyUnicode_AsEncodedString(repr, "utf-8", nullptr); 1114085328eeSLawrence D'Anna if (!m_repr_bytes) { 1115085328eeSLawrence D'Anna PyErr_Clear(); 1116085328eeSLawrence D'Anna } 1117085328eeSLawrence D'Anna Py_XDECREF(repr); 1118085328eeSLawrence D'Anna } else { 1119085328eeSLawrence D'Anna PyErr_Clear(); 1120085328eeSLawrence D'Anna } 1121085328eeSLawrence D'Anna } 1122085328eeSLawrence D'Anna Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT); 1123085328eeSLawrence D'Anna if (caller) 1124085328eeSLawrence D'Anna LLDB_LOGF(log, "%s failed with exception: %s", caller, toCString()); 1125085328eeSLawrence D'Anna else 1126085328eeSLawrence D'Anna LLDB_LOGF(log, "python exception: %s", toCString()); 1127085328eeSLawrence D'Anna } 1128085328eeSLawrence D'Anna void PythonException::Restore() { 1129085328eeSLawrence D'Anna if (m_exception_type && m_exception) { 1130085328eeSLawrence D'Anna PyErr_Restore(m_exception_type, m_exception, m_traceback); 1131085328eeSLawrence D'Anna } else { 1132085328eeSLawrence D'Anna PyErr_SetString(PyExc_Exception, toCString()); 1133085328eeSLawrence D'Anna } 1134085328eeSLawrence D'Anna m_exception_type = m_exception = m_traceback = NULL; 1135085328eeSLawrence D'Anna } 1136085328eeSLawrence D'Anna 1137085328eeSLawrence D'Anna PythonException::~PythonException() { 1138085328eeSLawrence D'Anna Py_XDECREF(m_exception_type); 1139085328eeSLawrence D'Anna Py_XDECREF(m_exception); 1140085328eeSLawrence D'Anna Py_XDECREF(m_traceback); 1141085328eeSLawrence D'Anna Py_XDECREF(m_repr_bytes); 1142085328eeSLawrence D'Anna } 1143085328eeSLawrence D'Anna 1144085328eeSLawrence D'Anna void PythonException::log(llvm::raw_ostream &OS) const { OS << toCString(); } 1145085328eeSLawrence D'Anna 1146085328eeSLawrence D'Anna std::error_code PythonException::convertToErrorCode() const { 1147085328eeSLawrence D'Anna return llvm::inconvertibleErrorCode(); 1148085328eeSLawrence D'Anna } 1149085328eeSLawrence D'Anna 1150085328eeSLawrence D'Anna char PythonException::ID = 0; 1151085328eeSLawrence D'Anna 115262c9fe42SLawrence D'Anna llvm::Expected<File::OpenOptions> 115362c9fe42SLawrence D'Anna GetOptionsForPyObject(const PythonObject &obj) { 115421b8a8aeSLawrence D'Anna #if PY_MAJOR_VERSION >= 3 115562c9fe42SLawrence D'Anna auto options = File::OpenOptions(0); 115621b8a8aeSLawrence D'Anna auto readable = As<bool>(obj.CallMethod("readable")); 115721b8a8aeSLawrence D'Anna if (!readable) 115821b8a8aeSLawrence D'Anna return readable.takeError(); 115921b8a8aeSLawrence D'Anna auto writable = As<bool>(obj.CallMethod("writable")); 116021b8a8aeSLawrence D'Anna if (!writable) 116121b8a8aeSLawrence D'Anna return writable.takeError(); 116221b8a8aeSLawrence D'Anna if (readable.get()) 116321b8a8aeSLawrence D'Anna options |= File::eOpenOptionRead; 116421b8a8aeSLawrence D'Anna if (writable.get()) 116521b8a8aeSLawrence D'Anna options |= File::eOpenOptionWrite; 116662c9fe42SLawrence D'Anna return options; 116721b8a8aeSLawrence D'Anna #else 116821b8a8aeSLawrence D'Anna PythonString py_mode = obj.GetAttributeValue("mode").AsType<PythonString>(); 116962c9fe42SLawrence D'Anna return File::GetOptionsFromMode(py_mode.GetString()); 117021b8a8aeSLawrence D'Anna #endif 117121b8a8aeSLawrence D'Anna } 117221b8a8aeSLawrence D'Anna 117321b8a8aeSLawrence D'Anna // Base class template for python files. All it knows how to do 117421b8a8aeSLawrence D'Anna // is hold a reference to the python object and close or flush it 117521b8a8aeSLawrence D'Anna // when the File is closed. 117621b8a8aeSLawrence D'Anna namespace { 117721b8a8aeSLawrence D'Anna template <typename Base> class OwnedPythonFile : public Base { 117821b8a8aeSLawrence D'Anna public: 117921b8a8aeSLawrence D'Anna template <typename... Args> 118021b8a8aeSLawrence D'Anna OwnedPythonFile(const PythonFile &file, bool borrowed, Args... args) 118121b8a8aeSLawrence D'Anna : Base(args...), m_py_obj(file), m_borrowed(borrowed) { 118221b8a8aeSLawrence D'Anna assert(m_py_obj); 118321b8a8aeSLawrence D'Anna } 118421b8a8aeSLawrence D'Anna 118521b8a8aeSLawrence D'Anna ~OwnedPythonFile() override { 118621b8a8aeSLawrence D'Anna assert(m_py_obj); 118721b8a8aeSLawrence D'Anna GIL takeGIL; 118821b8a8aeSLawrence D'Anna Close(); 118921b8a8aeSLawrence D'Anna m_py_obj.Reset(); 119021b8a8aeSLawrence D'Anna } 119121b8a8aeSLawrence D'Anna 119221b8a8aeSLawrence D'Anna bool IsPythonSideValid() const { 119321b8a8aeSLawrence D'Anna GIL takeGIL; 119421b8a8aeSLawrence D'Anna auto closed = As<bool>(m_py_obj.GetAttribute("closed")); 119521b8a8aeSLawrence D'Anna if (!closed) { 119621b8a8aeSLawrence D'Anna llvm::consumeError(closed.takeError()); 119721b8a8aeSLawrence D'Anna return false; 119821b8a8aeSLawrence D'Anna } 119921b8a8aeSLawrence D'Anna return !closed.get(); 120021b8a8aeSLawrence D'Anna } 120121b8a8aeSLawrence D'Anna 120221b8a8aeSLawrence D'Anna bool IsValid() const override { 120321b8a8aeSLawrence D'Anna return IsPythonSideValid() && Base::IsValid(); 120421b8a8aeSLawrence D'Anna } 120521b8a8aeSLawrence D'Anna 120621b8a8aeSLawrence D'Anna Status Close() override { 120721b8a8aeSLawrence D'Anna assert(m_py_obj); 120821b8a8aeSLawrence D'Anna Status py_error, base_error; 120921b8a8aeSLawrence D'Anna GIL takeGIL; 121021b8a8aeSLawrence D'Anna if (!m_borrowed) { 121121b8a8aeSLawrence D'Anna auto r = m_py_obj.CallMethod("close"); 121221b8a8aeSLawrence D'Anna if (!r) 121321b8a8aeSLawrence D'Anna py_error = Status(r.takeError()); 121421b8a8aeSLawrence D'Anna } 121521b8a8aeSLawrence D'Anna base_error = Base::Close(); 121621b8a8aeSLawrence D'Anna if (py_error.Fail()) 121721b8a8aeSLawrence D'Anna return py_error; 121821b8a8aeSLawrence D'Anna return base_error; 121921b8a8aeSLawrence D'Anna }; 122021b8a8aeSLawrence D'Anna 1221*d9b553ecSLawrence D'Anna PyObject *GetPythonObject() const { 1222*d9b553ecSLawrence D'Anna assert(m_py_obj.IsValid()); 1223*d9b553ecSLawrence D'Anna return m_py_obj.get(); 1224*d9b553ecSLawrence D'Anna } 1225*d9b553ecSLawrence D'Anna 1226*d9b553ecSLawrence D'Anna static bool classof(const File *file) = delete; 1227*d9b553ecSLawrence D'Anna 122821b8a8aeSLawrence D'Anna protected: 122921b8a8aeSLawrence D'Anna PythonFile m_py_obj; 123021b8a8aeSLawrence D'Anna bool m_borrowed; 123121b8a8aeSLawrence D'Anna }; 123221b8a8aeSLawrence D'Anna } // namespace 123321b8a8aeSLawrence D'Anna 123421b8a8aeSLawrence D'Anna // A SimplePythonFile is a OwnedPythonFile that just does all I/O as 123521b8a8aeSLawrence D'Anna // a NativeFile 123621b8a8aeSLawrence D'Anna namespace { 123721b8a8aeSLawrence D'Anna class SimplePythonFile : public OwnedPythonFile<NativeFile> { 123821b8a8aeSLawrence D'Anna public: 123921b8a8aeSLawrence D'Anna SimplePythonFile(const PythonFile &file, bool borrowed, int fd, 124062c9fe42SLawrence D'Anna File::OpenOptions options) 124121b8a8aeSLawrence D'Anna : OwnedPythonFile(file, borrowed, fd, options, false) {} 1242*d9b553ecSLawrence D'Anna 1243*d9b553ecSLawrence D'Anna static char ID; 1244*d9b553ecSLawrence D'Anna bool isA(const void *classID) const override { 1245*d9b553ecSLawrence D'Anna return classID == &ID || NativeFile::isA(classID); 1246*d9b553ecSLawrence D'Anna } 1247*d9b553ecSLawrence D'Anna static bool classof(const File *file) { return file->isA(&ID); } 124821b8a8aeSLawrence D'Anna }; 1249*d9b553ecSLawrence D'Anna char SimplePythonFile::ID = 0; 125021b8a8aeSLawrence D'Anna } // namespace 125121b8a8aeSLawrence D'Anna 125221b8a8aeSLawrence D'Anna #if PY_MAJOR_VERSION >= 3 125321b8a8aeSLawrence D'Anna 125421b8a8aeSLawrence D'Anna namespace { 125521b8a8aeSLawrence D'Anna class PythonBuffer { 125621b8a8aeSLawrence D'Anna public: 125721b8a8aeSLawrence D'Anna PythonBuffer &operator=(const PythonBuffer &) = delete; 125821b8a8aeSLawrence D'Anna PythonBuffer(const PythonBuffer &) = delete; 125921b8a8aeSLawrence D'Anna 126021b8a8aeSLawrence D'Anna static Expected<PythonBuffer> Create(PythonObject &obj, 126121b8a8aeSLawrence D'Anna int flags = PyBUF_SIMPLE) { 126221b8a8aeSLawrence D'Anna Py_buffer py_buffer = {}; 126321b8a8aeSLawrence D'Anna PyObject_GetBuffer(obj.get(), &py_buffer, flags); 126421b8a8aeSLawrence D'Anna if (!py_buffer.obj) 126521b8a8aeSLawrence D'Anna return llvm::make_error<PythonException>(); 126621b8a8aeSLawrence D'Anna return PythonBuffer(py_buffer); 126721b8a8aeSLawrence D'Anna } 126821b8a8aeSLawrence D'Anna 126921b8a8aeSLawrence D'Anna PythonBuffer(PythonBuffer &&other) { 127021b8a8aeSLawrence D'Anna m_buffer = other.m_buffer; 127121b8a8aeSLawrence D'Anna other.m_buffer.obj = nullptr; 127221b8a8aeSLawrence D'Anna } 127321b8a8aeSLawrence D'Anna 127421b8a8aeSLawrence D'Anna ~PythonBuffer() { 127521b8a8aeSLawrence D'Anna if (m_buffer.obj) 127621b8a8aeSLawrence D'Anna PyBuffer_Release(&m_buffer); 127721b8a8aeSLawrence D'Anna } 127821b8a8aeSLawrence D'Anna 127921b8a8aeSLawrence D'Anna Py_buffer &get() { return m_buffer; } 128021b8a8aeSLawrence D'Anna 128121b8a8aeSLawrence D'Anna private: 128221b8a8aeSLawrence D'Anna // takes ownership of the buffer. 128321b8a8aeSLawrence D'Anna PythonBuffer(const Py_buffer &py_buffer) : m_buffer(py_buffer) {} 128421b8a8aeSLawrence D'Anna Py_buffer m_buffer; 128521b8a8aeSLawrence D'Anna }; 128621b8a8aeSLawrence D'Anna } // namespace 128721b8a8aeSLawrence D'Anna 128821b8a8aeSLawrence D'Anna // Shared methods between TextPythonFile and BinaryPythonFile 128921b8a8aeSLawrence D'Anna namespace { 129021b8a8aeSLawrence D'Anna class PythonIOFile : public OwnedPythonFile<File> { 129121b8a8aeSLawrence D'Anna public: 129221b8a8aeSLawrence D'Anna PythonIOFile(const PythonFile &file, bool borrowed) 129321b8a8aeSLawrence D'Anna : OwnedPythonFile(file, borrowed) {} 129421b8a8aeSLawrence D'Anna 129521b8a8aeSLawrence D'Anna ~PythonIOFile() override { Close(); } 129621b8a8aeSLawrence D'Anna 129721b8a8aeSLawrence D'Anna bool IsValid() const override { return IsPythonSideValid(); } 129821b8a8aeSLawrence D'Anna 129921b8a8aeSLawrence D'Anna Status Close() override { 130021b8a8aeSLawrence D'Anna assert(m_py_obj); 130121b8a8aeSLawrence D'Anna GIL takeGIL; 130221b8a8aeSLawrence D'Anna if (m_borrowed) 130321b8a8aeSLawrence D'Anna return Flush(); 130421b8a8aeSLawrence D'Anna auto r = m_py_obj.CallMethod("close"); 130521b8a8aeSLawrence D'Anna if (!r) 130621b8a8aeSLawrence D'Anna return Status(r.takeError()); 130721b8a8aeSLawrence D'Anna return Status(); 130821b8a8aeSLawrence D'Anna } 130921b8a8aeSLawrence D'Anna 131021b8a8aeSLawrence D'Anna Status Flush() override { 131121b8a8aeSLawrence D'Anna GIL takeGIL; 131221b8a8aeSLawrence D'Anna auto r = m_py_obj.CallMethod("flush"); 131321b8a8aeSLawrence D'Anna if (!r) 131421b8a8aeSLawrence D'Anna return Status(r.takeError()); 131521b8a8aeSLawrence D'Anna return Status(); 131621b8a8aeSLawrence D'Anna } 131721b8a8aeSLawrence D'Anna 1318*d9b553ecSLawrence D'Anna Expected<File::OpenOptions> GetOptions() const override { 1319*d9b553ecSLawrence D'Anna GIL takeGIL; 1320*d9b553ecSLawrence D'Anna return GetOptionsForPyObject(m_py_obj); 1321*d9b553ecSLawrence D'Anna } 1322*d9b553ecSLawrence D'Anna 1323*d9b553ecSLawrence D'Anna static char ID; 1324*d9b553ecSLawrence D'Anna bool isA(const void *classID) const override { 1325*d9b553ecSLawrence D'Anna return classID == &ID || File::isA(classID); 1326*d9b553ecSLawrence D'Anna } 1327*d9b553ecSLawrence D'Anna static bool classof(const File *file) { return file->isA(&ID); } 132821b8a8aeSLawrence D'Anna }; 1329*d9b553ecSLawrence D'Anna char PythonIOFile::ID = 0; 133021b8a8aeSLawrence D'Anna } // namespace 133121b8a8aeSLawrence D'Anna 133221b8a8aeSLawrence D'Anna namespace { 133321b8a8aeSLawrence D'Anna class BinaryPythonFile : public PythonIOFile { 133421b8a8aeSLawrence D'Anna protected: 133521b8a8aeSLawrence D'Anna int m_descriptor; 133621b8a8aeSLawrence D'Anna 133721b8a8aeSLawrence D'Anna public: 133821b8a8aeSLawrence D'Anna BinaryPythonFile(int fd, const PythonFile &file, bool borrowed) 133921b8a8aeSLawrence D'Anna : PythonIOFile(file, borrowed), 134021b8a8aeSLawrence D'Anna m_descriptor(File::DescriptorIsValid(fd) ? fd 134121b8a8aeSLawrence D'Anna : File::kInvalidDescriptor) {} 134221b8a8aeSLawrence D'Anna 134321b8a8aeSLawrence D'Anna int GetDescriptor() const override { return m_descriptor; } 134421b8a8aeSLawrence D'Anna 134521b8a8aeSLawrence D'Anna Status Write(const void *buf, size_t &num_bytes) override { 134621b8a8aeSLawrence D'Anna GIL takeGIL; 134721b8a8aeSLawrence D'Anna PyObject *pybuffer_p = PyMemoryView_FromMemory( 134821b8a8aeSLawrence D'Anna const_cast<char *>((const char *)buf), num_bytes, PyBUF_READ); 134921b8a8aeSLawrence D'Anna if (!pybuffer_p) 135021b8a8aeSLawrence D'Anna return Status(llvm::make_error<PythonException>()); 135121b8a8aeSLawrence D'Anna auto pybuffer = Take<PythonObject>(pybuffer_p); 135221b8a8aeSLawrence D'Anna num_bytes = 0; 135321b8a8aeSLawrence D'Anna auto bytes_written = As<long long>(m_py_obj.CallMethod("write", pybuffer)); 135421b8a8aeSLawrence D'Anna if (!bytes_written) 135521b8a8aeSLawrence D'Anna return Status(bytes_written.takeError()); 135621b8a8aeSLawrence D'Anna if (bytes_written.get() < 0) 135721b8a8aeSLawrence D'Anna return Status(".write() method returned a negative number!"); 135821b8a8aeSLawrence D'Anna static_assert(sizeof(long long) >= sizeof(size_t), "overflow"); 135921b8a8aeSLawrence D'Anna num_bytes = bytes_written.get(); 136021b8a8aeSLawrence D'Anna return Status(); 136121b8a8aeSLawrence D'Anna } 136221b8a8aeSLawrence D'Anna 136321b8a8aeSLawrence D'Anna Status Read(void *buf, size_t &num_bytes) override { 136421b8a8aeSLawrence D'Anna GIL takeGIL; 136521b8a8aeSLawrence D'Anna static_assert(sizeof(long long) >= sizeof(size_t), "overflow"); 136621b8a8aeSLawrence D'Anna auto pybuffer_obj = 136721b8a8aeSLawrence D'Anna m_py_obj.CallMethod("read", (unsigned long long)num_bytes); 136821b8a8aeSLawrence D'Anna if (!pybuffer_obj) 136921b8a8aeSLawrence D'Anna return Status(pybuffer_obj.takeError()); 137021b8a8aeSLawrence D'Anna num_bytes = 0; 137121b8a8aeSLawrence D'Anna if (pybuffer_obj.get().IsNone()) { 137221b8a8aeSLawrence D'Anna // EOF 137321b8a8aeSLawrence D'Anna num_bytes = 0; 137421b8a8aeSLawrence D'Anna return Status(); 137521b8a8aeSLawrence D'Anna } 137621b8a8aeSLawrence D'Anna auto pybuffer = PythonBuffer::Create(pybuffer_obj.get()); 137721b8a8aeSLawrence D'Anna if (!pybuffer) 137821b8a8aeSLawrence D'Anna return Status(pybuffer.takeError()); 137921b8a8aeSLawrence D'Anna memcpy(buf, pybuffer.get().get().buf, pybuffer.get().get().len); 138021b8a8aeSLawrence D'Anna num_bytes = pybuffer.get().get().len; 138121b8a8aeSLawrence D'Anna return Status(); 138221b8a8aeSLawrence D'Anna } 138321b8a8aeSLawrence D'Anna }; 138421b8a8aeSLawrence D'Anna } // namespace 138521b8a8aeSLawrence D'Anna 138621b8a8aeSLawrence D'Anna namespace { 138721b8a8aeSLawrence D'Anna class TextPythonFile : public PythonIOFile { 138821b8a8aeSLawrence D'Anna protected: 138921b8a8aeSLawrence D'Anna int m_descriptor; 139021b8a8aeSLawrence D'Anna 139121b8a8aeSLawrence D'Anna public: 139221b8a8aeSLawrence D'Anna TextPythonFile(int fd, const PythonFile &file, bool borrowed) 139321b8a8aeSLawrence D'Anna : PythonIOFile(file, borrowed), 139421b8a8aeSLawrence D'Anna m_descriptor(File::DescriptorIsValid(fd) ? fd 139521b8a8aeSLawrence D'Anna : File::kInvalidDescriptor) {} 139621b8a8aeSLawrence D'Anna 139721b8a8aeSLawrence D'Anna int GetDescriptor() const override { return m_descriptor; } 139821b8a8aeSLawrence D'Anna 139921b8a8aeSLawrence D'Anna Status Write(const void *buf, size_t &num_bytes) override { 140021b8a8aeSLawrence D'Anna GIL takeGIL; 140121b8a8aeSLawrence D'Anna auto pystring = 140221b8a8aeSLawrence D'Anna PythonString::FromUTF8(llvm::StringRef((const char *)buf, num_bytes)); 140321b8a8aeSLawrence D'Anna if (!pystring) 140421b8a8aeSLawrence D'Anna return Status(pystring.takeError()); 140521b8a8aeSLawrence D'Anna num_bytes = 0; 140621b8a8aeSLawrence D'Anna auto bytes_written = 140721b8a8aeSLawrence D'Anna As<long long>(m_py_obj.CallMethod("write", pystring.get())); 140821b8a8aeSLawrence D'Anna if (!bytes_written) 140921b8a8aeSLawrence D'Anna return Status(bytes_written.takeError()); 141021b8a8aeSLawrence D'Anna if (bytes_written.get() < 0) 141121b8a8aeSLawrence D'Anna return Status(".write() method returned a negative number!"); 141221b8a8aeSLawrence D'Anna static_assert(sizeof(long long) >= sizeof(size_t), "overflow"); 141321b8a8aeSLawrence D'Anna num_bytes = bytes_written.get(); 141421b8a8aeSLawrence D'Anna return Status(); 141521b8a8aeSLawrence D'Anna } 141621b8a8aeSLawrence D'Anna 141721b8a8aeSLawrence D'Anna Status Read(void *buf, size_t &num_bytes) override { 141821b8a8aeSLawrence D'Anna GIL takeGIL; 141921b8a8aeSLawrence D'Anna size_t num_chars = num_bytes / 6; 142021b8a8aeSLawrence D'Anna size_t orig_num_bytes = num_bytes; 142121b8a8aeSLawrence D'Anna num_bytes = 0; 142221b8a8aeSLawrence D'Anna if (orig_num_bytes < 6) { 142321b8a8aeSLawrence D'Anna return Status("can't read less than 6 bytes from a utf8 text stream"); 142421b8a8aeSLawrence D'Anna } 142521b8a8aeSLawrence D'Anna auto pystring = As<PythonString>( 142621b8a8aeSLawrence D'Anna m_py_obj.CallMethod("read", (unsigned long long)num_chars)); 142721b8a8aeSLawrence D'Anna if (!pystring) 142821b8a8aeSLawrence D'Anna return Status(pystring.takeError()); 142921b8a8aeSLawrence D'Anna if (pystring.get().IsNone()) { 143021b8a8aeSLawrence D'Anna // EOF 143121b8a8aeSLawrence D'Anna return Status(); 143221b8a8aeSLawrence D'Anna } 143321b8a8aeSLawrence D'Anna auto stringref = pystring.get().AsUTF8(); 143421b8a8aeSLawrence D'Anna if (!stringref) 143521b8a8aeSLawrence D'Anna return Status(stringref.takeError()); 143621b8a8aeSLawrence D'Anna num_bytes = stringref.get().size(); 143721b8a8aeSLawrence D'Anna memcpy(buf, stringref.get().begin(), num_bytes); 143821b8a8aeSLawrence D'Anna return Status(); 143921b8a8aeSLawrence D'Anna } 144021b8a8aeSLawrence D'Anna }; 144121b8a8aeSLawrence D'Anna } // namespace 144221b8a8aeSLawrence D'Anna 144321b8a8aeSLawrence D'Anna #endif 144421b8a8aeSLawrence D'Anna 144521b8a8aeSLawrence D'Anna llvm::Expected<FileSP> PythonFile::ConvertToFile(bool borrowed) { 144621b8a8aeSLawrence D'Anna if (!IsValid()) 144721b8a8aeSLawrence D'Anna return llvm::createStringError(llvm::inconvertibleErrorCode(), 144821b8a8aeSLawrence D'Anna "invalid PythonFile"); 144921b8a8aeSLawrence D'Anna 145021b8a8aeSLawrence D'Anna int fd = PyObject_AsFileDescriptor(m_py_obj); 145121b8a8aeSLawrence D'Anna if (fd < 0) { 145221b8a8aeSLawrence D'Anna PyErr_Clear(); 145321b8a8aeSLawrence D'Anna return ConvertToFileForcingUseOfScriptingIOMethods(borrowed); 145421b8a8aeSLawrence D'Anna } 145521b8a8aeSLawrence D'Anna auto options = GetOptionsForPyObject(*this); 145621b8a8aeSLawrence D'Anna if (!options) 145721b8a8aeSLawrence D'Anna return options.takeError(); 145821b8a8aeSLawrence D'Anna 145921b8a8aeSLawrence D'Anna // LLDB and python will not share I/O buffers. We should probably 146021b8a8aeSLawrence D'Anna // flush the python buffers now. 146121b8a8aeSLawrence D'Anna auto r = CallMethod("flush"); 146221b8a8aeSLawrence D'Anna if (!r) 146321b8a8aeSLawrence D'Anna return r.takeError(); 146421b8a8aeSLawrence D'Anna 146521b8a8aeSLawrence D'Anna FileSP file_sp; 146621b8a8aeSLawrence D'Anna if (borrowed) { 146721b8a8aeSLawrence D'Anna // In this case we we don't need to retain the python 146821b8a8aeSLawrence D'Anna // object at all. 146921b8a8aeSLawrence D'Anna file_sp = std::make_shared<NativeFile>(fd, options.get(), false); 147021b8a8aeSLawrence D'Anna } else { 147121b8a8aeSLawrence D'Anna file_sp = std::static_pointer_cast<File>( 147221b8a8aeSLawrence D'Anna std::make_shared<SimplePythonFile>(*this, borrowed, fd, options.get())); 147321b8a8aeSLawrence D'Anna } 147421b8a8aeSLawrence D'Anna if (!file_sp->IsValid()) 147521b8a8aeSLawrence D'Anna return llvm::createStringError(llvm::inconvertibleErrorCode(), 147621b8a8aeSLawrence D'Anna "invalid File"); 147721b8a8aeSLawrence D'Anna 147821b8a8aeSLawrence D'Anna return file_sp; 147921b8a8aeSLawrence D'Anna } 148021b8a8aeSLawrence D'Anna 148121b8a8aeSLawrence D'Anna llvm::Expected<FileSP> 148221b8a8aeSLawrence D'Anna PythonFile::ConvertToFileForcingUseOfScriptingIOMethods(bool borrowed) { 148321b8a8aeSLawrence D'Anna 148421b8a8aeSLawrence D'Anna assert(!PyErr_Occurred()); 148521b8a8aeSLawrence D'Anna 148621b8a8aeSLawrence D'Anna if (!IsValid()) 148721b8a8aeSLawrence D'Anna return llvm::createStringError(llvm::inconvertibleErrorCode(), 148821b8a8aeSLawrence D'Anna "invalid PythonFile"); 148921b8a8aeSLawrence D'Anna 149021b8a8aeSLawrence D'Anna #if PY_MAJOR_VERSION < 3 149121b8a8aeSLawrence D'Anna 149221b8a8aeSLawrence D'Anna return llvm::createStringError(llvm::inconvertibleErrorCode(), 149321b8a8aeSLawrence D'Anna "not supported on python 2"); 149421b8a8aeSLawrence D'Anna 149521b8a8aeSLawrence D'Anna #else 149621b8a8aeSLawrence D'Anna 149721b8a8aeSLawrence D'Anna int fd = PyObject_AsFileDescriptor(m_py_obj); 149821b8a8aeSLawrence D'Anna if (fd < 0) { 149921b8a8aeSLawrence D'Anna PyErr_Clear(); 150021b8a8aeSLawrence D'Anna fd = File::kInvalidDescriptor; 150121b8a8aeSLawrence D'Anna } 150221b8a8aeSLawrence D'Anna 150321b8a8aeSLawrence D'Anna auto io_module = PythonModule::Import("io"); 150421b8a8aeSLawrence D'Anna if (!io_module) 150521b8a8aeSLawrence D'Anna return io_module.takeError(); 150621b8a8aeSLawrence D'Anna auto textIOBase = io_module.get().Get("TextIOBase"); 150721b8a8aeSLawrence D'Anna if (!textIOBase) 150821b8a8aeSLawrence D'Anna return textIOBase.takeError(); 150921b8a8aeSLawrence D'Anna auto rawIOBase = io_module.get().Get("RawIOBase"); 151021b8a8aeSLawrence D'Anna if (!rawIOBase) 151121b8a8aeSLawrence D'Anna return rawIOBase.takeError(); 151221b8a8aeSLawrence D'Anna auto bufferedIOBase = io_module.get().Get("BufferedIOBase"); 151321b8a8aeSLawrence D'Anna if (!bufferedIOBase) 151421b8a8aeSLawrence D'Anna return bufferedIOBase.takeError(); 151521b8a8aeSLawrence D'Anna 151621b8a8aeSLawrence D'Anna FileSP file_sp; 151721b8a8aeSLawrence D'Anna 151821b8a8aeSLawrence D'Anna auto isTextIO = IsInstance(textIOBase.get()); 151921b8a8aeSLawrence D'Anna if (!isTextIO) 152021b8a8aeSLawrence D'Anna return isTextIO.takeError(); 152121b8a8aeSLawrence D'Anna if (isTextIO.get()) 152221b8a8aeSLawrence D'Anna file_sp = std::static_pointer_cast<File>( 152321b8a8aeSLawrence D'Anna std::make_shared<TextPythonFile>(fd, *this, borrowed)); 152421b8a8aeSLawrence D'Anna 152521b8a8aeSLawrence D'Anna auto isRawIO = IsInstance(rawIOBase.get()); 152621b8a8aeSLawrence D'Anna if (!isRawIO) 152721b8a8aeSLawrence D'Anna return isRawIO.takeError(); 152821b8a8aeSLawrence D'Anna auto isBufferedIO = IsInstance(bufferedIOBase.get()); 152921b8a8aeSLawrence D'Anna if (!isBufferedIO) 153021b8a8aeSLawrence D'Anna return isBufferedIO.takeError(); 153121b8a8aeSLawrence D'Anna 153221b8a8aeSLawrence D'Anna if (isRawIO.get() || isBufferedIO.get()) { 153321b8a8aeSLawrence D'Anna file_sp = std::static_pointer_cast<File>( 153421b8a8aeSLawrence D'Anna std::make_shared<BinaryPythonFile>(fd, *this, borrowed)); 153521b8a8aeSLawrence D'Anna } 153621b8a8aeSLawrence D'Anna 153721b8a8aeSLawrence D'Anna if (!file_sp) 153821b8a8aeSLawrence D'Anna return llvm::createStringError(llvm::inconvertibleErrorCode(), 153921b8a8aeSLawrence D'Anna "python file is neither text nor binary"); 154021b8a8aeSLawrence D'Anna 154121b8a8aeSLawrence D'Anna if (!file_sp->IsValid()) 154221b8a8aeSLawrence D'Anna return llvm::createStringError(llvm::inconvertibleErrorCode(), 154321b8a8aeSLawrence D'Anna "invalid File"); 154421b8a8aeSLawrence D'Anna 154521b8a8aeSLawrence D'Anna return file_sp; 154621b8a8aeSLawrence D'Anna 154721b8a8aeSLawrence D'Anna #endif 154821b8a8aeSLawrence D'Anna } 154921b8a8aeSLawrence D'Anna 1550*d9b553ecSLawrence D'Anna Expected<PythonFile> PythonFile::FromFile(File &file, const char *mode) { 1551*d9b553ecSLawrence D'Anna if (!file.IsValid()) 1552*d9b553ecSLawrence D'Anna return llvm::createStringError(llvm::inconvertibleErrorCode(), 1553*d9b553ecSLawrence D'Anna "invalid file"); 1554*d9b553ecSLawrence D'Anna 1555*d9b553ecSLawrence D'Anna if (auto *simple = llvm::dyn_cast<SimplePythonFile>(&file)) 1556*d9b553ecSLawrence D'Anna return Retain<PythonFile>(simple->GetPythonObject()); 1557*d9b553ecSLawrence D'Anna #if PY_MAJOR_VERSION >= 3 1558*d9b553ecSLawrence D'Anna if (auto *pythonio = llvm::dyn_cast<PythonIOFile>(&file)) 1559*d9b553ecSLawrence D'Anna return Retain<PythonFile>(pythonio->GetPythonObject()); 1560*d9b553ecSLawrence D'Anna #endif 1561*d9b553ecSLawrence D'Anna 1562*d9b553ecSLawrence D'Anna if (!mode) { 1563*d9b553ecSLawrence D'Anna auto m = file.GetOpenMode(); 1564*d9b553ecSLawrence D'Anna if (!m) 1565*d9b553ecSLawrence D'Anna return m.takeError(); 1566*d9b553ecSLawrence D'Anna mode = m.get(); 1567*d9b553ecSLawrence D'Anna } 1568*d9b553ecSLawrence D'Anna 1569*d9b553ecSLawrence D'Anna PyObject *file_obj; 1570*d9b553ecSLawrence D'Anna #if PY_MAJOR_VERSION >= 3 1571*d9b553ecSLawrence D'Anna file_obj = PyFile_FromFd(file.GetDescriptor(), nullptr, mode, -1, nullptr, 1572*d9b553ecSLawrence D'Anna "ignore", nullptr, 0); 1573*d9b553ecSLawrence D'Anna #else 1574*d9b553ecSLawrence D'Anna // Read through the Python source, doesn't seem to modify these strings 1575*d9b553ecSLawrence D'Anna char *cmode = const_cast<char *>(mode); 1576*d9b553ecSLawrence D'Anna // We pass ::flush instead of ::fclose here so we borrow the FILE* -- 1577*d9b553ecSLawrence D'Anna // the lldb_private::File still owns it. 1578*d9b553ecSLawrence D'Anna file_obj = 1579*d9b553ecSLawrence D'Anna PyFile_FromFile(file.GetStream(), const_cast<char *>(""), cmode, ::fflush); 1580*d9b553ecSLawrence D'Anna #endif 1581*d9b553ecSLawrence D'Anna 1582*d9b553ecSLawrence D'Anna if (!file_obj) 1583*d9b553ecSLawrence D'Anna return exception(); 1584*d9b553ecSLawrence D'Anna 1585*d9b553ecSLawrence D'Anna return Take<PythonFile>(file_obj); 1586*d9b553ecSLawrence D'Anna } 1587*d9b553ecSLawrence D'Anna 1588d68983e3SPavel Labath #endif 1589