180814287SRaphael Isemann //===-- PythonDataObjects.cpp ---------------------------------------------===// 22c1f46dcSZachary Turner // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 62c1f46dcSZachary Turner // 72c1f46dcSZachary Turner //===----------------------------------------------------------------------===// 82c1f46dcSZachary Turner 959998b7bSJonas Devlieghere #include "lldb/Host/Config.h" 10d68983e3SPavel Labath 114e26cf2cSJonas Devlieghere #if LLDB_ENABLE_PYTHON 12d68983e3SPavel Labath 132c1f46dcSZachary Turner #include "PythonDataObjects.h" 142c1f46dcSZachary Turner #include "ScriptInterpreterPython.h" 152c1f46dcSZachary Turner 162c1f46dcSZachary Turner #include "lldb/Host/File.h" 17190fadcdSZachary Turner #include "lldb/Host/FileSystem.h" 182c1f46dcSZachary Turner #include "lldb/Interpreter/ScriptInterpreter.h" 19*c34698a8SPavel Labath #include "lldb/Utility/LLDBLog.h" 20085328eeSLawrence D'Anna #include "lldb/Utility/Log.h" 21bf9a7730SZachary Turner #include "lldb/Utility/Stream.h" 222c1f46dcSZachary Turner 239a6c7572SJonas Devlieghere #include "llvm/ADT/StringSwitch.h" 24d9b553ecSLawrence D'Anna #include "llvm/Support/Casting.h" 25190fadcdSZachary Turner #include "llvm/Support/ConvertUTF.h" 262819136fSMichal Gorny #include "llvm/Support/Errno.h" 27190fadcdSZachary Turner 2876e47d48SRaphael Isemann #include <cstdio> 292c1f46dcSZachary Turner 302c1f46dcSZachary Turner using namespace lldb_private; 312c1f46dcSZachary Turner using namespace lldb; 32085328eeSLawrence D'Anna using namespace lldb_private::python; 33c86a6acaSLawrence D'Anna using llvm::cantFail; 34085328eeSLawrence D'Anna using llvm::Error; 35085328eeSLawrence D'Anna using llvm::Expected; 36722b6189SLawrence D'Anna using llvm::Twine; 37085328eeSLawrence D'Anna 38085328eeSLawrence D'Anna template <> Expected<bool> python::As<bool>(Expected<PythonObject> &&obj) { 39085328eeSLawrence D'Anna if (!obj) 40085328eeSLawrence D'Anna return obj.takeError(); 41085328eeSLawrence D'Anna return obj.get().IsTrue(); 42085328eeSLawrence D'Anna } 43085328eeSLawrence D'Anna 44085328eeSLawrence D'Anna template <> 45085328eeSLawrence D'Anna Expected<long long> python::As<long long>(Expected<PythonObject> &&obj) { 46085328eeSLawrence D'Anna if (!obj) 47085328eeSLawrence D'Anna return obj.takeError(); 4852712d3fSLawrence D'Anna return obj->AsLongLong(); 4952712d3fSLawrence D'Anna } 5052712d3fSLawrence D'Anna 5152712d3fSLawrence D'Anna template <> 5252712d3fSLawrence D'Anna Expected<unsigned long long> 5352712d3fSLawrence D'Anna python::As<unsigned long long>(Expected<PythonObject> &&obj) { 5452712d3fSLawrence D'Anna if (!obj) 5552712d3fSLawrence D'Anna return obj.takeError(); 5652712d3fSLawrence D'Anna return obj->AsUnsignedLongLong(); 57085328eeSLawrence D'Anna } 582c1f46dcSZachary Turner 59c86a6acaSLawrence D'Anna template <> 60c86a6acaSLawrence D'Anna Expected<std::string> python::As<std::string>(Expected<PythonObject> &&obj) { 61c86a6acaSLawrence D'Anna if (!obj) 62c86a6acaSLawrence D'Anna return obj.takeError(); 63c86a6acaSLawrence D'Anna PyObject *str_obj = PyObject_Str(obj.get().get()); 64c86a6acaSLawrence D'Anna if (!obj) 65c86a6acaSLawrence D'Anna return llvm::make_error<PythonException>(); 66c86a6acaSLawrence D'Anna auto str = Take<PythonString>(str_obj); 67c86a6acaSLawrence D'Anna auto utf8 = str.AsUTF8(); 68c86a6acaSLawrence D'Anna if (!utf8) 69c86a6acaSLawrence D'Anna return utf8.takeError(); 7019580c37SBenjamin Kramer return std::string(utf8.get()); 71c86a6acaSLawrence D'Anna } 72c86a6acaSLawrence D'Anna 736ff4af8eSPavel Labath static bool python_is_finalizing() { 7416bff067SJonas Devlieghere #if PY_MAJOR_VERSION == 2 7516bff067SJonas Devlieghere return false; 7616bff067SJonas Devlieghere #elif PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 7 776ff4af8eSPavel Labath return _Py_Finalizing != nullptr; 786ff4af8eSPavel Labath #else 796ff4af8eSPavel Labath return _Py_IsFinalizing(); 806ff4af8eSPavel Labath #endif 816ff4af8eSPavel Labath } 826ff4af8eSPavel Labath 836ff4af8eSPavel Labath void PythonObject::Reset() { 846ff4af8eSPavel Labath if (m_py_obj && Py_IsInitialized()) { 856ff4af8eSPavel Labath if (python_is_finalizing()) { 866ff4af8eSPavel Labath // Leak m_py_obj rather than crashing the process. 876ff4af8eSPavel Labath // https://docs.python.org/3/c-api/init.html#c.PyGILState_Ensure 886ff4af8eSPavel Labath } else { 896ff4af8eSPavel Labath PyGILState_STATE state = PyGILState_Ensure(); 906ff4af8eSPavel Labath Py_DECREF(m_py_obj); 916ff4af8eSPavel Labath PyGILState_Release(state); 926ff4af8eSPavel Labath } 936ff4af8eSPavel Labath } 946ff4af8eSPavel Labath m_py_obj = nullptr; 956ff4af8eSPavel Labath } 966ff4af8eSPavel Labath 9752712d3fSLawrence D'Anna Expected<long long> PythonObject::AsLongLong() const { 9852712d3fSLawrence D'Anna if (!m_py_obj) 9952712d3fSLawrence D'Anna return nullDeref(); 10052712d3fSLawrence D'Anna #if PY_MAJOR_VERSION < 3 10152712d3fSLawrence D'Anna if (!PyLong_Check(m_py_obj)) { 10252712d3fSLawrence D'Anna PythonInteger i(PyRefType::Borrowed, m_py_obj); 10352712d3fSLawrence D'Anna return i.AsLongLong(); 10452712d3fSLawrence D'Anna } 10552712d3fSLawrence D'Anna #endif 10652712d3fSLawrence D'Anna assert(!PyErr_Occurred()); 10752712d3fSLawrence D'Anna long long r = PyLong_AsLongLong(m_py_obj); 10852712d3fSLawrence D'Anna if (PyErr_Occurred()) 10952712d3fSLawrence D'Anna return exception(); 11052712d3fSLawrence D'Anna return r; 11152712d3fSLawrence D'Anna } 11252712d3fSLawrence D'Anna 11352712d3fSLawrence D'Anna Expected<long long> PythonObject::AsUnsignedLongLong() const { 11452712d3fSLawrence D'Anna if (!m_py_obj) 11552712d3fSLawrence D'Anna return nullDeref(); 11652712d3fSLawrence D'Anna #if PY_MAJOR_VERSION < 3 11752712d3fSLawrence D'Anna if (!PyLong_Check(m_py_obj)) { 11852712d3fSLawrence D'Anna PythonInteger i(PyRefType::Borrowed, m_py_obj); 11952712d3fSLawrence D'Anna return i.AsUnsignedLongLong(); 12052712d3fSLawrence D'Anna } 12152712d3fSLawrence D'Anna #endif 12252712d3fSLawrence D'Anna assert(!PyErr_Occurred()); 12352712d3fSLawrence D'Anna long long r = PyLong_AsUnsignedLongLong(m_py_obj); 12452712d3fSLawrence D'Anna if (PyErr_Occurred()) 12552712d3fSLawrence D'Anna return exception(); 12652712d3fSLawrence D'Anna return r; 12752712d3fSLawrence D'Anna } 12852712d3fSLawrence D'Anna 12952712d3fSLawrence D'Anna // wraps on overflow, instead of raising an error. 13052712d3fSLawrence D'Anna Expected<unsigned long long> PythonObject::AsModuloUnsignedLongLong() const { 13152712d3fSLawrence D'Anna if (!m_py_obj) 13252712d3fSLawrence D'Anna return nullDeref(); 13352712d3fSLawrence D'Anna #if PY_MAJOR_VERSION < 3 13452712d3fSLawrence D'Anna if (!PyLong_Check(m_py_obj)) { 13552712d3fSLawrence D'Anna PythonInteger i(PyRefType::Borrowed, m_py_obj); 13652712d3fSLawrence D'Anna return i.AsModuloUnsignedLongLong(); 13752712d3fSLawrence D'Anna } 13852712d3fSLawrence D'Anna #endif 13952712d3fSLawrence D'Anna assert(!PyErr_Occurred()); 14052712d3fSLawrence D'Anna unsigned long long r = PyLong_AsUnsignedLongLongMask(m_py_obj); 14152712d3fSLawrence D'Anna if (PyErr_Occurred()) 14252712d3fSLawrence D'Anna return exception(); 14352712d3fSLawrence D'Anna return r; 14452712d3fSLawrence D'Anna } 14552712d3fSLawrence D'Anna 1462783d817SJonas Devlieghere void StructuredPythonObject::Serialize(llvm::json::OStream &s) const { 1472783d817SJonas Devlieghere s.value(llvm::formatv("Python Obj: {0:X}", GetValue()).str()); 1482c1f46dcSZachary Turner } 1492c1f46dcSZachary Turner 1502c1f46dcSZachary Turner // PythonObject 1512c1f46dcSZachary Turner 152b9c1b51eSKate Stone void PythonObject::Dump(Stream &strm) const { 153b9c1b51eSKate Stone if (m_py_obj) { 1542819136fSMichal Gorny FILE *file = llvm::sys::RetryAfterSignal(nullptr, ::tmpfile); 155b9c1b51eSKate Stone if (file) { 1562c1f46dcSZachary Turner ::PyObject_Print(m_py_obj, file, 0); 1572c1f46dcSZachary Turner const long length = ftell(file); 158b9c1b51eSKate Stone if (length) { 1592c1f46dcSZachary Turner ::rewind(file); 1602c1f46dcSZachary Turner std::vector<char> file_contents(length, '\0'); 161b9c1b51eSKate Stone const size_t length_read = 162b9c1b51eSKate Stone ::fread(file_contents.data(), 1, file_contents.size(), file); 1632c1f46dcSZachary Turner if (length_read > 0) 1642c1f46dcSZachary Turner strm.Write(file_contents.data(), length_read); 1652c1f46dcSZachary Turner } 1662c1f46dcSZachary Turner ::fclose(file); 1672c1f46dcSZachary Turner } 168b9c1b51eSKate Stone } else 1692c1f46dcSZachary Turner strm.PutCString("NULL"); 1702c1f46dcSZachary Turner } 1712c1f46dcSZachary Turner 172b9c1b51eSKate Stone PyObjectType PythonObject::GetObjectType() const { 173f8b22f8fSZachary Turner if (!IsAllocated()) 1742c1f46dcSZachary Turner return PyObjectType::None; 1752c1f46dcSZachary Turner 1767841efbbSZachary Turner if (PythonModule::Check(m_py_obj)) 1777841efbbSZachary Turner return PyObjectType::Module; 17818426935SZachary Turner if (PythonList::Check(m_py_obj)) 1792c1f46dcSZachary Turner return PyObjectType::List; 180a1405147SZachary Turner if (PythonTuple::Check(m_py_obj)) 181a1405147SZachary Turner return PyObjectType::Tuple; 18218426935SZachary Turner if (PythonDictionary::Check(m_py_obj)) 1832c1f46dcSZachary Turner return PyObjectType::Dictionary; 18418426935SZachary Turner if (PythonString::Check(m_py_obj)) 18522c8efcdSZachary Turner return PyObjectType::String; 1865a72c02bSZachary Turner #if PY_MAJOR_VERSION >= 3 1875a72c02bSZachary Turner if (PythonBytes::Check(m_py_obj)) 1885a72c02bSZachary Turner return PyObjectType::Bytes; 1895a72c02bSZachary Turner #endif 190f9d6d204SZachary Turner if (PythonByteArray::Check(m_py_obj)) 191f9d6d204SZachary Turner return PyObjectType::ByteArray; 192b81d715cSTatyana Krasnukha if (PythonBoolean::Check(m_py_obj)) 193b81d715cSTatyana Krasnukha return PyObjectType::Boolean; 19418426935SZachary Turner if (PythonInteger::Check(m_py_obj)) 19522c8efcdSZachary Turner return PyObjectType::Integer; 1969c40264fSZachary Turner if (PythonFile::Check(m_py_obj)) 1979c40264fSZachary Turner return PyObjectType::File; 198a1405147SZachary Turner if (PythonCallable::Check(m_py_obj)) 199a1405147SZachary Turner return PyObjectType::Callable; 2002c1f46dcSZachary Turner return PyObjectType::Unknown; 2012c1f46dcSZachary Turner } 2022c1f46dcSZachary Turner 203b9c1b51eSKate Stone PythonString PythonObject::Repr() const { 2042c1f46dcSZachary Turner if (!m_py_obj) 2052c1f46dcSZachary Turner return PythonString(); 2062c1f46dcSZachary Turner PyObject *repr = PyObject_Repr(m_py_obj); 2072c1f46dcSZachary Turner if (!repr) 2082c1f46dcSZachary Turner return PythonString(); 209f8b22f8fSZachary Turner return PythonString(PyRefType::Owned, repr); 2102c1f46dcSZachary Turner } 2112c1f46dcSZachary Turner 212b9c1b51eSKate Stone PythonString PythonObject::Str() const { 2132c1f46dcSZachary Turner if (!m_py_obj) 2142c1f46dcSZachary Turner return PythonString(); 2152c1f46dcSZachary Turner PyObject *str = PyObject_Str(m_py_obj); 2162c1f46dcSZachary Turner if (!str) 2172c1f46dcSZachary Turner return PythonString(); 218f8b22f8fSZachary Turner return PythonString(PyRefType::Owned, str); 2192c1f46dcSZachary Turner } 2202c1f46dcSZachary Turner 2217841efbbSZachary Turner PythonObject 222b9c1b51eSKate Stone PythonObject::ResolveNameWithDictionary(llvm::StringRef name, 223b9c1b51eSKate Stone const PythonDictionary &dict) { 224c712bac7SJonas Devlieghere size_t dot_pos = name.find('.'); 225a1405147SZachary Turner llvm::StringRef piece = name.substr(0, dot_pos); 226a1405147SZachary Turner PythonObject result = dict.GetItemForKey(PythonString(piece)); 227b9c1b51eSKate Stone if (dot_pos == llvm::StringRef::npos) { 228a1405147SZachary Turner // There was no dot, we're done. 229a1405147SZachary Turner return result; 230a1405147SZachary Turner } 231a1405147SZachary Turner 232a1405147SZachary Turner // There was a dot. The remaining portion of the name should be looked up in 233a1405147SZachary Turner // the context of the object that was found in the dictionary. 234a1405147SZachary Turner return result.ResolveName(name.substr(dot_pos + 1)); 2357841efbbSZachary Turner } 2367841efbbSZachary Turner 237b9c1b51eSKate Stone PythonObject PythonObject::ResolveName(llvm::StringRef name) const { 23805097246SAdrian Prantl // Resolve the name in the context of the specified object. If, for example, 23905097246SAdrian Prantl // `this` refers to a PyModule, then this will look for `name` in this 24005097246SAdrian Prantl // module. If `this` refers to a PyType, then it will resolve `name` as an 24105097246SAdrian Prantl // attribute of that type. If `this` refers to an instance of an object, 24205097246SAdrian Prantl // then it will resolve `name` as the value of the specified field. 2437841efbbSZachary Turner // 2447841efbbSZachary Turner // This function handles dotted names so that, for example, if `m_py_obj` 24505097246SAdrian Prantl // refers to the `sys` module, and `name` == "path.append", then it will find 24605097246SAdrian Prantl // the function `sys.path.append`. 2477841efbbSZachary Turner 248c712bac7SJonas Devlieghere size_t dot_pos = name.find('.'); 249b9c1b51eSKate Stone if (dot_pos == llvm::StringRef::npos) { 25005097246SAdrian Prantl // No dots in the name, we should be able to find the value immediately as 25105097246SAdrian Prantl // an attribute of `m_py_obj`. 2527841efbbSZachary Turner return GetAttributeValue(name); 2537841efbbSZachary Turner } 2547841efbbSZachary Turner 255b9c1b51eSKate Stone // Look up the first piece of the name, and resolve the rest as a child of 256b9c1b51eSKate Stone // that. 2577841efbbSZachary Turner PythonObject parent = ResolveName(name.substr(0, dot_pos)); 2587841efbbSZachary Turner if (!parent.IsAllocated()) 2597841efbbSZachary Turner return PythonObject(); 2607841efbbSZachary Turner 2617841efbbSZachary Turner // Tail recursion.. should be optimized by the compiler 2627841efbbSZachary Turner return parent.ResolveName(name.substr(dot_pos + 1)); 2637841efbbSZachary Turner } 2647841efbbSZachary Turner 265b9c1b51eSKate Stone bool PythonObject::HasAttribute(llvm::StringRef attr) const { 2669c40264fSZachary Turner if (!IsValid()) 2679c40264fSZachary Turner return false; 2689c40264fSZachary Turner PythonString py_attr(attr); 2699c40264fSZachary Turner return !!PyObject_HasAttr(m_py_obj, py_attr.get()); 2709c40264fSZachary Turner } 2719c40264fSZachary Turner 272b9c1b51eSKate Stone PythonObject PythonObject::GetAttributeValue(llvm::StringRef attr) const { 2737d6d218eSZachary Turner if (!IsValid()) 2747d6d218eSZachary Turner return PythonObject(); 2757d6d218eSZachary Turner 2767d6d218eSZachary Turner PythonString py_attr(attr); 2777d6d218eSZachary Turner if (!PyObject_HasAttr(m_py_obj, py_attr.get())) 2787d6d218eSZachary Turner return PythonObject(); 2797d6d218eSZachary Turner 2807d6d218eSZachary Turner return PythonObject(PyRefType::Owned, 2817d6d218eSZachary Turner PyObject_GetAttr(m_py_obj, py_attr.get())); 2827d6d218eSZachary Turner } 2837d6d218eSZachary Turner 284b9c1b51eSKate Stone StructuredData::ObjectSP PythonObject::CreateStructuredObject() const { 28516bff067SJonas Devlieghere #if PY_MAJOR_VERSION >= 3 286a6598575SRalf Grosse-Kunstleve assert(PyGILState_Check()); 28716bff067SJonas Devlieghere #endif 288b9c1b51eSKate Stone switch (GetObjectType()) { 2892c1f46dcSZachary Turner case PyObjectType::Dictionary: 290b9c1b51eSKate Stone return PythonDictionary(PyRefType::Borrowed, m_py_obj) 291b9c1b51eSKate Stone .CreateStructuredDictionary(); 292b81d715cSTatyana Krasnukha case PyObjectType::Boolean: 293b81d715cSTatyana Krasnukha return PythonBoolean(PyRefType::Borrowed, m_py_obj) 294b81d715cSTatyana Krasnukha .CreateStructuredBoolean(); 2952c1f46dcSZachary Turner case PyObjectType::Integer: 296b9c1b51eSKate Stone return PythonInteger(PyRefType::Borrowed, m_py_obj) 297b9c1b51eSKate Stone .CreateStructuredInteger(); 2982c1f46dcSZachary Turner case PyObjectType::List: 299f8b22f8fSZachary Turner return PythonList(PyRefType::Borrowed, m_py_obj).CreateStructuredArray(); 3002c1f46dcSZachary Turner case PyObjectType::String: 301f8b22f8fSZachary Turner return PythonString(PyRefType::Borrowed, m_py_obj).CreateStructuredString(); 3025a72c02bSZachary Turner case PyObjectType::Bytes: 3035a72c02bSZachary Turner return PythonBytes(PyRefType::Borrowed, m_py_obj).CreateStructuredString(); 304f9d6d204SZachary Turner case PyObjectType::ByteArray: 305b9c1b51eSKate Stone return PythonByteArray(PyRefType::Borrowed, m_py_obj) 306b9c1b51eSKate Stone .CreateStructuredString(); 3072c1f46dcSZachary Turner case PyObjectType::None: 3082c1f46dcSZachary Turner return StructuredData::ObjectSP(); 3092c1f46dcSZachary Turner default: 310c154f397SPavel Labath return StructuredData::ObjectSP(new StructuredPythonObject( 311c154f397SPavel Labath PythonObject(PyRefType::Borrowed, m_py_obj))); 3122c1f46dcSZachary Turner } 3132c1f46dcSZachary Turner } 3142c1f46dcSZachary Turner 3152c1f46dcSZachary Turner // PythonString 3165a72c02bSZachary Turner 317d3bd5b3dSLawrence D'Anna PythonBytes::PythonBytes(llvm::ArrayRef<uint8_t> bytes) { SetBytes(bytes); } 3185a72c02bSZachary Turner 319d3bd5b3dSLawrence D'Anna PythonBytes::PythonBytes(const uint8_t *bytes, size_t length) { 3205a72c02bSZachary Turner SetBytes(llvm::ArrayRef<uint8_t>(bytes, length)); 3215a72c02bSZachary Turner } 3225a72c02bSZachary Turner 323b9c1b51eSKate Stone bool PythonBytes::Check(PyObject *py_obj) { 3245a72c02bSZachary Turner if (!py_obj) 3255a72c02bSZachary Turner return false; 326a6682a41SJonas Devlieghere return PyBytes_Check(py_obj); 3275a72c02bSZachary Turner } 3285a72c02bSZachary Turner 329b9c1b51eSKate Stone llvm::ArrayRef<uint8_t> PythonBytes::GetBytes() const { 3305a72c02bSZachary Turner if (!IsValid()) 3315a72c02bSZachary Turner return llvm::ArrayRef<uint8_t>(); 3325a72c02bSZachary Turner 3335a72c02bSZachary Turner Py_ssize_t size; 3345a72c02bSZachary Turner char *c; 3355a72c02bSZachary Turner 3365a72c02bSZachary Turner PyBytes_AsStringAndSize(m_py_obj, &c, &size); 3375a72c02bSZachary Turner return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size); 3385a72c02bSZachary Turner } 3395a72c02bSZachary Turner 340b9c1b51eSKate Stone size_t PythonBytes::GetSize() const { 3415a72c02bSZachary Turner if (!IsValid()) 3425a72c02bSZachary Turner return 0; 3435a72c02bSZachary Turner return PyBytes_Size(m_py_obj); 3445a72c02bSZachary Turner } 3455a72c02bSZachary Turner 346b9c1b51eSKate Stone void PythonBytes::SetBytes(llvm::ArrayRef<uint8_t> bytes) { 3475a72c02bSZachary Turner const char *data = reinterpret_cast<const char *>(bytes.data()); 34804edd189SLawrence D'Anna *this = Take<PythonBytes>(PyBytes_FromStringAndSize(data, bytes.size())); 3495a72c02bSZachary Turner } 3505a72c02bSZachary Turner 351b9c1b51eSKate Stone StructuredData::StringSP PythonBytes::CreateStructuredString() const { 3525a72c02bSZachary Turner StructuredData::StringSP result(new StructuredData::String); 3535a72c02bSZachary Turner Py_ssize_t size; 3545a72c02bSZachary Turner char *c; 3555a72c02bSZachary Turner PyBytes_AsStringAndSize(m_py_obj, &c, &size); 3565a72c02bSZachary Turner result->SetValue(std::string(c, size)); 3575a72c02bSZachary Turner return result; 3585a72c02bSZachary Turner } 3595a72c02bSZachary Turner 360b9c1b51eSKate Stone PythonByteArray::PythonByteArray(llvm::ArrayRef<uint8_t> bytes) 361b9c1b51eSKate Stone : PythonByteArray(bytes.data(), bytes.size()) {} 362f9d6d204SZachary Turner 363b9c1b51eSKate Stone PythonByteArray::PythonByteArray(const uint8_t *bytes, size_t length) { 364f9d6d204SZachary Turner const char *str = reinterpret_cast<const char *>(bytes); 365722b6189SLawrence D'Anna *this = Take<PythonByteArray>(PyByteArray_FromStringAndSize(str, length)); 366f9d6d204SZachary Turner } 367f9d6d204SZachary Turner 368b9c1b51eSKate Stone bool PythonByteArray::Check(PyObject *py_obj) { 369f9d6d204SZachary Turner if (!py_obj) 370f9d6d204SZachary Turner return false; 371a6682a41SJonas Devlieghere return PyByteArray_Check(py_obj); 372f9d6d204SZachary Turner } 373f9d6d204SZachary Turner 374b9c1b51eSKate Stone llvm::ArrayRef<uint8_t> PythonByteArray::GetBytes() const { 375f9d6d204SZachary Turner if (!IsValid()) 376f9d6d204SZachary Turner return llvm::ArrayRef<uint8_t>(); 377f9d6d204SZachary Turner 378f9d6d204SZachary Turner char *c = PyByteArray_AsString(m_py_obj); 379f9d6d204SZachary Turner size_t size = GetSize(); 380f9d6d204SZachary Turner return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size); 381f9d6d204SZachary Turner } 382f9d6d204SZachary Turner 383b9c1b51eSKate Stone size_t PythonByteArray::GetSize() const { 384f9d6d204SZachary Turner if (!IsValid()) 385f9d6d204SZachary Turner return 0; 386f9d6d204SZachary Turner 387f9d6d204SZachary Turner return PyByteArray_Size(m_py_obj); 388f9d6d204SZachary Turner } 389f9d6d204SZachary Turner 390b9c1b51eSKate Stone StructuredData::StringSP PythonByteArray::CreateStructuredString() const { 391f9d6d204SZachary Turner StructuredData::StringSP result(new StructuredData::String); 392f9d6d204SZachary Turner llvm::ArrayRef<uint8_t> bytes = GetBytes(); 393f9d6d204SZachary Turner const char *str = reinterpret_cast<const char *>(bytes.data()); 394f9d6d204SZachary Turner result->SetValue(std::string(str, bytes.size())); 395f9d6d204SZachary Turner return result; 396f9d6d204SZachary Turner } 397f9d6d204SZachary Turner 3985a72c02bSZachary Turner // PythonString 3992c1f46dcSZachary Turner 400085328eeSLawrence D'Anna Expected<PythonString> PythonString::FromUTF8(llvm::StringRef string) { 401085328eeSLawrence D'Anna #if PY_MAJOR_VERSION >= 3 402085328eeSLawrence D'Anna PyObject *str = PyUnicode_FromStringAndSize(string.data(), string.size()); 403085328eeSLawrence D'Anna #else 404085328eeSLawrence D'Anna PyObject *str = PyString_FromStringAndSize(string.data(), string.size()); 405085328eeSLawrence D'Anna #endif 406085328eeSLawrence D'Anna if (!str) 407085328eeSLawrence D'Anna return llvm::make_error<PythonException>(); 408085328eeSLawrence D'Anna return Take<PythonString>(str); 409085328eeSLawrence D'Anna } 410085328eeSLawrence D'Anna 411d3bd5b3dSLawrence D'Anna PythonString::PythonString(llvm::StringRef string) { SetString(string); } 4122c1f46dcSZachary Turner 413b9c1b51eSKate Stone bool PythonString::Check(PyObject *py_obj) { 41422c8efcdSZachary Turner if (!py_obj) 41522c8efcdSZachary Turner return false; 41618426935SZachary Turner 4177d6d218eSZachary Turner if (PyUnicode_Check(py_obj)) 4187d6d218eSZachary Turner return true; 4197d6d218eSZachary Turner #if PY_MAJOR_VERSION < 3 4207d6d218eSZachary Turner if (PyString_Check(py_obj)) 4217d6d218eSZachary Turner return true; 42222c8efcdSZachary Turner #endif 4237d6d218eSZachary Turner return false; 42422c8efcdSZachary Turner } 42522c8efcdSZachary Turner 426d3bd5b3dSLawrence D'Anna void PythonString::Convert(PyRefType &type, PyObject *&py_obj) { 4277d6d218eSZachary Turner #if PY_MAJOR_VERSION < 3 4287d6d218eSZachary Turner // In Python 2, Don't store PyUnicode objects directly, because we need 4297d6d218eSZachary Turner // access to their underlying character buffers which Python 2 doesn't 4307d6d218eSZachary Turner // provide. 431085328eeSLawrence D'Anna if (PyUnicode_Check(py_obj)) { 432d3bd5b3dSLawrence D'Anna PyObject *s = PyUnicode_AsUTF8String(py_obj); 433d3bd5b3dSLawrence D'Anna if (s == nullptr) { 434085328eeSLawrence D'Anna PyErr_Clear(); 435d3bd5b3dSLawrence D'Anna if (type == PyRefType::Owned) 436d3bd5b3dSLawrence D'Anna Py_DECREF(py_obj); 437d3bd5b3dSLawrence D'Anna return; 438d3bd5b3dSLawrence D'Anna } 439d3bd5b3dSLawrence D'Anna if (type == PyRefType::Owned) 440d3bd5b3dSLawrence D'Anna Py_DECREF(py_obj); 441d3bd5b3dSLawrence D'Anna else 442d3bd5b3dSLawrence D'Anna type = PyRefType::Owned; 443d3bd5b3dSLawrence D'Anna py_obj = s; 444085328eeSLawrence D'Anna } 4457d6d218eSZachary Turner #endif 4462c1f46dcSZachary Turner } 4472c1f46dcSZachary Turner 448b9c1b51eSKate Stone llvm::StringRef PythonString::GetString() const { 449085328eeSLawrence D'Anna auto s = AsUTF8(); 450085328eeSLawrence D'Anna if (!s) { 451085328eeSLawrence D'Anna llvm::consumeError(s.takeError()); 452085328eeSLawrence D'Anna return llvm::StringRef(""); 453085328eeSLawrence D'Anna } 454085328eeSLawrence D'Anna return s.get(); 455085328eeSLawrence D'Anna } 456085328eeSLawrence D'Anna 457085328eeSLawrence D'Anna Expected<llvm::StringRef> PythonString::AsUTF8() const { 45818426935SZachary Turner if (!IsValid()) 459085328eeSLawrence D'Anna return nullDeref(); 46018426935SZachary Turner 46122c8efcdSZachary Turner Py_ssize_t size; 4625457b426SPavel Labath const char *data; 46318426935SZachary Turner 46418426935SZachary Turner #if PY_MAJOR_VERSION >= 3 4655457b426SPavel Labath data = PyUnicode_AsUTF8AndSize(m_py_obj, &size); 46618426935SZachary Turner #else 467085328eeSLawrence D'Anna char *c = NULL; 468085328eeSLawrence D'Anna int r = PyString_AsStringAndSize(m_py_obj, &c, &size); 469085328eeSLawrence D'Anna if (r < 0) 470085328eeSLawrence D'Anna c = NULL; 4715457b426SPavel Labath data = c; 47218426935SZachary Turner #endif 473085328eeSLawrence D'Anna 474085328eeSLawrence D'Anna if (!data) 475085328eeSLawrence D'Anna return exception(); 476085328eeSLawrence D'Anna 4775457b426SPavel Labath return llvm::StringRef(data, size); 47822c8efcdSZachary Turner } 4792c1f46dcSZachary Turner 480b9c1b51eSKate Stone size_t PythonString::GetSize() const { 481b9c1b51eSKate Stone if (IsValid()) { 48218426935SZachary Turner #if PY_MAJOR_VERSION >= 3 48375012a80STatyana Krasnukha #if PY_MINOR_VERSION >= 3 48475012a80STatyana Krasnukha return PyUnicode_GetLength(m_py_obj); 48575012a80STatyana Krasnukha #else 48618426935SZachary Turner return PyUnicode_GetSize(m_py_obj); 48775012a80STatyana Krasnukha #endif 48818426935SZachary Turner #else 48918426935SZachary Turner return PyString_Size(m_py_obj); 49018426935SZachary Turner #endif 49118426935SZachary Turner } 4922c1f46dcSZachary Turner return 0; 4932c1f46dcSZachary Turner } 4942c1f46dcSZachary Turner 495b9c1b51eSKate Stone void PythonString::SetString(llvm::StringRef string) { 496085328eeSLawrence D'Anna auto s = FromUTF8(string); 497085328eeSLawrence D'Anna if (!s) { 498085328eeSLawrence D'Anna llvm::consumeError(s.takeError()); 499085328eeSLawrence D'Anna Reset(); 500085328eeSLawrence D'Anna } else { 50103819d1cSLawrence D'Anna *this = std::move(s.get()); 502085328eeSLawrence D'Anna } 5032c1f46dcSZachary Turner } 5042c1f46dcSZachary Turner 505b9c1b51eSKate Stone StructuredData::StringSP PythonString::CreateStructuredString() const { 5062c1f46dcSZachary Turner StructuredData::StringSP result(new StructuredData::String); 5072c1f46dcSZachary Turner result->SetValue(GetString()); 5082c1f46dcSZachary Turner return result; 5092c1f46dcSZachary Turner } 5102c1f46dcSZachary Turner 5112c1f46dcSZachary Turner // PythonInteger 5122c1f46dcSZachary Turner 513d3bd5b3dSLawrence D'Anna PythonInteger::PythonInteger(int64_t value) { SetInteger(value); } 5142c1f46dcSZachary Turner 515b9c1b51eSKate Stone bool PythonInteger::Check(PyObject *py_obj) { 51622c8efcdSZachary Turner if (!py_obj) 51722c8efcdSZachary Turner return false; 51822c8efcdSZachary Turner 51922c8efcdSZachary Turner #if PY_MAJOR_VERSION >= 3 52005097246SAdrian Prantl // Python 3 does not have PyInt_Check. There is only one type of integral 52105097246SAdrian Prantl // value, long. 52222c8efcdSZachary Turner return PyLong_Check(py_obj); 52322c8efcdSZachary Turner #else 52422c8efcdSZachary Turner return PyLong_Check(py_obj) || PyInt_Check(py_obj); 52522c8efcdSZachary Turner #endif 5262c1f46dcSZachary Turner } 5272c1f46dcSZachary Turner 528d3bd5b3dSLawrence D'Anna void PythonInteger::Convert(PyRefType &type, PyObject *&py_obj) { 52922c8efcdSZachary Turner #if PY_MAJOR_VERSION < 3 53005097246SAdrian Prantl // Always store this as a PyLong, which makes interoperability between Python 53105097246SAdrian Prantl // 2.x and Python 3.x easier. This is only necessary in 2.x, since 3.x 53205097246SAdrian Prantl // doesn't even have a PyInt. 533b9c1b51eSKate Stone if (PyInt_Check(py_obj)) { 534f8b22f8fSZachary Turner // Since we converted the original object to a different type, the new 53505097246SAdrian Prantl // object is an owned object regardless of the ownership semantics 53605097246SAdrian Prantl // requested by the user. 537d3bd5b3dSLawrence D'Anna long long value = PyInt_AsLong(py_obj); 538d3bd5b3dSLawrence D'Anna PyObject *l = nullptr; 539d3bd5b3dSLawrence D'Anna if (!PyErr_Occurred()) 540d3bd5b3dSLawrence D'Anna l = PyLong_FromLongLong(value); 541d3bd5b3dSLawrence D'Anna if (l == nullptr) { 542d3bd5b3dSLawrence D'Anna PyErr_Clear(); 543d3bd5b3dSLawrence D'Anna if (type == PyRefType::Owned) 544d3bd5b3dSLawrence D'Anna Py_DECREF(py_obj); 545d3bd5b3dSLawrence D'Anna return; 546d3bd5b3dSLawrence D'Anna } 547d3bd5b3dSLawrence D'Anna if (type == PyRefType::Owned) 548d3bd5b3dSLawrence D'Anna Py_DECREF(py_obj); 549d3bd5b3dSLawrence D'Anna else 550d3bd5b3dSLawrence D'Anna type = PyRefType::Owned; 551d3bd5b3dSLawrence D'Anna py_obj = l; 55222c8efcdSZachary Turner } 55322c8efcdSZachary Turner #endif 5542c1f46dcSZachary Turner } 5552c1f46dcSZachary Turner 556b9c1b51eSKate Stone void PythonInteger::SetInteger(int64_t value) { 55704edd189SLawrence D'Anna *this = Take<PythonInteger>(PyLong_FromLongLong(value)); 5582c1f46dcSZachary Turner } 5592c1f46dcSZachary Turner 560b9c1b51eSKate Stone StructuredData::IntegerSP PythonInteger::CreateStructuredInteger() const { 5612c1f46dcSZachary Turner StructuredData::IntegerSP result(new StructuredData::Integer); 56252712d3fSLawrence D'Anna // FIXME this is really not ideal. Errors are silently converted to 0 56352712d3fSLawrence D'Anna // and overflows are silently wrapped. But we'd need larger changes 56452712d3fSLawrence D'Anna // to StructuredData to fix it, so that's how it is for now. 56552712d3fSLawrence D'Anna llvm::Expected<unsigned long long> value = AsModuloUnsignedLongLong(); 56652712d3fSLawrence D'Anna if (!value) { 56752712d3fSLawrence D'Anna llvm::consumeError(value.takeError()); 56852712d3fSLawrence D'Anna result->SetValue(0); 56952712d3fSLawrence D'Anna } else { 57052712d3fSLawrence D'Anna result->SetValue(value.get()); 57152712d3fSLawrence D'Anna } 5722c1f46dcSZachary Turner return result; 5732c1f46dcSZachary Turner } 5742c1f46dcSZachary Turner 575b81d715cSTatyana Krasnukha // PythonBoolean 576b81d715cSTatyana Krasnukha 577b81d715cSTatyana Krasnukha PythonBoolean::PythonBoolean(bool value) { 578b81d715cSTatyana Krasnukha SetValue(value); 579b81d715cSTatyana Krasnukha } 580b81d715cSTatyana Krasnukha 581b81d715cSTatyana Krasnukha bool PythonBoolean::Check(PyObject *py_obj) { 582b81d715cSTatyana Krasnukha return py_obj ? PyBool_Check(py_obj) : false; 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) { 59004edd189SLawrence D'Anna *this = Take<PythonBoolean>(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 601d3bd5b3dSLawrence D'Anna PythonList::PythonList(PyInitialValue value) { 602f8b22f8fSZachary Turner if (value == PyInitialValue::Empty) 603722b6189SLawrence D'Anna *this = Take<PythonList>(PyList_New(0)); 6042c1f46dcSZachary Turner } 6052c1f46dcSZachary Turner 606d3bd5b3dSLawrence D'Anna PythonList::PythonList(int list_size) { 607722b6189SLawrence D'Anna *this = Take<PythonList>(PyList_New(list_size)); 60887f47729SZachary Turner } 60987f47729SZachary Turner 610b9c1b51eSKate Stone bool PythonList::Check(PyObject *py_obj) { 61122c8efcdSZachary Turner if (!py_obj) 61222c8efcdSZachary Turner return false; 61322c8efcdSZachary Turner return PyList_Check(py_obj); 61422c8efcdSZachary Turner } 61522c8efcdSZachary Turner 616b9c1b51eSKate Stone uint32_t PythonList::GetSize() const { 617f8b22f8fSZachary Turner if (IsValid()) 6182c1f46dcSZachary Turner return PyList_GET_SIZE(m_py_obj); 6192c1f46dcSZachary Turner return 0; 6202c1f46dcSZachary Turner } 6212c1f46dcSZachary Turner 622b9c1b51eSKate Stone PythonObject PythonList::GetItemAtIndex(uint32_t index) const { 623f8b22f8fSZachary Turner if (IsValid()) 624f8b22f8fSZachary Turner return PythonObject(PyRefType::Borrowed, PyList_GetItem(m_py_obj, index)); 6252c1f46dcSZachary Turner return PythonObject(); 6262c1f46dcSZachary Turner } 6272c1f46dcSZachary Turner 628b9c1b51eSKate Stone void PythonList::SetItemAtIndex(uint32_t index, const PythonObject &object) { 629b9c1b51eSKate Stone if (IsAllocated() && object.IsValid()) { 630f8b22f8fSZachary Turner // PyList_SetItem is documented to "steal" a reference, so we need to 631f8b22f8fSZachary Turner // convert it to an owned reference by incrementing it. 632f8b22f8fSZachary Turner Py_INCREF(object.get()); 6332c1f46dcSZachary Turner PyList_SetItem(m_py_obj, index, object.get()); 6342c1f46dcSZachary Turner } 635f8b22f8fSZachary Turner } 6362c1f46dcSZachary Turner 637b9c1b51eSKate Stone void PythonList::AppendItem(const PythonObject &object) { 638b9c1b51eSKate Stone if (IsAllocated() && object.IsValid()) { 639f8b22f8fSZachary Turner // `PyList_Append` does *not* steal a reference, so do not call `Py_INCREF` 640f8b22f8fSZachary Turner // here like we do with `PyList_SetItem`. 6412c1f46dcSZachary Turner PyList_Append(m_py_obj, object.get()); 6422c1f46dcSZachary Turner } 643f8b22f8fSZachary Turner } 6442c1f46dcSZachary Turner 645b9c1b51eSKate Stone StructuredData::ArraySP PythonList::CreateStructuredArray() const { 6462c1f46dcSZachary Turner StructuredData::ArraySP result(new StructuredData::Array); 6472c1f46dcSZachary Turner uint32_t count = GetSize(); 648b9c1b51eSKate Stone for (uint32_t i = 0; i < count; ++i) { 6492c1f46dcSZachary Turner PythonObject obj = GetItemAtIndex(i); 6502c1f46dcSZachary Turner result->AddItem(obj.CreateStructuredObject()); 6512c1f46dcSZachary Turner } 6522c1f46dcSZachary Turner return result; 6532c1f46dcSZachary Turner } 6542c1f46dcSZachary Turner 655a1405147SZachary Turner // PythonTuple 656a1405147SZachary Turner 657d3bd5b3dSLawrence D'Anna PythonTuple::PythonTuple(PyInitialValue value) { 658a1405147SZachary Turner if (value == PyInitialValue::Empty) 659722b6189SLawrence D'Anna *this = Take<PythonTuple>(PyTuple_New(0)); 660a1405147SZachary Turner } 661a1405147SZachary Turner 662d3bd5b3dSLawrence D'Anna PythonTuple::PythonTuple(int tuple_size) { 663722b6189SLawrence D'Anna *this = Take<PythonTuple>(PyTuple_New(tuple_size)); 664a1405147SZachary Turner } 665a1405147SZachary Turner 666b9c1b51eSKate Stone PythonTuple::PythonTuple(std::initializer_list<PythonObject> objects) { 667a1405147SZachary Turner m_py_obj = PyTuple_New(objects.size()); 668a1405147SZachary Turner 669a1405147SZachary Turner uint32_t idx = 0; 670b9c1b51eSKate Stone for (auto object : objects) { 671a1405147SZachary Turner if (object.IsValid()) 672a1405147SZachary Turner SetItemAtIndex(idx, object); 673a1405147SZachary Turner idx++; 674a1405147SZachary Turner } 675a1405147SZachary Turner } 676a1405147SZachary Turner 677b9c1b51eSKate Stone PythonTuple::PythonTuple(std::initializer_list<PyObject *> objects) { 678a1405147SZachary Turner m_py_obj = PyTuple_New(objects.size()); 679a1405147SZachary Turner 680a1405147SZachary Turner uint32_t idx = 0; 681b9c1b51eSKate Stone for (auto py_object : objects) { 682a1405147SZachary Turner PythonObject object(PyRefType::Borrowed, py_object); 683a1405147SZachary Turner if (object.IsValid()) 684a1405147SZachary Turner SetItemAtIndex(idx, object); 685a1405147SZachary Turner idx++; 686a1405147SZachary Turner } 687a1405147SZachary Turner } 688a1405147SZachary Turner 689b9c1b51eSKate Stone bool PythonTuple::Check(PyObject *py_obj) { 690a1405147SZachary Turner if (!py_obj) 691a1405147SZachary Turner return false; 692a1405147SZachary Turner return PyTuple_Check(py_obj); 693a1405147SZachary Turner } 694a1405147SZachary Turner 695b9c1b51eSKate Stone uint32_t PythonTuple::GetSize() const { 696a1405147SZachary Turner if (IsValid()) 697a1405147SZachary Turner return PyTuple_GET_SIZE(m_py_obj); 698a1405147SZachary Turner return 0; 699a1405147SZachary Turner } 700a1405147SZachary Turner 701b9c1b51eSKate Stone PythonObject PythonTuple::GetItemAtIndex(uint32_t index) const { 702a1405147SZachary Turner if (IsValid()) 703a1405147SZachary Turner return PythonObject(PyRefType::Borrowed, PyTuple_GetItem(m_py_obj, index)); 704a1405147SZachary Turner return PythonObject(); 705a1405147SZachary Turner } 706a1405147SZachary Turner 707b9c1b51eSKate Stone void PythonTuple::SetItemAtIndex(uint32_t index, const PythonObject &object) { 708b9c1b51eSKate Stone if (IsAllocated() && object.IsValid()) { 709a1405147SZachary Turner // PyTuple_SetItem is documented to "steal" a reference, so we need to 710a1405147SZachary Turner // convert it to an owned reference by incrementing it. 711a1405147SZachary Turner Py_INCREF(object.get()); 712a1405147SZachary Turner PyTuple_SetItem(m_py_obj, index, object.get()); 713a1405147SZachary Turner } 714a1405147SZachary Turner } 715a1405147SZachary Turner 716b9c1b51eSKate Stone StructuredData::ArraySP PythonTuple::CreateStructuredArray() const { 717a1405147SZachary Turner StructuredData::ArraySP result(new StructuredData::Array); 718a1405147SZachary Turner uint32_t count = GetSize(); 719b9c1b51eSKate Stone for (uint32_t i = 0; i < count; ++i) { 720a1405147SZachary Turner PythonObject obj = GetItemAtIndex(i); 721a1405147SZachary Turner result->AddItem(obj.CreateStructuredObject()); 722a1405147SZachary Turner } 723a1405147SZachary Turner return result; 724a1405147SZachary Turner } 725a1405147SZachary Turner 7262c1f46dcSZachary Turner // PythonDictionary 7272c1f46dcSZachary Turner 728d3bd5b3dSLawrence D'Anna PythonDictionary::PythonDictionary(PyInitialValue value) { 729f8b22f8fSZachary Turner if (value == PyInitialValue::Empty) 730722b6189SLawrence D'Anna *this = Take<PythonDictionary>(PyDict_New()); 7312c1f46dcSZachary Turner } 7322c1f46dcSZachary Turner 733b9c1b51eSKate Stone bool PythonDictionary::Check(PyObject *py_obj) { 73422c8efcdSZachary Turner if (!py_obj) 73522c8efcdSZachary Turner return false; 73622c8efcdSZachary Turner 73722c8efcdSZachary Turner return PyDict_Check(py_obj); 73822c8efcdSZachary Turner } 73922c8efcdSZachary Turner 740b9c1b51eSKate Stone uint32_t PythonDictionary::GetSize() const { 741f8b22f8fSZachary Turner if (IsValid()) 7422c1f46dcSZachary Turner return PyDict_Size(m_py_obj); 7432c1f46dcSZachary Turner return 0; 7442c1f46dcSZachary Turner } 7452c1f46dcSZachary Turner 746b9c1b51eSKate Stone PythonList PythonDictionary::GetKeys() const { 747f8b22f8fSZachary Turner if (IsValid()) 748f8b22f8fSZachary Turner return PythonList(PyRefType::Owned, PyDict_Keys(m_py_obj)); 749f8b22f8fSZachary Turner return PythonList(PyInitialValue::Invalid); 7502c1f46dcSZachary Turner } 7512c1f46dcSZachary Turner 752b9c1b51eSKate Stone PythonObject PythonDictionary::GetItemForKey(const PythonObject &key) const { 753c86a6acaSLawrence D'Anna auto item = GetItem(key); 754c86a6acaSLawrence D'Anna if (!item) { 755c86a6acaSLawrence D'Anna llvm::consumeError(item.takeError()); 7562c1f46dcSZachary Turner return PythonObject(); 7572c1f46dcSZachary Turner } 758c86a6acaSLawrence D'Anna return std::move(item.get()); 759c86a6acaSLawrence D'Anna } 760c86a6acaSLawrence D'Anna 761c86a6acaSLawrence D'Anna Expected<PythonObject> 762c86a6acaSLawrence D'Anna PythonDictionary::GetItem(const PythonObject &key) const { 763c86a6acaSLawrence D'Anna if (!IsValid()) 764c86a6acaSLawrence D'Anna return nullDeref(); 765c86a6acaSLawrence D'Anna #if PY_MAJOR_VERSION >= 3 766c86a6acaSLawrence D'Anna PyObject *o = PyDict_GetItemWithError(m_py_obj, key.get()); 767c86a6acaSLawrence D'Anna if (PyErr_Occurred()) 768c86a6acaSLawrence D'Anna return exception(); 769c86a6acaSLawrence D'Anna #else 770c86a6acaSLawrence D'Anna PyObject *o = PyDict_GetItem(m_py_obj, key.get()); 771c86a6acaSLawrence D'Anna #endif 772c86a6acaSLawrence D'Anna if (!o) 773c86a6acaSLawrence D'Anna return keyError(); 774c86a6acaSLawrence D'Anna return Retain<PythonObject>(o); 775c86a6acaSLawrence D'Anna } 776c86a6acaSLawrence D'Anna 777722b6189SLawrence D'Anna Expected<PythonObject> PythonDictionary::GetItem(const Twine &key) const { 778c86a6acaSLawrence D'Anna if (!IsValid()) 779c86a6acaSLawrence D'Anna return nullDeref(); 780722b6189SLawrence D'Anna PyObject *o = PyDict_GetItemString(m_py_obj, NullTerminated(key)); 781c86a6acaSLawrence D'Anna if (PyErr_Occurred()) 782c86a6acaSLawrence D'Anna return exception(); 783c86a6acaSLawrence D'Anna if (!o) 784c86a6acaSLawrence D'Anna return keyError(); 785c86a6acaSLawrence D'Anna return Retain<PythonObject>(o); 786c86a6acaSLawrence D'Anna } 787c86a6acaSLawrence D'Anna 788c86a6acaSLawrence D'Anna Error PythonDictionary::SetItem(const PythonObject &key, 789c86a6acaSLawrence D'Anna const PythonObject &value) const { 790c86a6acaSLawrence D'Anna if (!IsValid() || !value.IsValid()) 791c86a6acaSLawrence D'Anna return nullDeref(); 792c86a6acaSLawrence D'Anna int r = PyDict_SetItem(m_py_obj, key.get(), value.get()); 793c86a6acaSLawrence D'Anna if (r < 0) 794c86a6acaSLawrence D'Anna return exception(); 795c86a6acaSLawrence D'Anna return Error::success(); 796c86a6acaSLawrence D'Anna } 797c86a6acaSLawrence D'Anna 798722b6189SLawrence D'Anna Error PythonDictionary::SetItem(const Twine &key, 799c86a6acaSLawrence D'Anna const PythonObject &value) const { 800c86a6acaSLawrence D'Anna if (!IsValid() || !value.IsValid()) 801c86a6acaSLawrence D'Anna return nullDeref(); 802722b6189SLawrence D'Anna int r = PyDict_SetItemString(m_py_obj, NullTerminated(key), value.get()); 803c86a6acaSLawrence D'Anna if (r < 0) 804c86a6acaSLawrence D'Anna return exception(); 805c86a6acaSLawrence D'Anna return Error::success(); 806c86a6acaSLawrence D'Anna } 8072c1f46dcSZachary Turner 808b9c1b51eSKate Stone void PythonDictionary::SetItemForKey(const PythonObject &key, 809b9c1b51eSKate Stone const PythonObject &value) { 810c86a6acaSLawrence D'Anna Error error = SetItem(key, value); 811c86a6acaSLawrence D'Anna if (error) 812c86a6acaSLawrence D'Anna llvm::consumeError(std::move(error)); 8132c1f46dcSZachary Turner } 8142c1f46dcSZachary Turner 8152c1f46dcSZachary Turner StructuredData::DictionarySP 816b9c1b51eSKate Stone PythonDictionary::CreateStructuredDictionary() const { 8172c1f46dcSZachary Turner StructuredData::DictionarySP result(new StructuredData::Dictionary); 8182c1f46dcSZachary Turner PythonList keys(GetKeys()); 8192c1f46dcSZachary Turner uint32_t num_keys = keys.GetSize(); 820b9c1b51eSKate Stone for (uint32_t i = 0; i < num_keys; ++i) { 8212c1f46dcSZachary Turner PythonObject key = keys.GetItemAtIndex(i); 8222c1f46dcSZachary Turner PythonObject value = GetItemForKey(key); 8232c1f46dcSZachary Turner StructuredData::ObjectSP structured_value = value.CreateStructuredObject(); 824f8b22f8fSZachary Turner result->AddItem(key.Str().GetString(), structured_value); 8252c1f46dcSZachary Turner } 8262c1f46dcSZachary Turner return result; 8272c1f46dcSZachary Turner } 8282c1f46dcSZachary Turner 829b9c1b51eSKate Stone PythonModule PythonModule::BuiltinsModule() { 830a1405147SZachary Turner #if PY_MAJOR_VERSION >= 3 831a1405147SZachary Turner return AddModule("builtins"); 832a1405147SZachary Turner #else 833a1405147SZachary Turner return AddModule("__builtin__"); 834a1405147SZachary Turner #endif 835a1405147SZachary Turner } 836a1405147SZachary Turner 837b9c1b51eSKate Stone PythonModule PythonModule::MainModule() { return AddModule("__main__"); } 838a1405147SZachary Turner 839b9c1b51eSKate Stone PythonModule PythonModule::AddModule(llvm::StringRef module) { 840a1405147SZachary Turner std::string str = module.str(); 841a1405147SZachary Turner return PythonModule(PyRefType::Borrowed, PyImport_AddModule(str.c_str())); 8427841efbbSZachary Turner } 8437841efbbSZachary Turner 844722b6189SLawrence D'Anna Expected<PythonModule> PythonModule::Import(const Twine &name) { 845722b6189SLawrence D'Anna PyObject *mod = PyImport_ImportModule(NullTerminated(name)); 846085328eeSLawrence D'Anna if (!mod) 847085328eeSLawrence D'Anna return exception(); 848085328eeSLawrence D'Anna return Take<PythonModule>(mod); 849085328eeSLawrence D'Anna } 850085328eeSLawrence D'Anna 851722b6189SLawrence D'Anna Expected<PythonObject> PythonModule::Get(const Twine &name) { 852085328eeSLawrence D'Anna if (!IsValid()) 853085328eeSLawrence D'Anna return nullDeref(); 854085328eeSLawrence D'Anna PyObject *dict = PyModule_GetDict(m_py_obj); 855085328eeSLawrence D'Anna if (!dict) 856085328eeSLawrence D'Anna return exception(); 857722b6189SLawrence D'Anna PyObject *item = PyDict_GetItemString(dict, NullTerminated(name)); 858085328eeSLawrence D'Anna if (!item) 859085328eeSLawrence D'Anna return exception(); 860085328eeSLawrence D'Anna return Retain<PythonObject>(item); 8612419f1d5SZachary Turner } 8622419f1d5SZachary Turner 863b9c1b51eSKate Stone bool PythonModule::Check(PyObject *py_obj) { 8647841efbbSZachary Turner if (!py_obj) 8657841efbbSZachary Turner return false; 8667841efbbSZachary Turner 8677841efbbSZachary Turner return PyModule_Check(py_obj); 8687841efbbSZachary Turner } 8697841efbbSZachary Turner 870b9c1b51eSKate Stone PythonDictionary PythonModule::GetDictionary() const { 871722b6189SLawrence D'Anna if (!IsValid()) 872722b6189SLawrence D'Anna return PythonDictionary(); 873722b6189SLawrence D'Anna return Retain<PythonDictionary>(PyModule_GetDict(m_py_obj)); 8747841efbbSZachary Turner } 8757841efbbSZachary Turner 876b9c1b51eSKate Stone bool PythonCallable::Check(PyObject *py_obj) { 877a1405147SZachary Turner if (!py_obj) 878a1405147SZachary Turner return false; 879a1405147SZachary Turner 880a1405147SZachary Turner return PyCallable_Check(py_obj); 881a1405147SZachary Turner } 882a1405147SZachary Turner 883c86a6acaSLawrence D'Anna #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3 884c86a6acaSLawrence D'Anna static const char get_arg_info_script[] = R"( 885c86a6acaSLawrence D'Anna from inspect import signature, Parameter, ismethod 886c86a6acaSLawrence D'Anna from collections import namedtuple 887adbf64ccSLawrence D'Anna ArgInfo = namedtuple('ArgInfo', ['count', 'has_varargs']) 88804edd189SLawrence D'Anna def main(f): 889c86a6acaSLawrence D'Anna count = 0 890c86a6acaSLawrence D'Anna varargs = False 891c86a6acaSLawrence D'Anna for parameter in signature(f).parameters.values(): 892c86a6acaSLawrence D'Anna kind = parameter.kind 893c86a6acaSLawrence D'Anna if kind in (Parameter.POSITIONAL_ONLY, 894c86a6acaSLawrence D'Anna Parameter.POSITIONAL_OR_KEYWORD): 895c86a6acaSLawrence D'Anna count += 1 896c86a6acaSLawrence D'Anna elif kind == Parameter.VAR_POSITIONAL: 897c86a6acaSLawrence D'Anna varargs = True 898c86a6acaSLawrence D'Anna elif kind in (Parameter.KEYWORD_ONLY, 899c86a6acaSLawrence D'Anna Parameter.VAR_KEYWORD): 900c86a6acaSLawrence D'Anna pass 901c86a6acaSLawrence D'Anna else: 902c86a6acaSLawrence D'Anna raise Exception(f'unknown parameter kind: {kind}') 903adbf64ccSLawrence D'Anna return ArgInfo(count, varargs) 904c86a6acaSLawrence D'Anna )"; 905c86a6acaSLawrence D'Anna #endif 906c86a6acaSLawrence D'Anna 907c86a6acaSLawrence D'Anna Expected<PythonCallable::ArgInfo> PythonCallable::GetArgInfo() const { 908c86a6acaSLawrence D'Anna ArgInfo result = {}; 909c86a6acaSLawrence D'Anna if (!IsValid()) 910c86a6acaSLawrence D'Anna return nullDeref(); 911c86a6acaSLawrence D'Anna 912c86a6acaSLawrence D'Anna #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3 913c86a6acaSLawrence D'Anna 91404edd189SLawrence D'Anna // no need to synchronize access to this global, we already have the GIL 91504edd189SLawrence D'Anna static PythonScript get_arg_info(get_arg_info_script); 91604edd189SLawrence D'Anna Expected<PythonObject> pyarginfo = get_arg_info(*this); 917c86a6acaSLawrence D'Anna if (!pyarginfo) 918c86a6acaSLawrence D'Anna return pyarginfo.takeError(); 919adbf64ccSLawrence D'Anna long long count = 920adbf64ccSLawrence D'Anna cantFail(As<long long>(pyarginfo.get().GetAttribute("count"))); 921adbf64ccSLawrence D'Anna bool has_varargs = 922c86a6acaSLawrence D'Anna cantFail(As<bool>(pyarginfo.get().GetAttribute("has_varargs"))); 923adbf64ccSLawrence D'Anna result.max_positional_args = has_varargs ? ArgInfo::UNBOUNDED : count; 924c86a6acaSLawrence D'Anna 925c86a6acaSLawrence D'Anna #else 926adbf64ccSLawrence D'Anna PyObject *py_func_obj; 9272386537cSLawrence D'Anna bool is_bound_method = false; 928adbf64ccSLawrence D'Anna bool is_class = false; 929adbf64ccSLawrence D'Anna 930adbf64ccSLawrence D'Anna if (PyType_Check(m_py_obj) || PyClass_Check(m_py_obj)) { 931adbf64ccSLawrence D'Anna auto init = GetAttribute("__init__"); 932adbf64ccSLawrence D'Anna if (!init) 933adbf64ccSLawrence D'Anna return init.takeError(); 934adbf64ccSLawrence D'Anna py_func_obj = init.get().get(); 935adbf64ccSLawrence D'Anna is_class = true; 936adbf64ccSLawrence D'Anna } else { 937adbf64ccSLawrence D'Anna py_func_obj = m_py_obj; 938adbf64ccSLawrence D'Anna } 939adbf64ccSLawrence D'Anna 940b9c1b51eSKate Stone if (PyMethod_Check(py_func_obj)) { 941a1405147SZachary Turner py_func_obj = PyMethod_GET_FUNCTION(py_func_obj); 942a5d6765cSEnrico Granata PythonObject im_self = GetAttributeValue("im_self"); 943a5d6765cSEnrico Granata if (im_self.IsValid() && !im_self.IsNone()) 9442386537cSLawrence D'Anna is_bound_method = true; 945b9c1b51eSKate Stone } else { 946a5d6765cSEnrico Granata // see if this is a callable object with an __call__ method 947b9c1b51eSKate Stone if (!PyFunction_Check(py_func_obj)) { 948a5d6765cSEnrico Granata PythonObject __call__ = GetAttributeValue("__call__"); 949b9c1b51eSKate Stone if (__call__.IsValid()) { 950a5d6765cSEnrico Granata auto __callable__ = __call__.AsType<PythonCallable>(); 951b9c1b51eSKate Stone if (__callable__.IsValid()) { 952a5d6765cSEnrico Granata py_func_obj = PyMethod_GET_FUNCTION(__callable__.get()); 9532386537cSLawrence D'Anna PythonObject im_self = __callable__.GetAttributeValue("im_self"); 954a5d6765cSEnrico Granata if (im_self.IsValid() && !im_self.IsNone()) 9552386537cSLawrence D'Anna is_bound_method = true; 956a5d6765cSEnrico Granata } 957a5d6765cSEnrico Granata } 958a5d6765cSEnrico Granata } 959a5d6765cSEnrico Granata } 960a1405147SZachary Turner 961a1405147SZachary Turner if (!py_func_obj) 962b58fb2f4SZachary Turner return result; 963a1405147SZachary Turner 964a1405147SZachary Turner PyCodeObject *code = (PyCodeObject *)PyFunction_GET_CODE(py_func_obj); 965a1405147SZachary Turner if (!code) 966b58fb2f4SZachary Turner return result; 967a1405147SZachary Turner 968adbf64ccSLawrence D'Anna auto count = code->co_argcount; 969adbf64ccSLawrence D'Anna bool has_varargs = !!(code->co_flags & CO_VARARGS); 970adbf64ccSLawrence D'Anna result.max_positional_args = 971adbf64ccSLawrence D'Anna has_varargs ? ArgInfo::UNBOUNDED 972adbf64ccSLawrence D'Anna : (count - (int)is_bound_method) - (int)is_class; 973c86a6acaSLawrence D'Anna 974c86a6acaSLawrence D'Anna #endif 975c86a6acaSLawrence D'Anna 976b58fb2f4SZachary Turner return result; 977b58fb2f4SZachary Turner } 978b58fb2f4SZachary Turner 9792386537cSLawrence D'Anna constexpr unsigned 9802386537cSLawrence D'Anna PythonCallable::ArgInfo::UNBOUNDED; // FIXME delete after c++17 9812386537cSLawrence D'Anna 982b9c1b51eSKate Stone PythonObject PythonCallable::operator()() { 983b9c1b51eSKate Stone return PythonObject(PyRefType::Owned, PyObject_CallObject(m_py_obj, nullptr)); 984a1405147SZachary Turner } 985a1405147SZachary Turner 986b9c1b51eSKate Stone PythonObject PythonCallable:: 987b9c1b51eSKate Stone operator()(std::initializer_list<PyObject *> args) { 988a1405147SZachary Turner PythonTuple arg_tuple(args); 989a1405147SZachary Turner return PythonObject(PyRefType::Owned, 990a1405147SZachary Turner PyObject_CallObject(m_py_obj, arg_tuple.get())); 991a1405147SZachary Turner } 992a1405147SZachary Turner 993b9c1b51eSKate Stone PythonObject PythonCallable:: 994b9c1b51eSKate Stone operator()(std::initializer_list<PythonObject> args) { 995a1405147SZachary Turner PythonTuple arg_tuple(args); 996a1405147SZachary Turner return PythonObject(PyRefType::Owned, 997a1405147SZachary Turner PyObject_CallObject(m_py_obj, arg_tuple.get())); 998a1405147SZachary Turner } 999a1405147SZachary Turner 1000b9c1b51eSKate Stone bool PythonFile::Check(PyObject *py_obj) { 100196898eb6SLawrence D'Anna if (!py_obj) 100296898eb6SLawrence D'Anna return false; 10039c40264fSZachary Turner #if PY_MAJOR_VERSION < 3 100423502721SJason Molenda return PyFile_Check(py_obj); 100523502721SJason Molenda #else 10069c40264fSZachary Turner // In Python 3, there is no `PyFile_Check`, and in fact PyFile is not even a 10079c40264fSZachary Turner // first-class object type anymore. `PyFile_FromFd` is just a thin wrapper 100805097246SAdrian Prantl // over `io.open()`, which returns some object derived from `io.IOBase`. As a 100905097246SAdrian Prantl // result, the only way to detect a file in Python 3 is to check whether it 101021b8a8aeSLawrence D'Anna // inherits from `io.IOBase`. 101121b8a8aeSLawrence D'Anna auto io_module = PythonModule::Import("io"); 101221b8a8aeSLawrence D'Anna if (!io_module) { 101321b8a8aeSLawrence D'Anna llvm::consumeError(io_module.takeError()); 10149c40264fSZachary Turner return false; 101521b8a8aeSLawrence D'Anna } 101621b8a8aeSLawrence D'Anna auto iobase = io_module.get().Get("IOBase"); 101721b8a8aeSLawrence D'Anna if (!iobase) { 101821b8a8aeSLawrence D'Anna llvm::consumeError(iobase.takeError()); 10199c40264fSZachary Turner return false; 102021b8a8aeSLawrence D'Anna } 102121b8a8aeSLawrence D'Anna int r = PyObject_IsInstance(py_obj, iobase.get().get()); 102221b8a8aeSLawrence D'Anna if (r < 0) { 102321b8a8aeSLawrence D'Anna llvm::consumeError(exception()); // clear the exception and log it. 102421b8a8aeSLawrence D'Anna return false; 102521b8a8aeSLawrence D'Anna } 102621b8a8aeSLawrence D'Anna return !!r; 102723502721SJason Molenda #endif 10289c40264fSZachary Turner } 10299c40264fSZachary Turner 1030085328eeSLawrence D'Anna const char *PythonException::toCString() const { 1031085328eeSLawrence D'Anna if (!m_repr_bytes) 1032085328eeSLawrence D'Anna return "unknown exception"; 1033085328eeSLawrence D'Anna return PyBytes_AS_STRING(m_repr_bytes); 1034085328eeSLawrence D'Anna } 1035085328eeSLawrence D'Anna 1036085328eeSLawrence D'Anna PythonException::PythonException(const char *caller) { 1037085328eeSLawrence D'Anna assert(PyErr_Occurred()); 1038085328eeSLawrence D'Anna m_exception_type = m_exception = m_traceback = m_repr_bytes = NULL; 1039085328eeSLawrence D'Anna PyErr_Fetch(&m_exception_type, &m_exception, &m_traceback); 1040085328eeSLawrence D'Anna PyErr_NormalizeException(&m_exception_type, &m_exception, &m_traceback); 1041085328eeSLawrence D'Anna PyErr_Clear(); 1042085328eeSLawrence D'Anna if (m_exception) { 1043085328eeSLawrence D'Anna PyObject *repr = PyObject_Repr(m_exception); 1044085328eeSLawrence D'Anna if (repr) { 1045085328eeSLawrence D'Anna m_repr_bytes = PyUnicode_AsEncodedString(repr, "utf-8", nullptr); 1046085328eeSLawrence D'Anna if (!m_repr_bytes) { 1047085328eeSLawrence D'Anna PyErr_Clear(); 1048085328eeSLawrence D'Anna } 1049085328eeSLawrence D'Anna Py_XDECREF(repr); 1050085328eeSLawrence D'Anna } else { 1051085328eeSLawrence D'Anna PyErr_Clear(); 1052085328eeSLawrence D'Anna } 1053085328eeSLawrence D'Anna } 1054a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Script); 1055085328eeSLawrence D'Anna if (caller) 1056085328eeSLawrence D'Anna LLDB_LOGF(log, "%s failed with exception: %s", caller, toCString()); 1057085328eeSLawrence D'Anna else 1058085328eeSLawrence D'Anna LLDB_LOGF(log, "python exception: %s", toCString()); 1059085328eeSLawrence D'Anna } 1060085328eeSLawrence D'Anna void PythonException::Restore() { 1061085328eeSLawrence D'Anna if (m_exception_type && m_exception) { 1062085328eeSLawrence D'Anna PyErr_Restore(m_exception_type, m_exception, m_traceback); 1063085328eeSLawrence D'Anna } else { 1064085328eeSLawrence D'Anna PyErr_SetString(PyExc_Exception, toCString()); 1065085328eeSLawrence D'Anna } 1066085328eeSLawrence D'Anna m_exception_type = m_exception = m_traceback = NULL; 1067085328eeSLawrence D'Anna } 1068085328eeSLawrence D'Anna 1069085328eeSLawrence D'Anna PythonException::~PythonException() { 1070085328eeSLawrence D'Anna Py_XDECREF(m_exception_type); 1071085328eeSLawrence D'Anna Py_XDECREF(m_exception); 1072085328eeSLawrence D'Anna Py_XDECREF(m_traceback); 1073085328eeSLawrence D'Anna Py_XDECREF(m_repr_bytes); 1074085328eeSLawrence D'Anna } 1075085328eeSLawrence D'Anna 1076085328eeSLawrence D'Anna void PythonException::log(llvm::raw_ostream &OS) const { OS << toCString(); } 1077085328eeSLawrence D'Anna 1078085328eeSLawrence D'Anna std::error_code PythonException::convertToErrorCode() const { 1079085328eeSLawrence D'Anna return llvm::inconvertibleErrorCode(); 1080085328eeSLawrence D'Anna } 1081085328eeSLawrence D'Anna 108204edd189SLawrence D'Anna bool PythonException::Matches(PyObject *exc) const { 108304edd189SLawrence D'Anna return PyErr_GivenExceptionMatches(m_exception_type, exc); 108404edd189SLawrence D'Anna } 108504edd189SLawrence D'Anna 108604edd189SLawrence D'Anna const char read_exception_script[] = R"( 108704edd189SLawrence D'Anna import sys 108804edd189SLawrence D'Anna from traceback import print_exception 108904edd189SLawrence D'Anna if sys.version_info.major < 3: 109004edd189SLawrence D'Anna from StringIO import StringIO 109104edd189SLawrence D'Anna else: 109204edd189SLawrence D'Anna from io import StringIO 109304edd189SLawrence D'Anna def main(exc_type, exc_value, tb): 109404edd189SLawrence D'Anna f = StringIO() 109504edd189SLawrence D'Anna print_exception(exc_type, exc_value, tb, file=f) 109604edd189SLawrence D'Anna return f.getvalue() 109704edd189SLawrence D'Anna )"; 109804edd189SLawrence D'Anna 109904edd189SLawrence D'Anna std::string PythonException::ReadBacktrace() const { 110004edd189SLawrence D'Anna 110104edd189SLawrence D'Anna if (!m_traceback) 110204edd189SLawrence D'Anna return toCString(); 110304edd189SLawrence D'Anna 110404edd189SLawrence D'Anna // no need to synchronize access to this global, we already have the GIL 110504edd189SLawrence D'Anna static PythonScript read_exception(read_exception_script); 110604edd189SLawrence D'Anna 110704edd189SLawrence D'Anna Expected<std::string> backtrace = As<std::string>( 110804edd189SLawrence D'Anna read_exception(m_exception_type, m_exception, m_traceback)); 110904edd189SLawrence D'Anna 111004edd189SLawrence D'Anna if (!backtrace) { 111104edd189SLawrence D'Anna std::string message = 111204edd189SLawrence D'Anna std::string(toCString()) + "\n" + 1113e9264b74SKazuaki Ishizaki "Traceback unavailable, an error occurred while reading it:\n"; 111404edd189SLawrence D'Anna return (message + llvm::toString(backtrace.takeError())); 111504edd189SLawrence D'Anna } 111604edd189SLawrence D'Anna 111704edd189SLawrence D'Anna return std::move(backtrace.get()); 111804edd189SLawrence D'Anna } 111904edd189SLawrence D'Anna 1120085328eeSLawrence D'Anna char PythonException::ID = 0; 1121085328eeSLawrence D'Anna 112262c9fe42SLawrence D'Anna llvm::Expected<File::OpenOptions> 112362c9fe42SLawrence D'Anna GetOptionsForPyObject(const PythonObject &obj) { 112421b8a8aeSLawrence D'Anna #if PY_MAJOR_VERSION >= 3 112562c9fe42SLawrence D'Anna auto options = File::OpenOptions(0); 112621b8a8aeSLawrence D'Anna auto readable = As<bool>(obj.CallMethod("readable")); 112721b8a8aeSLawrence D'Anna if (!readable) 112821b8a8aeSLawrence D'Anna return readable.takeError(); 112921b8a8aeSLawrence D'Anna auto writable = As<bool>(obj.CallMethod("writable")); 113021b8a8aeSLawrence D'Anna if (!writable) 113121b8a8aeSLawrence D'Anna return writable.takeError(); 113214735cabSMichał Górny if (readable.get() && writable.get()) 113314735cabSMichał Górny options |= File::eOpenOptionReadWrite; 113414735cabSMichał Górny else if (writable.get()) 113514735cabSMichał Górny options |= File::eOpenOptionWriteOnly; 113614735cabSMichał Górny else if (readable.get()) 113714735cabSMichał Górny options |= File::eOpenOptionReadOnly; 113862c9fe42SLawrence D'Anna return options; 113921b8a8aeSLawrence D'Anna #else 114021b8a8aeSLawrence D'Anna PythonString py_mode = obj.GetAttributeValue("mode").AsType<PythonString>(); 114162c9fe42SLawrence D'Anna return File::GetOptionsFromMode(py_mode.GetString()); 114221b8a8aeSLawrence D'Anna #endif 114321b8a8aeSLawrence D'Anna } 114421b8a8aeSLawrence D'Anna 114521b8a8aeSLawrence D'Anna // Base class template for python files. All it knows how to do 114621b8a8aeSLawrence D'Anna // is hold a reference to the python object and close or flush it 114721b8a8aeSLawrence D'Anna // when the File is closed. 114821b8a8aeSLawrence D'Anna namespace { 114921b8a8aeSLawrence D'Anna template <typename Base> class OwnedPythonFile : public Base { 115021b8a8aeSLawrence D'Anna public: 115121b8a8aeSLawrence D'Anna template <typename... Args> 115221b8a8aeSLawrence D'Anna OwnedPythonFile(const PythonFile &file, bool borrowed, Args... args) 115321b8a8aeSLawrence D'Anna : Base(args...), m_py_obj(file), m_borrowed(borrowed) { 115421b8a8aeSLawrence D'Anna assert(m_py_obj); 115521b8a8aeSLawrence D'Anna } 115621b8a8aeSLawrence D'Anna 115721b8a8aeSLawrence D'Anna ~OwnedPythonFile() override { 115821b8a8aeSLawrence D'Anna assert(m_py_obj); 115921b8a8aeSLawrence D'Anna GIL takeGIL; 116021b8a8aeSLawrence D'Anna Close(); 1161722b6189SLawrence D'Anna // we need to ensure the python object is released while we still 1162722b6189SLawrence D'Anna // hold the GIL 116321b8a8aeSLawrence D'Anna m_py_obj.Reset(); 116421b8a8aeSLawrence D'Anna } 116521b8a8aeSLawrence D'Anna 116621b8a8aeSLawrence D'Anna bool IsPythonSideValid() const { 116721b8a8aeSLawrence D'Anna GIL takeGIL; 116821b8a8aeSLawrence D'Anna auto closed = As<bool>(m_py_obj.GetAttribute("closed")); 116921b8a8aeSLawrence D'Anna if (!closed) { 117021b8a8aeSLawrence D'Anna llvm::consumeError(closed.takeError()); 117121b8a8aeSLawrence D'Anna return false; 117221b8a8aeSLawrence D'Anna } 117321b8a8aeSLawrence D'Anna return !closed.get(); 117421b8a8aeSLawrence D'Anna } 117521b8a8aeSLawrence D'Anna 117621b8a8aeSLawrence D'Anna bool IsValid() const override { 117721b8a8aeSLawrence D'Anna return IsPythonSideValid() && Base::IsValid(); 117821b8a8aeSLawrence D'Anna } 117921b8a8aeSLawrence D'Anna 118021b8a8aeSLawrence D'Anna Status Close() override { 118121b8a8aeSLawrence D'Anna assert(m_py_obj); 118221b8a8aeSLawrence D'Anna Status py_error, base_error; 118321b8a8aeSLawrence D'Anna GIL takeGIL; 118421b8a8aeSLawrence D'Anna if (!m_borrowed) { 118521b8a8aeSLawrence D'Anna auto r = m_py_obj.CallMethod("close"); 118621b8a8aeSLawrence D'Anna if (!r) 118721b8a8aeSLawrence D'Anna py_error = Status(r.takeError()); 118821b8a8aeSLawrence D'Anna } 118921b8a8aeSLawrence D'Anna base_error = Base::Close(); 119021b8a8aeSLawrence D'Anna if (py_error.Fail()) 119121b8a8aeSLawrence D'Anna return py_error; 119221b8a8aeSLawrence D'Anna return base_error; 119321b8a8aeSLawrence D'Anna }; 119421b8a8aeSLawrence D'Anna 1195d9b553ecSLawrence D'Anna PyObject *GetPythonObject() const { 1196d9b553ecSLawrence D'Anna assert(m_py_obj.IsValid()); 1197d9b553ecSLawrence D'Anna return m_py_obj.get(); 1198d9b553ecSLawrence D'Anna } 1199d9b553ecSLawrence D'Anna 1200d9b553ecSLawrence D'Anna static bool classof(const File *file) = delete; 1201d9b553ecSLawrence D'Anna 120221b8a8aeSLawrence D'Anna protected: 120321b8a8aeSLawrence D'Anna PythonFile m_py_obj; 120421b8a8aeSLawrence D'Anna bool m_borrowed; 120521b8a8aeSLawrence D'Anna }; 120621b8a8aeSLawrence D'Anna } // namespace 120721b8a8aeSLawrence D'Anna 120821b8a8aeSLawrence D'Anna // A SimplePythonFile is a OwnedPythonFile that just does all I/O as 120921b8a8aeSLawrence D'Anna // a NativeFile 121021b8a8aeSLawrence D'Anna namespace { 121121b8a8aeSLawrence D'Anna class SimplePythonFile : public OwnedPythonFile<NativeFile> { 121221b8a8aeSLawrence D'Anna public: 121321b8a8aeSLawrence D'Anna SimplePythonFile(const PythonFile &file, bool borrowed, int fd, 121462c9fe42SLawrence D'Anna File::OpenOptions options) 121521b8a8aeSLawrence D'Anna : OwnedPythonFile(file, borrowed, fd, options, false) {} 1216d9b553ecSLawrence D'Anna 1217d9b553ecSLawrence D'Anna static char ID; 1218d9b553ecSLawrence D'Anna bool isA(const void *classID) const override { 1219d9b553ecSLawrence D'Anna return classID == &ID || NativeFile::isA(classID); 1220d9b553ecSLawrence D'Anna } 1221d9b553ecSLawrence D'Anna static bool classof(const File *file) { return file->isA(&ID); } 122221b8a8aeSLawrence D'Anna }; 1223d9b553ecSLawrence D'Anna char SimplePythonFile::ID = 0; 122421b8a8aeSLawrence D'Anna } // namespace 122521b8a8aeSLawrence D'Anna 122621b8a8aeSLawrence D'Anna #if PY_MAJOR_VERSION >= 3 122721b8a8aeSLawrence D'Anna 122821b8a8aeSLawrence D'Anna namespace { 122921b8a8aeSLawrence D'Anna class PythonBuffer { 123021b8a8aeSLawrence D'Anna public: 123121b8a8aeSLawrence D'Anna PythonBuffer &operator=(const PythonBuffer &) = delete; 123221b8a8aeSLawrence D'Anna PythonBuffer(const PythonBuffer &) = delete; 123321b8a8aeSLawrence D'Anna 123421b8a8aeSLawrence D'Anna static Expected<PythonBuffer> Create(PythonObject &obj, 123521b8a8aeSLawrence D'Anna int flags = PyBUF_SIMPLE) { 123621b8a8aeSLawrence D'Anna Py_buffer py_buffer = {}; 123721b8a8aeSLawrence D'Anna PyObject_GetBuffer(obj.get(), &py_buffer, flags); 123821b8a8aeSLawrence D'Anna if (!py_buffer.obj) 123921b8a8aeSLawrence D'Anna return llvm::make_error<PythonException>(); 124021b8a8aeSLawrence D'Anna return PythonBuffer(py_buffer); 124121b8a8aeSLawrence D'Anna } 124221b8a8aeSLawrence D'Anna 124321b8a8aeSLawrence D'Anna PythonBuffer(PythonBuffer &&other) { 124421b8a8aeSLawrence D'Anna m_buffer = other.m_buffer; 124521b8a8aeSLawrence D'Anna other.m_buffer.obj = nullptr; 124621b8a8aeSLawrence D'Anna } 124721b8a8aeSLawrence D'Anna 124821b8a8aeSLawrence D'Anna ~PythonBuffer() { 124921b8a8aeSLawrence D'Anna if (m_buffer.obj) 125021b8a8aeSLawrence D'Anna PyBuffer_Release(&m_buffer); 125121b8a8aeSLawrence D'Anna } 125221b8a8aeSLawrence D'Anna 125321b8a8aeSLawrence D'Anna Py_buffer &get() { return m_buffer; } 125421b8a8aeSLawrence D'Anna 125521b8a8aeSLawrence D'Anna private: 125621b8a8aeSLawrence D'Anna // takes ownership of the buffer. 125721b8a8aeSLawrence D'Anna PythonBuffer(const Py_buffer &py_buffer) : m_buffer(py_buffer) {} 125821b8a8aeSLawrence D'Anna Py_buffer m_buffer; 125921b8a8aeSLawrence D'Anna }; 126021b8a8aeSLawrence D'Anna } // namespace 126121b8a8aeSLawrence D'Anna 126221b8a8aeSLawrence D'Anna // Shared methods between TextPythonFile and BinaryPythonFile 126321b8a8aeSLawrence D'Anna namespace { 126421b8a8aeSLawrence D'Anna class PythonIOFile : public OwnedPythonFile<File> { 126521b8a8aeSLawrence D'Anna public: 126621b8a8aeSLawrence D'Anna PythonIOFile(const PythonFile &file, bool borrowed) 126721b8a8aeSLawrence D'Anna : OwnedPythonFile(file, borrowed) {} 126821b8a8aeSLawrence D'Anna 126921b8a8aeSLawrence D'Anna ~PythonIOFile() override { Close(); } 127021b8a8aeSLawrence D'Anna 127121b8a8aeSLawrence D'Anna bool IsValid() const override { return IsPythonSideValid(); } 127221b8a8aeSLawrence D'Anna 127321b8a8aeSLawrence D'Anna Status Close() override { 127421b8a8aeSLawrence D'Anna assert(m_py_obj); 127521b8a8aeSLawrence D'Anna GIL takeGIL; 127621b8a8aeSLawrence D'Anna if (m_borrowed) 127721b8a8aeSLawrence D'Anna return Flush(); 127821b8a8aeSLawrence D'Anna auto r = m_py_obj.CallMethod("close"); 127921b8a8aeSLawrence D'Anna if (!r) 128021b8a8aeSLawrence D'Anna return Status(r.takeError()); 128121b8a8aeSLawrence D'Anna return Status(); 128221b8a8aeSLawrence D'Anna } 128321b8a8aeSLawrence D'Anna 128421b8a8aeSLawrence D'Anna Status Flush() override { 128521b8a8aeSLawrence D'Anna GIL takeGIL; 128621b8a8aeSLawrence D'Anna auto r = m_py_obj.CallMethod("flush"); 128721b8a8aeSLawrence D'Anna if (!r) 128821b8a8aeSLawrence D'Anna return Status(r.takeError()); 128921b8a8aeSLawrence D'Anna return Status(); 129021b8a8aeSLawrence D'Anna } 129121b8a8aeSLawrence D'Anna 1292d9b553ecSLawrence D'Anna Expected<File::OpenOptions> GetOptions() const override { 1293d9b553ecSLawrence D'Anna GIL takeGIL; 1294d9b553ecSLawrence D'Anna return GetOptionsForPyObject(m_py_obj); 1295d9b553ecSLawrence D'Anna } 1296d9b553ecSLawrence D'Anna 1297d9b553ecSLawrence D'Anna static char ID; 1298d9b553ecSLawrence D'Anna bool isA(const void *classID) const override { 1299d9b553ecSLawrence D'Anna return classID == &ID || File::isA(classID); 1300d9b553ecSLawrence D'Anna } 1301d9b553ecSLawrence D'Anna static bool classof(const File *file) { return file->isA(&ID); } 130221b8a8aeSLawrence D'Anna }; 1303d9b553ecSLawrence D'Anna char PythonIOFile::ID = 0; 130421b8a8aeSLawrence D'Anna } // namespace 130521b8a8aeSLawrence D'Anna 130621b8a8aeSLawrence D'Anna namespace { 130721b8a8aeSLawrence D'Anna class BinaryPythonFile : public PythonIOFile { 130821b8a8aeSLawrence D'Anna protected: 130921b8a8aeSLawrence D'Anna int m_descriptor; 131021b8a8aeSLawrence D'Anna 131121b8a8aeSLawrence D'Anna public: 131221b8a8aeSLawrence D'Anna BinaryPythonFile(int fd, const PythonFile &file, bool borrowed) 131321b8a8aeSLawrence D'Anna : PythonIOFile(file, borrowed), 131421b8a8aeSLawrence D'Anna m_descriptor(File::DescriptorIsValid(fd) ? fd 131521b8a8aeSLawrence D'Anna : File::kInvalidDescriptor) {} 131621b8a8aeSLawrence D'Anna 131721b8a8aeSLawrence D'Anna int GetDescriptor() const override { return m_descriptor; } 131821b8a8aeSLawrence D'Anna 131921b8a8aeSLawrence D'Anna Status Write(const void *buf, size_t &num_bytes) override { 132021b8a8aeSLawrence D'Anna GIL takeGIL; 132121b8a8aeSLawrence D'Anna PyObject *pybuffer_p = PyMemoryView_FromMemory( 132221b8a8aeSLawrence D'Anna const_cast<char *>((const char *)buf), num_bytes, PyBUF_READ); 132321b8a8aeSLawrence D'Anna if (!pybuffer_p) 132421b8a8aeSLawrence D'Anna return Status(llvm::make_error<PythonException>()); 132521b8a8aeSLawrence D'Anna auto pybuffer = Take<PythonObject>(pybuffer_p); 132621b8a8aeSLawrence D'Anna num_bytes = 0; 132721b8a8aeSLawrence D'Anna auto bytes_written = As<long long>(m_py_obj.CallMethod("write", pybuffer)); 132821b8a8aeSLawrence D'Anna if (!bytes_written) 132921b8a8aeSLawrence D'Anna return Status(bytes_written.takeError()); 133021b8a8aeSLawrence D'Anna if (bytes_written.get() < 0) 133121b8a8aeSLawrence D'Anna return Status(".write() method returned a negative number!"); 133221b8a8aeSLawrence D'Anna static_assert(sizeof(long long) >= sizeof(size_t), "overflow"); 133321b8a8aeSLawrence D'Anna num_bytes = bytes_written.get(); 133421b8a8aeSLawrence D'Anna return Status(); 133521b8a8aeSLawrence D'Anna } 133621b8a8aeSLawrence D'Anna 133721b8a8aeSLawrence D'Anna Status Read(void *buf, size_t &num_bytes) override { 133821b8a8aeSLawrence D'Anna GIL takeGIL; 133921b8a8aeSLawrence D'Anna static_assert(sizeof(long long) >= sizeof(size_t), "overflow"); 134021b8a8aeSLawrence D'Anna auto pybuffer_obj = 134121b8a8aeSLawrence D'Anna m_py_obj.CallMethod("read", (unsigned long long)num_bytes); 134221b8a8aeSLawrence D'Anna if (!pybuffer_obj) 134321b8a8aeSLawrence D'Anna return Status(pybuffer_obj.takeError()); 134421b8a8aeSLawrence D'Anna num_bytes = 0; 134521b8a8aeSLawrence D'Anna if (pybuffer_obj.get().IsNone()) { 134621b8a8aeSLawrence D'Anna // EOF 134721b8a8aeSLawrence D'Anna num_bytes = 0; 134821b8a8aeSLawrence D'Anna return Status(); 134921b8a8aeSLawrence D'Anna } 135021b8a8aeSLawrence D'Anna auto pybuffer = PythonBuffer::Create(pybuffer_obj.get()); 135121b8a8aeSLawrence D'Anna if (!pybuffer) 135221b8a8aeSLawrence D'Anna return Status(pybuffer.takeError()); 135321b8a8aeSLawrence D'Anna memcpy(buf, pybuffer.get().get().buf, pybuffer.get().get().len); 135421b8a8aeSLawrence D'Anna num_bytes = pybuffer.get().get().len; 135521b8a8aeSLawrence D'Anna return Status(); 135621b8a8aeSLawrence D'Anna } 135721b8a8aeSLawrence D'Anna }; 135821b8a8aeSLawrence D'Anna } // namespace 135921b8a8aeSLawrence D'Anna 136021b8a8aeSLawrence D'Anna namespace { 136121b8a8aeSLawrence D'Anna class TextPythonFile : public PythonIOFile { 136221b8a8aeSLawrence D'Anna protected: 136321b8a8aeSLawrence D'Anna int m_descriptor; 136421b8a8aeSLawrence D'Anna 136521b8a8aeSLawrence D'Anna public: 136621b8a8aeSLawrence D'Anna TextPythonFile(int fd, const PythonFile &file, bool borrowed) 136721b8a8aeSLawrence D'Anna : PythonIOFile(file, borrowed), 136821b8a8aeSLawrence D'Anna m_descriptor(File::DescriptorIsValid(fd) ? fd 136921b8a8aeSLawrence D'Anna : File::kInvalidDescriptor) {} 137021b8a8aeSLawrence D'Anna 137121b8a8aeSLawrence D'Anna int GetDescriptor() const override { return m_descriptor; } 137221b8a8aeSLawrence D'Anna 137321b8a8aeSLawrence D'Anna Status Write(const void *buf, size_t &num_bytes) override { 137421b8a8aeSLawrence D'Anna GIL takeGIL; 137521b8a8aeSLawrence D'Anna auto pystring = 137621b8a8aeSLawrence D'Anna PythonString::FromUTF8(llvm::StringRef((const char *)buf, num_bytes)); 137721b8a8aeSLawrence D'Anna if (!pystring) 137821b8a8aeSLawrence D'Anna return Status(pystring.takeError()); 137921b8a8aeSLawrence D'Anna num_bytes = 0; 138021b8a8aeSLawrence D'Anna auto bytes_written = 138121b8a8aeSLawrence D'Anna As<long long>(m_py_obj.CallMethod("write", pystring.get())); 138221b8a8aeSLawrence D'Anna if (!bytes_written) 138321b8a8aeSLawrence D'Anna return Status(bytes_written.takeError()); 138421b8a8aeSLawrence D'Anna if (bytes_written.get() < 0) 138521b8a8aeSLawrence D'Anna return Status(".write() method returned a negative number!"); 138621b8a8aeSLawrence D'Anna static_assert(sizeof(long long) >= sizeof(size_t), "overflow"); 138721b8a8aeSLawrence D'Anna num_bytes = bytes_written.get(); 138821b8a8aeSLawrence D'Anna return Status(); 138921b8a8aeSLawrence D'Anna } 139021b8a8aeSLawrence D'Anna 139121b8a8aeSLawrence D'Anna Status Read(void *buf, size_t &num_bytes) override { 139221b8a8aeSLawrence D'Anna GIL takeGIL; 139321b8a8aeSLawrence D'Anna size_t num_chars = num_bytes / 6; 139421b8a8aeSLawrence D'Anna size_t orig_num_bytes = num_bytes; 139521b8a8aeSLawrence D'Anna num_bytes = 0; 139621b8a8aeSLawrence D'Anna if (orig_num_bytes < 6) { 139721b8a8aeSLawrence D'Anna return Status("can't read less than 6 bytes from a utf8 text stream"); 139821b8a8aeSLawrence D'Anna } 139921b8a8aeSLawrence D'Anna auto pystring = As<PythonString>( 140021b8a8aeSLawrence D'Anna m_py_obj.CallMethod("read", (unsigned long long)num_chars)); 140121b8a8aeSLawrence D'Anna if (!pystring) 140221b8a8aeSLawrence D'Anna return Status(pystring.takeError()); 140321b8a8aeSLawrence D'Anna if (pystring.get().IsNone()) { 140421b8a8aeSLawrence D'Anna // EOF 140521b8a8aeSLawrence D'Anna return Status(); 140621b8a8aeSLawrence D'Anna } 140721b8a8aeSLawrence D'Anna auto stringref = pystring.get().AsUTF8(); 140821b8a8aeSLawrence D'Anna if (!stringref) 140921b8a8aeSLawrence D'Anna return Status(stringref.takeError()); 141021b8a8aeSLawrence D'Anna num_bytes = stringref.get().size(); 141121b8a8aeSLawrence D'Anna memcpy(buf, stringref.get().begin(), num_bytes); 141221b8a8aeSLawrence D'Anna return Status(); 141321b8a8aeSLawrence D'Anna } 141421b8a8aeSLawrence D'Anna }; 141521b8a8aeSLawrence D'Anna } // namespace 141621b8a8aeSLawrence D'Anna 141721b8a8aeSLawrence D'Anna #endif 141821b8a8aeSLawrence D'Anna 141921b8a8aeSLawrence D'Anna llvm::Expected<FileSP> PythonFile::ConvertToFile(bool borrowed) { 142021b8a8aeSLawrence D'Anna if (!IsValid()) 142121b8a8aeSLawrence D'Anna return llvm::createStringError(llvm::inconvertibleErrorCode(), 142221b8a8aeSLawrence D'Anna "invalid PythonFile"); 142321b8a8aeSLawrence D'Anna 142421b8a8aeSLawrence D'Anna int fd = PyObject_AsFileDescriptor(m_py_obj); 142521b8a8aeSLawrence D'Anna if (fd < 0) { 142621b8a8aeSLawrence D'Anna PyErr_Clear(); 142721b8a8aeSLawrence D'Anna return ConvertToFileForcingUseOfScriptingIOMethods(borrowed); 142821b8a8aeSLawrence D'Anna } 142921b8a8aeSLawrence D'Anna auto options = GetOptionsForPyObject(*this); 143021b8a8aeSLawrence D'Anna if (!options) 143121b8a8aeSLawrence D'Anna return options.takeError(); 143221b8a8aeSLawrence D'Anna 143314735cabSMichał Górny File::OpenOptions rw = 143414735cabSMichał Górny options.get() & (File::eOpenOptionReadOnly | File::eOpenOptionWriteOnly | 143514735cabSMichał Górny File::eOpenOptionReadWrite); 143614735cabSMichał Górny if (rw == File::eOpenOptionWriteOnly || rw == File::eOpenOptionReadWrite) { 143721b8a8aeSLawrence D'Anna // LLDB and python will not share I/O buffers. We should probably 143821b8a8aeSLawrence D'Anna // flush the python buffers now. 143921b8a8aeSLawrence D'Anna auto r = CallMethod("flush"); 144021b8a8aeSLawrence D'Anna if (!r) 144121b8a8aeSLawrence D'Anna return r.takeError(); 1442267cc329SMichal Gorny } 144321b8a8aeSLawrence D'Anna 144421b8a8aeSLawrence D'Anna FileSP file_sp; 144521b8a8aeSLawrence D'Anna if (borrowed) { 144621b8a8aeSLawrence D'Anna // In this case we we don't need to retain the python 144721b8a8aeSLawrence D'Anna // object at all. 144821b8a8aeSLawrence D'Anna file_sp = std::make_shared<NativeFile>(fd, options.get(), false); 144921b8a8aeSLawrence D'Anna } else { 145021b8a8aeSLawrence D'Anna file_sp = std::static_pointer_cast<File>( 145121b8a8aeSLawrence D'Anna std::make_shared<SimplePythonFile>(*this, borrowed, fd, options.get())); 145221b8a8aeSLawrence D'Anna } 145321b8a8aeSLawrence D'Anna if (!file_sp->IsValid()) 145421b8a8aeSLawrence D'Anna return llvm::createStringError(llvm::inconvertibleErrorCode(), 145521b8a8aeSLawrence D'Anna "invalid File"); 145621b8a8aeSLawrence D'Anna 145721b8a8aeSLawrence D'Anna return file_sp; 145821b8a8aeSLawrence D'Anna } 145921b8a8aeSLawrence D'Anna 146021b8a8aeSLawrence D'Anna llvm::Expected<FileSP> 146121b8a8aeSLawrence D'Anna PythonFile::ConvertToFileForcingUseOfScriptingIOMethods(bool borrowed) { 146221b8a8aeSLawrence D'Anna 146321b8a8aeSLawrence D'Anna assert(!PyErr_Occurred()); 146421b8a8aeSLawrence D'Anna 146521b8a8aeSLawrence D'Anna if (!IsValid()) 146621b8a8aeSLawrence D'Anna return llvm::createStringError(llvm::inconvertibleErrorCode(), 146721b8a8aeSLawrence D'Anna "invalid PythonFile"); 146821b8a8aeSLawrence D'Anna 146921b8a8aeSLawrence D'Anna #if PY_MAJOR_VERSION < 3 147021b8a8aeSLawrence D'Anna 147121b8a8aeSLawrence D'Anna return llvm::createStringError(llvm::inconvertibleErrorCode(), 147221b8a8aeSLawrence D'Anna "not supported on python 2"); 147321b8a8aeSLawrence D'Anna 147421b8a8aeSLawrence D'Anna #else 147521b8a8aeSLawrence D'Anna 147621b8a8aeSLawrence D'Anna int fd = PyObject_AsFileDescriptor(m_py_obj); 147721b8a8aeSLawrence D'Anna if (fd < 0) { 147821b8a8aeSLawrence D'Anna PyErr_Clear(); 147921b8a8aeSLawrence D'Anna fd = File::kInvalidDescriptor; 148021b8a8aeSLawrence D'Anna } 148121b8a8aeSLawrence D'Anna 148221b8a8aeSLawrence D'Anna auto io_module = PythonModule::Import("io"); 148321b8a8aeSLawrence D'Anna if (!io_module) 148421b8a8aeSLawrence D'Anna return io_module.takeError(); 148521b8a8aeSLawrence D'Anna auto textIOBase = io_module.get().Get("TextIOBase"); 148621b8a8aeSLawrence D'Anna if (!textIOBase) 148721b8a8aeSLawrence D'Anna return textIOBase.takeError(); 148821b8a8aeSLawrence D'Anna auto rawIOBase = io_module.get().Get("RawIOBase"); 148921b8a8aeSLawrence D'Anna if (!rawIOBase) 149021b8a8aeSLawrence D'Anna return rawIOBase.takeError(); 149121b8a8aeSLawrence D'Anna auto bufferedIOBase = io_module.get().Get("BufferedIOBase"); 149221b8a8aeSLawrence D'Anna if (!bufferedIOBase) 149321b8a8aeSLawrence D'Anna return bufferedIOBase.takeError(); 149421b8a8aeSLawrence D'Anna 149521b8a8aeSLawrence D'Anna FileSP file_sp; 149621b8a8aeSLawrence D'Anna 149721b8a8aeSLawrence D'Anna auto isTextIO = IsInstance(textIOBase.get()); 149821b8a8aeSLawrence D'Anna if (!isTextIO) 149921b8a8aeSLawrence D'Anna return isTextIO.takeError(); 150021b8a8aeSLawrence D'Anna if (isTextIO.get()) 150121b8a8aeSLawrence D'Anna file_sp = std::static_pointer_cast<File>( 150221b8a8aeSLawrence D'Anna std::make_shared<TextPythonFile>(fd, *this, borrowed)); 150321b8a8aeSLawrence D'Anna 150421b8a8aeSLawrence D'Anna auto isRawIO = IsInstance(rawIOBase.get()); 150521b8a8aeSLawrence D'Anna if (!isRawIO) 150621b8a8aeSLawrence D'Anna return isRawIO.takeError(); 150721b8a8aeSLawrence D'Anna auto isBufferedIO = IsInstance(bufferedIOBase.get()); 150821b8a8aeSLawrence D'Anna if (!isBufferedIO) 150921b8a8aeSLawrence D'Anna return isBufferedIO.takeError(); 151021b8a8aeSLawrence D'Anna 151121b8a8aeSLawrence D'Anna if (isRawIO.get() || isBufferedIO.get()) { 151221b8a8aeSLawrence D'Anna file_sp = std::static_pointer_cast<File>( 151321b8a8aeSLawrence D'Anna std::make_shared<BinaryPythonFile>(fd, *this, borrowed)); 151421b8a8aeSLawrence D'Anna } 151521b8a8aeSLawrence D'Anna 151621b8a8aeSLawrence D'Anna if (!file_sp) 151721b8a8aeSLawrence D'Anna return llvm::createStringError(llvm::inconvertibleErrorCode(), 151821b8a8aeSLawrence D'Anna "python file is neither text nor binary"); 151921b8a8aeSLawrence D'Anna 152021b8a8aeSLawrence D'Anna if (!file_sp->IsValid()) 152121b8a8aeSLawrence D'Anna return llvm::createStringError(llvm::inconvertibleErrorCode(), 152221b8a8aeSLawrence D'Anna "invalid File"); 152321b8a8aeSLawrence D'Anna 152421b8a8aeSLawrence D'Anna return file_sp; 152521b8a8aeSLawrence D'Anna 152621b8a8aeSLawrence D'Anna #endif 152721b8a8aeSLawrence D'Anna } 152821b8a8aeSLawrence D'Anna 1529d9b553ecSLawrence D'Anna Expected<PythonFile> PythonFile::FromFile(File &file, const char *mode) { 1530d9b553ecSLawrence D'Anna if (!file.IsValid()) 1531d9b553ecSLawrence D'Anna return llvm::createStringError(llvm::inconvertibleErrorCode(), 1532d9b553ecSLawrence D'Anna "invalid file"); 1533d9b553ecSLawrence D'Anna 1534d9b553ecSLawrence D'Anna if (auto *simple = llvm::dyn_cast<SimplePythonFile>(&file)) 1535d9b553ecSLawrence D'Anna return Retain<PythonFile>(simple->GetPythonObject()); 1536d9b553ecSLawrence D'Anna #if PY_MAJOR_VERSION >= 3 1537d9b553ecSLawrence D'Anna if (auto *pythonio = llvm::dyn_cast<PythonIOFile>(&file)) 1538d9b553ecSLawrence D'Anna return Retain<PythonFile>(pythonio->GetPythonObject()); 1539d9b553ecSLawrence D'Anna #endif 1540d9b553ecSLawrence D'Anna 1541d9b553ecSLawrence D'Anna if (!mode) { 1542d9b553ecSLawrence D'Anna auto m = file.GetOpenMode(); 1543d9b553ecSLawrence D'Anna if (!m) 1544d9b553ecSLawrence D'Anna return m.takeError(); 1545d9b553ecSLawrence D'Anna mode = m.get(); 1546d9b553ecSLawrence D'Anna } 1547d9b553ecSLawrence D'Anna 1548d9b553ecSLawrence D'Anna PyObject *file_obj; 1549d9b553ecSLawrence D'Anna #if PY_MAJOR_VERSION >= 3 1550d9b553ecSLawrence D'Anna file_obj = PyFile_FromFd(file.GetDescriptor(), nullptr, mode, -1, nullptr, 15513071ebf7SLawrence D'Anna "ignore", nullptr, /*closefd=*/0); 1552d9b553ecSLawrence D'Anna #else 15533071ebf7SLawrence D'Anna // I'd like to pass ::fflush here if the file is writable, so that 15543071ebf7SLawrence D'Anna // when the python side destructs the file object it will be flushed. 15553071ebf7SLawrence D'Anna // However, this would be dangerous. It can cause fflush to be called 15563071ebf7SLawrence D'Anna // after fclose if the python program keeps a reference to the file after 15573071ebf7SLawrence D'Anna // the original lldb_private::File has been destructed. 15583071ebf7SLawrence D'Anna // 15593071ebf7SLawrence D'Anna // It's all well and good to ask a python program not to use a closed file 15603071ebf7SLawrence D'Anna // but asking a python program to make sure objects get released in a 15613071ebf7SLawrence D'Anna // particular order is not safe. 15623071ebf7SLawrence D'Anna // 15633071ebf7SLawrence D'Anna // The tradeoff here is that if a python 2 program wants to make sure this 15643071ebf7SLawrence D'Anna // file gets flushed, they'll have to do it explicitly or wait untill the 15653071ebf7SLawrence D'Anna // original lldb File itself gets flushed. 15666a93a12aSLawrence D'Anna file_obj = PyFile_FromFile(file.GetStream(), py2_const_cast(""), 15673071ebf7SLawrence D'Anna py2_const_cast(mode), [](FILE *) { return 0; }); 1568d9b553ecSLawrence D'Anna #endif 1569d9b553ecSLawrence D'Anna 1570d9b553ecSLawrence D'Anna if (!file_obj) 1571d9b553ecSLawrence D'Anna return exception(); 1572d9b553ecSLawrence D'Anna 1573d9b553ecSLawrence D'Anna return Take<PythonFile>(file_obj); 1574d9b553ecSLawrence D'Anna } 1575d9b553ecSLawrence D'Anna 157604edd189SLawrence D'Anna Error PythonScript::Init() { 157704edd189SLawrence D'Anna if (function.IsValid()) 157804edd189SLawrence D'Anna return Error::success(); 157904edd189SLawrence D'Anna 158004edd189SLawrence D'Anna PythonDictionary globals(PyInitialValue::Empty); 158104edd189SLawrence D'Anna auto builtins = PythonModule::BuiltinsModule(); 158204edd189SLawrence D'Anna if (Error error = globals.SetItem("__builtins__", builtins)) 158304edd189SLawrence D'Anna return error; 158404edd189SLawrence D'Anna PyObject *o = 158504edd189SLawrence D'Anna PyRun_String(script, Py_file_input, globals.get(), globals.get()); 158604edd189SLawrence D'Anna if (!o) 158704edd189SLawrence D'Anna return exception(); 158804edd189SLawrence D'Anna Take<PythonObject>(o); 158904edd189SLawrence D'Anna auto f = As<PythonCallable>(globals.GetItem("main")); 159004edd189SLawrence D'Anna if (!f) 159104edd189SLawrence D'Anna return f.takeError(); 159204edd189SLawrence D'Anna function = std::move(f.get()); 159304edd189SLawrence D'Anna 159404edd189SLawrence D'Anna return Error::success(); 159504edd189SLawrence D'Anna } 159604edd189SLawrence D'Anna 159704edd189SLawrence D'Anna llvm::Expected<PythonObject> 159804edd189SLawrence D'Anna python::runStringOneLine(const llvm::Twine &string, 159904edd189SLawrence D'Anna const PythonDictionary &globals, 160004edd189SLawrence D'Anna const PythonDictionary &locals) { 160104edd189SLawrence D'Anna if (!globals.IsValid() || !locals.IsValid()) 160204edd189SLawrence D'Anna return nullDeref(); 160304edd189SLawrence D'Anna 160404edd189SLawrence D'Anna PyObject *code = 160504edd189SLawrence D'Anna Py_CompileString(NullTerminated(string), "<string>", Py_eval_input); 160604edd189SLawrence D'Anna if (!code) { 160704edd189SLawrence D'Anna PyErr_Clear(); 160804edd189SLawrence D'Anna code = 160904edd189SLawrence D'Anna Py_CompileString(NullTerminated(string), "<string>", Py_single_input); 161004edd189SLawrence D'Anna } 161104edd189SLawrence D'Anna if (!code) 161204edd189SLawrence D'Anna return exception(); 161304edd189SLawrence D'Anna auto code_ref = Take<PythonObject>(code); 161404edd189SLawrence D'Anna 161504edd189SLawrence D'Anna #if PY_MAJOR_VERSION < 3 161604edd189SLawrence D'Anna PyObject *result = 161704edd189SLawrence D'Anna PyEval_EvalCode((PyCodeObject *)code, globals.get(), locals.get()); 161804edd189SLawrence D'Anna #else 161904edd189SLawrence D'Anna PyObject *result = PyEval_EvalCode(code, globals.get(), locals.get()); 162004edd189SLawrence D'Anna #endif 162104edd189SLawrence D'Anna 162204edd189SLawrence D'Anna if (!result) 162304edd189SLawrence D'Anna return exception(); 162404edd189SLawrence D'Anna 162504edd189SLawrence D'Anna return Take<PythonObject>(result); 162604edd189SLawrence D'Anna } 162704edd189SLawrence D'Anna 162804edd189SLawrence D'Anna llvm::Expected<PythonObject> 162904edd189SLawrence D'Anna python::runStringMultiLine(const llvm::Twine &string, 163004edd189SLawrence D'Anna const PythonDictionary &globals, 163104edd189SLawrence D'Anna const PythonDictionary &locals) { 163204edd189SLawrence D'Anna if (!globals.IsValid() || !locals.IsValid()) 163304edd189SLawrence D'Anna return nullDeref(); 163404edd189SLawrence D'Anna PyObject *result = PyRun_String(NullTerminated(string), Py_file_input, 163504edd189SLawrence D'Anna globals.get(), locals.get()); 163604edd189SLawrence D'Anna if (!result) 163704edd189SLawrence D'Anna return exception(); 163804edd189SLawrence D'Anna return Take<PythonObject>(result); 163904edd189SLawrence D'Anna } 164004edd189SLawrence D'Anna 1641d68983e3SPavel Labath #endif 1642