10b57cec5SDimitry Andric //===-- PythonDataObjects.cpp -----------------------------------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #ifdef LLDB_DISABLE_PYTHON 100b57cec5SDimitry Andric 110b57cec5SDimitry Andric // Python is disabled in this build 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #else 140b57cec5SDimitry Andric 150b57cec5SDimitry Andric #include "PythonDataObjects.h" 160b57cec5SDimitry Andric #include "ScriptInterpreterPython.h" 170b57cec5SDimitry Andric 180b57cec5SDimitry Andric #include "lldb/Host/File.h" 190b57cec5SDimitry Andric #include "lldb/Host/FileSystem.h" 200b57cec5SDimitry Andric #include "lldb/Interpreter/ScriptInterpreter.h" 21*9dba64beSDimitry Andric #include "lldb/Utility/Log.h" 220b57cec5SDimitry Andric #include "lldb/Utility/Stream.h" 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h" 25*9dba64beSDimitry Andric #include "llvm/Support/Casting.h" 260b57cec5SDimitry Andric #include "llvm/Support/ConvertUTF.h" 270b57cec5SDimitry Andric #include "llvm/Support/Errno.h" 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric #include <stdio.h> 300b57cec5SDimitry Andric 310b57cec5SDimitry Andric using namespace lldb_private; 320b57cec5SDimitry Andric using namespace lldb; 33*9dba64beSDimitry Andric using namespace lldb_private::python; 34*9dba64beSDimitry Andric using llvm::cantFail; 35*9dba64beSDimitry Andric using llvm::Error; 36*9dba64beSDimitry Andric using llvm::Expected; 37*9dba64beSDimitry Andric using llvm::Twine; 380b57cec5SDimitry Andric 39*9dba64beSDimitry Andric template <> Expected<bool> python::As<bool>(Expected<PythonObject> &&obj) { 40*9dba64beSDimitry Andric if (!obj) 41*9dba64beSDimitry Andric return obj.takeError(); 42*9dba64beSDimitry Andric return obj.get().IsTrue(); 43*9dba64beSDimitry Andric } 44*9dba64beSDimitry Andric 45*9dba64beSDimitry Andric template <> 46*9dba64beSDimitry Andric Expected<long long> python::As<long long>(Expected<PythonObject> &&obj) { 47*9dba64beSDimitry Andric if (!obj) 48*9dba64beSDimitry Andric return obj.takeError(); 49*9dba64beSDimitry Andric return obj.get().AsLongLong(); 50*9dba64beSDimitry Andric } 51*9dba64beSDimitry Andric 52*9dba64beSDimitry Andric template <> 53*9dba64beSDimitry Andric Expected<std::string> python::As<std::string>(Expected<PythonObject> &&obj) { 54*9dba64beSDimitry Andric if (!obj) 55*9dba64beSDimitry Andric return obj.takeError(); 56*9dba64beSDimitry Andric PyObject *str_obj = PyObject_Str(obj.get().get()); 57*9dba64beSDimitry Andric if (!obj) 58*9dba64beSDimitry Andric return llvm::make_error<PythonException>(); 59*9dba64beSDimitry Andric auto str = Take<PythonString>(str_obj); 60*9dba64beSDimitry Andric auto utf8 = str.AsUTF8(); 61*9dba64beSDimitry Andric if (!utf8) 62*9dba64beSDimitry Andric return utf8.takeError(); 63*9dba64beSDimitry Andric return utf8.get(); 64*9dba64beSDimitry Andric } 65*9dba64beSDimitry Andric 66*9dba64beSDimitry Andric void StructuredPythonObject::Serialize(llvm::json::OStream &s) const { 67*9dba64beSDimitry Andric s.value(llvm::formatv("Python Obj: {0:X}", GetValue()).str()); 680b57cec5SDimitry Andric } 690b57cec5SDimitry Andric 700b57cec5SDimitry Andric // PythonObject 710b57cec5SDimitry Andric 720b57cec5SDimitry Andric void PythonObject::Dump(Stream &strm) const { 730b57cec5SDimitry Andric if (m_py_obj) { 740b57cec5SDimitry Andric FILE *file = llvm::sys::RetryAfterSignal(nullptr, ::tmpfile); 750b57cec5SDimitry Andric if (file) { 760b57cec5SDimitry Andric ::PyObject_Print(m_py_obj, file, 0); 770b57cec5SDimitry Andric const long length = ftell(file); 780b57cec5SDimitry Andric if (length) { 790b57cec5SDimitry Andric ::rewind(file); 800b57cec5SDimitry Andric std::vector<char> file_contents(length, '\0'); 810b57cec5SDimitry Andric const size_t length_read = 820b57cec5SDimitry Andric ::fread(file_contents.data(), 1, file_contents.size(), file); 830b57cec5SDimitry Andric if (length_read > 0) 840b57cec5SDimitry Andric strm.Write(file_contents.data(), length_read); 850b57cec5SDimitry Andric } 860b57cec5SDimitry Andric ::fclose(file); 870b57cec5SDimitry Andric } 880b57cec5SDimitry Andric } else 890b57cec5SDimitry Andric strm.PutCString("NULL"); 900b57cec5SDimitry Andric } 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric PyObjectType PythonObject::GetObjectType() const { 930b57cec5SDimitry Andric if (!IsAllocated()) 940b57cec5SDimitry Andric return PyObjectType::None; 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric if (PythonModule::Check(m_py_obj)) 970b57cec5SDimitry Andric return PyObjectType::Module; 980b57cec5SDimitry Andric if (PythonList::Check(m_py_obj)) 990b57cec5SDimitry Andric return PyObjectType::List; 1000b57cec5SDimitry Andric if (PythonTuple::Check(m_py_obj)) 1010b57cec5SDimitry Andric return PyObjectType::Tuple; 1020b57cec5SDimitry Andric if (PythonDictionary::Check(m_py_obj)) 1030b57cec5SDimitry Andric return PyObjectType::Dictionary; 1040b57cec5SDimitry Andric if (PythonString::Check(m_py_obj)) 1050b57cec5SDimitry Andric return PyObjectType::String; 1060b57cec5SDimitry Andric #if PY_MAJOR_VERSION >= 3 1070b57cec5SDimitry Andric if (PythonBytes::Check(m_py_obj)) 1080b57cec5SDimitry Andric return PyObjectType::Bytes; 1090b57cec5SDimitry Andric #endif 1100b57cec5SDimitry Andric if (PythonByteArray::Check(m_py_obj)) 1110b57cec5SDimitry Andric return PyObjectType::ByteArray; 1120b57cec5SDimitry Andric if (PythonBoolean::Check(m_py_obj)) 1130b57cec5SDimitry Andric return PyObjectType::Boolean; 1140b57cec5SDimitry Andric if (PythonInteger::Check(m_py_obj)) 1150b57cec5SDimitry Andric return PyObjectType::Integer; 1160b57cec5SDimitry Andric if (PythonFile::Check(m_py_obj)) 1170b57cec5SDimitry Andric return PyObjectType::File; 1180b57cec5SDimitry Andric if (PythonCallable::Check(m_py_obj)) 1190b57cec5SDimitry Andric return PyObjectType::Callable; 1200b57cec5SDimitry Andric return PyObjectType::Unknown; 1210b57cec5SDimitry Andric } 1220b57cec5SDimitry Andric 1230b57cec5SDimitry Andric PythonString PythonObject::Repr() const { 1240b57cec5SDimitry Andric if (!m_py_obj) 1250b57cec5SDimitry Andric return PythonString(); 1260b57cec5SDimitry Andric PyObject *repr = PyObject_Repr(m_py_obj); 1270b57cec5SDimitry Andric if (!repr) 1280b57cec5SDimitry Andric return PythonString(); 1290b57cec5SDimitry Andric return PythonString(PyRefType::Owned, repr); 1300b57cec5SDimitry Andric } 1310b57cec5SDimitry Andric 1320b57cec5SDimitry Andric PythonString PythonObject::Str() const { 1330b57cec5SDimitry Andric if (!m_py_obj) 1340b57cec5SDimitry Andric return PythonString(); 1350b57cec5SDimitry Andric PyObject *str = PyObject_Str(m_py_obj); 1360b57cec5SDimitry Andric if (!str) 1370b57cec5SDimitry Andric return PythonString(); 1380b57cec5SDimitry Andric return PythonString(PyRefType::Owned, str); 1390b57cec5SDimitry Andric } 1400b57cec5SDimitry Andric 1410b57cec5SDimitry Andric PythonObject 1420b57cec5SDimitry Andric PythonObject::ResolveNameWithDictionary(llvm::StringRef name, 1430b57cec5SDimitry Andric const PythonDictionary &dict) { 1440b57cec5SDimitry Andric size_t dot_pos = name.find('.'); 1450b57cec5SDimitry Andric llvm::StringRef piece = name.substr(0, dot_pos); 1460b57cec5SDimitry Andric PythonObject result = dict.GetItemForKey(PythonString(piece)); 1470b57cec5SDimitry Andric if (dot_pos == llvm::StringRef::npos) { 1480b57cec5SDimitry Andric // There was no dot, we're done. 1490b57cec5SDimitry Andric return result; 1500b57cec5SDimitry Andric } 1510b57cec5SDimitry Andric 1520b57cec5SDimitry Andric // There was a dot. The remaining portion of the name should be looked up in 1530b57cec5SDimitry Andric // the context of the object that was found in the dictionary. 1540b57cec5SDimitry Andric return result.ResolveName(name.substr(dot_pos + 1)); 1550b57cec5SDimitry Andric } 1560b57cec5SDimitry Andric 1570b57cec5SDimitry Andric PythonObject PythonObject::ResolveName(llvm::StringRef name) const { 1580b57cec5SDimitry Andric // Resolve the name in the context of the specified object. If, for example, 1590b57cec5SDimitry Andric // `this` refers to a PyModule, then this will look for `name` in this 1600b57cec5SDimitry Andric // module. If `this` refers to a PyType, then it will resolve `name` as an 1610b57cec5SDimitry Andric // attribute of that type. If `this` refers to an instance of an object, 1620b57cec5SDimitry Andric // then it will resolve `name` as the value of the specified field. 1630b57cec5SDimitry Andric // 1640b57cec5SDimitry Andric // This function handles dotted names so that, for example, if `m_py_obj` 1650b57cec5SDimitry Andric // refers to the `sys` module, and `name` == "path.append", then it will find 1660b57cec5SDimitry Andric // the function `sys.path.append`. 1670b57cec5SDimitry Andric 1680b57cec5SDimitry Andric size_t dot_pos = name.find('.'); 1690b57cec5SDimitry Andric if (dot_pos == llvm::StringRef::npos) { 1700b57cec5SDimitry Andric // No dots in the name, we should be able to find the value immediately as 1710b57cec5SDimitry Andric // an attribute of `m_py_obj`. 1720b57cec5SDimitry Andric return GetAttributeValue(name); 1730b57cec5SDimitry Andric } 1740b57cec5SDimitry Andric 1750b57cec5SDimitry Andric // Look up the first piece of the name, and resolve the rest as a child of 1760b57cec5SDimitry Andric // that. 1770b57cec5SDimitry Andric PythonObject parent = ResolveName(name.substr(0, dot_pos)); 1780b57cec5SDimitry Andric if (!parent.IsAllocated()) 1790b57cec5SDimitry Andric return PythonObject(); 1800b57cec5SDimitry Andric 1810b57cec5SDimitry Andric // Tail recursion.. should be optimized by the compiler 1820b57cec5SDimitry Andric return parent.ResolveName(name.substr(dot_pos + 1)); 1830b57cec5SDimitry Andric } 1840b57cec5SDimitry Andric 1850b57cec5SDimitry Andric bool PythonObject::HasAttribute(llvm::StringRef attr) const { 1860b57cec5SDimitry Andric if (!IsValid()) 1870b57cec5SDimitry Andric return false; 1880b57cec5SDimitry Andric PythonString py_attr(attr); 1890b57cec5SDimitry Andric return !!PyObject_HasAttr(m_py_obj, py_attr.get()); 1900b57cec5SDimitry Andric } 1910b57cec5SDimitry Andric 1920b57cec5SDimitry Andric PythonObject PythonObject::GetAttributeValue(llvm::StringRef attr) const { 1930b57cec5SDimitry Andric if (!IsValid()) 1940b57cec5SDimitry Andric return PythonObject(); 1950b57cec5SDimitry Andric 1960b57cec5SDimitry Andric PythonString py_attr(attr); 1970b57cec5SDimitry Andric if (!PyObject_HasAttr(m_py_obj, py_attr.get())) 1980b57cec5SDimitry Andric return PythonObject(); 1990b57cec5SDimitry Andric 2000b57cec5SDimitry Andric return PythonObject(PyRefType::Owned, 2010b57cec5SDimitry Andric PyObject_GetAttr(m_py_obj, py_attr.get())); 2020b57cec5SDimitry Andric } 2030b57cec5SDimitry Andric 2040b57cec5SDimitry Andric StructuredData::ObjectSP PythonObject::CreateStructuredObject() const { 2050b57cec5SDimitry Andric switch (GetObjectType()) { 2060b57cec5SDimitry Andric case PyObjectType::Dictionary: 2070b57cec5SDimitry Andric return PythonDictionary(PyRefType::Borrowed, m_py_obj) 2080b57cec5SDimitry Andric .CreateStructuredDictionary(); 2090b57cec5SDimitry Andric case PyObjectType::Boolean: 2100b57cec5SDimitry Andric return PythonBoolean(PyRefType::Borrowed, m_py_obj) 2110b57cec5SDimitry Andric .CreateStructuredBoolean(); 2120b57cec5SDimitry Andric case PyObjectType::Integer: 2130b57cec5SDimitry Andric return PythonInteger(PyRefType::Borrowed, m_py_obj) 2140b57cec5SDimitry Andric .CreateStructuredInteger(); 2150b57cec5SDimitry Andric case PyObjectType::List: 2160b57cec5SDimitry Andric return PythonList(PyRefType::Borrowed, m_py_obj).CreateStructuredArray(); 2170b57cec5SDimitry Andric case PyObjectType::String: 2180b57cec5SDimitry Andric return PythonString(PyRefType::Borrowed, m_py_obj).CreateStructuredString(); 2190b57cec5SDimitry Andric case PyObjectType::Bytes: 2200b57cec5SDimitry Andric return PythonBytes(PyRefType::Borrowed, m_py_obj).CreateStructuredString(); 2210b57cec5SDimitry Andric case PyObjectType::ByteArray: 2220b57cec5SDimitry Andric return PythonByteArray(PyRefType::Borrowed, m_py_obj) 2230b57cec5SDimitry Andric .CreateStructuredString(); 2240b57cec5SDimitry Andric case PyObjectType::None: 2250b57cec5SDimitry Andric return StructuredData::ObjectSP(); 2260b57cec5SDimitry Andric default: 2270b57cec5SDimitry Andric return StructuredData::ObjectSP(new StructuredPythonObject(m_py_obj)); 2280b57cec5SDimitry Andric } 2290b57cec5SDimitry Andric } 2300b57cec5SDimitry Andric 2310b57cec5SDimitry Andric // PythonString 2320b57cec5SDimitry Andric 233*9dba64beSDimitry Andric PythonBytes::PythonBytes(llvm::ArrayRef<uint8_t> bytes) { SetBytes(bytes); } 2340b57cec5SDimitry Andric 235*9dba64beSDimitry Andric PythonBytes::PythonBytes(const uint8_t *bytes, size_t length) { 2360b57cec5SDimitry Andric SetBytes(llvm::ArrayRef<uint8_t>(bytes, length)); 2370b57cec5SDimitry Andric } 2380b57cec5SDimitry Andric 2390b57cec5SDimitry Andric bool PythonBytes::Check(PyObject *py_obj) { 2400b57cec5SDimitry Andric if (!py_obj) 2410b57cec5SDimitry Andric return false; 2420b57cec5SDimitry Andric return PyBytes_Check(py_obj); 2430b57cec5SDimitry Andric } 2440b57cec5SDimitry Andric 2450b57cec5SDimitry Andric llvm::ArrayRef<uint8_t> PythonBytes::GetBytes() const { 2460b57cec5SDimitry Andric if (!IsValid()) 2470b57cec5SDimitry Andric return llvm::ArrayRef<uint8_t>(); 2480b57cec5SDimitry Andric 2490b57cec5SDimitry Andric Py_ssize_t size; 2500b57cec5SDimitry Andric char *c; 2510b57cec5SDimitry Andric 2520b57cec5SDimitry Andric PyBytes_AsStringAndSize(m_py_obj, &c, &size); 2530b57cec5SDimitry Andric return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size); 2540b57cec5SDimitry Andric } 2550b57cec5SDimitry Andric 2560b57cec5SDimitry Andric size_t PythonBytes::GetSize() const { 2570b57cec5SDimitry Andric if (!IsValid()) 2580b57cec5SDimitry Andric return 0; 2590b57cec5SDimitry Andric return PyBytes_Size(m_py_obj); 2600b57cec5SDimitry Andric } 2610b57cec5SDimitry Andric 2620b57cec5SDimitry Andric void PythonBytes::SetBytes(llvm::ArrayRef<uint8_t> bytes) { 2630b57cec5SDimitry Andric const char *data = reinterpret_cast<const char *>(bytes.data()); 264*9dba64beSDimitry Andric *this = Take<PythonBytes>(PyBytes_FromStringAndSize(data, bytes.size())); 2650b57cec5SDimitry Andric } 2660b57cec5SDimitry Andric 2670b57cec5SDimitry Andric StructuredData::StringSP PythonBytes::CreateStructuredString() const { 2680b57cec5SDimitry Andric StructuredData::StringSP result(new StructuredData::String); 2690b57cec5SDimitry Andric Py_ssize_t size; 2700b57cec5SDimitry Andric char *c; 2710b57cec5SDimitry Andric PyBytes_AsStringAndSize(m_py_obj, &c, &size); 2720b57cec5SDimitry Andric result->SetValue(std::string(c, size)); 2730b57cec5SDimitry Andric return result; 2740b57cec5SDimitry Andric } 2750b57cec5SDimitry Andric 2760b57cec5SDimitry Andric PythonByteArray::PythonByteArray(llvm::ArrayRef<uint8_t> bytes) 2770b57cec5SDimitry Andric : PythonByteArray(bytes.data(), bytes.size()) {} 2780b57cec5SDimitry Andric 2790b57cec5SDimitry Andric PythonByteArray::PythonByteArray(const uint8_t *bytes, size_t length) { 2800b57cec5SDimitry Andric const char *str = reinterpret_cast<const char *>(bytes); 281*9dba64beSDimitry Andric *this = Take<PythonByteArray>(PyByteArray_FromStringAndSize(str, length)); 2820b57cec5SDimitry Andric } 2830b57cec5SDimitry Andric 2840b57cec5SDimitry Andric bool PythonByteArray::Check(PyObject *py_obj) { 2850b57cec5SDimitry Andric if (!py_obj) 2860b57cec5SDimitry Andric return false; 2870b57cec5SDimitry Andric return PyByteArray_Check(py_obj); 2880b57cec5SDimitry Andric } 2890b57cec5SDimitry Andric 2900b57cec5SDimitry Andric llvm::ArrayRef<uint8_t> PythonByteArray::GetBytes() const { 2910b57cec5SDimitry Andric if (!IsValid()) 2920b57cec5SDimitry Andric return llvm::ArrayRef<uint8_t>(); 2930b57cec5SDimitry Andric 2940b57cec5SDimitry Andric char *c = PyByteArray_AsString(m_py_obj); 2950b57cec5SDimitry Andric size_t size = GetSize(); 2960b57cec5SDimitry Andric return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size); 2970b57cec5SDimitry Andric } 2980b57cec5SDimitry Andric 2990b57cec5SDimitry Andric size_t PythonByteArray::GetSize() const { 3000b57cec5SDimitry Andric if (!IsValid()) 3010b57cec5SDimitry Andric return 0; 3020b57cec5SDimitry Andric 3030b57cec5SDimitry Andric return PyByteArray_Size(m_py_obj); 3040b57cec5SDimitry Andric } 3050b57cec5SDimitry Andric 3060b57cec5SDimitry Andric StructuredData::StringSP PythonByteArray::CreateStructuredString() const { 3070b57cec5SDimitry Andric StructuredData::StringSP result(new StructuredData::String); 3080b57cec5SDimitry Andric llvm::ArrayRef<uint8_t> bytes = GetBytes(); 3090b57cec5SDimitry Andric const char *str = reinterpret_cast<const char *>(bytes.data()); 3100b57cec5SDimitry Andric result->SetValue(std::string(str, bytes.size())); 3110b57cec5SDimitry Andric return result; 3120b57cec5SDimitry Andric } 3130b57cec5SDimitry Andric 3140b57cec5SDimitry Andric // PythonString 3150b57cec5SDimitry Andric 316*9dba64beSDimitry Andric Expected<PythonString> PythonString::FromUTF8(llvm::StringRef string) { 317*9dba64beSDimitry Andric #if PY_MAJOR_VERSION >= 3 318*9dba64beSDimitry Andric PyObject *str = PyUnicode_FromStringAndSize(string.data(), string.size()); 319*9dba64beSDimitry Andric #else 320*9dba64beSDimitry Andric PyObject *str = PyString_FromStringAndSize(string.data(), string.size()); 321*9dba64beSDimitry Andric #endif 322*9dba64beSDimitry Andric if (!str) 323*9dba64beSDimitry Andric return llvm::make_error<PythonException>(); 324*9dba64beSDimitry Andric return Take<PythonString>(str); 3250b57cec5SDimitry Andric } 3260b57cec5SDimitry Andric 327*9dba64beSDimitry Andric PythonString::PythonString(llvm::StringRef string) { SetString(string); } 3280b57cec5SDimitry Andric 3290b57cec5SDimitry Andric bool PythonString::Check(PyObject *py_obj) { 3300b57cec5SDimitry Andric if (!py_obj) 3310b57cec5SDimitry Andric return false; 3320b57cec5SDimitry Andric 3330b57cec5SDimitry Andric if (PyUnicode_Check(py_obj)) 3340b57cec5SDimitry Andric return true; 3350b57cec5SDimitry Andric #if PY_MAJOR_VERSION < 3 3360b57cec5SDimitry Andric if (PyString_Check(py_obj)) 3370b57cec5SDimitry Andric return true; 3380b57cec5SDimitry Andric #endif 3390b57cec5SDimitry Andric return false; 3400b57cec5SDimitry Andric } 3410b57cec5SDimitry Andric 342*9dba64beSDimitry Andric void PythonString::Convert(PyRefType &type, PyObject *&py_obj) { 3430b57cec5SDimitry Andric #if PY_MAJOR_VERSION < 3 3440b57cec5SDimitry Andric // In Python 2, Don't store PyUnicode objects directly, because we need 3450b57cec5SDimitry Andric // access to their underlying character buffers which Python 2 doesn't 3460b57cec5SDimitry Andric // provide. 347*9dba64beSDimitry Andric if (PyUnicode_Check(py_obj)) { 348*9dba64beSDimitry Andric PyObject *s = PyUnicode_AsUTF8String(py_obj); 349*9dba64beSDimitry Andric if (s == nullptr) { 350*9dba64beSDimitry Andric PyErr_Clear(); 351*9dba64beSDimitry Andric if (type == PyRefType::Owned) 352*9dba64beSDimitry Andric Py_DECREF(py_obj); 353*9dba64beSDimitry Andric return; 354*9dba64beSDimitry Andric } 355*9dba64beSDimitry Andric if (type == PyRefType::Owned) 356*9dba64beSDimitry Andric Py_DECREF(py_obj); 357*9dba64beSDimitry Andric else 358*9dba64beSDimitry Andric type = PyRefType::Owned; 359*9dba64beSDimitry Andric py_obj = s; 360*9dba64beSDimitry Andric } 3610b57cec5SDimitry Andric #endif 3620b57cec5SDimitry Andric } 3630b57cec5SDimitry Andric 3640b57cec5SDimitry Andric llvm::StringRef PythonString::GetString() const { 365*9dba64beSDimitry Andric auto s = AsUTF8(); 366*9dba64beSDimitry Andric if (!s) { 367*9dba64beSDimitry Andric llvm::consumeError(s.takeError()); 368*9dba64beSDimitry Andric return llvm::StringRef(""); 369*9dba64beSDimitry Andric } 370*9dba64beSDimitry Andric return s.get(); 371*9dba64beSDimitry Andric } 372*9dba64beSDimitry Andric 373*9dba64beSDimitry Andric Expected<llvm::StringRef> PythonString::AsUTF8() const { 3740b57cec5SDimitry Andric if (!IsValid()) 375*9dba64beSDimitry Andric return nullDeref(); 3760b57cec5SDimitry Andric 3770b57cec5SDimitry Andric Py_ssize_t size; 3780b57cec5SDimitry Andric const char *data; 3790b57cec5SDimitry Andric 3800b57cec5SDimitry Andric #if PY_MAJOR_VERSION >= 3 3810b57cec5SDimitry Andric data = PyUnicode_AsUTF8AndSize(m_py_obj, &size); 3820b57cec5SDimitry Andric #else 383*9dba64beSDimitry Andric char *c = NULL; 384*9dba64beSDimitry Andric int r = PyString_AsStringAndSize(m_py_obj, &c, &size); 385*9dba64beSDimitry Andric if (r < 0) 386*9dba64beSDimitry Andric c = NULL; 3870b57cec5SDimitry Andric data = c; 3880b57cec5SDimitry Andric #endif 389*9dba64beSDimitry Andric 390*9dba64beSDimitry Andric if (!data) 391*9dba64beSDimitry Andric return exception(); 392*9dba64beSDimitry Andric 3930b57cec5SDimitry Andric return llvm::StringRef(data, size); 3940b57cec5SDimitry Andric } 3950b57cec5SDimitry Andric 3960b57cec5SDimitry Andric size_t PythonString::GetSize() const { 3970b57cec5SDimitry Andric if (IsValid()) { 3980b57cec5SDimitry Andric #if PY_MAJOR_VERSION >= 3 3990b57cec5SDimitry Andric return PyUnicode_GetSize(m_py_obj); 4000b57cec5SDimitry Andric #else 4010b57cec5SDimitry Andric return PyString_Size(m_py_obj); 4020b57cec5SDimitry Andric #endif 4030b57cec5SDimitry Andric } 4040b57cec5SDimitry Andric return 0; 4050b57cec5SDimitry Andric } 4060b57cec5SDimitry Andric 4070b57cec5SDimitry Andric void PythonString::SetString(llvm::StringRef string) { 408*9dba64beSDimitry Andric auto s = FromUTF8(string); 409*9dba64beSDimitry Andric if (!s) { 410*9dba64beSDimitry Andric llvm::consumeError(s.takeError()); 411*9dba64beSDimitry Andric Reset(); 412*9dba64beSDimitry Andric } else { 413*9dba64beSDimitry Andric *this = std::move(s.get()); 414*9dba64beSDimitry Andric } 4150b57cec5SDimitry Andric } 4160b57cec5SDimitry Andric 4170b57cec5SDimitry Andric StructuredData::StringSP PythonString::CreateStructuredString() const { 4180b57cec5SDimitry Andric StructuredData::StringSP result(new StructuredData::String); 4190b57cec5SDimitry Andric result->SetValue(GetString()); 4200b57cec5SDimitry Andric return result; 4210b57cec5SDimitry Andric } 4220b57cec5SDimitry Andric 4230b57cec5SDimitry Andric // PythonInteger 4240b57cec5SDimitry Andric 425*9dba64beSDimitry Andric PythonInteger::PythonInteger(int64_t value) { SetInteger(value); } 4260b57cec5SDimitry Andric 4270b57cec5SDimitry Andric bool PythonInteger::Check(PyObject *py_obj) { 4280b57cec5SDimitry Andric if (!py_obj) 4290b57cec5SDimitry Andric return false; 4300b57cec5SDimitry Andric 4310b57cec5SDimitry Andric #if PY_MAJOR_VERSION >= 3 4320b57cec5SDimitry Andric // Python 3 does not have PyInt_Check. There is only one type of integral 4330b57cec5SDimitry Andric // value, long. 4340b57cec5SDimitry Andric return PyLong_Check(py_obj); 4350b57cec5SDimitry Andric #else 4360b57cec5SDimitry Andric return PyLong_Check(py_obj) || PyInt_Check(py_obj); 4370b57cec5SDimitry Andric #endif 4380b57cec5SDimitry Andric } 4390b57cec5SDimitry Andric 440*9dba64beSDimitry Andric void PythonInteger::Convert(PyRefType &type, PyObject *&py_obj) { 4410b57cec5SDimitry Andric #if PY_MAJOR_VERSION < 3 4420b57cec5SDimitry Andric // Always store this as a PyLong, which makes interoperability between Python 4430b57cec5SDimitry Andric // 2.x and Python 3.x easier. This is only necessary in 2.x, since 3.x 4440b57cec5SDimitry Andric // doesn't even have a PyInt. 4450b57cec5SDimitry Andric if (PyInt_Check(py_obj)) { 4460b57cec5SDimitry Andric // Since we converted the original object to a different type, the new 4470b57cec5SDimitry Andric // object is an owned object regardless of the ownership semantics 4480b57cec5SDimitry Andric // requested by the user. 449*9dba64beSDimitry Andric long long value = PyInt_AsLong(py_obj); 450*9dba64beSDimitry Andric PyObject *l = nullptr; 451*9dba64beSDimitry Andric if (!PyErr_Occurred()) 452*9dba64beSDimitry Andric l = PyLong_FromLongLong(value); 453*9dba64beSDimitry Andric if (l == nullptr) { 454*9dba64beSDimitry Andric PyErr_Clear(); 455*9dba64beSDimitry Andric if (type == PyRefType::Owned) 456*9dba64beSDimitry Andric Py_DECREF(py_obj); 457*9dba64beSDimitry Andric return; 458*9dba64beSDimitry Andric } 459*9dba64beSDimitry Andric if (type == PyRefType::Owned) 460*9dba64beSDimitry Andric Py_DECREF(py_obj); 461*9dba64beSDimitry Andric else 462*9dba64beSDimitry Andric type = PyRefType::Owned; 463*9dba64beSDimitry Andric py_obj = l; 4640b57cec5SDimitry Andric } 4650b57cec5SDimitry Andric #endif 4660b57cec5SDimitry Andric } 4670b57cec5SDimitry Andric 4680b57cec5SDimitry Andric int64_t PythonInteger::GetInteger() const { 4690b57cec5SDimitry Andric if (m_py_obj) { 4700b57cec5SDimitry Andric assert(PyLong_Check(m_py_obj) && 4710b57cec5SDimitry Andric "PythonInteger::GetInteger has a PyObject that isn't a PyLong"); 4720b57cec5SDimitry Andric 4730b57cec5SDimitry Andric int overflow = 0; 4740b57cec5SDimitry Andric int64_t result = PyLong_AsLongLongAndOverflow(m_py_obj, &overflow); 4750b57cec5SDimitry Andric if (overflow != 0) { 4760b57cec5SDimitry Andric // We got an integer that overflows, like 18446744072853913392L we can't 4770b57cec5SDimitry Andric // use PyLong_AsLongLong() as it will return 0xffffffffffffffff. If we 4780b57cec5SDimitry Andric // use the unsigned long long it will work as expected. 4790b57cec5SDimitry Andric const uint64_t uval = PyLong_AsUnsignedLongLong(m_py_obj); 4800b57cec5SDimitry Andric result = static_cast<int64_t>(uval); 4810b57cec5SDimitry Andric } 4820b57cec5SDimitry Andric return result; 4830b57cec5SDimitry Andric } 4840b57cec5SDimitry Andric return UINT64_MAX; 4850b57cec5SDimitry Andric } 4860b57cec5SDimitry Andric 4870b57cec5SDimitry Andric void PythonInteger::SetInteger(int64_t value) { 488*9dba64beSDimitry Andric *this = Take<PythonInteger>(PyLong_FromLongLong(value)); 4890b57cec5SDimitry Andric } 4900b57cec5SDimitry Andric 4910b57cec5SDimitry Andric StructuredData::IntegerSP PythonInteger::CreateStructuredInteger() const { 4920b57cec5SDimitry Andric StructuredData::IntegerSP result(new StructuredData::Integer); 4930b57cec5SDimitry Andric result->SetValue(GetInteger()); 4940b57cec5SDimitry Andric return result; 4950b57cec5SDimitry Andric } 4960b57cec5SDimitry Andric 4970b57cec5SDimitry Andric // PythonBoolean 4980b57cec5SDimitry Andric 4990b57cec5SDimitry Andric PythonBoolean::PythonBoolean(bool value) { 5000b57cec5SDimitry Andric SetValue(value); 5010b57cec5SDimitry Andric } 5020b57cec5SDimitry Andric 5030b57cec5SDimitry Andric bool PythonBoolean::Check(PyObject *py_obj) { 5040b57cec5SDimitry Andric return py_obj ? PyBool_Check(py_obj) : false; 5050b57cec5SDimitry Andric } 5060b57cec5SDimitry Andric 5070b57cec5SDimitry Andric bool PythonBoolean::GetValue() const { 5080b57cec5SDimitry Andric return m_py_obj ? PyObject_IsTrue(m_py_obj) : false; 5090b57cec5SDimitry Andric } 5100b57cec5SDimitry Andric 5110b57cec5SDimitry Andric void PythonBoolean::SetValue(bool value) { 512*9dba64beSDimitry Andric *this = Take<PythonBoolean>(PyBool_FromLong(value)); 5130b57cec5SDimitry Andric } 5140b57cec5SDimitry Andric 5150b57cec5SDimitry Andric StructuredData::BooleanSP PythonBoolean::CreateStructuredBoolean() const { 5160b57cec5SDimitry Andric StructuredData::BooleanSP result(new StructuredData::Boolean); 5170b57cec5SDimitry Andric result->SetValue(GetValue()); 5180b57cec5SDimitry Andric return result; 5190b57cec5SDimitry Andric } 5200b57cec5SDimitry Andric 5210b57cec5SDimitry Andric // PythonList 5220b57cec5SDimitry Andric 523*9dba64beSDimitry Andric PythonList::PythonList(PyInitialValue value) { 5240b57cec5SDimitry Andric if (value == PyInitialValue::Empty) 525*9dba64beSDimitry Andric *this = Take<PythonList>(PyList_New(0)); 5260b57cec5SDimitry Andric } 5270b57cec5SDimitry Andric 528*9dba64beSDimitry Andric PythonList::PythonList(int list_size) { 529*9dba64beSDimitry Andric *this = Take<PythonList>(PyList_New(list_size)); 5300b57cec5SDimitry Andric } 5310b57cec5SDimitry Andric 5320b57cec5SDimitry Andric bool PythonList::Check(PyObject *py_obj) { 5330b57cec5SDimitry Andric if (!py_obj) 5340b57cec5SDimitry Andric return false; 5350b57cec5SDimitry Andric return PyList_Check(py_obj); 5360b57cec5SDimitry Andric } 5370b57cec5SDimitry Andric 5380b57cec5SDimitry Andric uint32_t PythonList::GetSize() const { 5390b57cec5SDimitry Andric if (IsValid()) 5400b57cec5SDimitry Andric return PyList_GET_SIZE(m_py_obj); 5410b57cec5SDimitry Andric return 0; 5420b57cec5SDimitry Andric } 5430b57cec5SDimitry Andric 5440b57cec5SDimitry Andric PythonObject PythonList::GetItemAtIndex(uint32_t index) const { 5450b57cec5SDimitry Andric if (IsValid()) 5460b57cec5SDimitry Andric return PythonObject(PyRefType::Borrowed, PyList_GetItem(m_py_obj, index)); 5470b57cec5SDimitry Andric return PythonObject(); 5480b57cec5SDimitry Andric } 5490b57cec5SDimitry Andric 5500b57cec5SDimitry Andric void PythonList::SetItemAtIndex(uint32_t index, const PythonObject &object) { 5510b57cec5SDimitry Andric if (IsAllocated() && object.IsValid()) { 5520b57cec5SDimitry Andric // PyList_SetItem is documented to "steal" a reference, so we need to 5530b57cec5SDimitry Andric // convert it to an owned reference by incrementing it. 5540b57cec5SDimitry Andric Py_INCREF(object.get()); 5550b57cec5SDimitry Andric PyList_SetItem(m_py_obj, index, object.get()); 5560b57cec5SDimitry Andric } 5570b57cec5SDimitry Andric } 5580b57cec5SDimitry Andric 5590b57cec5SDimitry Andric void PythonList::AppendItem(const PythonObject &object) { 5600b57cec5SDimitry Andric if (IsAllocated() && object.IsValid()) { 5610b57cec5SDimitry Andric // `PyList_Append` does *not* steal a reference, so do not call `Py_INCREF` 5620b57cec5SDimitry Andric // here like we do with `PyList_SetItem`. 5630b57cec5SDimitry Andric PyList_Append(m_py_obj, object.get()); 5640b57cec5SDimitry Andric } 5650b57cec5SDimitry Andric } 5660b57cec5SDimitry Andric 5670b57cec5SDimitry Andric StructuredData::ArraySP PythonList::CreateStructuredArray() const { 5680b57cec5SDimitry Andric StructuredData::ArraySP result(new StructuredData::Array); 5690b57cec5SDimitry Andric uint32_t count = GetSize(); 5700b57cec5SDimitry Andric for (uint32_t i = 0; i < count; ++i) { 5710b57cec5SDimitry Andric PythonObject obj = GetItemAtIndex(i); 5720b57cec5SDimitry Andric result->AddItem(obj.CreateStructuredObject()); 5730b57cec5SDimitry Andric } 5740b57cec5SDimitry Andric return result; 5750b57cec5SDimitry Andric } 5760b57cec5SDimitry Andric 5770b57cec5SDimitry Andric // PythonTuple 5780b57cec5SDimitry Andric 579*9dba64beSDimitry Andric PythonTuple::PythonTuple(PyInitialValue value) { 5800b57cec5SDimitry Andric if (value == PyInitialValue::Empty) 581*9dba64beSDimitry Andric *this = Take<PythonTuple>(PyTuple_New(0)); 5820b57cec5SDimitry Andric } 5830b57cec5SDimitry Andric 584*9dba64beSDimitry Andric PythonTuple::PythonTuple(int tuple_size) { 585*9dba64beSDimitry Andric *this = Take<PythonTuple>(PyTuple_New(tuple_size)); 5860b57cec5SDimitry Andric } 5870b57cec5SDimitry Andric 5880b57cec5SDimitry Andric PythonTuple::PythonTuple(std::initializer_list<PythonObject> objects) { 5890b57cec5SDimitry Andric m_py_obj = PyTuple_New(objects.size()); 5900b57cec5SDimitry Andric 5910b57cec5SDimitry Andric uint32_t idx = 0; 5920b57cec5SDimitry Andric for (auto object : objects) { 5930b57cec5SDimitry Andric if (object.IsValid()) 5940b57cec5SDimitry Andric SetItemAtIndex(idx, object); 5950b57cec5SDimitry Andric idx++; 5960b57cec5SDimitry Andric } 5970b57cec5SDimitry Andric } 5980b57cec5SDimitry Andric 5990b57cec5SDimitry Andric PythonTuple::PythonTuple(std::initializer_list<PyObject *> objects) { 6000b57cec5SDimitry Andric m_py_obj = PyTuple_New(objects.size()); 6010b57cec5SDimitry Andric 6020b57cec5SDimitry Andric uint32_t idx = 0; 6030b57cec5SDimitry Andric for (auto py_object : objects) { 6040b57cec5SDimitry Andric PythonObject object(PyRefType::Borrowed, py_object); 6050b57cec5SDimitry Andric if (object.IsValid()) 6060b57cec5SDimitry Andric SetItemAtIndex(idx, object); 6070b57cec5SDimitry Andric idx++; 6080b57cec5SDimitry Andric } 6090b57cec5SDimitry Andric } 6100b57cec5SDimitry Andric 6110b57cec5SDimitry Andric bool PythonTuple::Check(PyObject *py_obj) { 6120b57cec5SDimitry Andric if (!py_obj) 6130b57cec5SDimitry Andric return false; 6140b57cec5SDimitry Andric return PyTuple_Check(py_obj); 6150b57cec5SDimitry Andric } 6160b57cec5SDimitry Andric 6170b57cec5SDimitry Andric uint32_t PythonTuple::GetSize() const { 6180b57cec5SDimitry Andric if (IsValid()) 6190b57cec5SDimitry Andric return PyTuple_GET_SIZE(m_py_obj); 6200b57cec5SDimitry Andric return 0; 6210b57cec5SDimitry Andric } 6220b57cec5SDimitry Andric 6230b57cec5SDimitry Andric PythonObject PythonTuple::GetItemAtIndex(uint32_t index) const { 6240b57cec5SDimitry Andric if (IsValid()) 6250b57cec5SDimitry Andric return PythonObject(PyRefType::Borrowed, PyTuple_GetItem(m_py_obj, index)); 6260b57cec5SDimitry Andric return PythonObject(); 6270b57cec5SDimitry Andric } 6280b57cec5SDimitry Andric 6290b57cec5SDimitry Andric void PythonTuple::SetItemAtIndex(uint32_t index, const PythonObject &object) { 6300b57cec5SDimitry Andric if (IsAllocated() && object.IsValid()) { 6310b57cec5SDimitry Andric // PyTuple_SetItem is documented to "steal" a reference, so we need to 6320b57cec5SDimitry Andric // convert it to an owned reference by incrementing it. 6330b57cec5SDimitry Andric Py_INCREF(object.get()); 6340b57cec5SDimitry Andric PyTuple_SetItem(m_py_obj, index, object.get()); 6350b57cec5SDimitry Andric } 6360b57cec5SDimitry Andric } 6370b57cec5SDimitry Andric 6380b57cec5SDimitry Andric StructuredData::ArraySP PythonTuple::CreateStructuredArray() const { 6390b57cec5SDimitry Andric StructuredData::ArraySP result(new StructuredData::Array); 6400b57cec5SDimitry Andric uint32_t count = GetSize(); 6410b57cec5SDimitry Andric for (uint32_t i = 0; i < count; ++i) { 6420b57cec5SDimitry Andric PythonObject obj = GetItemAtIndex(i); 6430b57cec5SDimitry Andric result->AddItem(obj.CreateStructuredObject()); 6440b57cec5SDimitry Andric } 6450b57cec5SDimitry Andric return result; 6460b57cec5SDimitry Andric } 6470b57cec5SDimitry Andric 6480b57cec5SDimitry Andric // PythonDictionary 6490b57cec5SDimitry Andric 650*9dba64beSDimitry Andric PythonDictionary::PythonDictionary(PyInitialValue value) { 6510b57cec5SDimitry Andric if (value == PyInitialValue::Empty) 652*9dba64beSDimitry Andric *this = Take<PythonDictionary>(PyDict_New()); 6530b57cec5SDimitry Andric } 6540b57cec5SDimitry Andric 6550b57cec5SDimitry Andric bool PythonDictionary::Check(PyObject *py_obj) { 6560b57cec5SDimitry Andric if (!py_obj) 6570b57cec5SDimitry Andric return false; 6580b57cec5SDimitry Andric 6590b57cec5SDimitry Andric return PyDict_Check(py_obj); 6600b57cec5SDimitry Andric } 6610b57cec5SDimitry Andric 6620b57cec5SDimitry Andric uint32_t PythonDictionary::GetSize() const { 6630b57cec5SDimitry Andric if (IsValid()) 6640b57cec5SDimitry Andric return PyDict_Size(m_py_obj); 6650b57cec5SDimitry Andric return 0; 6660b57cec5SDimitry Andric } 6670b57cec5SDimitry Andric 6680b57cec5SDimitry Andric PythonList PythonDictionary::GetKeys() const { 6690b57cec5SDimitry Andric if (IsValid()) 6700b57cec5SDimitry Andric return PythonList(PyRefType::Owned, PyDict_Keys(m_py_obj)); 6710b57cec5SDimitry Andric return PythonList(PyInitialValue::Invalid); 6720b57cec5SDimitry Andric } 6730b57cec5SDimitry Andric 6740b57cec5SDimitry Andric PythonObject PythonDictionary::GetItemForKey(const PythonObject &key) const { 675*9dba64beSDimitry Andric auto item = GetItem(key); 676*9dba64beSDimitry Andric if (!item) { 677*9dba64beSDimitry Andric llvm::consumeError(item.takeError()); 6780b57cec5SDimitry Andric return PythonObject(); 6790b57cec5SDimitry Andric } 680*9dba64beSDimitry Andric return std::move(item.get()); 681*9dba64beSDimitry Andric } 682*9dba64beSDimitry Andric 683*9dba64beSDimitry Andric Expected<PythonObject> 684*9dba64beSDimitry Andric PythonDictionary::GetItem(const PythonObject &key) const { 685*9dba64beSDimitry Andric if (!IsValid()) 686*9dba64beSDimitry Andric return nullDeref(); 687*9dba64beSDimitry Andric #if PY_MAJOR_VERSION >= 3 688*9dba64beSDimitry Andric PyObject *o = PyDict_GetItemWithError(m_py_obj, key.get()); 689*9dba64beSDimitry Andric if (PyErr_Occurred()) 690*9dba64beSDimitry Andric return exception(); 691*9dba64beSDimitry Andric #else 692*9dba64beSDimitry Andric PyObject *o = PyDict_GetItem(m_py_obj, key.get()); 693*9dba64beSDimitry Andric #endif 694*9dba64beSDimitry Andric if (!o) 695*9dba64beSDimitry Andric return keyError(); 696*9dba64beSDimitry Andric return Retain<PythonObject>(o); 697*9dba64beSDimitry Andric } 698*9dba64beSDimitry Andric 699*9dba64beSDimitry Andric Expected<PythonObject> PythonDictionary::GetItem(const Twine &key) const { 700*9dba64beSDimitry Andric if (!IsValid()) 701*9dba64beSDimitry Andric return nullDeref(); 702*9dba64beSDimitry Andric PyObject *o = PyDict_GetItemString(m_py_obj, NullTerminated(key)); 703*9dba64beSDimitry Andric if (PyErr_Occurred()) 704*9dba64beSDimitry Andric return exception(); 705*9dba64beSDimitry Andric if (!o) 706*9dba64beSDimitry Andric return keyError(); 707*9dba64beSDimitry Andric return Retain<PythonObject>(o); 708*9dba64beSDimitry Andric } 709*9dba64beSDimitry Andric 710*9dba64beSDimitry Andric Error PythonDictionary::SetItem(const PythonObject &key, 711*9dba64beSDimitry Andric const PythonObject &value) const { 712*9dba64beSDimitry Andric if (!IsValid() || !value.IsValid()) 713*9dba64beSDimitry Andric return nullDeref(); 714*9dba64beSDimitry Andric int r = PyDict_SetItem(m_py_obj, key.get(), value.get()); 715*9dba64beSDimitry Andric if (r < 0) 716*9dba64beSDimitry Andric return exception(); 717*9dba64beSDimitry Andric return Error::success(); 718*9dba64beSDimitry Andric } 719*9dba64beSDimitry Andric 720*9dba64beSDimitry Andric Error PythonDictionary::SetItem(const Twine &key, 721*9dba64beSDimitry Andric const PythonObject &value) const { 722*9dba64beSDimitry Andric if (!IsValid() || !value.IsValid()) 723*9dba64beSDimitry Andric return nullDeref(); 724*9dba64beSDimitry Andric int r = PyDict_SetItemString(m_py_obj, NullTerminated(key), value.get()); 725*9dba64beSDimitry Andric if (r < 0) 726*9dba64beSDimitry Andric return exception(); 727*9dba64beSDimitry Andric return Error::success(); 728*9dba64beSDimitry Andric } 7290b57cec5SDimitry Andric 7300b57cec5SDimitry Andric void PythonDictionary::SetItemForKey(const PythonObject &key, 7310b57cec5SDimitry Andric const PythonObject &value) { 732*9dba64beSDimitry Andric Error error = SetItem(key, value); 733*9dba64beSDimitry Andric if (error) 734*9dba64beSDimitry Andric llvm::consumeError(std::move(error)); 7350b57cec5SDimitry Andric } 7360b57cec5SDimitry Andric 7370b57cec5SDimitry Andric StructuredData::DictionarySP 7380b57cec5SDimitry Andric PythonDictionary::CreateStructuredDictionary() const { 7390b57cec5SDimitry Andric StructuredData::DictionarySP result(new StructuredData::Dictionary); 7400b57cec5SDimitry Andric PythonList keys(GetKeys()); 7410b57cec5SDimitry Andric uint32_t num_keys = keys.GetSize(); 7420b57cec5SDimitry Andric for (uint32_t i = 0; i < num_keys; ++i) { 7430b57cec5SDimitry Andric PythonObject key = keys.GetItemAtIndex(i); 7440b57cec5SDimitry Andric PythonObject value = GetItemForKey(key); 7450b57cec5SDimitry Andric StructuredData::ObjectSP structured_value = value.CreateStructuredObject(); 7460b57cec5SDimitry Andric result->AddItem(key.Str().GetString(), structured_value); 7470b57cec5SDimitry Andric } 7480b57cec5SDimitry Andric return result; 7490b57cec5SDimitry Andric } 7500b57cec5SDimitry Andric 7510b57cec5SDimitry Andric PythonModule PythonModule::BuiltinsModule() { 7520b57cec5SDimitry Andric #if PY_MAJOR_VERSION >= 3 7530b57cec5SDimitry Andric return AddModule("builtins"); 7540b57cec5SDimitry Andric #else 7550b57cec5SDimitry Andric return AddModule("__builtin__"); 7560b57cec5SDimitry Andric #endif 7570b57cec5SDimitry Andric } 7580b57cec5SDimitry Andric 7590b57cec5SDimitry Andric PythonModule PythonModule::MainModule() { return AddModule("__main__"); } 7600b57cec5SDimitry Andric 7610b57cec5SDimitry Andric PythonModule PythonModule::AddModule(llvm::StringRef module) { 7620b57cec5SDimitry Andric std::string str = module.str(); 7630b57cec5SDimitry Andric return PythonModule(PyRefType::Borrowed, PyImport_AddModule(str.c_str())); 7640b57cec5SDimitry Andric } 7650b57cec5SDimitry Andric 766*9dba64beSDimitry Andric Expected<PythonModule> PythonModule::Import(const Twine &name) { 767*9dba64beSDimitry Andric PyObject *mod = PyImport_ImportModule(NullTerminated(name)); 768*9dba64beSDimitry Andric if (!mod) 769*9dba64beSDimitry Andric return exception(); 770*9dba64beSDimitry Andric return Take<PythonModule>(mod); 771*9dba64beSDimitry Andric } 772*9dba64beSDimitry Andric 773*9dba64beSDimitry Andric Expected<PythonObject> PythonModule::Get(const Twine &name) { 774*9dba64beSDimitry Andric if (!IsValid()) 775*9dba64beSDimitry Andric return nullDeref(); 776*9dba64beSDimitry Andric PyObject *dict = PyModule_GetDict(m_py_obj); 777*9dba64beSDimitry Andric if (!dict) 778*9dba64beSDimitry Andric return exception(); 779*9dba64beSDimitry Andric PyObject *item = PyDict_GetItemString(dict, NullTerminated(name)); 780*9dba64beSDimitry Andric if (!item) 781*9dba64beSDimitry Andric return exception(); 782*9dba64beSDimitry Andric return Retain<PythonObject>(item); 7830b57cec5SDimitry Andric } 7840b57cec5SDimitry Andric 7850b57cec5SDimitry Andric bool PythonModule::Check(PyObject *py_obj) { 7860b57cec5SDimitry Andric if (!py_obj) 7870b57cec5SDimitry Andric return false; 7880b57cec5SDimitry Andric 7890b57cec5SDimitry Andric return PyModule_Check(py_obj); 7900b57cec5SDimitry Andric } 7910b57cec5SDimitry Andric 7920b57cec5SDimitry Andric PythonDictionary PythonModule::GetDictionary() const { 793*9dba64beSDimitry Andric if (!IsValid()) 794*9dba64beSDimitry Andric return PythonDictionary(); 795*9dba64beSDimitry Andric return Retain<PythonDictionary>(PyModule_GetDict(m_py_obj)); 7960b57cec5SDimitry Andric } 7970b57cec5SDimitry Andric 7980b57cec5SDimitry Andric bool PythonCallable::Check(PyObject *py_obj) { 7990b57cec5SDimitry Andric if (!py_obj) 8000b57cec5SDimitry Andric return false; 8010b57cec5SDimitry Andric 8020b57cec5SDimitry Andric return PyCallable_Check(py_obj); 8030b57cec5SDimitry Andric } 8040b57cec5SDimitry Andric 805*9dba64beSDimitry Andric PythonCallable::ArgInfo PythonCallable::GetNumInitArguments() const { 806*9dba64beSDimitry Andric auto arginfo = GetInitArgInfo(); 807*9dba64beSDimitry Andric if (!arginfo) { 808*9dba64beSDimitry Andric llvm::consumeError(arginfo.takeError()); 809*9dba64beSDimitry Andric return ArgInfo{}; 810*9dba64beSDimitry Andric } 811*9dba64beSDimitry Andric return arginfo.get(); 8120b57cec5SDimitry Andric } 8130b57cec5SDimitry Andric 814*9dba64beSDimitry Andric Expected<PythonCallable::ArgInfo> PythonCallable::GetInitArgInfo() const { 8150b57cec5SDimitry Andric if (!IsValid()) 816*9dba64beSDimitry Andric return nullDeref(); 817*9dba64beSDimitry Andric auto init = As<PythonCallable>(GetAttribute("__init__")); 818*9dba64beSDimitry Andric if (!init) 819*9dba64beSDimitry Andric return init.takeError(); 820*9dba64beSDimitry Andric return init.get().GetArgInfo(); 821*9dba64beSDimitry Andric } 8220b57cec5SDimitry Andric 823*9dba64beSDimitry Andric #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3 824*9dba64beSDimitry Andric static const char get_arg_info_script[] = R"( 825*9dba64beSDimitry Andric from inspect import signature, Parameter, ismethod 826*9dba64beSDimitry Andric from collections import namedtuple 827*9dba64beSDimitry Andric ArgInfo = namedtuple('ArgInfo', ['count', 'has_varargs', 'is_bound_method']) 828*9dba64beSDimitry Andric def main(f): 829*9dba64beSDimitry Andric count = 0 830*9dba64beSDimitry Andric varargs = False 831*9dba64beSDimitry Andric for parameter in signature(f).parameters.values(): 832*9dba64beSDimitry Andric kind = parameter.kind 833*9dba64beSDimitry Andric if kind in (Parameter.POSITIONAL_ONLY, 834*9dba64beSDimitry Andric Parameter.POSITIONAL_OR_KEYWORD): 835*9dba64beSDimitry Andric count += 1 836*9dba64beSDimitry Andric elif kind == Parameter.VAR_POSITIONAL: 837*9dba64beSDimitry Andric varargs = True 838*9dba64beSDimitry Andric elif kind in (Parameter.KEYWORD_ONLY, 839*9dba64beSDimitry Andric Parameter.VAR_KEYWORD): 840*9dba64beSDimitry Andric pass 841*9dba64beSDimitry Andric else: 842*9dba64beSDimitry Andric raise Exception(f'unknown parameter kind: {kind}') 843*9dba64beSDimitry Andric return ArgInfo(count, varargs, ismethod(f)) 844*9dba64beSDimitry Andric )"; 845*9dba64beSDimitry Andric #endif 846*9dba64beSDimitry Andric 847*9dba64beSDimitry Andric Expected<PythonCallable::ArgInfo> PythonCallable::GetArgInfo() const { 848*9dba64beSDimitry Andric ArgInfo result = {}; 849*9dba64beSDimitry Andric if (!IsValid()) 850*9dba64beSDimitry Andric return nullDeref(); 851*9dba64beSDimitry Andric 852*9dba64beSDimitry Andric #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3 853*9dba64beSDimitry Andric 854*9dba64beSDimitry Andric // no need to synchronize access to this global, we already have the GIL 855*9dba64beSDimitry Andric static PythonScript get_arg_info(get_arg_info_script); 856*9dba64beSDimitry Andric Expected<PythonObject> pyarginfo = get_arg_info(*this); 857*9dba64beSDimitry Andric if (!pyarginfo) 858*9dba64beSDimitry Andric return pyarginfo.takeError(); 859*9dba64beSDimitry Andric result.count = cantFail(As<long long>(pyarginfo.get().GetAttribute("count"))); 860*9dba64beSDimitry Andric result.has_varargs = 861*9dba64beSDimitry Andric cantFail(As<bool>(pyarginfo.get().GetAttribute("has_varargs"))); 862*9dba64beSDimitry Andric bool is_method = 863*9dba64beSDimitry Andric cantFail(As<bool>(pyarginfo.get().GetAttribute("is_bound_method"))); 864*9dba64beSDimitry Andric result.max_positional_args = 865*9dba64beSDimitry Andric result.has_varargs ? ArgInfo::UNBOUNDED : result.count; 866*9dba64beSDimitry Andric 867*9dba64beSDimitry Andric // FIXME emulate old broken behavior 868*9dba64beSDimitry Andric if (is_method) 869*9dba64beSDimitry Andric result.count++; 870*9dba64beSDimitry Andric 871*9dba64beSDimitry Andric #else 872*9dba64beSDimitry Andric bool is_bound_method = false; 8730b57cec5SDimitry Andric PyObject *py_func_obj = m_py_obj; 8740b57cec5SDimitry Andric if (PyMethod_Check(py_func_obj)) { 8750b57cec5SDimitry Andric py_func_obj = PyMethod_GET_FUNCTION(py_func_obj); 8760b57cec5SDimitry Andric PythonObject im_self = GetAttributeValue("im_self"); 8770b57cec5SDimitry Andric if (im_self.IsValid() && !im_self.IsNone()) 878*9dba64beSDimitry Andric is_bound_method = true; 8790b57cec5SDimitry Andric } else { 8800b57cec5SDimitry Andric // see if this is a callable object with an __call__ method 8810b57cec5SDimitry Andric if (!PyFunction_Check(py_func_obj)) { 8820b57cec5SDimitry Andric PythonObject __call__ = GetAttributeValue("__call__"); 8830b57cec5SDimitry Andric if (__call__.IsValid()) { 8840b57cec5SDimitry Andric auto __callable__ = __call__.AsType<PythonCallable>(); 8850b57cec5SDimitry Andric if (__callable__.IsValid()) { 8860b57cec5SDimitry Andric py_func_obj = PyMethod_GET_FUNCTION(__callable__.get()); 887*9dba64beSDimitry Andric PythonObject im_self = __callable__.GetAttributeValue("im_self"); 8880b57cec5SDimitry Andric if (im_self.IsValid() && !im_self.IsNone()) 889*9dba64beSDimitry Andric is_bound_method = true; 8900b57cec5SDimitry Andric } 8910b57cec5SDimitry Andric } 8920b57cec5SDimitry Andric } 8930b57cec5SDimitry Andric } 8940b57cec5SDimitry Andric 8950b57cec5SDimitry Andric if (!py_func_obj) 8960b57cec5SDimitry Andric return result; 8970b57cec5SDimitry Andric 8980b57cec5SDimitry Andric PyCodeObject *code = (PyCodeObject *)PyFunction_GET_CODE(py_func_obj); 8990b57cec5SDimitry Andric if (!code) 9000b57cec5SDimitry Andric return result; 9010b57cec5SDimitry Andric 9020b57cec5SDimitry Andric result.count = code->co_argcount; 9030b57cec5SDimitry Andric result.has_varargs = !!(code->co_flags & CO_VARARGS); 904*9dba64beSDimitry Andric result.max_positional_args = result.has_varargs 905*9dba64beSDimitry Andric ? ArgInfo::UNBOUNDED 906*9dba64beSDimitry Andric : (result.count - (int)is_bound_method); 907*9dba64beSDimitry Andric 908*9dba64beSDimitry Andric #endif 909*9dba64beSDimitry Andric 9100b57cec5SDimitry Andric return result; 9110b57cec5SDimitry Andric } 9120b57cec5SDimitry Andric 913*9dba64beSDimitry Andric constexpr unsigned 914*9dba64beSDimitry Andric PythonCallable::ArgInfo::UNBOUNDED; // FIXME delete after c++17 915*9dba64beSDimitry Andric 916*9dba64beSDimitry Andric PythonCallable::ArgInfo PythonCallable::GetNumArguments() const { 917*9dba64beSDimitry Andric auto arginfo = GetArgInfo(); 918*9dba64beSDimitry Andric if (!arginfo) { 919*9dba64beSDimitry Andric llvm::consumeError(arginfo.takeError()); 920*9dba64beSDimitry Andric return ArgInfo{}; 921*9dba64beSDimitry Andric } 922*9dba64beSDimitry Andric return arginfo.get(); 923*9dba64beSDimitry Andric } 924*9dba64beSDimitry Andric 9250b57cec5SDimitry Andric PythonObject PythonCallable::operator()() { 9260b57cec5SDimitry Andric return PythonObject(PyRefType::Owned, PyObject_CallObject(m_py_obj, nullptr)); 9270b57cec5SDimitry Andric } 9280b57cec5SDimitry Andric 9290b57cec5SDimitry Andric PythonObject PythonCallable:: 9300b57cec5SDimitry Andric operator()(std::initializer_list<PyObject *> args) { 9310b57cec5SDimitry Andric PythonTuple arg_tuple(args); 9320b57cec5SDimitry Andric return PythonObject(PyRefType::Owned, 9330b57cec5SDimitry Andric PyObject_CallObject(m_py_obj, arg_tuple.get())); 9340b57cec5SDimitry Andric } 9350b57cec5SDimitry Andric 9360b57cec5SDimitry Andric PythonObject PythonCallable:: 9370b57cec5SDimitry Andric operator()(std::initializer_list<PythonObject> args) { 9380b57cec5SDimitry Andric PythonTuple arg_tuple(args); 9390b57cec5SDimitry Andric return PythonObject(PyRefType::Owned, 9400b57cec5SDimitry Andric PyObject_CallObject(m_py_obj, arg_tuple.get())); 9410b57cec5SDimitry Andric } 9420b57cec5SDimitry Andric 9430b57cec5SDimitry Andric bool PythonFile::Check(PyObject *py_obj) { 944*9dba64beSDimitry Andric if (!py_obj) 945*9dba64beSDimitry Andric return false; 9460b57cec5SDimitry Andric #if PY_MAJOR_VERSION < 3 9470b57cec5SDimitry Andric return PyFile_Check(py_obj); 9480b57cec5SDimitry Andric #else 9490b57cec5SDimitry Andric // In Python 3, there is no `PyFile_Check`, and in fact PyFile is not even a 9500b57cec5SDimitry Andric // first-class object type anymore. `PyFile_FromFd` is just a thin wrapper 9510b57cec5SDimitry Andric // over `io.open()`, which returns some object derived from `io.IOBase`. As a 9520b57cec5SDimitry Andric // result, the only way to detect a file in Python 3 is to check whether it 953*9dba64beSDimitry Andric // inherits from `io.IOBase`. 954*9dba64beSDimitry Andric auto io_module = PythonModule::Import("io"); 955*9dba64beSDimitry Andric if (!io_module) { 956*9dba64beSDimitry Andric llvm::consumeError(io_module.takeError()); 9570b57cec5SDimitry Andric return false; 958*9dba64beSDimitry Andric } 959*9dba64beSDimitry Andric auto iobase = io_module.get().Get("IOBase"); 960*9dba64beSDimitry Andric if (!iobase) { 961*9dba64beSDimitry Andric llvm::consumeError(iobase.takeError()); 9620b57cec5SDimitry Andric return false; 963*9dba64beSDimitry Andric } 964*9dba64beSDimitry Andric int r = PyObject_IsInstance(py_obj, iobase.get().get()); 965*9dba64beSDimitry Andric if (r < 0) { 966*9dba64beSDimitry Andric llvm::consumeError(exception()); // clear the exception and log it. 967*9dba64beSDimitry Andric return false; 968*9dba64beSDimitry Andric } 969*9dba64beSDimitry Andric return !!r; 9700b57cec5SDimitry Andric #endif 9710b57cec5SDimitry Andric } 9720b57cec5SDimitry Andric 973*9dba64beSDimitry Andric namespace { 974*9dba64beSDimitry Andric class GIL { 975*9dba64beSDimitry Andric public: 976*9dba64beSDimitry Andric GIL() { 977*9dba64beSDimitry Andric m_state = PyGILState_Ensure(); 978*9dba64beSDimitry Andric assert(!PyErr_Occurred()); 979*9dba64beSDimitry Andric } 980*9dba64beSDimitry Andric ~GIL() { PyGILState_Release(m_state); } 9810b57cec5SDimitry Andric 982*9dba64beSDimitry Andric protected: 983*9dba64beSDimitry Andric PyGILState_STATE m_state; 984*9dba64beSDimitry Andric }; 985*9dba64beSDimitry Andric } // namespace 986*9dba64beSDimitry Andric 987*9dba64beSDimitry Andric const char *PythonException::toCString() const { 988*9dba64beSDimitry Andric if (!m_repr_bytes) 989*9dba64beSDimitry Andric return "unknown exception"; 990*9dba64beSDimitry Andric return PyBytes_AS_STRING(m_repr_bytes); 9910b57cec5SDimitry Andric } 9920b57cec5SDimitry Andric 993*9dba64beSDimitry Andric PythonException::PythonException(const char *caller) { 994*9dba64beSDimitry Andric assert(PyErr_Occurred()); 995*9dba64beSDimitry Andric m_exception_type = m_exception = m_traceback = m_repr_bytes = NULL; 996*9dba64beSDimitry Andric PyErr_Fetch(&m_exception_type, &m_exception, &m_traceback); 997*9dba64beSDimitry Andric PyErr_NormalizeException(&m_exception_type, &m_exception, &m_traceback); 998*9dba64beSDimitry Andric PyErr_Clear(); 999*9dba64beSDimitry Andric if (m_exception) { 1000*9dba64beSDimitry Andric PyObject *repr = PyObject_Repr(m_exception); 1001*9dba64beSDimitry Andric if (repr) { 1002*9dba64beSDimitry Andric m_repr_bytes = PyUnicode_AsEncodedString(repr, "utf-8", nullptr); 1003*9dba64beSDimitry Andric if (!m_repr_bytes) { 1004*9dba64beSDimitry Andric PyErr_Clear(); 1005*9dba64beSDimitry Andric } 1006*9dba64beSDimitry Andric Py_XDECREF(repr); 1007*9dba64beSDimitry Andric } else { 1008*9dba64beSDimitry Andric PyErr_Clear(); 1009*9dba64beSDimitry Andric } 1010*9dba64beSDimitry Andric } 1011*9dba64beSDimitry Andric Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT); 1012*9dba64beSDimitry Andric if (caller) 1013*9dba64beSDimitry Andric LLDB_LOGF(log, "%s failed with exception: %s", caller, toCString()); 1014*9dba64beSDimitry Andric else 1015*9dba64beSDimitry Andric LLDB_LOGF(log, "python exception: %s", toCString()); 1016*9dba64beSDimitry Andric } 1017*9dba64beSDimitry Andric void PythonException::Restore() { 1018*9dba64beSDimitry Andric if (m_exception_type && m_exception) { 1019*9dba64beSDimitry Andric PyErr_Restore(m_exception_type, m_exception, m_traceback); 1020*9dba64beSDimitry Andric } else { 1021*9dba64beSDimitry Andric PyErr_SetString(PyExc_Exception, toCString()); 1022*9dba64beSDimitry Andric } 1023*9dba64beSDimitry Andric m_exception_type = m_exception = m_traceback = NULL; 10240b57cec5SDimitry Andric } 10250b57cec5SDimitry Andric 1026*9dba64beSDimitry Andric PythonException::~PythonException() { 1027*9dba64beSDimitry Andric Py_XDECREF(m_exception_type); 1028*9dba64beSDimitry Andric Py_XDECREF(m_exception); 1029*9dba64beSDimitry Andric Py_XDECREF(m_traceback); 1030*9dba64beSDimitry Andric Py_XDECREF(m_repr_bytes); 10310b57cec5SDimitry Andric } 10320b57cec5SDimitry Andric 1033*9dba64beSDimitry Andric void PythonException::log(llvm::raw_ostream &OS) const { OS << toCString(); } 1034*9dba64beSDimitry Andric 1035*9dba64beSDimitry Andric std::error_code PythonException::convertToErrorCode() const { 1036*9dba64beSDimitry Andric return llvm::inconvertibleErrorCode(); 1037*9dba64beSDimitry Andric } 1038*9dba64beSDimitry Andric 1039*9dba64beSDimitry Andric bool PythonException::Matches(PyObject *exc) const { 1040*9dba64beSDimitry Andric return PyErr_GivenExceptionMatches(m_exception_type, exc); 1041*9dba64beSDimitry Andric } 1042*9dba64beSDimitry Andric 1043*9dba64beSDimitry Andric const char read_exception_script[] = R"( 1044*9dba64beSDimitry Andric import sys 1045*9dba64beSDimitry Andric from traceback import print_exception 1046*9dba64beSDimitry Andric if sys.version_info.major < 3: 1047*9dba64beSDimitry Andric from StringIO import StringIO 1048*9dba64beSDimitry Andric else: 1049*9dba64beSDimitry Andric from io import StringIO 1050*9dba64beSDimitry Andric def main(exc_type, exc_value, tb): 1051*9dba64beSDimitry Andric f = StringIO() 1052*9dba64beSDimitry Andric print_exception(exc_type, exc_value, tb, file=f) 1053*9dba64beSDimitry Andric return f.getvalue() 1054*9dba64beSDimitry Andric )"; 1055*9dba64beSDimitry Andric 1056*9dba64beSDimitry Andric std::string PythonException::ReadBacktrace() const { 1057*9dba64beSDimitry Andric 1058*9dba64beSDimitry Andric if (!m_traceback) 1059*9dba64beSDimitry Andric return toCString(); 1060*9dba64beSDimitry Andric 1061*9dba64beSDimitry Andric // no need to synchronize access to this global, we already have the GIL 1062*9dba64beSDimitry Andric static PythonScript read_exception(read_exception_script); 1063*9dba64beSDimitry Andric 1064*9dba64beSDimitry Andric Expected<std::string> backtrace = As<std::string>( 1065*9dba64beSDimitry Andric read_exception(m_exception_type, m_exception, m_traceback)); 1066*9dba64beSDimitry Andric 1067*9dba64beSDimitry Andric if (!backtrace) { 1068*9dba64beSDimitry Andric std::string message = 1069*9dba64beSDimitry Andric std::string(toCString()) + "\n" + 1070*9dba64beSDimitry Andric "Traceback unavailble, an error occurred while reading it:\n"; 1071*9dba64beSDimitry Andric return (message + llvm::toString(backtrace.takeError())); 1072*9dba64beSDimitry Andric } 1073*9dba64beSDimitry Andric 1074*9dba64beSDimitry Andric return std::move(backtrace.get()); 1075*9dba64beSDimitry Andric } 1076*9dba64beSDimitry Andric 1077*9dba64beSDimitry Andric char PythonException::ID = 0; 1078*9dba64beSDimitry Andric 1079*9dba64beSDimitry Andric llvm::Expected<File::OpenOptions> 1080*9dba64beSDimitry Andric GetOptionsForPyObject(const PythonObject &obj) { 10810b57cec5SDimitry Andric #if PY_MAJOR_VERSION >= 3 1082*9dba64beSDimitry Andric auto options = File::OpenOptions(0); 1083*9dba64beSDimitry Andric auto readable = As<bool>(obj.CallMethod("readable")); 1084*9dba64beSDimitry Andric if (!readable) 1085*9dba64beSDimitry Andric return readable.takeError(); 1086*9dba64beSDimitry Andric auto writable = As<bool>(obj.CallMethod("writable")); 1087*9dba64beSDimitry Andric if (!writable) 1088*9dba64beSDimitry Andric return writable.takeError(); 1089*9dba64beSDimitry Andric if (readable.get()) 1090*9dba64beSDimitry Andric options |= File::eOpenOptionRead; 1091*9dba64beSDimitry Andric if (writable.get()) 1092*9dba64beSDimitry Andric options |= File::eOpenOptionWrite; 1093*9dba64beSDimitry Andric return options; 1094*9dba64beSDimitry Andric #else 1095*9dba64beSDimitry Andric PythonString py_mode = obj.GetAttributeValue("mode").AsType<PythonString>(); 1096*9dba64beSDimitry Andric return File::GetOptionsFromMode(py_mode.GetString()); 1097*9dba64beSDimitry Andric #endif 1098*9dba64beSDimitry Andric } 1099*9dba64beSDimitry Andric 1100*9dba64beSDimitry Andric // Base class template for python files. All it knows how to do 1101*9dba64beSDimitry Andric // is hold a reference to the python object and close or flush it 1102*9dba64beSDimitry Andric // when the File is closed. 1103*9dba64beSDimitry Andric namespace { 1104*9dba64beSDimitry Andric template <typename Base> class OwnedPythonFile : public Base { 1105*9dba64beSDimitry Andric public: 1106*9dba64beSDimitry Andric template <typename... Args> 1107*9dba64beSDimitry Andric OwnedPythonFile(const PythonFile &file, bool borrowed, Args... args) 1108*9dba64beSDimitry Andric : Base(args...), m_py_obj(file), m_borrowed(borrowed) { 1109*9dba64beSDimitry Andric assert(m_py_obj); 1110*9dba64beSDimitry Andric } 1111*9dba64beSDimitry Andric 1112*9dba64beSDimitry Andric ~OwnedPythonFile() override { 1113*9dba64beSDimitry Andric assert(m_py_obj); 1114*9dba64beSDimitry Andric GIL takeGIL; 1115*9dba64beSDimitry Andric Close(); 1116*9dba64beSDimitry Andric // we need to ensure the python object is released while we still 1117*9dba64beSDimitry Andric // hold the GIL 1118*9dba64beSDimitry Andric m_py_obj.Reset(); 1119*9dba64beSDimitry Andric } 1120*9dba64beSDimitry Andric 1121*9dba64beSDimitry Andric bool IsPythonSideValid() const { 1122*9dba64beSDimitry Andric GIL takeGIL; 1123*9dba64beSDimitry Andric auto closed = As<bool>(m_py_obj.GetAttribute("closed")); 1124*9dba64beSDimitry Andric if (!closed) { 1125*9dba64beSDimitry Andric llvm::consumeError(closed.takeError()); 1126*9dba64beSDimitry Andric return false; 1127*9dba64beSDimitry Andric } 1128*9dba64beSDimitry Andric return !closed.get(); 1129*9dba64beSDimitry Andric } 1130*9dba64beSDimitry Andric 1131*9dba64beSDimitry Andric bool IsValid() const override { 1132*9dba64beSDimitry Andric return IsPythonSideValid() && Base::IsValid(); 1133*9dba64beSDimitry Andric } 1134*9dba64beSDimitry Andric 1135*9dba64beSDimitry Andric Status Close() override { 1136*9dba64beSDimitry Andric assert(m_py_obj); 1137*9dba64beSDimitry Andric Status py_error, base_error; 1138*9dba64beSDimitry Andric GIL takeGIL; 1139*9dba64beSDimitry Andric if (!m_borrowed) { 1140*9dba64beSDimitry Andric auto r = m_py_obj.CallMethod("close"); 1141*9dba64beSDimitry Andric if (!r) 1142*9dba64beSDimitry Andric py_error = Status(r.takeError()); 1143*9dba64beSDimitry Andric } 1144*9dba64beSDimitry Andric base_error = Base::Close(); 1145*9dba64beSDimitry Andric if (py_error.Fail()) 1146*9dba64beSDimitry Andric return py_error; 1147*9dba64beSDimitry Andric return base_error; 1148*9dba64beSDimitry Andric }; 1149*9dba64beSDimitry Andric 1150*9dba64beSDimitry Andric PyObject *GetPythonObject() const { 1151*9dba64beSDimitry Andric assert(m_py_obj.IsValid()); 1152*9dba64beSDimitry Andric return m_py_obj.get(); 1153*9dba64beSDimitry Andric } 1154*9dba64beSDimitry Andric 1155*9dba64beSDimitry Andric static bool classof(const File *file) = delete; 1156*9dba64beSDimitry Andric 1157*9dba64beSDimitry Andric protected: 1158*9dba64beSDimitry Andric PythonFile m_py_obj; 1159*9dba64beSDimitry Andric bool m_borrowed; 1160*9dba64beSDimitry Andric }; 1161*9dba64beSDimitry Andric } // namespace 1162*9dba64beSDimitry Andric 1163*9dba64beSDimitry Andric // A SimplePythonFile is a OwnedPythonFile that just does all I/O as 1164*9dba64beSDimitry Andric // a NativeFile 1165*9dba64beSDimitry Andric namespace { 1166*9dba64beSDimitry Andric class SimplePythonFile : public OwnedPythonFile<NativeFile> { 1167*9dba64beSDimitry Andric public: 1168*9dba64beSDimitry Andric SimplePythonFile(const PythonFile &file, bool borrowed, int fd, 1169*9dba64beSDimitry Andric File::OpenOptions options) 1170*9dba64beSDimitry Andric : OwnedPythonFile(file, borrowed, fd, options, false) {} 1171*9dba64beSDimitry Andric 1172*9dba64beSDimitry Andric static char ID; 1173*9dba64beSDimitry Andric bool isA(const void *classID) const override { 1174*9dba64beSDimitry Andric return classID == &ID || NativeFile::isA(classID); 1175*9dba64beSDimitry Andric } 1176*9dba64beSDimitry Andric static bool classof(const File *file) { return file->isA(&ID); } 1177*9dba64beSDimitry Andric }; 1178*9dba64beSDimitry Andric char SimplePythonFile::ID = 0; 1179*9dba64beSDimitry Andric } // namespace 1180*9dba64beSDimitry Andric 1181*9dba64beSDimitry Andric #if PY_MAJOR_VERSION >= 3 1182*9dba64beSDimitry Andric 1183*9dba64beSDimitry Andric namespace { 1184*9dba64beSDimitry Andric class PythonBuffer { 1185*9dba64beSDimitry Andric public: 1186*9dba64beSDimitry Andric PythonBuffer &operator=(const PythonBuffer &) = delete; 1187*9dba64beSDimitry Andric PythonBuffer(const PythonBuffer &) = delete; 1188*9dba64beSDimitry Andric 1189*9dba64beSDimitry Andric static Expected<PythonBuffer> Create(PythonObject &obj, 1190*9dba64beSDimitry Andric int flags = PyBUF_SIMPLE) { 1191*9dba64beSDimitry Andric Py_buffer py_buffer = {}; 1192*9dba64beSDimitry Andric PyObject_GetBuffer(obj.get(), &py_buffer, flags); 1193*9dba64beSDimitry Andric if (!py_buffer.obj) 1194*9dba64beSDimitry Andric return llvm::make_error<PythonException>(); 1195*9dba64beSDimitry Andric return PythonBuffer(py_buffer); 1196*9dba64beSDimitry Andric } 1197*9dba64beSDimitry Andric 1198*9dba64beSDimitry Andric PythonBuffer(PythonBuffer &&other) { 1199*9dba64beSDimitry Andric m_buffer = other.m_buffer; 1200*9dba64beSDimitry Andric other.m_buffer.obj = nullptr; 1201*9dba64beSDimitry Andric } 1202*9dba64beSDimitry Andric 1203*9dba64beSDimitry Andric ~PythonBuffer() { 1204*9dba64beSDimitry Andric if (m_buffer.obj) 1205*9dba64beSDimitry Andric PyBuffer_Release(&m_buffer); 1206*9dba64beSDimitry Andric } 1207*9dba64beSDimitry Andric 1208*9dba64beSDimitry Andric Py_buffer &get() { return m_buffer; } 1209*9dba64beSDimitry Andric 1210*9dba64beSDimitry Andric private: 1211*9dba64beSDimitry Andric // takes ownership of the buffer. 1212*9dba64beSDimitry Andric PythonBuffer(const Py_buffer &py_buffer) : m_buffer(py_buffer) {} 1213*9dba64beSDimitry Andric Py_buffer m_buffer; 1214*9dba64beSDimitry Andric }; 1215*9dba64beSDimitry Andric } // namespace 1216*9dba64beSDimitry Andric 1217*9dba64beSDimitry Andric // Shared methods between TextPythonFile and BinaryPythonFile 1218*9dba64beSDimitry Andric namespace { 1219*9dba64beSDimitry Andric class PythonIOFile : public OwnedPythonFile<File> { 1220*9dba64beSDimitry Andric public: 1221*9dba64beSDimitry Andric PythonIOFile(const PythonFile &file, bool borrowed) 1222*9dba64beSDimitry Andric : OwnedPythonFile(file, borrowed) {} 1223*9dba64beSDimitry Andric 1224*9dba64beSDimitry Andric ~PythonIOFile() override { Close(); } 1225*9dba64beSDimitry Andric 1226*9dba64beSDimitry Andric bool IsValid() const override { return IsPythonSideValid(); } 1227*9dba64beSDimitry Andric 1228*9dba64beSDimitry Andric Status Close() override { 1229*9dba64beSDimitry Andric assert(m_py_obj); 1230*9dba64beSDimitry Andric GIL takeGIL; 1231*9dba64beSDimitry Andric if (m_borrowed) 1232*9dba64beSDimitry Andric return Flush(); 1233*9dba64beSDimitry Andric auto r = m_py_obj.CallMethod("close"); 1234*9dba64beSDimitry Andric if (!r) 1235*9dba64beSDimitry Andric return Status(r.takeError()); 1236*9dba64beSDimitry Andric return Status(); 1237*9dba64beSDimitry Andric } 1238*9dba64beSDimitry Andric 1239*9dba64beSDimitry Andric Status Flush() override { 1240*9dba64beSDimitry Andric GIL takeGIL; 1241*9dba64beSDimitry Andric auto r = m_py_obj.CallMethod("flush"); 1242*9dba64beSDimitry Andric if (!r) 1243*9dba64beSDimitry Andric return Status(r.takeError()); 1244*9dba64beSDimitry Andric return Status(); 1245*9dba64beSDimitry Andric } 1246*9dba64beSDimitry Andric 1247*9dba64beSDimitry Andric Expected<File::OpenOptions> GetOptions() const override { 1248*9dba64beSDimitry Andric GIL takeGIL; 1249*9dba64beSDimitry Andric return GetOptionsForPyObject(m_py_obj); 1250*9dba64beSDimitry Andric } 1251*9dba64beSDimitry Andric 1252*9dba64beSDimitry Andric static char ID; 1253*9dba64beSDimitry Andric bool isA(const void *classID) const override { 1254*9dba64beSDimitry Andric return classID == &ID || File::isA(classID); 1255*9dba64beSDimitry Andric } 1256*9dba64beSDimitry Andric static bool classof(const File *file) { return file->isA(&ID); } 1257*9dba64beSDimitry Andric }; 1258*9dba64beSDimitry Andric char PythonIOFile::ID = 0; 1259*9dba64beSDimitry Andric } // namespace 1260*9dba64beSDimitry Andric 1261*9dba64beSDimitry Andric namespace { 1262*9dba64beSDimitry Andric class BinaryPythonFile : public PythonIOFile { 1263*9dba64beSDimitry Andric protected: 1264*9dba64beSDimitry Andric int m_descriptor; 1265*9dba64beSDimitry Andric 1266*9dba64beSDimitry Andric public: 1267*9dba64beSDimitry Andric BinaryPythonFile(int fd, const PythonFile &file, bool borrowed) 1268*9dba64beSDimitry Andric : PythonIOFile(file, borrowed), 1269*9dba64beSDimitry Andric m_descriptor(File::DescriptorIsValid(fd) ? fd 1270*9dba64beSDimitry Andric : File::kInvalidDescriptor) {} 1271*9dba64beSDimitry Andric 1272*9dba64beSDimitry Andric int GetDescriptor() const override { return m_descriptor; } 1273*9dba64beSDimitry Andric 1274*9dba64beSDimitry Andric Status Write(const void *buf, size_t &num_bytes) override { 1275*9dba64beSDimitry Andric GIL takeGIL; 1276*9dba64beSDimitry Andric PyObject *pybuffer_p = PyMemoryView_FromMemory( 1277*9dba64beSDimitry Andric const_cast<char *>((const char *)buf), num_bytes, PyBUF_READ); 1278*9dba64beSDimitry Andric if (!pybuffer_p) 1279*9dba64beSDimitry Andric return Status(llvm::make_error<PythonException>()); 1280*9dba64beSDimitry Andric auto pybuffer = Take<PythonObject>(pybuffer_p); 1281*9dba64beSDimitry Andric num_bytes = 0; 1282*9dba64beSDimitry Andric auto bytes_written = As<long long>(m_py_obj.CallMethod("write", pybuffer)); 1283*9dba64beSDimitry Andric if (!bytes_written) 1284*9dba64beSDimitry Andric return Status(bytes_written.takeError()); 1285*9dba64beSDimitry Andric if (bytes_written.get() < 0) 1286*9dba64beSDimitry Andric return Status(".write() method returned a negative number!"); 1287*9dba64beSDimitry Andric static_assert(sizeof(long long) >= sizeof(size_t), "overflow"); 1288*9dba64beSDimitry Andric num_bytes = bytes_written.get(); 1289*9dba64beSDimitry Andric return Status(); 1290*9dba64beSDimitry Andric } 1291*9dba64beSDimitry Andric 1292*9dba64beSDimitry Andric Status Read(void *buf, size_t &num_bytes) override { 1293*9dba64beSDimitry Andric GIL takeGIL; 1294*9dba64beSDimitry Andric static_assert(sizeof(long long) >= sizeof(size_t), "overflow"); 1295*9dba64beSDimitry Andric auto pybuffer_obj = 1296*9dba64beSDimitry Andric m_py_obj.CallMethod("read", (unsigned long long)num_bytes); 1297*9dba64beSDimitry Andric if (!pybuffer_obj) 1298*9dba64beSDimitry Andric return Status(pybuffer_obj.takeError()); 1299*9dba64beSDimitry Andric num_bytes = 0; 1300*9dba64beSDimitry Andric if (pybuffer_obj.get().IsNone()) { 1301*9dba64beSDimitry Andric // EOF 1302*9dba64beSDimitry Andric num_bytes = 0; 1303*9dba64beSDimitry Andric return Status(); 1304*9dba64beSDimitry Andric } 1305*9dba64beSDimitry Andric auto pybuffer = PythonBuffer::Create(pybuffer_obj.get()); 1306*9dba64beSDimitry Andric if (!pybuffer) 1307*9dba64beSDimitry Andric return Status(pybuffer.takeError()); 1308*9dba64beSDimitry Andric memcpy(buf, pybuffer.get().get().buf, pybuffer.get().get().len); 1309*9dba64beSDimitry Andric num_bytes = pybuffer.get().get().len; 1310*9dba64beSDimitry Andric return Status(); 1311*9dba64beSDimitry Andric } 1312*9dba64beSDimitry Andric }; 1313*9dba64beSDimitry Andric } // namespace 1314*9dba64beSDimitry Andric 1315*9dba64beSDimitry Andric namespace { 1316*9dba64beSDimitry Andric class TextPythonFile : public PythonIOFile { 1317*9dba64beSDimitry Andric protected: 1318*9dba64beSDimitry Andric int m_descriptor; 1319*9dba64beSDimitry Andric 1320*9dba64beSDimitry Andric public: 1321*9dba64beSDimitry Andric TextPythonFile(int fd, const PythonFile &file, bool borrowed) 1322*9dba64beSDimitry Andric : PythonIOFile(file, borrowed), 1323*9dba64beSDimitry Andric m_descriptor(File::DescriptorIsValid(fd) ? fd 1324*9dba64beSDimitry Andric : File::kInvalidDescriptor) {} 1325*9dba64beSDimitry Andric 1326*9dba64beSDimitry Andric int GetDescriptor() const override { return m_descriptor; } 1327*9dba64beSDimitry Andric 1328*9dba64beSDimitry Andric Status Write(const void *buf, size_t &num_bytes) override { 1329*9dba64beSDimitry Andric GIL takeGIL; 1330*9dba64beSDimitry Andric auto pystring = 1331*9dba64beSDimitry Andric PythonString::FromUTF8(llvm::StringRef((const char *)buf, num_bytes)); 1332*9dba64beSDimitry Andric if (!pystring) 1333*9dba64beSDimitry Andric return Status(pystring.takeError()); 1334*9dba64beSDimitry Andric num_bytes = 0; 1335*9dba64beSDimitry Andric auto bytes_written = 1336*9dba64beSDimitry Andric As<long long>(m_py_obj.CallMethod("write", pystring.get())); 1337*9dba64beSDimitry Andric if (!bytes_written) 1338*9dba64beSDimitry Andric return Status(bytes_written.takeError()); 1339*9dba64beSDimitry Andric if (bytes_written.get() < 0) 1340*9dba64beSDimitry Andric return Status(".write() method returned a negative number!"); 1341*9dba64beSDimitry Andric static_assert(sizeof(long long) >= sizeof(size_t), "overflow"); 1342*9dba64beSDimitry Andric num_bytes = bytes_written.get(); 1343*9dba64beSDimitry Andric return Status(); 1344*9dba64beSDimitry Andric } 1345*9dba64beSDimitry Andric 1346*9dba64beSDimitry Andric Status Read(void *buf, size_t &num_bytes) override { 1347*9dba64beSDimitry Andric GIL takeGIL; 1348*9dba64beSDimitry Andric size_t num_chars = num_bytes / 6; 1349*9dba64beSDimitry Andric size_t orig_num_bytes = num_bytes; 1350*9dba64beSDimitry Andric num_bytes = 0; 1351*9dba64beSDimitry Andric if (orig_num_bytes < 6) { 1352*9dba64beSDimitry Andric return Status("can't read less than 6 bytes from a utf8 text stream"); 1353*9dba64beSDimitry Andric } 1354*9dba64beSDimitry Andric auto pystring = As<PythonString>( 1355*9dba64beSDimitry Andric m_py_obj.CallMethod("read", (unsigned long long)num_chars)); 1356*9dba64beSDimitry Andric if (!pystring) 1357*9dba64beSDimitry Andric return Status(pystring.takeError()); 1358*9dba64beSDimitry Andric if (pystring.get().IsNone()) { 1359*9dba64beSDimitry Andric // EOF 1360*9dba64beSDimitry Andric return Status(); 1361*9dba64beSDimitry Andric } 1362*9dba64beSDimitry Andric auto stringref = pystring.get().AsUTF8(); 1363*9dba64beSDimitry Andric if (!stringref) 1364*9dba64beSDimitry Andric return Status(stringref.takeError()); 1365*9dba64beSDimitry Andric num_bytes = stringref.get().size(); 1366*9dba64beSDimitry Andric memcpy(buf, stringref.get().begin(), num_bytes); 1367*9dba64beSDimitry Andric return Status(); 1368*9dba64beSDimitry Andric } 1369*9dba64beSDimitry Andric }; 1370*9dba64beSDimitry Andric } // namespace 1371*9dba64beSDimitry Andric 1372*9dba64beSDimitry Andric #endif 1373*9dba64beSDimitry Andric 1374*9dba64beSDimitry Andric llvm::Expected<FileSP> PythonFile::ConvertToFile(bool borrowed) { 1375*9dba64beSDimitry Andric if (!IsValid()) 1376*9dba64beSDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(), 1377*9dba64beSDimitry Andric "invalid PythonFile"); 1378*9dba64beSDimitry Andric 1379*9dba64beSDimitry Andric int fd = PyObject_AsFileDescriptor(m_py_obj); 1380*9dba64beSDimitry Andric if (fd < 0) { 1381*9dba64beSDimitry Andric PyErr_Clear(); 1382*9dba64beSDimitry Andric return ConvertToFileForcingUseOfScriptingIOMethods(borrowed); 1383*9dba64beSDimitry Andric } 1384*9dba64beSDimitry Andric auto options = GetOptionsForPyObject(*this); 1385*9dba64beSDimitry Andric if (!options) 1386*9dba64beSDimitry Andric return options.takeError(); 1387*9dba64beSDimitry Andric 1388*9dba64beSDimitry Andric // LLDB and python will not share I/O buffers. We should probably 1389*9dba64beSDimitry Andric // flush the python buffers now. 1390*9dba64beSDimitry Andric auto r = CallMethod("flush"); 1391*9dba64beSDimitry Andric if (!r) 1392*9dba64beSDimitry Andric return r.takeError(); 1393*9dba64beSDimitry Andric 1394*9dba64beSDimitry Andric FileSP file_sp; 1395*9dba64beSDimitry Andric if (borrowed) { 1396*9dba64beSDimitry Andric // In this case we we don't need to retain the python 1397*9dba64beSDimitry Andric // object at all. 1398*9dba64beSDimitry Andric file_sp = std::make_shared<NativeFile>(fd, options.get(), false); 1399*9dba64beSDimitry Andric } else { 1400*9dba64beSDimitry Andric file_sp = std::static_pointer_cast<File>( 1401*9dba64beSDimitry Andric std::make_shared<SimplePythonFile>(*this, borrowed, fd, options.get())); 1402*9dba64beSDimitry Andric } 1403*9dba64beSDimitry Andric if (!file_sp->IsValid()) 1404*9dba64beSDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(), 1405*9dba64beSDimitry Andric "invalid File"); 1406*9dba64beSDimitry Andric 1407*9dba64beSDimitry Andric return file_sp; 1408*9dba64beSDimitry Andric } 1409*9dba64beSDimitry Andric 1410*9dba64beSDimitry Andric llvm::Expected<FileSP> 1411*9dba64beSDimitry Andric PythonFile::ConvertToFileForcingUseOfScriptingIOMethods(bool borrowed) { 1412*9dba64beSDimitry Andric 1413*9dba64beSDimitry Andric assert(!PyErr_Occurred()); 1414*9dba64beSDimitry Andric 1415*9dba64beSDimitry Andric if (!IsValid()) 1416*9dba64beSDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(), 1417*9dba64beSDimitry Andric "invalid PythonFile"); 1418*9dba64beSDimitry Andric 1419*9dba64beSDimitry Andric #if PY_MAJOR_VERSION < 3 1420*9dba64beSDimitry Andric 1421*9dba64beSDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(), 1422*9dba64beSDimitry Andric "not supported on python 2"); 1423*9dba64beSDimitry Andric 1424*9dba64beSDimitry Andric #else 1425*9dba64beSDimitry Andric 1426*9dba64beSDimitry Andric int fd = PyObject_AsFileDescriptor(m_py_obj); 1427*9dba64beSDimitry Andric if (fd < 0) { 1428*9dba64beSDimitry Andric PyErr_Clear(); 1429*9dba64beSDimitry Andric fd = File::kInvalidDescriptor; 1430*9dba64beSDimitry Andric } 1431*9dba64beSDimitry Andric 1432*9dba64beSDimitry Andric auto io_module = PythonModule::Import("io"); 1433*9dba64beSDimitry Andric if (!io_module) 1434*9dba64beSDimitry Andric return io_module.takeError(); 1435*9dba64beSDimitry Andric auto textIOBase = io_module.get().Get("TextIOBase"); 1436*9dba64beSDimitry Andric if (!textIOBase) 1437*9dba64beSDimitry Andric return textIOBase.takeError(); 1438*9dba64beSDimitry Andric auto rawIOBase = io_module.get().Get("RawIOBase"); 1439*9dba64beSDimitry Andric if (!rawIOBase) 1440*9dba64beSDimitry Andric return rawIOBase.takeError(); 1441*9dba64beSDimitry Andric auto bufferedIOBase = io_module.get().Get("BufferedIOBase"); 1442*9dba64beSDimitry Andric if (!bufferedIOBase) 1443*9dba64beSDimitry Andric return bufferedIOBase.takeError(); 1444*9dba64beSDimitry Andric 1445*9dba64beSDimitry Andric FileSP file_sp; 1446*9dba64beSDimitry Andric 1447*9dba64beSDimitry Andric auto isTextIO = IsInstance(textIOBase.get()); 1448*9dba64beSDimitry Andric if (!isTextIO) 1449*9dba64beSDimitry Andric return isTextIO.takeError(); 1450*9dba64beSDimitry Andric if (isTextIO.get()) 1451*9dba64beSDimitry Andric file_sp = std::static_pointer_cast<File>( 1452*9dba64beSDimitry Andric std::make_shared<TextPythonFile>(fd, *this, borrowed)); 1453*9dba64beSDimitry Andric 1454*9dba64beSDimitry Andric auto isRawIO = IsInstance(rawIOBase.get()); 1455*9dba64beSDimitry Andric if (!isRawIO) 1456*9dba64beSDimitry Andric return isRawIO.takeError(); 1457*9dba64beSDimitry Andric auto isBufferedIO = IsInstance(bufferedIOBase.get()); 1458*9dba64beSDimitry Andric if (!isBufferedIO) 1459*9dba64beSDimitry Andric return isBufferedIO.takeError(); 1460*9dba64beSDimitry Andric 1461*9dba64beSDimitry Andric if (isRawIO.get() || isBufferedIO.get()) { 1462*9dba64beSDimitry Andric file_sp = std::static_pointer_cast<File>( 1463*9dba64beSDimitry Andric std::make_shared<BinaryPythonFile>(fd, *this, borrowed)); 1464*9dba64beSDimitry Andric } 1465*9dba64beSDimitry Andric 1466*9dba64beSDimitry Andric if (!file_sp) 1467*9dba64beSDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(), 1468*9dba64beSDimitry Andric "python file is neither text nor binary"); 1469*9dba64beSDimitry Andric 1470*9dba64beSDimitry Andric if (!file_sp->IsValid()) 1471*9dba64beSDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(), 1472*9dba64beSDimitry Andric "invalid File"); 1473*9dba64beSDimitry Andric 1474*9dba64beSDimitry Andric return file_sp; 1475*9dba64beSDimitry Andric 1476*9dba64beSDimitry Andric #endif 1477*9dba64beSDimitry Andric } 1478*9dba64beSDimitry Andric 1479*9dba64beSDimitry Andric Expected<PythonFile> PythonFile::FromFile(File &file, const char *mode) { 1480*9dba64beSDimitry Andric if (!file.IsValid()) 1481*9dba64beSDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(), 1482*9dba64beSDimitry Andric "invalid file"); 1483*9dba64beSDimitry Andric 1484*9dba64beSDimitry Andric if (auto *simple = llvm::dyn_cast<SimplePythonFile>(&file)) 1485*9dba64beSDimitry Andric return Retain<PythonFile>(simple->GetPythonObject()); 1486*9dba64beSDimitry Andric #if PY_MAJOR_VERSION >= 3 1487*9dba64beSDimitry Andric if (auto *pythonio = llvm::dyn_cast<PythonIOFile>(&file)) 1488*9dba64beSDimitry Andric return Retain<PythonFile>(pythonio->GetPythonObject()); 1489*9dba64beSDimitry Andric #endif 1490*9dba64beSDimitry Andric 1491*9dba64beSDimitry Andric if (!mode) { 1492*9dba64beSDimitry Andric auto m = file.GetOpenMode(); 1493*9dba64beSDimitry Andric if (!m) 1494*9dba64beSDimitry Andric return m.takeError(); 1495*9dba64beSDimitry Andric mode = m.get(); 1496*9dba64beSDimitry Andric } 1497*9dba64beSDimitry Andric 1498*9dba64beSDimitry Andric PyObject *file_obj; 1499*9dba64beSDimitry Andric #if PY_MAJOR_VERSION >= 3 1500*9dba64beSDimitry Andric file_obj = PyFile_FromFd(file.GetDescriptor(), nullptr, mode, -1, nullptr, 1501*9dba64beSDimitry Andric "ignore", nullptr, 0); 15020b57cec5SDimitry Andric #else 15030b57cec5SDimitry Andric // Read through the Python source, doesn't seem to modify these strings 1504*9dba64beSDimitry Andric char *cmode = const_cast<char *>(mode); 1505*9dba64beSDimitry Andric // We pass ::flush instead of ::fclose here so we borrow the FILE* -- 1506*9dba64beSDimitry Andric // the lldb_private::File still owns it. 1507*9dba64beSDimitry Andric file_obj = 1508*9dba64beSDimitry Andric PyFile_FromFile(file.GetStream(), const_cast<char *>(""), cmode, ::fflush); 15090b57cec5SDimitry Andric #endif 1510*9dba64beSDimitry Andric 1511*9dba64beSDimitry Andric if (!file_obj) 1512*9dba64beSDimitry Andric return exception(); 1513*9dba64beSDimitry Andric 1514*9dba64beSDimitry Andric return Take<PythonFile>(file_obj); 15150b57cec5SDimitry Andric } 15160b57cec5SDimitry Andric 1517*9dba64beSDimitry Andric Error PythonScript::Init() { 1518*9dba64beSDimitry Andric if (function.IsValid()) 1519*9dba64beSDimitry Andric return Error::success(); 15200b57cec5SDimitry Andric 1521*9dba64beSDimitry Andric PythonDictionary globals(PyInitialValue::Empty); 1522*9dba64beSDimitry Andric auto builtins = PythonModule::BuiltinsModule(); 1523*9dba64beSDimitry Andric if (Error error = globals.SetItem("__builtins__", builtins)) 1524*9dba64beSDimitry Andric return error; 1525*9dba64beSDimitry Andric PyObject *o = 1526*9dba64beSDimitry Andric PyRun_String(script, Py_file_input, globals.get(), globals.get()); 1527*9dba64beSDimitry Andric if (!o) 1528*9dba64beSDimitry Andric return exception(); 1529*9dba64beSDimitry Andric Take<PythonObject>(o); 1530*9dba64beSDimitry Andric auto f = As<PythonCallable>(globals.GetItem("main")); 1531*9dba64beSDimitry Andric if (!f) 1532*9dba64beSDimitry Andric return f.takeError(); 1533*9dba64beSDimitry Andric function = std::move(f.get()); 1534*9dba64beSDimitry Andric 1535*9dba64beSDimitry Andric return Error::success(); 15360b57cec5SDimitry Andric } 15370b57cec5SDimitry Andric 1538*9dba64beSDimitry Andric llvm::Expected<PythonObject> 1539*9dba64beSDimitry Andric python::runStringOneLine(const llvm::Twine &string, 1540*9dba64beSDimitry Andric const PythonDictionary &globals, 1541*9dba64beSDimitry Andric const PythonDictionary &locals) { 1542*9dba64beSDimitry Andric if (!globals.IsValid() || !locals.IsValid()) 1543*9dba64beSDimitry Andric return nullDeref(); 15440b57cec5SDimitry Andric 1545*9dba64beSDimitry Andric PyObject *code = 1546*9dba64beSDimitry Andric Py_CompileString(NullTerminated(string), "<string>", Py_eval_input); 1547*9dba64beSDimitry Andric if (!code) { 1548*9dba64beSDimitry Andric PyErr_Clear(); 1549*9dba64beSDimitry Andric code = 1550*9dba64beSDimitry Andric Py_CompileString(NullTerminated(string), "<string>", Py_single_input); 1551*9dba64beSDimitry Andric } 1552*9dba64beSDimitry Andric if (!code) 1553*9dba64beSDimitry Andric return exception(); 1554*9dba64beSDimitry Andric auto code_ref = Take<PythonObject>(code); 1555*9dba64beSDimitry Andric 1556*9dba64beSDimitry Andric #if PY_MAJOR_VERSION < 3 1557*9dba64beSDimitry Andric PyObject *result = 1558*9dba64beSDimitry Andric PyEval_EvalCode((PyCodeObject *)code, globals.get(), locals.get()); 1559*9dba64beSDimitry Andric #else 1560*9dba64beSDimitry Andric PyObject *result = PyEval_EvalCode(code, globals.get(), locals.get()); 1561*9dba64beSDimitry Andric #endif 1562*9dba64beSDimitry Andric 1563*9dba64beSDimitry Andric if (!result) 1564*9dba64beSDimitry Andric return exception(); 1565*9dba64beSDimitry Andric 1566*9dba64beSDimitry Andric return Take<PythonObject>(result); 1567*9dba64beSDimitry Andric } 1568*9dba64beSDimitry Andric 1569*9dba64beSDimitry Andric llvm::Expected<PythonObject> 1570*9dba64beSDimitry Andric python::runStringMultiLine(const llvm::Twine &string, 1571*9dba64beSDimitry Andric const PythonDictionary &globals, 1572*9dba64beSDimitry Andric const PythonDictionary &locals) { 1573*9dba64beSDimitry Andric if (!globals.IsValid() || !locals.IsValid()) 1574*9dba64beSDimitry Andric return nullDeref(); 1575*9dba64beSDimitry Andric PyObject *result = PyRun_String(NullTerminated(string), Py_file_input, 1576*9dba64beSDimitry Andric globals.get(), locals.get()); 1577*9dba64beSDimitry Andric if (!result) 1578*9dba64beSDimitry Andric return exception(); 1579*9dba64beSDimitry Andric return Take<PythonObject>(result); 15800b57cec5SDimitry Andric } 15810b57cec5SDimitry Andric 15820b57cec5SDimitry Andric #endif 1583