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" 25190fadcdSZachary Turner #include "llvm/Support/ConvertUTF.h" 262819136fSMichal Gorny #include "llvm/Support/Errno.h" 27190fadcdSZachary Turner 282c1f46dcSZachary Turner #include <stdio.h> 292c1f46dcSZachary Turner 302c1f46dcSZachary Turner using namespace lldb_private; 312c1f46dcSZachary Turner using namespace lldb; 32085328eeSLawrence D'Anna using namespace lldb_private::python; 33085328eeSLawrence D'Anna using llvm::Error; 34085328eeSLawrence D'Anna using llvm::Expected; 35085328eeSLawrence D'Anna 36085328eeSLawrence D'Anna template <> Expected<bool> python::As<bool>(Expected<PythonObject> &&obj) { 37085328eeSLawrence D'Anna if (!obj) 38085328eeSLawrence D'Anna return obj.takeError(); 39085328eeSLawrence D'Anna return obj.get().IsTrue(); 40085328eeSLawrence D'Anna } 41085328eeSLawrence D'Anna 42085328eeSLawrence D'Anna template <> 43085328eeSLawrence D'Anna Expected<long long> python::As<long long>(Expected<PythonObject> &&obj) { 44085328eeSLawrence D'Anna if (!obj) 45085328eeSLawrence D'Anna return obj.takeError(); 46085328eeSLawrence D'Anna return obj.get().AsLongLong(); 47085328eeSLawrence D'Anna } 482c1f46dcSZachary Turner 492783d817SJonas Devlieghere void StructuredPythonObject::Serialize(llvm::json::OStream &s) const { 502783d817SJonas Devlieghere s.value(llvm::formatv("Python Obj: {0:X}", GetValue()).str()); 512c1f46dcSZachary Turner } 522c1f46dcSZachary Turner 532c1f46dcSZachary Turner // PythonObject 542c1f46dcSZachary Turner 55b9c1b51eSKate Stone void PythonObject::Dump(Stream &strm) const { 56b9c1b51eSKate Stone if (m_py_obj) { 572819136fSMichal Gorny FILE *file = llvm::sys::RetryAfterSignal(nullptr, ::tmpfile); 58b9c1b51eSKate Stone if (file) { 592c1f46dcSZachary Turner ::PyObject_Print(m_py_obj, file, 0); 602c1f46dcSZachary Turner const long length = ftell(file); 61b9c1b51eSKate Stone if (length) { 622c1f46dcSZachary Turner ::rewind(file); 632c1f46dcSZachary Turner std::vector<char> file_contents(length, '\0'); 64b9c1b51eSKate Stone const size_t length_read = 65b9c1b51eSKate Stone ::fread(file_contents.data(), 1, file_contents.size(), file); 662c1f46dcSZachary Turner if (length_read > 0) 672c1f46dcSZachary Turner strm.Write(file_contents.data(), length_read); 682c1f46dcSZachary Turner } 692c1f46dcSZachary Turner ::fclose(file); 702c1f46dcSZachary Turner } 71b9c1b51eSKate Stone } else 722c1f46dcSZachary Turner strm.PutCString("NULL"); 732c1f46dcSZachary Turner } 742c1f46dcSZachary Turner 75b9c1b51eSKate Stone PyObjectType PythonObject::GetObjectType() const { 76f8b22f8fSZachary Turner if (!IsAllocated()) 772c1f46dcSZachary Turner return PyObjectType::None; 782c1f46dcSZachary Turner 797841efbbSZachary Turner if (PythonModule::Check(m_py_obj)) 807841efbbSZachary Turner return PyObjectType::Module; 8118426935SZachary Turner if (PythonList::Check(m_py_obj)) 822c1f46dcSZachary Turner return PyObjectType::List; 83a1405147SZachary Turner if (PythonTuple::Check(m_py_obj)) 84a1405147SZachary Turner return PyObjectType::Tuple; 8518426935SZachary Turner if (PythonDictionary::Check(m_py_obj)) 862c1f46dcSZachary Turner return PyObjectType::Dictionary; 8718426935SZachary Turner if (PythonString::Check(m_py_obj)) 8822c8efcdSZachary Turner return PyObjectType::String; 895a72c02bSZachary Turner #if PY_MAJOR_VERSION >= 3 905a72c02bSZachary Turner if (PythonBytes::Check(m_py_obj)) 915a72c02bSZachary Turner return PyObjectType::Bytes; 925a72c02bSZachary Turner #endif 93f9d6d204SZachary Turner if (PythonByteArray::Check(m_py_obj)) 94f9d6d204SZachary Turner return PyObjectType::ByteArray; 95b81d715cSTatyana Krasnukha if (PythonBoolean::Check(m_py_obj)) 96b81d715cSTatyana Krasnukha return PyObjectType::Boolean; 9718426935SZachary Turner if (PythonInteger::Check(m_py_obj)) 9822c8efcdSZachary Turner return PyObjectType::Integer; 999c40264fSZachary Turner if (PythonFile::Check(m_py_obj)) 1009c40264fSZachary Turner return PyObjectType::File; 101a1405147SZachary Turner if (PythonCallable::Check(m_py_obj)) 102a1405147SZachary Turner return PyObjectType::Callable; 1032c1f46dcSZachary Turner return PyObjectType::Unknown; 1042c1f46dcSZachary Turner } 1052c1f46dcSZachary Turner 106b9c1b51eSKate Stone PythonString PythonObject::Repr() const { 1072c1f46dcSZachary Turner if (!m_py_obj) 1082c1f46dcSZachary Turner return PythonString(); 1092c1f46dcSZachary Turner PyObject *repr = PyObject_Repr(m_py_obj); 1102c1f46dcSZachary Turner if (!repr) 1112c1f46dcSZachary Turner return PythonString(); 112f8b22f8fSZachary Turner return PythonString(PyRefType::Owned, repr); 1132c1f46dcSZachary Turner } 1142c1f46dcSZachary Turner 115b9c1b51eSKate Stone PythonString PythonObject::Str() const { 1162c1f46dcSZachary Turner if (!m_py_obj) 1172c1f46dcSZachary Turner return PythonString(); 1182c1f46dcSZachary Turner PyObject *str = PyObject_Str(m_py_obj); 1192c1f46dcSZachary Turner if (!str) 1202c1f46dcSZachary Turner return PythonString(); 121f8b22f8fSZachary Turner return PythonString(PyRefType::Owned, str); 1222c1f46dcSZachary Turner } 1232c1f46dcSZachary Turner 1247841efbbSZachary Turner PythonObject 125b9c1b51eSKate Stone PythonObject::ResolveNameWithDictionary(llvm::StringRef name, 126b9c1b51eSKate Stone const PythonDictionary &dict) { 127c712bac7SJonas Devlieghere size_t dot_pos = name.find('.'); 128a1405147SZachary Turner llvm::StringRef piece = name.substr(0, dot_pos); 129a1405147SZachary Turner PythonObject result = dict.GetItemForKey(PythonString(piece)); 130b9c1b51eSKate Stone if (dot_pos == llvm::StringRef::npos) { 131a1405147SZachary Turner // There was no dot, we're done. 132a1405147SZachary Turner return result; 133a1405147SZachary Turner } 134a1405147SZachary Turner 135a1405147SZachary Turner // There was a dot. The remaining portion of the name should be looked up in 136a1405147SZachary Turner // the context of the object that was found in the dictionary. 137a1405147SZachary Turner return result.ResolveName(name.substr(dot_pos + 1)); 1387841efbbSZachary Turner } 1397841efbbSZachary Turner 140b9c1b51eSKate Stone PythonObject PythonObject::ResolveName(llvm::StringRef name) const { 14105097246SAdrian Prantl // Resolve the name in the context of the specified object. If, for example, 14205097246SAdrian Prantl // `this` refers to a PyModule, then this will look for `name` in this 14305097246SAdrian Prantl // module. If `this` refers to a PyType, then it will resolve `name` as an 14405097246SAdrian Prantl // attribute of that type. If `this` refers to an instance of an object, 14505097246SAdrian Prantl // then it will resolve `name` as the value of the specified field. 1467841efbbSZachary Turner // 1477841efbbSZachary Turner // This function handles dotted names so that, for example, if `m_py_obj` 14805097246SAdrian Prantl // refers to the `sys` module, and `name` == "path.append", then it will find 14905097246SAdrian Prantl // the function `sys.path.append`. 1507841efbbSZachary Turner 151c712bac7SJonas Devlieghere size_t dot_pos = name.find('.'); 152b9c1b51eSKate Stone if (dot_pos == llvm::StringRef::npos) { 15305097246SAdrian Prantl // No dots in the name, we should be able to find the value immediately as 15405097246SAdrian Prantl // an attribute of `m_py_obj`. 1557841efbbSZachary Turner return GetAttributeValue(name); 1567841efbbSZachary Turner } 1577841efbbSZachary Turner 158b9c1b51eSKate Stone // Look up the first piece of the name, and resolve the rest as a child of 159b9c1b51eSKate Stone // that. 1607841efbbSZachary Turner PythonObject parent = ResolveName(name.substr(0, dot_pos)); 1617841efbbSZachary Turner if (!parent.IsAllocated()) 1627841efbbSZachary Turner return PythonObject(); 1637841efbbSZachary Turner 1647841efbbSZachary Turner // Tail recursion.. should be optimized by the compiler 1657841efbbSZachary Turner return parent.ResolveName(name.substr(dot_pos + 1)); 1667841efbbSZachary Turner } 1677841efbbSZachary Turner 168b9c1b51eSKate Stone bool PythonObject::HasAttribute(llvm::StringRef attr) const { 1699c40264fSZachary Turner if (!IsValid()) 1709c40264fSZachary Turner return false; 1719c40264fSZachary Turner PythonString py_attr(attr); 1729c40264fSZachary Turner return !!PyObject_HasAttr(m_py_obj, py_attr.get()); 1739c40264fSZachary Turner } 1749c40264fSZachary Turner 175b9c1b51eSKate Stone PythonObject PythonObject::GetAttributeValue(llvm::StringRef attr) const { 1767d6d218eSZachary Turner if (!IsValid()) 1777d6d218eSZachary Turner return PythonObject(); 1787d6d218eSZachary Turner 1797d6d218eSZachary Turner PythonString py_attr(attr); 1807d6d218eSZachary Turner if (!PyObject_HasAttr(m_py_obj, py_attr.get())) 1817d6d218eSZachary Turner return PythonObject(); 1827d6d218eSZachary Turner 1837d6d218eSZachary Turner return PythonObject(PyRefType::Owned, 1847d6d218eSZachary Turner PyObject_GetAttr(m_py_obj, py_attr.get())); 1857d6d218eSZachary Turner } 1867d6d218eSZachary Turner 187b9c1b51eSKate Stone StructuredData::ObjectSP PythonObject::CreateStructuredObject() const { 188b9c1b51eSKate Stone switch (GetObjectType()) { 1892c1f46dcSZachary Turner case PyObjectType::Dictionary: 190b9c1b51eSKate Stone return PythonDictionary(PyRefType::Borrowed, m_py_obj) 191b9c1b51eSKate Stone .CreateStructuredDictionary(); 192b81d715cSTatyana Krasnukha case PyObjectType::Boolean: 193b81d715cSTatyana Krasnukha return PythonBoolean(PyRefType::Borrowed, m_py_obj) 194b81d715cSTatyana Krasnukha .CreateStructuredBoolean(); 1952c1f46dcSZachary Turner case PyObjectType::Integer: 196b9c1b51eSKate Stone return PythonInteger(PyRefType::Borrowed, m_py_obj) 197b9c1b51eSKate Stone .CreateStructuredInteger(); 1982c1f46dcSZachary Turner case PyObjectType::List: 199f8b22f8fSZachary Turner return PythonList(PyRefType::Borrowed, m_py_obj).CreateStructuredArray(); 2002c1f46dcSZachary Turner case PyObjectType::String: 201f8b22f8fSZachary Turner return PythonString(PyRefType::Borrowed, m_py_obj).CreateStructuredString(); 2025a72c02bSZachary Turner case PyObjectType::Bytes: 2035a72c02bSZachary Turner return PythonBytes(PyRefType::Borrowed, m_py_obj).CreateStructuredString(); 204f9d6d204SZachary Turner case PyObjectType::ByteArray: 205b9c1b51eSKate Stone return PythonByteArray(PyRefType::Borrowed, m_py_obj) 206b9c1b51eSKate Stone .CreateStructuredString(); 2072c1f46dcSZachary Turner case PyObjectType::None: 2082c1f46dcSZachary Turner return StructuredData::ObjectSP(); 2092c1f46dcSZachary Turner default: 2102c1f46dcSZachary Turner return StructuredData::ObjectSP(new StructuredPythonObject(m_py_obj)); 2112c1f46dcSZachary Turner } 2122c1f46dcSZachary Turner } 2132c1f46dcSZachary Turner 2142c1f46dcSZachary Turner // PythonString 215b9c1b51eSKate Stone PythonBytes::PythonBytes() : PythonObject() {} 2165a72c02bSZachary Turner 217b9c1b51eSKate Stone PythonBytes::PythonBytes(llvm::ArrayRef<uint8_t> bytes) : PythonObject() { 2185a72c02bSZachary Turner SetBytes(bytes); 2195a72c02bSZachary Turner } 2205a72c02bSZachary Turner 221b9c1b51eSKate Stone PythonBytes::PythonBytes(const uint8_t *bytes, size_t length) : PythonObject() { 2225a72c02bSZachary Turner SetBytes(llvm::ArrayRef<uint8_t>(bytes, length)); 2235a72c02bSZachary Turner } 2245a72c02bSZachary Turner 225b9c1b51eSKate Stone PythonBytes::PythonBytes(PyRefType type, PyObject *py_obj) : PythonObject() { 2265a72c02bSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string 2275a72c02bSZachary Turner } 2285a72c02bSZachary Turner 229b9c1b51eSKate Stone PythonBytes::~PythonBytes() {} 2305a72c02bSZachary Turner 231b9c1b51eSKate Stone bool PythonBytes::Check(PyObject *py_obj) { 2325a72c02bSZachary Turner if (!py_obj) 2335a72c02bSZachary Turner return false; 234a6682a41SJonas Devlieghere return PyBytes_Check(py_obj); 2355a72c02bSZachary Turner } 2365a72c02bSZachary Turner 237b9c1b51eSKate Stone void PythonBytes::Reset(PyRefType type, PyObject *py_obj) { 23805097246SAdrian Prantl // Grab the desired reference type so that if we end up rejecting `py_obj` it 23905097246SAdrian Prantl // still gets decremented if necessary. 2405a72c02bSZachary Turner PythonObject result(type, py_obj); 2415a72c02bSZachary Turner 242b9c1b51eSKate Stone if (!PythonBytes::Check(py_obj)) { 2435a72c02bSZachary Turner PythonObject::Reset(); 2445a72c02bSZachary Turner return; 2455a72c02bSZachary Turner } 2465a72c02bSZachary Turner 247b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 24805097246SAdrian Prantl // overflow since it calls back into the virtual implementation. 2495a72c02bSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 2505a72c02bSZachary Turner } 2515a72c02bSZachary Turner 252b9c1b51eSKate Stone llvm::ArrayRef<uint8_t> PythonBytes::GetBytes() const { 2535a72c02bSZachary Turner if (!IsValid()) 2545a72c02bSZachary Turner return llvm::ArrayRef<uint8_t>(); 2555a72c02bSZachary Turner 2565a72c02bSZachary Turner Py_ssize_t size; 2575a72c02bSZachary Turner char *c; 2585a72c02bSZachary Turner 2595a72c02bSZachary Turner PyBytes_AsStringAndSize(m_py_obj, &c, &size); 2605a72c02bSZachary Turner return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size); 2615a72c02bSZachary Turner } 2625a72c02bSZachary Turner 263b9c1b51eSKate Stone size_t PythonBytes::GetSize() const { 2645a72c02bSZachary Turner if (!IsValid()) 2655a72c02bSZachary Turner return 0; 2665a72c02bSZachary Turner return PyBytes_Size(m_py_obj); 2675a72c02bSZachary Turner } 2685a72c02bSZachary Turner 269b9c1b51eSKate Stone void PythonBytes::SetBytes(llvm::ArrayRef<uint8_t> bytes) { 2705a72c02bSZachary Turner const char *data = reinterpret_cast<const char *>(bytes.data()); 2715a72c02bSZachary Turner PyObject *py_bytes = PyBytes_FromStringAndSize(data, bytes.size()); 2725a72c02bSZachary Turner PythonObject::Reset(PyRefType::Owned, py_bytes); 2735a72c02bSZachary Turner } 2745a72c02bSZachary Turner 275b9c1b51eSKate Stone StructuredData::StringSP PythonBytes::CreateStructuredString() const { 2765a72c02bSZachary Turner StructuredData::StringSP result(new StructuredData::String); 2775a72c02bSZachary Turner Py_ssize_t size; 2785a72c02bSZachary Turner char *c; 2795a72c02bSZachary Turner PyBytes_AsStringAndSize(m_py_obj, &c, &size); 2805a72c02bSZachary Turner result->SetValue(std::string(c, size)); 2815a72c02bSZachary Turner return result; 2825a72c02bSZachary Turner } 2835a72c02bSZachary Turner 284b9c1b51eSKate Stone PythonByteArray::PythonByteArray(llvm::ArrayRef<uint8_t> bytes) 285b9c1b51eSKate Stone : PythonByteArray(bytes.data(), bytes.size()) {} 286f9d6d204SZachary Turner 287b9c1b51eSKate Stone PythonByteArray::PythonByteArray(const uint8_t *bytes, size_t length) { 288f9d6d204SZachary Turner const char *str = reinterpret_cast<const char *>(bytes); 289f9d6d204SZachary Turner Reset(PyRefType::Owned, PyByteArray_FromStringAndSize(str, length)); 290f9d6d204SZachary Turner } 291f9d6d204SZachary Turner 292b9c1b51eSKate Stone PythonByteArray::PythonByteArray(PyRefType type, PyObject *o) { 293f9d6d204SZachary Turner Reset(type, o); 294f9d6d204SZachary Turner } 295f9d6d204SZachary Turner 296b9c1b51eSKate Stone PythonByteArray::PythonByteArray(const PythonBytes &object) 297b9c1b51eSKate Stone : PythonObject(object) {} 298f9d6d204SZachary Turner 299b9c1b51eSKate Stone PythonByteArray::~PythonByteArray() {} 300f9d6d204SZachary Turner 301b9c1b51eSKate Stone bool PythonByteArray::Check(PyObject *py_obj) { 302f9d6d204SZachary Turner if (!py_obj) 303f9d6d204SZachary Turner return false; 304a6682a41SJonas Devlieghere return PyByteArray_Check(py_obj); 305f9d6d204SZachary Turner } 306f9d6d204SZachary Turner 307b9c1b51eSKate Stone void PythonByteArray::Reset(PyRefType type, PyObject *py_obj) { 30805097246SAdrian Prantl // Grab the desired reference type so that if we end up rejecting `py_obj` it 30905097246SAdrian Prantl // still gets decremented if necessary. 310f9d6d204SZachary Turner PythonObject result(type, py_obj); 311f9d6d204SZachary Turner 312b9c1b51eSKate Stone if (!PythonByteArray::Check(py_obj)) { 313f9d6d204SZachary Turner PythonObject::Reset(); 314f9d6d204SZachary Turner return; 315f9d6d204SZachary Turner } 316f9d6d204SZachary Turner 317b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 31805097246SAdrian Prantl // overflow since it calls back into the virtual implementation. 319f9d6d204SZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 320f9d6d204SZachary Turner } 321f9d6d204SZachary Turner 322b9c1b51eSKate Stone llvm::ArrayRef<uint8_t> PythonByteArray::GetBytes() const { 323f9d6d204SZachary Turner if (!IsValid()) 324f9d6d204SZachary Turner return llvm::ArrayRef<uint8_t>(); 325f9d6d204SZachary Turner 326f9d6d204SZachary Turner char *c = PyByteArray_AsString(m_py_obj); 327f9d6d204SZachary Turner size_t size = GetSize(); 328f9d6d204SZachary Turner return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size); 329f9d6d204SZachary Turner } 330f9d6d204SZachary Turner 331b9c1b51eSKate Stone size_t PythonByteArray::GetSize() const { 332f9d6d204SZachary Turner if (!IsValid()) 333f9d6d204SZachary Turner return 0; 334f9d6d204SZachary Turner 335f9d6d204SZachary Turner return PyByteArray_Size(m_py_obj); 336f9d6d204SZachary Turner } 337f9d6d204SZachary Turner 338b9c1b51eSKate Stone StructuredData::StringSP PythonByteArray::CreateStructuredString() const { 339f9d6d204SZachary Turner StructuredData::StringSP result(new StructuredData::String); 340f9d6d204SZachary Turner llvm::ArrayRef<uint8_t> bytes = GetBytes(); 341f9d6d204SZachary Turner const char *str = reinterpret_cast<const char *>(bytes.data()); 342f9d6d204SZachary Turner result->SetValue(std::string(str, bytes.size())); 343f9d6d204SZachary Turner return result; 344f9d6d204SZachary Turner } 345f9d6d204SZachary Turner 3465a72c02bSZachary Turner // PythonString 3472c1f46dcSZachary Turner 348085328eeSLawrence D'Anna Expected<PythonString> PythonString::FromUTF8(llvm::StringRef string) { 349085328eeSLawrence D'Anna #if PY_MAJOR_VERSION >= 3 350085328eeSLawrence D'Anna PyObject *str = PyUnicode_FromStringAndSize(string.data(), string.size()); 351085328eeSLawrence D'Anna #else 352085328eeSLawrence D'Anna PyObject *str = PyString_FromStringAndSize(string.data(), string.size()); 353085328eeSLawrence D'Anna #endif 354085328eeSLawrence D'Anna if (!str) 355085328eeSLawrence D'Anna return llvm::make_error<PythonException>(); 356085328eeSLawrence D'Anna return Take<PythonString>(str); 357085328eeSLawrence D'Anna } 358085328eeSLawrence D'Anna 359b9c1b51eSKate Stone PythonString::PythonString(PyRefType type, PyObject *py_obj) : PythonObject() { 360f8b22f8fSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string 3612c1f46dcSZachary Turner } 3622c1f46dcSZachary Turner 363b9c1b51eSKate Stone PythonString::PythonString(llvm::StringRef string) : PythonObject() { 36422c8efcdSZachary Turner SetString(string); 3652c1f46dcSZachary Turner } 3662c1f46dcSZachary Turner 367b9c1b51eSKate Stone PythonString::PythonString() : PythonObject() {} 3682c1f46dcSZachary Turner 369b9c1b51eSKate Stone PythonString::~PythonString() {} 3702c1f46dcSZachary Turner 371b9c1b51eSKate Stone bool PythonString::Check(PyObject *py_obj) { 37222c8efcdSZachary Turner if (!py_obj) 37322c8efcdSZachary Turner return false; 37418426935SZachary Turner 3757d6d218eSZachary Turner if (PyUnicode_Check(py_obj)) 3767d6d218eSZachary Turner return true; 3777d6d218eSZachary Turner #if PY_MAJOR_VERSION < 3 3787d6d218eSZachary Turner if (PyString_Check(py_obj)) 3797d6d218eSZachary Turner return true; 38022c8efcdSZachary Turner #endif 3817d6d218eSZachary Turner return false; 38222c8efcdSZachary Turner } 38322c8efcdSZachary Turner 384b9c1b51eSKate Stone void PythonString::Reset(PyRefType type, PyObject *py_obj) { 38505097246SAdrian Prantl // Grab the desired reference type so that if we end up rejecting `py_obj` it 38605097246SAdrian Prantl // still gets decremented if necessary. 387f8b22f8fSZachary Turner PythonObject result(type, py_obj); 388f8b22f8fSZachary Turner 389b9c1b51eSKate Stone if (!PythonString::Check(py_obj)) { 390f8b22f8fSZachary Turner PythonObject::Reset(); 391f8b22f8fSZachary Turner return; 39222c8efcdSZachary Turner } 3937d6d218eSZachary Turner #if PY_MAJOR_VERSION < 3 3947d6d218eSZachary Turner // In Python 2, Don't store PyUnicode objects directly, because we need 3957d6d218eSZachary Turner // access to their underlying character buffers which Python 2 doesn't 3967d6d218eSZachary Turner // provide. 397085328eeSLawrence D'Anna if (PyUnicode_Check(py_obj)) { 398085328eeSLawrence D'Anna PyObject *s = PyUnicode_AsUTF8String(result.get()); 399085328eeSLawrence D'Anna if (s == NULL) 400085328eeSLawrence D'Anna PyErr_Clear(); 401085328eeSLawrence D'Anna result.Reset(PyRefType::Owned, s); 402085328eeSLawrence D'Anna } 4037d6d218eSZachary Turner #endif 404b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 40505097246SAdrian Prantl // overflow since it calls back into the virtual implementation. 406f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 4072c1f46dcSZachary Turner } 4082c1f46dcSZachary Turner 409b9c1b51eSKate Stone llvm::StringRef PythonString::GetString() const { 410085328eeSLawrence D'Anna auto s = AsUTF8(); 411085328eeSLawrence D'Anna if (!s) { 412085328eeSLawrence D'Anna llvm::consumeError(s.takeError()); 413085328eeSLawrence D'Anna return llvm::StringRef(""); 414085328eeSLawrence D'Anna } 415085328eeSLawrence D'Anna return s.get(); 416085328eeSLawrence D'Anna } 417085328eeSLawrence D'Anna 418085328eeSLawrence D'Anna Expected<llvm::StringRef> PythonString::AsUTF8() const { 41918426935SZachary Turner if (!IsValid()) 420085328eeSLawrence D'Anna return nullDeref(); 42118426935SZachary Turner 42222c8efcdSZachary Turner Py_ssize_t size; 4235457b426SPavel Labath const char *data; 42418426935SZachary Turner 42518426935SZachary Turner #if PY_MAJOR_VERSION >= 3 4265457b426SPavel Labath data = PyUnicode_AsUTF8AndSize(m_py_obj, &size); 42718426935SZachary Turner #else 428085328eeSLawrence D'Anna char *c = NULL; 429085328eeSLawrence D'Anna int r = PyString_AsStringAndSize(m_py_obj, &c, &size); 430085328eeSLawrence D'Anna if (r < 0) 431085328eeSLawrence D'Anna c = NULL; 4325457b426SPavel Labath data = c; 43318426935SZachary Turner #endif 434085328eeSLawrence D'Anna 435085328eeSLawrence D'Anna if (!data) 436085328eeSLawrence D'Anna return exception(); 437085328eeSLawrence D'Anna 4385457b426SPavel Labath return llvm::StringRef(data, size); 43922c8efcdSZachary Turner } 4402c1f46dcSZachary Turner 441b9c1b51eSKate Stone size_t PythonString::GetSize() const { 442b9c1b51eSKate Stone if (IsValid()) { 44318426935SZachary Turner #if PY_MAJOR_VERSION >= 3 44418426935SZachary Turner return PyUnicode_GetSize(m_py_obj); 44518426935SZachary Turner #else 44618426935SZachary Turner return PyString_Size(m_py_obj); 44718426935SZachary Turner #endif 44818426935SZachary Turner } 4492c1f46dcSZachary Turner return 0; 4502c1f46dcSZachary Turner } 4512c1f46dcSZachary Turner 452b9c1b51eSKate Stone void PythonString::SetString(llvm::StringRef string) { 453085328eeSLawrence D'Anna auto s = FromUTF8(string); 454085328eeSLawrence D'Anna if (!s) { 455085328eeSLawrence D'Anna llvm::consumeError(s.takeError()); 456085328eeSLawrence D'Anna Reset(); 457085328eeSLawrence D'Anna } else { 458085328eeSLawrence D'Anna PythonObject::Reset(std::move(s.get())); 459085328eeSLawrence D'Anna } 4602c1f46dcSZachary Turner } 4612c1f46dcSZachary Turner 462b9c1b51eSKate Stone StructuredData::StringSP PythonString::CreateStructuredString() const { 4632c1f46dcSZachary Turner StructuredData::StringSP result(new StructuredData::String); 4642c1f46dcSZachary Turner result->SetValue(GetString()); 4652c1f46dcSZachary Turner return result; 4662c1f46dcSZachary Turner } 4672c1f46dcSZachary Turner 4682c1f46dcSZachary Turner // PythonInteger 4692c1f46dcSZachary Turner 470b9c1b51eSKate Stone PythonInteger::PythonInteger() : PythonObject() {} 4717d6d218eSZachary Turner 472f8b22f8fSZachary Turner PythonInteger::PythonInteger(PyRefType type, PyObject *py_obj) 473b9c1b51eSKate Stone : PythonObject() { 474f8b22f8fSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a integer type 4752c1f46dcSZachary Turner } 4762c1f46dcSZachary Turner 477b9c1b51eSKate Stone PythonInteger::PythonInteger(int64_t value) : PythonObject() { 4782c1f46dcSZachary Turner SetInteger(value); 4792c1f46dcSZachary Turner } 4802c1f46dcSZachary Turner 481b9c1b51eSKate Stone PythonInteger::~PythonInteger() {} 4822c1f46dcSZachary Turner 483b9c1b51eSKate Stone bool PythonInteger::Check(PyObject *py_obj) { 48422c8efcdSZachary Turner if (!py_obj) 48522c8efcdSZachary Turner return false; 48622c8efcdSZachary Turner 48722c8efcdSZachary Turner #if PY_MAJOR_VERSION >= 3 48805097246SAdrian Prantl // Python 3 does not have PyInt_Check. There is only one type of integral 48905097246SAdrian Prantl // value, long. 49022c8efcdSZachary Turner return PyLong_Check(py_obj); 49122c8efcdSZachary Turner #else 49222c8efcdSZachary Turner return PyLong_Check(py_obj) || PyInt_Check(py_obj); 49322c8efcdSZachary Turner #endif 4942c1f46dcSZachary Turner } 4952c1f46dcSZachary Turner 496b9c1b51eSKate Stone void PythonInteger::Reset(PyRefType type, PyObject *py_obj) { 49705097246SAdrian Prantl // Grab the desired reference type so that if we end up rejecting `py_obj` it 49805097246SAdrian Prantl // still gets decremented if necessary. 499f8b22f8fSZachary Turner PythonObject result(type, py_obj); 500f8b22f8fSZachary Turner 501b9c1b51eSKate Stone if (!PythonInteger::Check(py_obj)) { 502f8b22f8fSZachary Turner PythonObject::Reset(); 503f8b22f8fSZachary Turner return; 50422c8efcdSZachary Turner } 50522c8efcdSZachary Turner 50622c8efcdSZachary Turner #if PY_MAJOR_VERSION < 3 50705097246SAdrian Prantl // Always store this as a PyLong, which makes interoperability between Python 50805097246SAdrian Prantl // 2.x and Python 3.x easier. This is only necessary in 2.x, since 3.x 50905097246SAdrian Prantl // doesn't even have a PyInt. 510b9c1b51eSKate Stone if (PyInt_Check(py_obj)) { 511f8b22f8fSZachary Turner // Since we converted the original object to a different type, the new 51205097246SAdrian Prantl // object is an owned object regardless of the ownership semantics 51305097246SAdrian Prantl // requested by the user. 514f8b22f8fSZachary Turner result.Reset(PyRefType::Owned, PyLong_FromLongLong(PyInt_AsLong(py_obj))); 51522c8efcdSZachary Turner } 51622c8efcdSZachary Turner #endif 51722c8efcdSZachary Turner 518b9c1b51eSKate Stone assert(PyLong_Check(result.get()) && 519b9c1b51eSKate Stone "Couldn't get a PyLong from this PyObject"); 52022c8efcdSZachary Turner 521b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 52205097246SAdrian Prantl // overflow since it calls back into the virtual implementation. 523f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 5242c1f46dcSZachary Turner } 5252c1f46dcSZachary Turner 526b9c1b51eSKate Stone int64_t PythonInteger::GetInteger() const { 527b9c1b51eSKate Stone if (m_py_obj) { 528b9c1b51eSKate Stone assert(PyLong_Check(m_py_obj) && 529b9c1b51eSKate Stone "PythonInteger::GetInteger has a PyObject that isn't a PyLong"); 53022c8efcdSZachary Turner 531008ec446SGreg Clayton int overflow = 0; 532008ec446SGreg Clayton int64_t result = PyLong_AsLongLongAndOverflow(m_py_obj, &overflow); 533b9c1b51eSKate Stone if (overflow != 0) { 53405097246SAdrian Prantl // We got an integer that overflows, like 18446744072853913392L we can't 53505097246SAdrian Prantl // use PyLong_AsLongLong() as it will return 0xffffffffffffffff. If we 53605097246SAdrian Prantl // use the unsigned long long it will work as expected. 537008ec446SGreg Clayton const uint64_t uval = PyLong_AsUnsignedLongLong(m_py_obj); 5384f730dc7SIlia K result = static_cast<int64_t>(uval); 539008ec446SGreg Clayton } 540008ec446SGreg Clayton return result; 5412c1f46dcSZachary Turner } 5422c1f46dcSZachary Turner return UINT64_MAX; 5432c1f46dcSZachary Turner } 5442c1f46dcSZachary Turner 545b9c1b51eSKate Stone void PythonInteger::SetInteger(int64_t value) { 546f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Owned, PyLong_FromLongLong(value)); 5472c1f46dcSZachary Turner } 5482c1f46dcSZachary Turner 549b9c1b51eSKate Stone StructuredData::IntegerSP PythonInteger::CreateStructuredInteger() const { 5502c1f46dcSZachary Turner StructuredData::IntegerSP result(new StructuredData::Integer); 5512c1f46dcSZachary Turner result->SetValue(GetInteger()); 5522c1f46dcSZachary Turner return result; 5532c1f46dcSZachary Turner } 5542c1f46dcSZachary Turner 555b81d715cSTatyana Krasnukha // PythonBoolean 556b81d715cSTatyana Krasnukha 557b81d715cSTatyana Krasnukha PythonBoolean::PythonBoolean(PyRefType type, PyObject *py_obj) 558b81d715cSTatyana Krasnukha : PythonObject() { 559b81d715cSTatyana Krasnukha Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a boolean type 560b81d715cSTatyana Krasnukha } 561b81d715cSTatyana Krasnukha 562b81d715cSTatyana Krasnukha PythonBoolean::PythonBoolean(bool value) { 563b81d715cSTatyana Krasnukha SetValue(value); 564b81d715cSTatyana Krasnukha } 565b81d715cSTatyana Krasnukha 566b81d715cSTatyana Krasnukha bool PythonBoolean::Check(PyObject *py_obj) { 567b81d715cSTatyana Krasnukha return py_obj ? PyBool_Check(py_obj) : false; 568b81d715cSTatyana Krasnukha } 569b81d715cSTatyana Krasnukha 570b81d715cSTatyana Krasnukha void PythonBoolean::Reset(PyRefType type, PyObject *py_obj) { 571b81d715cSTatyana Krasnukha // Grab the desired reference type so that if we end up rejecting `py_obj` it 572b81d715cSTatyana Krasnukha // still gets decremented if necessary. 573b81d715cSTatyana Krasnukha PythonObject result(type, py_obj); 574b81d715cSTatyana Krasnukha 575b81d715cSTatyana Krasnukha if (!PythonBoolean::Check(py_obj)) { 576b81d715cSTatyana Krasnukha PythonObject::Reset(); 577b81d715cSTatyana Krasnukha return; 578b81d715cSTatyana Krasnukha } 579b81d715cSTatyana Krasnukha 580b81d715cSTatyana Krasnukha // Calling PythonObject::Reset(const PythonObject&) will lead to stack 581b81d715cSTatyana Krasnukha // overflow since it calls back into the virtual implementation. 582b81d715cSTatyana Krasnukha PythonObject::Reset(PyRefType::Borrowed, result.get()); 583b81d715cSTatyana Krasnukha } 584b81d715cSTatyana Krasnukha 585b81d715cSTatyana Krasnukha bool PythonBoolean::GetValue() const { 586b81d715cSTatyana Krasnukha return m_py_obj ? PyObject_IsTrue(m_py_obj) : false; 587b81d715cSTatyana Krasnukha } 588b81d715cSTatyana Krasnukha 589b81d715cSTatyana Krasnukha void PythonBoolean::SetValue(bool value) { 590b81d715cSTatyana Krasnukha PythonObject::Reset(PyRefType::Owned, PyBool_FromLong(value)); 591b81d715cSTatyana Krasnukha } 592b81d715cSTatyana Krasnukha 593b81d715cSTatyana Krasnukha StructuredData::BooleanSP PythonBoolean::CreateStructuredBoolean() const { 594b81d715cSTatyana Krasnukha StructuredData::BooleanSP result(new StructuredData::Boolean); 595b81d715cSTatyana Krasnukha result->SetValue(GetValue()); 596b81d715cSTatyana Krasnukha return result; 597b81d715cSTatyana Krasnukha } 598b81d715cSTatyana Krasnukha 5992c1f46dcSZachary Turner // PythonList 6002c1f46dcSZachary Turner 601b9c1b51eSKate Stone PythonList::PythonList(PyInitialValue value) : PythonObject() { 602f8b22f8fSZachary Turner if (value == PyInitialValue::Empty) 603f8b22f8fSZachary Turner Reset(PyRefType::Owned, PyList_New(0)); 6042c1f46dcSZachary Turner } 6052c1f46dcSZachary Turner 606b9c1b51eSKate Stone PythonList::PythonList(int list_size) : PythonObject() { 60787f47729SZachary Turner Reset(PyRefType::Owned, PyList_New(list_size)); 60887f47729SZachary Turner } 60987f47729SZachary Turner 610b9c1b51eSKate Stone PythonList::PythonList(PyRefType type, PyObject *py_obj) : PythonObject() { 611f8b22f8fSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a list 6122c1f46dcSZachary Turner } 6132c1f46dcSZachary Turner 614b9c1b51eSKate Stone PythonList::~PythonList() {} 6152c1f46dcSZachary Turner 616b9c1b51eSKate Stone bool PythonList::Check(PyObject *py_obj) { 61722c8efcdSZachary Turner if (!py_obj) 61822c8efcdSZachary Turner return false; 61922c8efcdSZachary Turner return PyList_Check(py_obj); 62022c8efcdSZachary Turner } 62122c8efcdSZachary Turner 622b9c1b51eSKate Stone void PythonList::Reset(PyRefType type, PyObject *py_obj) { 62305097246SAdrian Prantl // Grab the desired reference type so that if we end up rejecting `py_obj` it 62405097246SAdrian Prantl // still gets decremented if necessary. 625f8b22f8fSZachary Turner PythonObject result(type, py_obj); 626f8b22f8fSZachary Turner 627b9c1b51eSKate Stone if (!PythonList::Check(py_obj)) { 628f8b22f8fSZachary Turner PythonObject::Reset(); 629f8b22f8fSZachary Turner return; 63022c8efcdSZachary Turner } 63122c8efcdSZachary Turner 632b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 63305097246SAdrian Prantl // overflow since it calls back into the virtual implementation. 634f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 6352c1f46dcSZachary Turner } 6362c1f46dcSZachary Turner 637b9c1b51eSKate Stone uint32_t PythonList::GetSize() const { 638f8b22f8fSZachary Turner if (IsValid()) 6392c1f46dcSZachary Turner return PyList_GET_SIZE(m_py_obj); 6402c1f46dcSZachary Turner return 0; 6412c1f46dcSZachary Turner } 6422c1f46dcSZachary Turner 643b9c1b51eSKate Stone PythonObject PythonList::GetItemAtIndex(uint32_t index) const { 644f8b22f8fSZachary Turner if (IsValid()) 645f8b22f8fSZachary Turner return PythonObject(PyRefType::Borrowed, PyList_GetItem(m_py_obj, index)); 6462c1f46dcSZachary Turner return PythonObject(); 6472c1f46dcSZachary Turner } 6482c1f46dcSZachary Turner 649b9c1b51eSKate Stone void PythonList::SetItemAtIndex(uint32_t index, const PythonObject &object) { 650b9c1b51eSKate Stone if (IsAllocated() && object.IsValid()) { 651f8b22f8fSZachary Turner // PyList_SetItem is documented to "steal" a reference, so we need to 652f8b22f8fSZachary Turner // convert it to an owned reference by incrementing it. 653f8b22f8fSZachary Turner Py_INCREF(object.get()); 6542c1f46dcSZachary Turner PyList_SetItem(m_py_obj, index, object.get()); 6552c1f46dcSZachary Turner } 656f8b22f8fSZachary Turner } 6572c1f46dcSZachary Turner 658b9c1b51eSKate Stone void PythonList::AppendItem(const PythonObject &object) { 659b9c1b51eSKate Stone if (IsAllocated() && object.IsValid()) { 660f8b22f8fSZachary Turner // `PyList_Append` does *not* steal a reference, so do not call `Py_INCREF` 661f8b22f8fSZachary Turner // here like we do with `PyList_SetItem`. 6622c1f46dcSZachary Turner PyList_Append(m_py_obj, object.get()); 6632c1f46dcSZachary Turner } 664f8b22f8fSZachary Turner } 6652c1f46dcSZachary Turner 666b9c1b51eSKate Stone StructuredData::ArraySP PythonList::CreateStructuredArray() const { 6672c1f46dcSZachary Turner StructuredData::ArraySP result(new StructuredData::Array); 6682c1f46dcSZachary Turner uint32_t count = GetSize(); 669b9c1b51eSKate Stone for (uint32_t i = 0; i < count; ++i) { 6702c1f46dcSZachary Turner PythonObject obj = GetItemAtIndex(i); 6712c1f46dcSZachary Turner result->AddItem(obj.CreateStructuredObject()); 6722c1f46dcSZachary Turner } 6732c1f46dcSZachary Turner return result; 6742c1f46dcSZachary Turner } 6752c1f46dcSZachary Turner 676a1405147SZachary Turner // PythonTuple 677a1405147SZachary Turner 678b9c1b51eSKate Stone PythonTuple::PythonTuple(PyInitialValue value) : PythonObject() { 679a1405147SZachary Turner if (value == PyInitialValue::Empty) 680a1405147SZachary Turner Reset(PyRefType::Owned, PyTuple_New(0)); 681a1405147SZachary Turner } 682a1405147SZachary Turner 683b9c1b51eSKate Stone PythonTuple::PythonTuple(int tuple_size) : PythonObject() { 684a1405147SZachary Turner Reset(PyRefType::Owned, PyTuple_New(tuple_size)); 685a1405147SZachary Turner } 686a1405147SZachary Turner 687b9c1b51eSKate Stone PythonTuple::PythonTuple(PyRefType type, PyObject *py_obj) : PythonObject() { 688a1405147SZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a tuple 689a1405147SZachary Turner } 690a1405147SZachary Turner 691b9c1b51eSKate Stone PythonTuple::PythonTuple(std::initializer_list<PythonObject> objects) { 692a1405147SZachary Turner m_py_obj = PyTuple_New(objects.size()); 693a1405147SZachary Turner 694a1405147SZachary Turner uint32_t idx = 0; 695b9c1b51eSKate Stone for (auto object : objects) { 696a1405147SZachary Turner if (object.IsValid()) 697a1405147SZachary Turner SetItemAtIndex(idx, object); 698a1405147SZachary Turner idx++; 699a1405147SZachary Turner } 700a1405147SZachary Turner } 701a1405147SZachary Turner 702b9c1b51eSKate Stone PythonTuple::PythonTuple(std::initializer_list<PyObject *> objects) { 703a1405147SZachary Turner m_py_obj = PyTuple_New(objects.size()); 704a1405147SZachary Turner 705a1405147SZachary Turner uint32_t idx = 0; 706b9c1b51eSKate Stone for (auto py_object : objects) { 707a1405147SZachary Turner PythonObject object(PyRefType::Borrowed, py_object); 708a1405147SZachary Turner if (object.IsValid()) 709a1405147SZachary Turner SetItemAtIndex(idx, object); 710a1405147SZachary Turner idx++; 711a1405147SZachary Turner } 712a1405147SZachary Turner } 713a1405147SZachary Turner 714b9c1b51eSKate Stone PythonTuple::~PythonTuple() {} 715a1405147SZachary Turner 716b9c1b51eSKate Stone bool PythonTuple::Check(PyObject *py_obj) { 717a1405147SZachary Turner if (!py_obj) 718a1405147SZachary Turner return false; 719a1405147SZachary Turner return PyTuple_Check(py_obj); 720a1405147SZachary Turner } 721a1405147SZachary Turner 722b9c1b51eSKate Stone void PythonTuple::Reset(PyRefType type, PyObject *py_obj) { 72305097246SAdrian Prantl // Grab the desired reference type so that if we end up rejecting `py_obj` it 72405097246SAdrian Prantl // still gets decremented if necessary. 725a1405147SZachary Turner PythonObject result(type, py_obj); 726a1405147SZachary Turner 727b9c1b51eSKate Stone if (!PythonTuple::Check(py_obj)) { 728a1405147SZachary Turner PythonObject::Reset(); 729a1405147SZachary Turner return; 730a1405147SZachary Turner } 731a1405147SZachary Turner 732b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 73305097246SAdrian Prantl // overflow since it calls back into the virtual implementation. 734a1405147SZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 735a1405147SZachary Turner } 736a1405147SZachary Turner 737b9c1b51eSKate Stone uint32_t PythonTuple::GetSize() const { 738a1405147SZachary Turner if (IsValid()) 739a1405147SZachary Turner return PyTuple_GET_SIZE(m_py_obj); 740a1405147SZachary Turner return 0; 741a1405147SZachary Turner } 742a1405147SZachary Turner 743b9c1b51eSKate Stone PythonObject PythonTuple::GetItemAtIndex(uint32_t index) const { 744a1405147SZachary Turner if (IsValid()) 745a1405147SZachary Turner return PythonObject(PyRefType::Borrowed, PyTuple_GetItem(m_py_obj, index)); 746a1405147SZachary Turner return PythonObject(); 747a1405147SZachary Turner } 748a1405147SZachary Turner 749b9c1b51eSKate Stone void PythonTuple::SetItemAtIndex(uint32_t index, const PythonObject &object) { 750b9c1b51eSKate Stone if (IsAllocated() && object.IsValid()) { 751a1405147SZachary Turner // PyTuple_SetItem is documented to "steal" a reference, so we need to 752a1405147SZachary Turner // convert it to an owned reference by incrementing it. 753a1405147SZachary Turner Py_INCREF(object.get()); 754a1405147SZachary Turner PyTuple_SetItem(m_py_obj, index, object.get()); 755a1405147SZachary Turner } 756a1405147SZachary Turner } 757a1405147SZachary Turner 758b9c1b51eSKate Stone StructuredData::ArraySP PythonTuple::CreateStructuredArray() const { 759a1405147SZachary Turner StructuredData::ArraySP result(new StructuredData::Array); 760a1405147SZachary Turner uint32_t count = GetSize(); 761b9c1b51eSKate Stone for (uint32_t i = 0; i < count; ++i) { 762a1405147SZachary Turner PythonObject obj = GetItemAtIndex(i); 763a1405147SZachary Turner result->AddItem(obj.CreateStructuredObject()); 764a1405147SZachary Turner } 765a1405147SZachary Turner return result; 766a1405147SZachary Turner } 767a1405147SZachary Turner 7682c1f46dcSZachary Turner // PythonDictionary 7692c1f46dcSZachary Turner 770b9c1b51eSKate Stone PythonDictionary::PythonDictionary(PyInitialValue value) : PythonObject() { 771f8b22f8fSZachary Turner if (value == PyInitialValue::Empty) 772f8b22f8fSZachary Turner Reset(PyRefType::Owned, PyDict_New()); 7732c1f46dcSZachary Turner } 7742c1f46dcSZachary Turner 775f8b22f8fSZachary Turner PythonDictionary::PythonDictionary(PyRefType type, PyObject *py_obj) 776b9c1b51eSKate Stone : PythonObject() { 777f8b22f8fSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a dictionary 7782c1f46dcSZachary Turner } 7792c1f46dcSZachary Turner 780b9c1b51eSKate Stone PythonDictionary::~PythonDictionary() {} 7812c1f46dcSZachary Turner 782b9c1b51eSKate Stone bool PythonDictionary::Check(PyObject *py_obj) { 78322c8efcdSZachary Turner if (!py_obj) 78422c8efcdSZachary Turner return false; 78522c8efcdSZachary Turner 78622c8efcdSZachary Turner return PyDict_Check(py_obj); 78722c8efcdSZachary Turner } 78822c8efcdSZachary Turner 789b9c1b51eSKate Stone void PythonDictionary::Reset(PyRefType type, PyObject *py_obj) { 79005097246SAdrian Prantl // Grab the desired reference type so that if we end up rejecting `py_obj` it 79105097246SAdrian Prantl // still gets decremented if necessary. 792f8b22f8fSZachary Turner PythonObject result(type, py_obj); 793f8b22f8fSZachary Turner 794b9c1b51eSKate Stone if (!PythonDictionary::Check(py_obj)) { 795f8b22f8fSZachary Turner PythonObject::Reset(); 796f8b22f8fSZachary Turner return; 79722c8efcdSZachary Turner } 79822c8efcdSZachary Turner 799b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 80005097246SAdrian Prantl // overflow since it calls back into the virtual implementation. 801f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 8022c1f46dcSZachary Turner } 8032c1f46dcSZachary Turner 804b9c1b51eSKate Stone uint32_t PythonDictionary::GetSize() const { 805f8b22f8fSZachary Turner if (IsValid()) 8062c1f46dcSZachary Turner return PyDict_Size(m_py_obj); 8072c1f46dcSZachary Turner return 0; 8082c1f46dcSZachary Turner } 8092c1f46dcSZachary Turner 810b9c1b51eSKate Stone PythonList PythonDictionary::GetKeys() const { 811f8b22f8fSZachary Turner if (IsValid()) 812f8b22f8fSZachary Turner return PythonList(PyRefType::Owned, PyDict_Keys(m_py_obj)); 813f8b22f8fSZachary Turner return PythonList(PyInitialValue::Invalid); 8142c1f46dcSZachary Turner } 8152c1f46dcSZachary Turner 816b9c1b51eSKate Stone PythonObject PythonDictionary::GetItemForKey(const PythonObject &key) const { 817f8b22f8fSZachary Turner if (IsAllocated() && key.IsValid()) 818b9c1b51eSKate Stone return PythonObject(PyRefType::Borrowed, 819b9c1b51eSKate Stone PyDict_GetItem(m_py_obj, key.get())); 8202c1f46dcSZachary Turner return PythonObject(); 8212c1f46dcSZachary Turner } 8222c1f46dcSZachary Turner 823b9c1b51eSKate Stone void PythonDictionary::SetItemForKey(const PythonObject &key, 824b9c1b51eSKate Stone const PythonObject &value) { 825f8b22f8fSZachary Turner if (IsAllocated() && key.IsValid() && value.IsValid()) 8262c1f46dcSZachary Turner PyDict_SetItem(m_py_obj, key.get(), value.get()); 8272c1f46dcSZachary Turner } 8282c1f46dcSZachary Turner 8292c1f46dcSZachary Turner StructuredData::DictionarySP 830b9c1b51eSKate Stone PythonDictionary::CreateStructuredDictionary() const { 8312c1f46dcSZachary Turner StructuredData::DictionarySP result(new StructuredData::Dictionary); 8322c1f46dcSZachary Turner PythonList keys(GetKeys()); 8332c1f46dcSZachary Turner uint32_t num_keys = keys.GetSize(); 834b9c1b51eSKate Stone for (uint32_t i = 0; i < num_keys; ++i) { 8352c1f46dcSZachary Turner PythonObject key = keys.GetItemAtIndex(i); 8362c1f46dcSZachary Turner PythonObject value = GetItemForKey(key); 8372c1f46dcSZachary Turner StructuredData::ObjectSP structured_value = value.CreateStructuredObject(); 838f8b22f8fSZachary Turner result->AddItem(key.Str().GetString(), structured_value); 8392c1f46dcSZachary Turner } 8402c1f46dcSZachary Turner return result; 8412c1f46dcSZachary Turner } 8422c1f46dcSZachary Turner 843b9c1b51eSKate Stone PythonModule::PythonModule() : PythonObject() {} 8447841efbbSZachary Turner 845b9c1b51eSKate Stone PythonModule::PythonModule(PyRefType type, PyObject *py_obj) { 8467841efbbSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a module 8477841efbbSZachary Turner } 8487841efbbSZachary Turner 849b9c1b51eSKate Stone PythonModule::~PythonModule() {} 8507841efbbSZachary Turner 851b9c1b51eSKate Stone PythonModule PythonModule::BuiltinsModule() { 852a1405147SZachary Turner #if PY_MAJOR_VERSION >= 3 853a1405147SZachary Turner return AddModule("builtins"); 854a1405147SZachary Turner #else 855a1405147SZachary Turner return AddModule("__builtin__"); 856a1405147SZachary Turner #endif 857a1405147SZachary Turner } 858a1405147SZachary Turner 859b9c1b51eSKate Stone PythonModule PythonModule::MainModule() { return AddModule("__main__"); } 860a1405147SZachary Turner 861b9c1b51eSKate Stone PythonModule PythonModule::AddModule(llvm::StringRef module) { 862a1405147SZachary Turner std::string str = module.str(); 863a1405147SZachary Turner return PythonModule(PyRefType::Borrowed, PyImport_AddModule(str.c_str())); 8647841efbbSZachary Turner } 8657841efbbSZachary Turner 866085328eeSLawrence D'Anna Expected<PythonModule> PythonModule::Import(const char *name) { 867085328eeSLawrence D'Anna PyObject *mod = PyImport_ImportModule(name); 868085328eeSLawrence D'Anna if (!mod) 869085328eeSLawrence D'Anna return exception(); 870085328eeSLawrence D'Anna return Take<PythonModule>(mod); 871085328eeSLawrence D'Anna } 872085328eeSLawrence D'Anna 873085328eeSLawrence D'Anna Expected<PythonObject> PythonModule::Get(const char *name) { 874085328eeSLawrence D'Anna if (!IsValid()) 875085328eeSLawrence D'Anna return nullDeref(); 876085328eeSLawrence D'Anna PyObject *dict = PyModule_GetDict(m_py_obj); 877085328eeSLawrence D'Anna if (!dict) 878085328eeSLawrence D'Anna return exception(); 879085328eeSLawrence D'Anna PyObject *item = PyDict_GetItemString(dict, name); 880085328eeSLawrence D'Anna if (!item) 881085328eeSLawrence D'Anna return exception(); 882085328eeSLawrence D'Anna return Retain<PythonObject>(item); 8832419f1d5SZachary Turner } 8842419f1d5SZachary Turner 885b9c1b51eSKate Stone bool PythonModule::Check(PyObject *py_obj) { 8867841efbbSZachary Turner if (!py_obj) 8877841efbbSZachary Turner return false; 8887841efbbSZachary Turner 8897841efbbSZachary Turner return PyModule_Check(py_obj); 8907841efbbSZachary Turner } 8917841efbbSZachary Turner 892b9c1b51eSKate Stone void PythonModule::Reset(PyRefType type, PyObject *py_obj) { 89305097246SAdrian Prantl // Grab the desired reference type so that if we end up rejecting `py_obj` it 89405097246SAdrian Prantl // still gets decremented if necessary. 8957841efbbSZachary Turner PythonObject result(type, py_obj); 8967841efbbSZachary Turner 897b9c1b51eSKate Stone if (!PythonModule::Check(py_obj)) { 8987841efbbSZachary Turner PythonObject::Reset(); 8997841efbbSZachary Turner return; 9007841efbbSZachary Turner } 9017841efbbSZachary Turner 902b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 90305097246SAdrian Prantl // overflow since it calls back into the virtual implementation. 9047841efbbSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 9057841efbbSZachary Turner } 9067841efbbSZachary Turner 907b9c1b51eSKate Stone PythonDictionary PythonModule::GetDictionary() const { 9087841efbbSZachary Turner return PythonDictionary(PyRefType::Borrowed, PyModule_GetDict(m_py_obj)); 9097841efbbSZachary Turner } 9107841efbbSZachary Turner 911b9c1b51eSKate Stone PythonCallable::PythonCallable() : PythonObject() {} 912a1405147SZachary Turner 913b9c1b51eSKate Stone PythonCallable::PythonCallable(PyRefType type, PyObject *py_obj) { 914a1405147SZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a callable 915a1405147SZachary Turner } 916a1405147SZachary Turner 917b9c1b51eSKate Stone PythonCallable::~PythonCallable() {} 918a1405147SZachary Turner 919b9c1b51eSKate Stone bool PythonCallable::Check(PyObject *py_obj) { 920a1405147SZachary Turner if (!py_obj) 921a1405147SZachary Turner return false; 922a1405147SZachary Turner 923a1405147SZachary Turner return PyCallable_Check(py_obj); 924a1405147SZachary Turner } 925a1405147SZachary Turner 926b9c1b51eSKate Stone void PythonCallable::Reset(PyRefType type, PyObject *py_obj) { 92705097246SAdrian Prantl // Grab the desired reference type so that if we end up rejecting `py_obj` it 92805097246SAdrian Prantl // still gets decremented if necessary. 929a1405147SZachary Turner PythonObject result(type, py_obj); 930a1405147SZachary Turner 931b9c1b51eSKate Stone if (!PythonCallable::Check(py_obj)) { 932a1405147SZachary Turner PythonObject::Reset(); 933a1405147SZachary Turner return; 934a1405147SZachary Turner } 935a1405147SZachary Turner 936b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 93705097246SAdrian Prantl // overflow since it calls back into the virtual implementation. 938a1405147SZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 939a1405147SZachary Turner } 940a1405147SZachary Turner 94127a14f19SJim Ingham PythonCallable::ArgInfo PythonCallable::GetNumInitArguments() const { 94227a14f19SJim Ingham ArgInfo result = {0, false, false, false}; 94327a14f19SJim Ingham if (!IsValid()) 94427a14f19SJim Ingham return result; 94527a14f19SJim Ingham 94627a14f19SJim Ingham PythonObject __init__ = GetAttributeValue("__init__"); 94727a14f19SJim Ingham if (__init__.IsValid() ) { 94827a14f19SJim Ingham auto __init_callable__ = __init__.AsType<PythonCallable>(); 94927a14f19SJim Ingham if (__init_callable__.IsValid()) 95027a14f19SJim Ingham return __init_callable__.GetNumArguments(); 95127a14f19SJim Ingham } 95227a14f19SJim Ingham return result; 95327a14f19SJim Ingham } 95427a14f19SJim Ingham 955b9c1b51eSKate Stone PythonCallable::ArgInfo PythonCallable::GetNumArguments() const { 956a5d6765cSEnrico Granata ArgInfo result = {0, false, false, false}; 957a1405147SZachary Turner if (!IsValid()) 958b58fb2f4SZachary Turner return result; 959a1405147SZachary Turner 960a1405147SZachary Turner PyObject *py_func_obj = m_py_obj; 961b9c1b51eSKate Stone if (PyMethod_Check(py_func_obj)) { 962a1405147SZachary Turner py_func_obj = PyMethod_GET_FUNCTION(py_func_obj); 963a5d6765cSEnrico Granata PythonObject im_self = GetAttributeValue("im_self"); 964a5d6765cSEnrico Granata if (im_self.IsValid() && !im_self.IsNone()) 965a5d6765cSEnrico Granata result.is_bound_method = true; 966b9c1b51eSKate Stone } else { 967a5d6765cSEnrico Granata // see if this is a callable object with an __call__ method 968b9c1b51eSKate Stone if (!PyFunction_Check(py_func_obj)) { 969a5d6765cSEnrico Granata PythonObject __call__ = GetAttributeValue("__call__"); 970b9c1b51eSKate Stone if (__call__.IsValid()) { 971a5d6765cSEnrico Granata auto __callable__ = __call__.AsType<PythonCallable>(); 972b9c1b51eSKate Stone if (__callable__.IsValid()) { 973a5d6765cSEnrico Granata py_func_obj = PyMethod_GET_FUNCTION(__callable__.get()); 974a5d6765cSEnrico Granata PythonObject im_self = GetAttributeValue("im_self"); 975a5d6765cSEnrico Granata if (im_self.IsValid() && !im_self.IsNone()) 976a5d6765cSEnrico Granata result.is_bound_method = true; 977a5d6765cSEnrico Granata } 978a5d6765cSEnrico Granata } 979a5d6765cSEnrico Granata } 980a5d6765cSEnrico Granata } 981a1405147SZachary Turner 982a1405147SZachary Turner if (!py_func_obj) 983b58fb2f4SZachary Turner return result; 984a1405147SZachary Turner 985a1405147SZachary Turner PyCodeObject *code = (PyCodeObject *)PyFunction_GET_CODE(py_func_obj); 986a1405147SZachary Turner if (!code) 987b58fb2f4SZachary Turner return result; 988a1405147SZachary Turner 989b58fb2f4SZachary Turner result.count = code->co_argcount; 990b58fb2f4SZachary Turner result.has_varargs = !!(code->co_flags & CO_VARARGS); 991b58fb2f4SZachary Turner result.has_kwargs = !!(code->co_flags & CO_VARKEYWORDS); 992b58fb2f4SZachary Turner return result; 993b58fb2f4SZachary Turner } 994b58fb2f4SZachary Turner 995b9c1b51eSKate Stone PythonObject PythonCallable::operator()() { 996b9c1b51eSKate Stone return PythonObject(PyRefType::Owned, PyObject_CallObject(m_py_obj, nullptr)); 997a1405147SZachary Turner } 998a1405147SZachary Turner 999b9c1b51eSKate Stone PythonObject PythonCallable:: 1000b9c1b51eSKate Stone operator()(std::initializer_list<PyObject *> args) { 1001a1405147SZachary Turner PythonTuple arg_tuple(args); 1002a1405147SZachary Turner return PythonObject(PyRefType::Owned, 1003a1405147SZachary Turner PyObject_CallObject(m_py_obj, arg_tuple.get())); 1004a1405147SZachary Turner } 1005a1405147SZachary Turner 1006b9c1b51eSKate Stone PythonObject PythonCallable:: 1007b9c1b51eSKate Stone operator()(std::initializer_list<PythonObject> args) { 1008a1405147SZachary Turner PythonTuple arg_tuple(args); 1009a1405147SZachary Turner return PythonObject(PyRefType::Owned, 1010a1405147SZachary Turner PyObject_CallObject(m_py_obj, arg_tuple.get())); 1011a1405147SZachary Turner } 1012a1405147SZachary Turner 1013b9c1b51eSKate Stone PythonFile::PythonFile() : PythonObject() {} 101432064024SZachary Turner 1015b9c1b51eSKate Stone PythonFile::PythonFile(File &file, const char *mode) { Reset(file, mode); } 10169c40264fSZachary Turner 1017b9c1b51eSKate Stone PythonFile::PythonFile(PyRefType type, PyObject *o) { Reset(type, o); } 10189c40264fSZachary Turner 1019b9c1b51eSKate Stone PythonFile::~PythonFile() {} 10209c40264fSZachary Turner 1021b9c1b51eSKate Stone bool PythonFile::Check(PyObject *py_obj) { 102296898eb6SLawrence D'Anna if (!py_obj) 102396898eb6SLawrence D'Anna return false; 10249c40264fSZachary Turner #if PY_MAJOR_VERSION < 3 102523502721SJason Molenda return PyFile_Check(py_obj); 102623502721SJason Molenda #else 10279c40264fSZachary Turner // In Python 3, there is no `PyFile_Check`, and in fact PyFile is not even a 10289c40264fSZachary Turner // first-class object type anymore. `PyFile_FromFd` is just a thin wrapper 102905097246SAdrian Prantl // over `io.open()`, which returns some object derived from `io.IOBase`. As a 103005097246SAdrian Prantl // result, the only way to detect a file in Python 3 is to check whether it 1031*21b8a8aeSLawrence D'Anna // inherits from `io.IOBase`. 1032*21b8a8aeSLawrence D'Anna auto io_module = PythonModule::Import("io"); 1033*21b8a8aeSLawrence D'Anna if (!io_module) { 1034*21b8a8aeSLawrence D'Anna llvm::consumeError(io_module.takeError()); 10359c40264fSZachary Turner return false; 1036*21b8a8aeSLawrence D'Anna } 1037*21b8a8aeSLawrence D'Anna auto iobase = io_module.get().Get("IOBase"); 1038*21b8a8aeSLawrence D'Anna if (!iobase) { 1039*21b8a8aeSLawrence D'Anna llvm::consumeError(iobase.takeError()); 10409c40264fSZachary Turner return false; 1041*21b8a8aeSLawrence D'Anna } 1042*21b8a8aeSLawrence D'Anna int r = PyObject_IsInstance(py_obj, iobase.get().get()); 1043*21b8a8aeSLawrence D'Anna if (r < 0) { 1044*21b8a8aeSLawrence D'Anna llvm::consumeError(exception()); // clear the exception and log it. 1045*21b8a8aeSLawrence D'Anna return false; 1046*21b8a8aeSLawrence D'Anna } 1047*21b8a8aeSLawrence D'Anna return !!r; 104823502721SJason Molenda #endif 10499c40264fSZachary Turner } 10509c40264fSZachary Turner 1051b9c1b51eSKate Stone void PythonFile::Reset(PyRefType type, PyObject *py_obj) { 105205097246SAdrian Prantl // Grab the desired reference type so that if we end up rejecting `py_obj` it 105305097246SAdrian Prantl // still gets decremented if necessary. 10549c40264fSZachary Turner PythonObject result(type, py_obj); 10559c40264fSZachary Turner 105623502721SJason Molenda if (!PythonFile::Check(py_obj)) { 10579c40264fSZachary Turner PythonObject::Reset(); 10589c40264fSZachary Turner return; 10599c40264fSZachary Turner } 10609c40264fSZachary Turner 10619c40264fSZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack 10629c40264fSZachary Turner // overflow since it calls back into the virtual implementation. 10639c40264fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 10649c40264fSZachary Turner } 10659c40264fSZachary Turner 1066b9c1b51eSKate Stone void PythonFile::Reset(File &file, const char *mode) { 1067b9c1b51eSKate Stone if (!file.IsValid()) { 106832ac147bSZachary Turner Reset(); 106932ac147bSZachary Turner return; 107032ac147bSZachary Turner } 107132ac147bSZachary Turner 10729c40264fSZachary Turner char *cmode = const_cast<char *>(mode); 10739c40264fSZachary Turner #if PY_MAJOR_VERSION >= 3 1074b9c1b51eSKate Stone Reset(PyRefType::Owned, PyFile_FromFd(file.GetDescriptor(), nullptr, cmode, 1075b9c1b51eSKate Stone -1, nullptr, "ignore", nullptr, 0)); 10769c40264fSZachary Turner #else 10779c40264fSZachary Turner // Read through the Python source, doesn't seem to modify these strings 10789c40264fSZachary Turner Reset(PyRefType::Owned, 1079b9c1b51eSKate Stone PyFile_FromFile(file.GetStream(), const_cast<char *>(""), cmode, 1080b9c1b51eSKate Stone nullptr)); 10819c40264fSZachary Turner #endif 10829c40264fSZachary Turner } 10839c40264fSZachary Turner 1084744959b9SEnrico Granata 10852fce1137SLawrence D'Anna FileUP PythonFile::GetUnderlyingFile() const { 1086eda01c31SZachary Turner if (!IsValid()) 10872fce1137SLawrence D'Anna return nullptr; 1088eda01c31SZachary Turner 1089eda01c31SZachary Turner // We don't own the file descriptor returned by this function, make sure the 1090eda01c31SZachary Turner // File object knows about that. 1091744959b9SEnrico Granata PythonString py_mode = GetAttributeValue("mode").AsType<PythonString>(); 109257504530SLawrence D'Anna auto options = File::GetOptionsFromMode(py_mode.GetString()); 1093f913fd6eSLawrence D'Anna auto file = std::unique_ptr<File>( 1094f913fd6eSLawrence D'Anna new NativeFile(PyObject_AsFileDescriptor(m_py_obj), options, false)); 10952fce1137SLawrence D'Anna if (!file->IsValid()) 10962fce1137SLawrence D'Anna return nullptr; 10972fce1137SLawrence D'Anna return file; 1098eda01c31SZachary Turner } 1099d68983e3SPavel Labath 1100*21b8a8aeSLawrence D'Anna namespace { 1101*21b8a8aeSLawrence D'Anna class GIL { 1102*21b8a8aeSLawrence D'Anna public: 1103*21b8a8aeSLawrence D'Anna GIL() { 1104*21b8a8aeSLawrence D'Anna m_state = PyGILState_Ensure(); 1105*21b8a8aeSLawrence D'Anna assert(!PyErr_Occurred()); 1106*21b8a8aeSLawrence D'Anna } 1107*21b8a8aeSLawrence D'Anna ~GIL() { PyGILState_Release(m_state); } 1108*21b8a8aeSLawrence D'Anna 1109*21b8a8aeSLawrence D'Anna protected: 1110*21b8a8aeSLawrence D'Anna PyGILState_STATE m_state; 1111*21b8a8aeSLawrence D'Anna }; 1112*21b8a8aeSLawrence D'Anna } // namespace 1113*21b8a8aeSLawrence D'Anna 1114085328eeSLawrence D'Anna const char *PythonException::toCString() const { 1115085328eeSLawrence D'Anna if (!m_repr_bytes) 1116085328eeSLawrence D'Anna return "unknown exception"; 1117085328eeSLawrence D'Anna return PyBytes_AS_STRING(m_repr_bytes); 1118085328eeSLawrence D'Anna } 1119085328eeSLawrence D'Anna 1120085328eeSLawrence D'Anna PythonException::PythonException(const char *caller) { 1121085328eeSLawrence D'Anna assert(PyErr_Occurred()); 1122085328eeSLawrence D'Anna m_exception_type = m_exception = m_traceback = m_repr_bytes = NULL; 1123085328eeSLawrence D'Anna PyErr_Fetch(&m_exception_type, &m_exception, &m_traceback); 1124085328eeSLawrence D'Anna PyErr_NormalizeException(&m_exception_type, &m_exception, &m_traceback); 1125085328eeSLawrence D'Anna PyErr_Clear(); 1126085328eeSLawrence D'Anna if (m_exception) { 1127085328eeSLawrence D'Anna PyObject *repr = PyObject_Repr(m_exception); 1128085328eeSLawrence D'Anna if (repr) { 1129085328eeSLawrence D'Anna m_repr_bytes = PyUnicode_AsEncodedString(repr, "utf-8", nullptr); 1130085328eeSLawrence D'Anna if (!m_repr_bytes) { 1131085328eeSLawrence D'Anna PyErr_Clear(); 1132085328eeSLawrence D'Anna } 1133085328eeSLawrence D'Anna Py_XDECREF(repr); 1134085328eeSLawrence D'Anna } else { 1135085328eeSLawrence D'Anna PyErr_Clear(); 1136085328eeSLawrence D'Anna } 1137085328eeSLawrence D'Anna } 1138085328eeSLawrence D'Anna Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT); 1139085328eeSLawrence D'Anna if (caller) 1140085328eeSLawrence D'Anna LLDB_LOGF(log, "%s failed with exception: %s", caller, toCString()); 1141085328eeSLawrence D'Anna else 1142085328eeSLawrence D'Anna LLDB_LOGF(log, "python exception: %s", toCString()); 1143085328eeSLawrence D'Anna } 1144085328eeSLawrence D'Anna void PythonException::Restore() { 1145085328eeSLawrence D'Anna if (m_exception_type && m_exception) { 1146085328eeSLawrence D'Anna PyErr_Restore(m_exception_type, m_exception, m_traceback); 1147085328eeSLawrence D'Anna } else { 1148085328eeSLawrence D'Anna PyErr_SetString(PyExc_Exception, toCString()); 1149085328eeSLawrence D'Anna } 1150085328eeSLawrence D'Anna m_exception_type = m_exception = m_traceback = NULL; 1151085328eeSLawrence D'Anna } 1152085328eeSLawrence D'Anna 1153085328eeSLawrence D'Anna PythonException::~PythonException() { 1154085328eeSLawrence D'Anna Py_XDECREF(m_exception_type); 1155085328eeSLawrence D'Anna Py_XDECREF(m_exception); 1156085328eeSLawrence D'Anna Py_XDECREF(m_traceback); 1157085328eeSLawrence D'Anna Py_XDECREF(m_repr_bytes); 1158085328eeSLawrence D'Anna } 1159085328eeSLawrence D'Anna 1160085328eeSLawrence D'Anna void PythonException::log(llvm::raw_ostream &OS) const { OS << toCString(); } 1161085328eeSLawrence D'Anna 1162085328eeSLawrence D'Anna std::error_code PythonException::convertToErrorCode() const { 1163085328eeSLawrence D'Anna return llvm::inconvertibleErrorCode(); 1164085328eeSLawrence D'Anna } 1165085328eeSLawrence D'Anna 1166085328eeSLawrence D'Anna char PythonException::ID = 0; 1167085328eeSLawrence D'Anna 1168*21b8a8aeSLawrence D'Anna llvm::Expected<uint32_t> GetOptionsForPyObject(const PythonObject &obj) { 1169*21b8a8aeSLawrence D'Anna uint32_t options = 0; 1170*21b8a8aeSLawrence D'Anna #if PY_MAJOR_VERSION >= 3 1171*21b8a8aeSLawrence D'Anna auto readable = As<bool>(obj.CallMethod("readable")); 1172*21b8a8aeSLawrence D'Anna if (!readable) 1173*21b8a8aeSLawrence D'Anna return readable.takeError(); 1174*21b8a8aeSLawrence D'Anna auto writable = As<bool>(obj.CallMethod("writable")); 1175*21b8a8aeSLawrence D'Anna if (!writable) 1176*21b8a8aeSLawrence D'Anna return writable.takeError(); 1177*21b8a8aeSLawrence D'Anna if (readable.get()) 1178*21b8a8aeSLawrence D'Anna options |= File::eOpenOptionRead; 1179*21b8a8aeSLawrence D'Anna if (writable.get()) 1180*21b8a8aeSLawrence D'Anna options |= File::eOpenOptionWrite; 1181*21b8a8aeSLawrence D'Anna #else 1182*21b8a8aeSLawrence D'Anna PythonString py_mode = obj.GetAttributeValue("mode").AsType<PythonString>(); 1183*21b8a8aeSLawrence D'Anna options = File::GetOptionsFromMode(py_mode.GetString()); 1184*21b8a8aeSLawrence D'Anna #endif 1185*21b8a8aeSLawrence D'Anna return options; 1186*21b8a8aeSLawrence D'Anna } 1187*21b8a8aeSLawrence D'Anna 1188*21b8a8aeSLawrence D'Anna // Base class template for python files. All it knows how to do 1189*21b8a8aeSLawrence D'Anna // is hold a reference to the python object and close or flush it 1190*21b8a8aeSLawrence D'Anna // when the File is closed. 1191*21b8a8aeSLawrence D'Anna namespace { 1192*21b8a8aeSLawrence D'Anna template <typename Base> class OwnedPythonFile : public Base { 1193*21b8a8aeSLawrence D'Anna public: 1194*21b8a8aeSLawrence D'Anna template <typename... Args> 1195*21b8a8aeSLawrence D'Anna OwnedPythonFile(const PythonFile &file, bool borrowed, Args... args) 1196*21b8a8aeSLawrence D'Anna : Base(args...), m_py_obj(file), m_borrowed(borrowed) { 1197*21b8a8aeSLawrence D'Anna assert(m_py_obj); 1198*21b8a8aeSLawrence D'Anna } 1199*21b8a8aeSLawrence D'Anna 1200*21b8a8aeSLawrence D'Anna ~OwnedPythonFile() override { 1201*21b8a8aeSLawrence D'Anna assert(m_py_obj); 1202*21b8a8aeSLawrence D'Anna GIL takeGIL; 1203*21b8a8aeSLawrence D'Anna Close(); 1204*21b8a8aeSLawrence D'Anna m_py_obj.Reset(); 1205*21b8a8aeSLawrence D'Anna } 1206*21b8a8aeSLawrence D'Anna 1207*21b8a8aeSLawrence D'Anna bool IsPythonSideValid() const { 1208*21b8a8aeSLawrence D'Anna GIL takeGIL; 1209*21b8a8aeSLawrence D'Anna auto closed = As<bool>(m_py_obj.GetAttribute("closed")); 1210*21b8a8aeSLawrence D'Anna if (!closed) { 1211*21b8a8aeSLawrence D'Anna llvm::consumeError(closed.takeError()); 1212*21b8a8aeSLawrence D'Anna return false; 1213*21b8a8aeSLawrence D'Anna } 1214*21b8a8aeSLawrence D'Anna return !closed.get(); 1215*21b8a8aeSLawrence D'Anna } 1216*21b8a8aeSLawrence D'Anna 1217*21b8a8aeSLawrence D'Anna bool IsValid() const override { 1218*21b8a8aeSLawrence D'Anna return IsPythonSideValid() && Base::IsValid(); 1219*21b8a8aeSLawrence D'Anna } 1220*21b8a8aeSLawrence D'Anna 1221*21b8a8aeSLawrence D'Anna Status Close() override { 1222*21b8a8aeSLawrence D'Anna assert(m_py_obj); 1223*21b8a8aeSLawrence D'Anna Status py_error, base_error; 1224*21b8a8aeSLawrence D'Anna GIL takeGIL; 1225*21b8a8aeSLawrence D'Anna if (!m_borrowed) { 1226*21b8a8aeSLawrence D'Anna auto r = m_py_obj.CallMethod("close"); 1227*21b8a8aeSLawrence D'Anna if (!r) 1228*21b8a8aeSLawrence D'Anna py_error = Status(r.takeError()); 1229*21b8a8aeSLawrence D'Anna } 1230*21b8a8aeSLawrence D'Anna base_error = Base::Close(); 1231*21b8a8aeSLawrence D'Anna if (py_error.Fail()) 1232*21b8a8aeSLawrence D'Anna return py_error; 1233*21b8a8aeSLawrence D'Anna return base_error; 1234*21b8a8aeSLawrence D'Anna }; 1235*21b8a8aeSLawrence D'Anna 1236*21b8a8aeSLawrence D'Anna protected: 1237*21b8a8aeSLawrence D'Anna PythonFile m_py_obj; 1238*21b8a8aeSLawrence D'Anna bool m_borrowed; 1239*21b8a8aeSLawrence D'Anna }; 1240*21b8a8aeSLawrence D'Anna } // namespace 1241*21b8a8aeSLawrence D'Anna 1242*21b8a8aeSLawrence D'Anna // A SimplePythonFile is a OwnedPythonFile that just does all I/O as 1243*21b8a8aeSLawrence D'Anna // a NativeFile 1244*21b8a8aeSLawrence D'Anna namespace { 1245*21b8a8aeSLawrence D'Anna class SimplePythonFile : public OwnedPythonFile<NativeFile> { 1246*21b8a8aeSLawrence D'Anna public: 1247*21b8a8aeSLawrence D'Anna SimplePythonFile(const PythonFile &file, bool borrowed, int fd, 1248*21b8a8aeSLawrence D'Anna uint32_t options) 1249*21b8a8aeSLawrence D'Anna : OwnedPythonFile(file, borrowed, fd, options, false) {} 1250*21b8a8aeSLawrence D'Anna }; 1251*21b8a8aeSLawrence D'Anna } // namespace 1252*21b8a8aeSLawrence D'Anna 1253*21b8a8aeSLawrence D'Anna #if PY_MAJOR_VERSION >= 3 1254*21b8a8aeSLawrence D'Anna 1255*21b8a8aeSLawrence D'Anna namespace { 1256*21b8a8aeSLawrence D'Anna class PythonBuffer { 1257*21b8a8aeSLawrence D'Anna public: 1258*21b8a8aeSLawrence D'Anna PythonBuffer &operator=(const PythonBuffer &) = delete; 1259*21b8a8aeSLawrence D'Anna PythonBuffer(const PythonBuffer &) = delete; 1260*21b8a8aeSLawrence D'Anna 1261*21b8a8aeSLawrence D'Anna static Expected<PythonBuffer> Create(PythonObject &obj, 1262*21b8a8aeSLawrence D'Anna int flags = PyBUF_SIMPLE) { 1263*21b8a8aeSLawrence D'Anna Py_buffer py_buffer = {}; 1264*21b8a8aeSLawrence D'Anna PyObject_GetBuffer(obj.get(), &py_buffer, flags); 1265*21b8a8aeSLawrence D'Anna if (!py_buffer.obj) 1266*21b8a8aeSLawrence D'Anna return llvm::make_error<PythonException>(); 1267*21b8a8aeSLawrence D'Anna return PythonBuffer(py_buffer); 1268*21b8a8aeSLawrence D'Anna } 1269*21b8a8aeSLawrence D'Anna 1270*21b8a8aeSLawrence D'Anna PythonBuffer(PythonBuffer &&other) { 1271*21b8a8aeSLawrence D'Anna m_buffer = other.m_buffer; 1272*21b8a8aeSLawrence D'Anna other.m_buffer.obj = nullptr; 1273*21b8a8aeSLawrence D'Anna } 1274*21b8a8aeSLawrence D'Anna 1275*21b8a8aeSLawrence D'Anna ~PythonBuffer() { 1276*21b8a8aeSLawrence D'Anna if (m_buffer.obj) 1277*21b8a8aeSLawrence D'Anna PyBuffer_Release(&m_buffer); 1278*21b8a8aeSLawrence D'Anna } 1279*21b8a8aeSLawrence D'Anna 1280*21b8a8aeSLawrence D'Anna Py_buffer &get() { return m_buffer; } 1281*21b8a8aeSLawrence D'Anna 1282*21b8a8aeSLawrence D'Anna private: 1283*21b8a8aeSLawrence D'Anna // takes ownership of the buffer. 1284*21b8a8aeSLawrence D'Anna PythonBuffer(const Py_buffer &py_buffer) : m_buffer(py_buffer) {} 1285*21b8a8aeSLawrence D'Anna Py_buffer m_buffer; 1286*21b8a8aeSLawrence D'Anna }; 1287*21b8a8aeSLawrence D'Anna } // namespace 1288*21b8a8aeSLawrence D'Anna 1289*21b8a8aeSLawrence D'Anna // Shared methods between TextPythonFile and BinaryPythonFile 1290*21b8a8aeSLawrence D'Anna namespace { 1291*21b8a8aeSLawrence D'Anna class PythonIOFile : public OwnedPythonFile<File> { 1292*21b8a8aeSLawrence D'Anna public: 1293*21b8a8aeSLawrence D'Anna PythonIOFile(const PythonFile &file, bool borrowed) 1294*21b8a8aeSLawrence D'Anna : OwnedPythonFile(file, borrowed) {} 1295*21b8a8aeSLawrence D'Anna 1296*21b8a8aeSLawrence D'Anna ~PythonIOFile() override { Close(); } 1297*21b8a8aeSLawrence D'Anna 1298*21b8a8aeSLawrence D'Anna bool IsValid() const override { return IsPythonSideValid(); } 1299*21b8a8aeSLawrence D'Anna 1300*21b8a8aeSLawrence D'Anna Status Close() override { 1301*21b8a8aeSLawrence D'Anna assert(m_py_obj); 1302*21b8a8aeSLawrence D'Anna GIL takeGIL; 1303*21b8a8aeSLawrence D'Anna if (m_borrowed) 1304*21b8a8aeSLawrence D'Anna return Flush(); 1305*21b8a8aeSLawrence D'Anna auto r = m_py_obj.CallMethod("close"); 1306*21b8a8aeSLawrence D'Anna if (!r) 1307*21b8a8aeSLawrence D'Anna return Status(r.takeError()); 1308*21b8a8aeSLawrence D'Anna return Status(); 1309*21b8a8aeSLawrence D'Anna } 1310*21b8a8aeSLawrence D'Anna 1311*21b8a8aeSLawrence D'Anna Status Flush() override { 1312*21b8a8aeSLawrence D'Anna GIL takeGIL; 1313*21b8a8aeSLawrence D'Anna auto r = m_py_obj.CallMethod("flush"); 1314*21b8a8aeSLawrence D'Anna if (!r) 1315*21b8a8aeSLawrence D'Anna return Status(r.takeError()); 1316*21b8a8aeSLawrence D'Anna return Status(); 1317*21b8a8aeSLawrence D'Anna } 1318*21b8a8aeSLawrence D'Anna 1319*21b8a8aeSLawrence D'Anna }; 1320*21b8a8aeSLawrence D'Anna } // namespace 1321*21b8a8aeSLawrence D'Anna 1322*21b8a8aeSLawrence D'Anna namespace { 1323*21b8a8aeSLawrence D'Anna class BinaryPythonFile : public PythonIOFile { 1324*21b8a8aeSLawrence D'Anna protected: 1325*21b8a8aeSLawrence D'Anna int m_descriptor; 1326*21b8a8aeSLawrence D'Anna 1327*21b8a8aeSLawrence D'Anna public: 1328*21b8a8aeSLawrence D'Anna BinaryPythonFile(int fd, const PythonFile &file, bool borrowed) 1329*21b8a8aeSLawrence D'Anna : PythonIOFile(file, borrowed), 1330*21b8a8aeSLawrence D'Anna m_descriptor(File::DescriptorIsValid(fd) ? fd 1331*21b8a8aeSLawrence D'Anna : File::kInvalidDescriptor) {} 1332*21b8a8aeSLawrence D'Anna 1333*21b8a8aeSLawrence D'Anna int GetDescriptor() const override { return m_descriptor; } 1334*21b8a8aeSLawrence D'Anna 1335*21b8a8aeSLawrence D'Anna Status Write(const void *buf, size_t &num_bytes) override { 1336*21b8a8aeSLawrence D'Anna GIL takeGIL; 1337*21b8a8aeSLawrence D'Anna PyObject *pybuffer_p = PyMemoryView_FromMemory( 1338*21b8a8aeSLawrence D'Anna const_cast<char *>((const char *)buf), num_bytes, PyBUF_READ); 1339*21b8a8aeSLawrence D'Anna if (!pybuffer_p) 1340*21b8a8aeSLawrence D'Anna return Status(llvm::make_error<PythonException>()); 1341*21b8a8aeSLawrence D'Anna auto pybuffer = Take<PythonObject>(pybuffer_p); 1342*21b8a8aeSLawrence D'Anna num_bytes = 0; 1343*21b8a8aeSLawrence D'Anna auto bytes_written = As<long long>(m_py_obj.CallMethod("write", pybuffer)); 1344*21b8a8aeSLawrence D'Anna if (!bytes_written) 1345*21b8a8aeSLawrence D'Anna return Status(bytes_written.takeError()); 1346*21b8a8aeSLawrence D'Anna if (bytes_written.get() < 0) 1347*21b8a8aeSLawrence D'Anna return Status(".write() method returned a negative number!"); 1348*21b8a8aeSLawrence D'Anna static_assert(sizeof(long long) >= sizeof(size_t), "overflow"); 1349*21b8a8aeSLawrence D'Anna num_bytes = bytes_written.get(); 1350*21b8a8aeSLawrence D'Anna return Status(); 1351*21b8a8aeSLawrence D'Anna } 1352*21b8a8aeSLawrence D'Anna 1353*21b8a8aeSLawrence D'Anna Status Read(void *buf, size_t &num_bytes) override { 1354*21b8a8aeSLawrence D'Anna GIL takeGIL; 1355*21b8a8aeSLawrence D'Anna static_assert(sizeof(long long) >= sizeof(size_t), "overflow"); 1356*21b8a8aeSLawrence D'Anna auto pybuffer_obj = 1357*21b8a8aeSLawrence D'Anna m_py_obj.CallMethod("read", (unsigned long long)num_bytes); 1358*21b8a8aeSLawrence D'Anna if (!pybuffer_obj) 1359*21b8a8aeSLawrence D'Anna return Status(pybuffer_obj.takeError()); 1360*21b8a8aeSLawrence D'Anna num_bytes = 0; 1361*21b8a8aeSLawrence D'Anna if (pybuffer_obj.get().IsNone()) { 1362*21b8a8aeSLawrence D'Anna // EOF 1363*21b8a8aeSLawrence D'Anna num_bytes = 0; 1364*21b8a8aeSLawrence D'Anna return Status(); 1365*21b8a8aeSLawrence D'Anna } 1366*21b8a8aeSLawrence D'Anna auto pybuffer = PythonBuffer::Create(pybuffer_obj.get()); 1367*21b8a8aeSLawrence D'Anna if (!pybuffer) 1368*21b8a8aeSLawrence D'Anna return Status(pybuffer.takeError()); 1369*21b8a8aeSLawrence D'Anna memcpy(buf, pybuffer.get().get().buf, pybuffer.get().get().len); 1370*21b8a8aeSLawrence D'Anna num_bytes = pybuffer.get().get().len; 1371*21b8a8aeSLawrence D'Anna return Status(); 1372*21b8a8aeSLawrence D'Anna } 1373*21b8a8aeSLawrence D'Anna }; 1374*21b8a8aeSLawrence D'Anna } // namespace 1375*21b8a8aeSLawrence D'Anna 1376*21b8a8aeSLawrence D'Anna namespace { 1377*21b8a8aeSLawrence D'Anna class TextPythonFile : public PythonIOFile { 1378*21b8a8aeSLawrence D'Anna protected: 1379*21b8a8aeSLawrence D'Anna int m_descriptor; 1380*21b8a8aeSLawrence D'Anna 1381*21b8a8aeSLawrence D'Anna public: 1382*21b8a8aeSLawrence D'Anna TextPythonFile(int fd, const PythonFile &file, bool borrowed) 1383*21b8a8aeSLawrence D'Anna : PythonIOFile(file, borrowed), 1384*21b8a8aeSLawrence D'Anna m_descriptor(File::DescriptorIsValid(fd) ? fd 1385*21b8a8aeSLawrence D'Anna : File::kInvalidDescriptor) {} 1386*21b8a8aeSLawrence D'Anna 1387*21b8a8aeSLawrence D'Anna int GetDescriptor() const override { return m_descriptor; } 1388*21b8a8aeSLawrence D'Anna 1389*21b8a8aeSLawrence D'Anna Status Write(const void *buf, size_t &num_bytes) override { 1390*21b8a8aeSLawrence D'Anna GIL takeGIL; 1391*21b8a8aeSLawrence D'Anna auto pystring = 1392*21b8a8aeSLawrence D'Anna PythonString::FromUTF8(llvm::StringRef((const char *)buf, num_bytes)); 1393*21b8a8aeSLawrence D'Anna if (!pystring) 1394*21b8a8aeSLawrence D'Anna return Status(pystring.takeError()); 1395*21b8a8aeSLawrence D'Anna num_bytes = 0; 1396*21b8a8aeSLawrence D'Anna auto bytes_written = 1397*21b8a8aeSLawrence D'Anna As<long long>(m_py_obj.CallMethod("write", pystring.get())); 1398*21b8a8aeSLawrence D'Anna if (!bytes_written) 1399*21b8a8aeSLawrence D'Anna return Status(bytes_written.takeError()); 1400*21b8a8aeSLawrence D'Anna if (bytes_written.get() < 0) 1401*21b8a8aeSLawrence D'Anna return Status(".write() method returned a negative number!"); 1402*21b8a8aeSLawrence D'Anna static_assert(sizeof(long long) >= sizeof(size_t), "overflow"); 1403*21b8a8aeSLawrence D'Anna num_bytes = bytes_written.get(); 1404*21b8a8aeSLawrence D'Anna return Status(); 1405*21b8a8aeSLawrence D'Anna } 1406*21b8a8aeSLawrence D'Anna 1407*21b8a8aeSLawrence D'Anna Status Read(void *buf, size_t &num_bytes) override { 1408*21b8a8aeSLawrence D'Anna GIL takeGIL; 1409*21b8a8aeSLawrence D'Anna size_t num_chars = num_bytes / 6; 1410*21b8a8aeSLawrence D'Anna size_t orig_num_bytes = num_bytes; 1411*21b8a8aeSLawrence D'Anna num_bytes = 0; 1412*21b8a8aeSLawrence D'Anna if (orig_num_bytes < 6) { 1413*21b8a8aeSLawrence D'Anna return Status("can't read less than 6 bytes from a utf8 text stream"); 1414*21b8a8aeSLawrence D'Anna } 1415*21b8a8aeSLawrence D'Anna auto pystring = As<PythonString>( 1416*21b8a8aeSLawrence D'Anna m_py_obj.CallMethod("read", (unsigned long long)num_chars)); 1417*21b8a8aeSLawrence D'Anna if (!pystring) 1418*21b8a8aeSLawrence D'Anna return Status(pystring.takeError()); 1419*21b8a8aeSLawrence D'Anna if (pystring.get().IsNone()) { 1420*21b8a8aeSLawrence D'Anna // EOF 1421*21b8a8aeSLawrence D'Anna return Status(); 1422*21b8a8aeSLawrence D'Anna } 1423*21b8a8aeSLawrence D'Anna auto stringref = pystring.get().AsUTF8(); 1424*21b8a8aeSLawrence D'Anna if (!stringref) 1425*21b8a8aeSLawrence D'Anna return Status(stringref.takeError()); 1426*21b8a8aeSLawrence D'Anna num_bytes = stringref.get().size(); 1427*21b8a8aeSLawrence D'Anna memcpy(buf, stringref.get().begin(), num_bytes); 1428*21b8a8aeSLawrence D'Anna return Status(); 1429*21b8a8aeSLawrence D'Anna } 1430*21b8a8aeSLawrence D'Anna }; 1431*21b8a8aeSLawrence D'Anna } // namespace 1432*21b8a8aeSLawrence D'Anna 1433*21b8a8aeSLawrence D'Anna #endif 1434*21b8a8aeSLawrence D'Anna 1435*21b8a8aeSLawrence D'Anna llvm::Expected<FileSP> PythonFile::ConvertToFile(bool borrowed) { 1436*21b8a8aeSLawrence D'Anna if (!IsValid()) 1437*21b8a8aeSLawrence D'Anna return llvm::createStringError(llvm::inconvertibleErrorCode(), 1438*21b8a8aeSLawrence D'Anna "invalid PythonFile"); 1439*21b8a8aeSLawrence D'Anna 1440*21b8a8aeSLawrence D'Anna int fd = PyObject_AsFileDescriptor(m_py_obj); 1441*21b8a8aeSLawrence D'Anna if (fd < 0) { 1442*21b8a8aeSLawrence D'Anna PyErr_Clear(); 1443*21b8a8aeSLawrence D'Anna return ConvertToFileForcingUseOfScriptingIOMethods(borrowed); 1444*21b8a8aeSLawrence D'Anna } 1445*21b8a8aeSLawrence D'Anna auto options = GetOptionsForPyObject(*this); 1446*21b8a8aeSLawrence D'Anna if (!options) 1447*21b8a8aeSLawrence D'Anna return options.takeError(); 1448*21b8a8aeSLawrence D'Anna 1449*21b8a8aeSLawrence D'Anna // LLDB and python will not share I/O buffers. We should probably 1450*21b8a8aeSLawrence D'Anna // flush the python buffers now. 1451*21b8a8aeSLawrence D'Anna auto r = CallMethod("flush"); 1452*21b8a8aeSLawrence D'Anna if (!r) 1453*21b8a8aeSLawrence D'Anna return r.takeError(); 1454*21b8a8aeSLawrence D'Anna 1455*21b8a8aeSLawrence D'Anna FileSP file_sp; 1456*21b8a8aeSLawrence D'Anna if (borrowed) { 1457*21b8a8aeSLawrence D'Anna // In this case we we don't need to retain the python 1458*21b8a8aeSLawrence D'Anna // object at all. 1459*21b8a8aeSLawrence D'Anna file_sp = std::make_shared<NativeFile>(fd, options.get(), false); 1460*21b8a8aeSLawrence D'Anna } else { 1461*21b8a8aeSLawrence D'Anna file_sp = std::static_pointer_cast<File>( 1462*21b8a8aeSLawrence D'Anna std::make_shared<SimplePythonFile>(*this, borrowed, fd, options.get())); 1463*21b8a8aeSLawrence D'Anna } 1464*21b8a8aeSLawrence D'Anna if (!file_sp->IsValid()) 1465*21b8a8aeSLawrence D'Anna return llvm::createStringError(llvm::inconvertibleErrorCode(), 1466*21b8a8aeSLawrence D'Anna "invalid File"); 1467*21b8a8aeSLawrence D'Anna 1468*21b8a8aeSLawrence D'Anna return file_sp; 1469*21b8a8aeSLawrence D'Anna } 1470*21b8a8aeSLawrence D'Anna 1471*21b8a8aeSLawrence D'Anna llvm::Expected<FileSP> 1472*21b8a8aeSLawrence D'Anna PythonFile::ConvertToFileForcingUseOfScriptingIOMethods(bool borrowed) { 1473*21b8a8aeSLawrence D'Anna 1474*21b8a8aeSLawrence D'Anna assert(!PyErr_Occurred()); 1475*21b8a8aeSLawrence D'Anna 1476*21b8a8aeSLawrence D'Anna if (!IsValid()) 1477*21b8a8aeSLawrence D'Anna return llvm::createStringError(llvm::inconvertibleErrorCode(), 1478*21b8a8aeSLawrence D'Anna "invalid PythonFile"); 1479*21b8a8aeSLawrence D'Anna 1480*21b8a8aeSLawrence D'Anna #if PY_MAJOR_VERSION < 3 1481*21b8a8aeSLawrence D'Anna 1482*21b8a8aeSLawrence D'Anna return llvm::createStringError(llvm::inconvertibleErrorCode(), 1483*21b8a8aeSLawrence D'Anna "not supported on python 2"); 1484*21b8a8aeSLawrence D'Anna 1485*21b8a8aeSLawrence D'Anna #else 1486*21b8a8aeSLawrence D'Anna 1487*21b8a8aeSLawrence D'Anna int fd = PyObject_AsFileDescriptor(m_py_obj); 1488*21b8a8aeSLawrence D'Anna if (fd < 0) { 1489*21b8a8aeSLawrence D'Anna PyErr_Clear(); 1490*21b8a8aeSLawrence D'Anna fd = File::kInvalidDescriptor; 1491*21b8a8aeSLawrence D'Anna } 1492*21b8a8aeSLawrence D'Anna 1493*21b8a8aeSLawrence D'Anna auto io_module = PythonModule::Import("io"); 1494*21b8a8aeSLawrence D'Anna if (!io_module) 1495*21b8a8aeSLawrence D'Anna return io_module.takeError(); 1496*21b8a8aeSLawrence D'Anna auto textIOBase = io_module.get().Get("TextIOBase"); 1497*21b8a8aeSLawrence D'Anna if (!textIOBase) 1498*21b8a8aeSLawrence D'Anna return textIOBase.takeError(); 1499*21b8a8aeSLawrence D'Anna auto rawIOBase = io_module.get().Get("RawIOBase"); 1500*21b8a8aeSLawrence D'Anna if (!rawIOBase) 1501*21b8a8aeSLawrence D'Anna return rawIOBase.takeError(); 1502*21b8a8aeSLawrence D'Anna auto bufferedIOBase = io_module.get().Get("BufferedIOBase"); 1503*21b8a8aeSLawrence D'Anna if (!bufferedIOBase) 1504*21b8a8aeSLawrence D'Anna return bufferedIOBase.takeError(); 1505*21b8a8aeSLawrence D'Anna 1506*21b8a8aeSLawrence D'Anna FileSP file_sp; 1507*21b8a8aeSLawrence D'Anna 1508*21b8a8aeSLawrence D'Anna auto isTextIO = IsInstance(textIOBase.get()); 1509*21b8a8aeSLawrence D'Anna if (!isTextIO) 1510*21b8a8aeSLawrence D'Anna return isTextIO.takeError(); 1511*21b8a8aeSLawrence D'Anna if (isTextIO.get()) 1512*21b8a8aeSLawrence D'Anna file_sp = std::static_pointer_cast<File>( 1513*21b8a8aeSLawrence D'Anna std::make_shared<TextPythonFile>(fd, *this, borrowed)); 1514*21b8a8aeSLawrence D'Anna 1515*21b8a8aeSLawrence D'Anna auto isRawIO = IsInstance(rawIOBase.get()); 1516*21b8a8aeSLawrence D'Anna if (!isRawIO) 1517*21b8a8aeSLawrence D'Anna return isRawIO.takeError(); 1518*21b8a8aeSLawrence D'Anna auto isBufferedIO = IsInstance(bufferedIOBase.get()); 1519*21b8a8aeSLawrence D'Anna if (!isBufferedIO) 1520*21b8a8aeSLawrence D'Anna return isBufferedIO.takeError(); 1521*21b8a8aeSLawrence D'Anna 1522*21b8a8aeSLawrence D'Anna if (isRawIO.get() || isBufferedIO.get()) { 1523*21b8a8aeSLawrence D'Anna file_sp = std::static_pointer_cast<File>( 1524*21b8a8aeSLawrence D'Anna std::make_shared<BinaryPythonFile>(fd, *this, borrowed)); 1525*21b8a8aeSLawrence D'Anna } 1526*21b8a8aeSLawrence D'Anna 1527*21b8a8aeSLawrence D'Anna if (!file_sp) 1528*21b8a8aeSLawrence D'Anna return llvm::createStringError(llvm::inconvertibleErrorCode(), 1529*21b8a8aeSLawrence D'Anna "python file is neither text nor binary"); 1530*21b8a8aeSLawrence D'Anna 1531*21b8a8aeSLawrence D'Anna if (!file_sp->IsValid()) 1532*21b8a8aeSLawrence D'Anna return llvm::createStringError(llvm::inconvertibleErrorCode(), 1533*21b8a8aeSLawrence D'Anna "invalid File"); 1534*21b8a8aeSLawrence D'Anna 1535*21b8a8aeSLawrence D'Anna return file_sp; 1536*21b8a8aeSLawrence D'Anna 1537*21b8a8aeSLawrence D'Anna #endif 1538*21b8a8aeSLawrence D'Anna } 1539*21b8a8aeSLawrence D'Anna 1540d68983e3SPavel Labath #endif 1541