1bcadb5a3SPavel Labath //===-- PythonDataObjects.cpp -----------------------------------*- C++ -*-===// 22c1f46dcSZachary Turner // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 62c1f46dcSZachary Turner // 72c1f46dcSZachary Turner //===----------------------------------------------------------------------===// 82c1f46dcSZachary Turner 9d68983e3SPavel Labath #ifdef LLDB_DISABLE_PYTHON 10d68983e3SPavel Labath 11d68983e3SPavel Labath // Python is disabled in this build 12d68983e3SPavel Labath 13d68983e3SPavel Labath #else 14d68983e3SPavel Labath 152c1f46dcSZachary Turner #include "PythonDataObjects.h" 162c1f46dcSZachary Turner #include "ScriptInterpreterPython.h" 172c1f46dcSZachary Turner 182c1f46dcSZachary Turner #include "lldb/Host/File.h" 19190fadcdSZachary Turner #include "lldb/Host/FileSystem.h" 202c1f46dcSZachary Turner #include "lldb/Interpreter/ScriptInterpreter.h" 21bf9a7730SZachary Turner #include "lldb/Utility/Stream.h" 222c1f46dcSZachary Turner 23190fadcdSZachary Turner #include "llvm/Support/ConvertUTF.h" 24*2819136fSMichal Gorny #include "llvm/Support/Errno.h" 25190fadcdSZachary Turner 262c1f46dcSZachary Turner #include <stdio.h> 272c1f46dcSZachary Turner 28744959b9SEnrico Granata #include "llvm/ADT/StringSwitch.h" 29744959b9SEnrico Granata 302c1f46dcSZachary Turner using namespace lldb_private; 312c1f46dcSZachary Turner using namespace lldb; 322c1f46dcSZachary Turner 33b9c1b51eSKate Stone void StructuredPythonObject::Dump(Stream &s, bool pretty_print) const { 342c1f46dcSZachary Turner s << "Python Obj: 0x" << GetValue(); 352c1f46dcSZachary Turner } 362c1f46dcSZachary Turner 372c1f46dcSZachary Turner //---------------------------------------------------------------------- 382c1f46dcSZachary Turner // PythonObject 392c1f46dcSZachary Turner //---------------------------------------------------------------------- 402c1f46dcSZachary Turner 41b9c1b51eSKate Stone void PythonObject::Dump(Stream &strm) const { 42b9c1b51eSKate Stone if (m_py_obj) { 43*2819136fSMichal Gorny FILE *file = llvm::sys::RetryAfterSignal(nullptr, ::tmpfile); 44b9c1b51eSKate Stone if (file) { 452c1f46dcSZachary Turner ::PyObject_Print(m_py_obj, file, 0); 462c1f46dcSZachary Turner const long length = ftell(file); 47b9c1b51eSKate Stone if (length) { 482c1f46dcSZachary Turner ::rewind(file); 492c1f46dcSZachary Turner std::vector<char> file_contents(length, '\0'); 50b9c1b51eSKate Stone const size_t length_read = 51b9c1b51eSKate Stone ::fread(file_contents.data(), 1, file_contents.size(), file); 522c1f46dcSZachary Turner if (length_read > 0) 532c1f46dcSZachary Turner strm.Write(file_contents.data(), length_read); 542c1f46dcSZachary Turner } 552c1f46dcSZachary Turner ::fclose(file); 562c1f46dcSZachary Turner } 57b9c1b51eSKate Stone } else 582c1f46dcSZachary Turner strm.PutCString("NULL"); 592c1f46dcSZachary Turner } 602c1f46dcSZachary Turner 61b9c1b51eSKate Stone PyObjectType PythonObject::GetObjectType() const { 62f8b22f8fSZachary Turner if (!IsAllocated()) 632c1f46dcSZachary Turner return PyObjectType::None; 642c1f46dcSZachary Turner 657841efbbSZachary Turner if (PythonModule::Check(m_py_obj)) 667841efbbSZachary Turner return PyObjectType::Module; 6718426935SZachary Turner if (PythonList::Check(m_py_obj)) 682c1f46dcSZachary Turner return PyObjectType::List; 69a1405147SZachary Turner if (PythonTuple::Check(m_py_obj)) 70a1405147SZachary Turner return PyObjectType::Tuple; 7118426935SZachary Turner if (PythonDictionary::Check(m_py_obj)) 722c1f46dcSZachary Turner return PyObjectType::Dictionary; 7318426935SZachary Turner if (PythonString::Check(m_py_obj)) 7422c8efcdSZachary Turner return PyObjectType::String; 755a72c02bSZachary Turner #if PY_MAJOR_VERSION >= 3 765a72c02bSZachary Turner if (PythonBytes::Check(m_py_obj)) 775a72c02bSZachary Turner return PyObjectType::Bytes; 785a72c02bSZachary Turner #endif 79f9d6d204SZachary Turner if (PythonByteArray::Check(m_py_obj)) 80f9d6d204SZachary Turner return PyObjectType::ByteArray; 81b81d715cSTatyana Krasnukha if (PythonBoolean::Check(m_py_obj)) 82b81d715cSTatyana Krasnukha return PyObjectType::Boolean; 8318426935SZachary Turner if (PythonInteger::Check(m_py_obj)) 8422c8efcdSZachary Turner return PyObjectType::Integer; 859c40264fSZachary Turner if (PythonFile::Check(m_py_obj)) 869c40264fSZachary Turner return PyObjectType::File; 87a1405147SZachary Turner if (PythonCallable::Check(m_py_obj)) 88a1405147SZachary Turner return PyObjectType::Callable; 892c1f46dcSZachary Turner return PyObjectType::Unknown; 902c1f46dcSZachary Turner } 912c1f46dcSZachary Turner 92b9c1b51eSKate Stone PythonString PythonObject::Repr() const { 932c1f46dcSZachary Turner if (!m_py_obj) 942c1f46dcSZachary Turner return PythonString(); 952c1f46dcSZachary Turner PyObject *repr = PyObject_Repr(m_py_obj); 962c1f46dcSZachary Turner if (!repr) 972c1f46dcSZachary Turner return PythonString(); 98f8b22f8fSZachary Turner return PythonString(PyRefType::Owned, repr); 992c1f46dcSZachary Turner } 1002c1f46dcSZachary Turner 101b9c1b51eSKate Stone PythonString PythonObject::Str() const { 1022c1f46dcSZachary Turner if (!m_py_obj) 1032c1f46dcSZachary Turner return PythonString(); 1042c1f46dcSZachary Turner PyObject *str = PyObject_Str(m_py_obj); 1052c1f46dcSZachary Turner if (!str) 1062c1f46dcSZachary Turner return PythonString(); 107f8b22f8fSZachary Turner return PythonString(PyRefType::Owned, str); 1082c1f46dcSZachary Turner } 1092c1f46dcSZachary Turner 1107841efbbSZachary Turner PythonObject 111b9c1b51eSKate Stone PythonObject::ResolveNameWithDictionary(llvm::StringRef name, 112b9c1b51eSKate Stone const PythonDictionary &dict) { 113a1405147SZachary Turner size_t dot_pos = name.find_first_of('.'); 114a1405147SZachary Turner llvm::StringRef piece = name.substr(0, dot_pos); 115a1405147SZachary Turner PythonObject result = dict.GetItemForKey(PythonString(piece)); 116b9c1b51eSKate Stone if (dot_pos == llvm::StringRef::npos) { 117a1405147SZachary Turner // There was no dot, we're done. 118a1405147SZachary Turner return result; 119a1405147SZachary Turner } 120a1405147SZachary Turner 121a1405147SZachary Turner // There was a dot. The remaining portion of the name should be looked up in 122a1405147SZachary Turner // the context of the object that was found in the dictionary. 123a1405147SZachary Turner return result.ResolveName(name.substr(dot_pos + 1)); 1247841efbbSZachary Turner } 1257841efbbSZachary Turner 126b9c1b51eSKate Stone PythonObject PythonObject::ResolveName(llvm::StringRef name) const { 12705097246SAdrian Prantl // Resolve the name in the context of the specified object. If, for example, 12805097246SAdrian Prantl // `this` refers to a PyModule, then this will look for `name` in this 12905097246SAdrian Prantl // module. If `this` refers to a PyType, then it will resolve `name` as an 13005097246SAdrian Prantl // attribute of that type. If `this` refers to an instance of an object, 13105097246SAdrian Prantl // then it will resolve `name` as the value of the specified field. 1327841efbbSZachary Turner // 1337841efbbSZachary Turner // This function handles dotted names so that, for example, if `m_py_obj` 13405097246SAdrian Prantl // refers to the `sys` module, and `name` == "path.append", then it will find 13505097246SAdrian Prantl // the function `sys.path.append`. 1367841efbbSZachary Turner 1377841efbbSZachary Turner size_t dot_pos = name.find_first_of('.'); 138b9c1b51eSKate Stone if (dot_pos == llvm::StringRef::npos) { 13905097246SAdrian Prantl // No dots in the name, we should be able to find the value immediately as 14005097246SAdrian Prantl // an attribute of `m_py_obj`. 1417841efbbSZachary Turner return GetAttributeValue(name); 1427841efbbSZachary Turner } 1437841efbbSZachary Turner 144b9c1b51eSKate Stone // Look up the first piece of the name, and resolve the rest as a child of 145b9c1b51eSKate Stone // that. 1467841efbbSZachary Turner PythonObject parent = ResolveName(name.substr(0, dot_pos)); 1477841efbbSZachary Turner if (!parent.IsAllocated()) 1487841efbbSZachary Turner return PythonObject(); 1497841efbbSZachary Turner 1507841efbbSZachary Turner // Tail recursion.. should be optimized by the compiler 1517841efbbSZachary Turner return parent.ResolveName(name.substr(dot_pos + 1)); 1527841efbbSZachary Turner } 1537841efbbSZachary Turner 154b9c1b51eSKate Stone bool PythonObject::HasAttribute(llvm::StringRef attr) const { 1559c40264fSZachary Turner if (!IsValid()) 1569c40264fSZachary Turner return false; 1579c40264fSZachary Turner PythonString py_attr(attr); 1589c40264fSZachary Turner return !!PyObject_HasAttr(m_py_obj, py_attr.get()); 1599c40264fSZachary Turner } 1609c40264fSZachary Turner 161b9c1b51eSKate Stone PythonObject PythonObject::GetAttributeValue(llvm::StringRef attr) const { 1627d6d218eSZachary Turner if (!IsValid()) 1637d6d218eSZachary Turner return PythonObject(); 1647d6d218eSZachary Turner 1657d6d218eSZachary Turner PythonString py_attr(attr); 1667d6d218eSZachary Turner if (!PyObject_HasAttr(m_py_obj, py_attr.get())) 1677d6d218eSZachary Turner return PythonObject(); 1687d6d218eSZachary Turner 1697d6d218eSZachary Turner return PythonObject(PyRefType::Owned, 1707d6d218eSZachary Turner PyObject_GetAttr(m_py_obj, py_attr.get())); 1717d6d218eSZachary Turner } 1727d6d218eSZachary Turner 173b9c1b51eSKate Stone bool PythonObject::IsNone() const { return m_py_obj == Py_None; } 174f8b22f8fSZachary Turner 175b9c1b51eSKate Stone bool PythonObject::IsValid() const { return m_py_obj != nullptr; } 176f8b22f8fSZachary Turner 177b9c1b51eSKate Stone bool PythonObject::IsAllocated() const { return IsValid() && !IsNone(); } 1782c1f46dcSZachary Turner 179b9c1b51eSKate Stone StructuredData::ObjectSP PythonObject::CreateStructuredObject() const { 180b9c1b51eSKate Stone switch (GetObjectType()) { 1812c1f46dcSZachary Turner case PyObjectType::Dictionary: 182b9c1b51eSKate Stone return PythonDictionary(PyRefType::Borrowed, m_py_obj) 183b9c1b51eSKate Stone .CreateStructuredDictionary(); 184b81d715cSTatyana Krasnukha case PyObjectType::Boolean: 185b81d715cSTatyana Krasnukha return PythonBoolean(PyRefType::Borrowed, m_py_obj) 186b81d715cSTatyana Krasnukha .CreateStructuredBoolean(); 1872c1f46dcSZachary Turner case PyObjectType::Integer: 188b9c1b51eSKate Stone return PythonInteger(PyRefType::Borrowed, m_py_obj) 189b9c1b51eSKate Stone .CreateStructuredInteger(); 1902c1f46dcSZachary Turner case PyObjectType::List: 191f8b22f8fSZachary Turner return PythonList(PyRefType::Borrowed, m_py_obj).CreateStructuredArray(); 1922c1f46dcSZachary Turner case PyObjectType::String: 193f8b22f8fSZachary Turner return PythonString(PyRefType::Borrowed, m_py_obj).CreateStructuredString(); 1945a72c02bSZachary Turner case PyObjectType::Bytes: 1955a72c02bSZachary Turner return PythonBytes(PyRefType::Borrowed, m_py_obj).CreateStructuredString(); 196f9d6d204SZachary Turner case PyObjectType::ByteArray: 197b9c1b51eSKate Stone return PythonByteArray(PyRefType::Borrowed, m_py_obj) 198b9c1b51eSKate Stone .CreateStructuredString(); 1992c1f46dcSZachary Turner case PyObjectType::None: 2002c1f46dcSZachary Turner return StructuredData::ObjectSP(); 2012c1f46dcSZachary Turner default: 2022c1f46dcSZachary Turner return StructuredData::ObjectSP(new StructuredPythonObject(m_py_obj)); 2032c1f46dcSZachary Turner } 2042c1f46dcSZachary Turner } 2052c1f46dcSZachary Turner 2062c1f46dcSZachary Turner //---------------------------------------------------------------------- 2072c1f46dcSZachary Turner // PythonString 2082c1f46dcSZachary Turner //---------------------------------------------------------------------- 209b9c1b51eSKate Stone PythonBytes::PythonBytes() : PythonObject() {} 2105a72c02bSZachary Turner 211b9c1b51eSKate Stone PythonBytes::PythonBytes(llvm::ArrayRef<uint8_t> bytes) : PythonObject() { 2125a72c02bSZachary Turner SetBytes(bytes); 2135a72c02bSZachary Turner } 2145a72c02bSZachary Turner 215b9c1b51eSKate Stone PythonBytes::PythonBytes(const uint8_t *bytes, size_t length) : PythonObject() { 2165a72c02bSZachary Turner SetBytes(llvm::ArrayRef<uint8_t>(bytes, length)); 2175a72c02bSZachary Turner } 2185a72c02bSZachary Turner 219b9c1b51eSKate Stone PythonBytes::PythonBytes(PyRefType type, PyObject *py_obj) : PythonObject() { 2205a72c02bSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string 2215a72c02bSZachary Turner } 2225a72c02bSZachary Turner 223b9c1b51eSKate Stone PythonBytes::PythonBytes(const PythonBytes &object) : PythonObject(object) {} 2245a72c02bSZachary Turner 225b9c1b51eSKate Stone PythonBytes::~PythonBytes() {} 2265a72c02bSZachary Turner 227b9c1b51eSKate Stone bool PythonBytes::Check(PyObject *py_obj) { 2285a72c02bSZachary Turner if (!py_obj) 2295a72c02bSZachary Turner return false; 230a6682a41SJonas Devlieghere return PyBytes_Check(py_obj); 2315a72c02bSZachary Turner } 2325a72c02bSZachary Turner 233b9c1b51eSKate Stone void PythonBytes::Reset(PyRefType type, PyObject *py_obj) { 23405097246SAdrian Prantl // Grab the desired reference type so that if we end up rejecting `py_obj` it 23505097246SAdrian Prantl // still gets decremented if necessary. 2365a72c02bSZachary Turner PythonObject result(type, py_obj); 2375a72c02bSZachary Turner 238b9c1b51eSKate Stone if (!PythonBytes::Check(py_obj)) { 2395a72c02bSZachary Turner PythonObject::Reset(); 2405a72c02bSZachary Turner return; 2415a72c02bSZachary Turner } 2425a72c02bSZachary Turner 243b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 24405097246SAdrian Prantl // overflow since it calls back into the virtual implementation. 2455a72c02bSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 2465a72c02bSZachary Turner } 2475a72c02bSZachary Turner 248b9c1b51eSKate Stone llvm::ArrayRef<uint8_t> PythonBytes::GetBytes() const { 2495a72c02bSZachary Turner if (!IsValid()) 2505a72c02bSZachary Turner return llvm::ArrayRef<uint8_t>(); 2515a72c02bSZachary Turner 2525a72c02bSZachary Turner Py_ssize_t size; 2535a72c02bSZachary Turner char *c; 2545a72c02bSZachary Turner 2555a72c02bSZachary Turner PyBytes_AsStringAndSize(m_py_obj, &c, &size); 2565a72c02bSZachary Turner return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size); 2575a72c02bSZachary Turner } 2585a72c02bSZachary Turner 259b9c1b51eSKate Stone size_t PythonBytes::GetSize() const { 2605a72c02bSZachary Turner if (!IsValid()) 2615a72c02bSZachary Turner return 0; 2625a72c02bSZachary Turner return PyBytes_Size(m_py_obj); 2635a72c02bSZachary Turner } 2645a72c02bSZachary Turner 265b9c1b51eSKate Stone void PythonBytes::SetBytes(llvm::ArrayRef<uint8_t> bytes) { 2665a72c02bSZachary Turner const char *data = reinterpret_cast<const char *>(bytes.data()); 2675a72c02bSZachary Turner PyObject *py_bytes = PyBytes_FromStringAndSize(data, bytes.size()); 2685a72c02bSZachary Turner PythonObject::Reset(PyRefType::Owned, py_bytes); 2695a72c02bSZachary Turner } 2705a72c02bSZachary Turner 271b9c1b51eSKate Stone StructuredData::StringSP PythonBytes::CreateStructuredString() const { 2725a72c02bSZachary Turner StructuredData::StringSP result(new StructuredData::String); 2735a72c02bSZachary Turner Py_ssize_t size; 2745a72c02bSZachary Turner char *c; 2755a72c02bSZachary Turner PyBytes_AsStringAndSize(m_py_obj, &c, &size); 2765a72c02bSZachary Turner result->SetValue(std::string(c, size)); 2775a72c02bSZachary Turner return result; 2785a72c02bSZachary Turner } 2795a72c02bSZachary Turner 280b9c1b51eSKate Stone PythonByteArray::PythonByteArray(llvm::ArrayRef<uint8_t> bytes) 281b9c1b51eSKate Stone : PythonByteArray(bytes.data(), bytes.size()) {} 282f9d6d204SZachary Turner 283b9c1b51eSKate Stone PythonByteArray::PythonByteArray(const uint8_t *bytes, size_t length) { 284f9d6d204SZachary Turner const char *str = reinterpret_cast<const char *>(bytes); 285f9d6d204SZachary Turner Reset(PyRefType::Owned, PyByteArray_FromStringAndSize(str, length)); 286f9d6d204SZachary Turner } 287f9d6d204SZachary Turner 288b9c1b51eSKate Stone PythonByteArray::PythonByteArray(PyRefType type, PyObject *o) { 289f9d6d204SZachary Turner Reset(type, o); 290f9d6d204SZachary Turner } 291f9d6d204SZachary Turner 292b9c1b51eSKate Stone PythonByteArray::PythonByteArray(const PythonBytes &object) 293b9c1b51eSKate Stone : PythonObject(object) {} 294f9d6d204SZachary Turner 295b9c1b51eSKate Stone PythonByteArray::~PythonByteArray() {} 296f9d6d204SZachary Turner 297b9c1b51eSKate Stone bool PythonByteArray::Check(PyObject *py_obj) { 298f9d6d204SZachary Turner if (!py_obj) 299f9d6d204SZachary Turner return false; 300a6682a41SJonas Devlieghere return PyByteArray_Check(py_obj); 301f9d6d204SZachary Turner } 302f9d6d204SZachary Turner 303b9c1b51eSKate Stone void PythonByteArray::Reset(PyRefType type, PyObject *py_obj) { 30405097246SAdrian Prantl // Grab the desired reference type so that if we end up rejecting `py_obj` it 30505097246SAdrian Prantl // still gets decremented if necessary. 306f9d6d204SZachary Turner PythonObject result(type, py_obj); 307f9d6d204SZachary Turner 308b9c1b51eSKate Stone if (!PythonByteArray::Check(py_obj)) { 309f9d6d204SZachary Turner PythonObject::Reset(); 310f9d6d204SZachary Turner return; 311f9d6d204SZachary Turner } 312f9d6d204SZachary Turner 313b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 31405097246SAdrian Prantl // overflow since it calls back into the virtual implementation. 315f9d6d204SZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 316f9d6d204SZachary Turner } 317f9d6d204SZachary Turner 318b9c1b51eSKate Stone llvm::ArrayRef<uint8_t> PythonByteArray::GetBytes() const { 319f9d6d204SZachary Turner if (!IsValid()) 320f9d6d204SZachary Turner return llvm::ArrayRef<uint8_t>(); 321f9d6d204SZachary Turner 322f9d6d204SZachary Turner char *c = PyByteArray_AsString(m_py_obj); 323f9d6d204SZachary Turner size_t size = GetSize(); 324f9d6d204SZachary Turner return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size); 325f9d6d204SZachary Turner } 326f9d6d204SZachary Turner 327b9c1b51eSKate Stone size_t PythonByteArray::GetSize() const { 328f9d6d204SZachary Turner if (!IsValid()) 329f9d6d204SZachary Turner return 0; 330f9d6d204SZachary Turner 331f9d6d204SZachary Turner return PyByteArray_Size(m_py_obj); 332f9d6d204SZachary Turner } 333f9d6d204SZachary Turner 334b9c1b51eSKate Stone StructuredData::StringSP PythonByteArray::CreateStructuredString() const { 335f9d6d204SZachary Turner StructuredData::StringSP result(new StructuredData::String); 336f9d6d204SZachary Turner llvm::ArrayRef<uint8_t> bytes = GetBytes(); 337f9d6d204SZachary Turner const char *str = reinterpret_cast<const char *>(bytes.data()); 338f9d6d204SZachary Turner result->SetValue(std::string(str, bytes.size())); 339f9d6d204SZachary Turner return result; 340f9d6d204SZachary Turner } 341f9d6d204SZachary Turner 3425a72c02bSZachary Turner //---------------------------------------------------------------------- 3435a72c02bSZachary Turner // PythonString 3445a72c02bSZachary Turner //---------------------------------------------------------------------- 3452c1f46dcSZachary Turner 346b9c1b51eSKate Stone PythonString::PythonString(PyRefType type, PyObject *py_obj) : PythonObject() { 347f8b22f8fSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string 3482c1f46dcSZachary Turner } 3492c1f46dcSZachary Turner 350b9c1b51eSKate Stone PythonString::PythonString(const PythonString &object) : PythonObject(object) {} 3512c1f46dcSZachary Turner 352b9c1b51eSKate Stone PythonString::PythonString(llvm::StringRef string) : PythonObject() { 35322c8efcdSZachary Turner SetString(string); 3542c1f46dcSZachary Turner } 3552c1f46dcSZachary Turner 356b9c1b51eSKate Stone PythonString::PythonString(const char *string) : PythonObject() { 35722c8efcdSZachary Turner SetString(llvm::StringRef(string)); 3582c1f46dcSZachary Turner } 3592c1f46dcSZachary Turner 360b9c1b51eSKate Stone PythonString::PythonString() : PythonObject() {} 3612c1f46dcSZachary Turner 362b9c1b51eSKate Stone PythonString::~PythonString() {} 3632c1f46dcSZachary Turner 364b9c1b51eSKate Stone bool PythonString::Check(PyObject *py_obj) { 36522c8efcdSZachary Turner if (!py_obj) 36622c8efcdSZachary Turner return false; 36718426935SZachary Turner 3687d6d218eSZachary Turner if (PyUnicode_Check(py_obj)) 3697d6d218eSZachary Turner return true; 3707d6d218eSZachary Turner #if PY_MAJOR_VERSION < 3 3717d6d218eSZachary Turner if (PyString_Check(py_obj)) 3727d6d218eSZachary Turner return true; 37322c8efcdSZachary Turner #endif 3747d6d218eSZachary Turner return false; 37522c8efcdSZachary Turner } 37622c8efcdSZachary Turner 377b9c1b51eSKate Stone void PythonString::Reset(PyRefType type, PyObject *py_obj) { 37805097246SAdrian Prantl // Grab the desired reference type so that if we end up rejecting `py_obj` it 37905097246SAdrian Prantl // still gets decremented if necessary. 380f8b22f8fSZachary Turner PythonObject result(type, py_obj); 381f8b22f8fSZachary Turner 382b9c1b51eSKate Stone if (!PythonString::Check(py_obj)) { 383f8b22f8fSZachary Turner PythonObject::Reset(); 384f8b22f8fSZachary Turner return; 38522c8efcdSZachary Turner } 3867d6d218eSZachary Turner #if PY_MAJOR_VERSION < 3 3877d6d218eSZachary Turner // In Python 2, Don't store PyUnicode objects directly, because we need 3887d6d218eSZachary Turner // access to their underlying character buffers which Python 2 doesn't 3897d6d218eSZachary Turner // provide. 3907d6d218eSZachary Turner if (PyUnicode_Check(py_obj)) 3917d6d218eSZachary Turner result.Reset(PyRefType::Owned, PyUnicode_AsUTF8String(result.get())); 3927d6d218eSZachary Turner #endif 393b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 39405097246SAdrian Prantl // overflow since it calls back into the virtual implementation. 395f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 3962c1f46dcSZachary Turner } 3972c1f46dcSZachary Turner 398b9c1b51eSKate Stone llvm::StringRef PythonString::GetString() const { 39918426935SZachary Turner if (!IsValid()) 40018426935SZachary Turner return llvm::StringRef(); 40118426935SZachary Turner 40222c8efcdSZachary Turner Py_ssize_t size; 4035457b426SPavel Labath const char *data; 40418426935SZachary Turner 40518426935SZachary Turner #if PY_MAJOR_VERSION >= 3 4065457b426SPavel Labath data = PyUnicode_AsUTF8AndSize(m_py_obj, &size); 40718426935SZachary Turner #else 4085457b426SPavel Labath char *c; 40918426935SZachary Turner PyString_AsStringAndSize(m_py_obj, &c, &size); 4105457b426SPavel Labath data = c; 41118426935SZachary Turner #endif 4125457b426SPavel Labath return llvm::StringRef(data, size); 41322c8efcdSZachary Turner } 4142c1f46dcSZachary Turner 415b9c1b51eSKate Stone size_t PythonString::GetSize() const { 416b9c1b51eSKate Stone if (IsValid()) { 41718426935SZachary Turner #if PY_MAJOR_VERSION >= 3 41818426935SZachary Turner return PyUnicode_GetSize(m_py_obj); 41918426935SZachary Turner #else 42018426935SZachary Turner return PyString_Size(m_py_obj); 42118426935SZachary Turner #endif 42218426935SZachary Turner } 4232c1f46dcSZachary Turner return 0; 4242c1f46dcSZachary Turner } 4252c1f46dcSZachary Turner 426b9c1b51eSKate Stone void PythonString::SetString(llvm::StringRef string) { 42722c8efcdSZachary Turner #if PY_MAJOR_VERSION >= 3 42822c8efcdSZachary Turner PyObject *unicode = PyUnicode_FromStringAndSize(string.data(), string.size()); 42918426935SZachary Turner PythonObject::Reset(PyRefType::Owned, unicode); 43022c8efcdSZachary Turner #else 43118426935SZachary Turner PyObject *str = PyString_FromStringAndSize(string.data(), string.size()); 43218426935SZachary Turner PythonObject::Reset(PyRefType::Owned, str); 43322c8efcdSZachary Turner #endif 4342c1f46dcSZachary Turner } 4352c1f46dcSZachary Turner 436b9c1b51eSKate Stone StructuredData::StringSP PythonString::CreateStructuredString() const { 4372c1f46dcSZachary Turner StructuredData::StringSP result(new StructuredData::String); 4382c1f46dcSZachary Turner result->SetValue(GetString()); 4392c1f46dcSZachary Turner return result; 4402c1f46dcSZachary Turner } 4412c1f46dcSZachary Turner 4422c1f46dcSZachary Turner //---------------------------------------------------------------------- 4432c1f46dcSZachary Turner // PythonInteger 4442c1f46dcSZachary Turner //---------------------------------------------------------------------- 4452c1f46dcSZachary Turner 446b9c1b51eSKate Stone PythonInteger::PythonInteger() : PythonObject() {} 4477d6d218eSZachary Turner 448f8b22f8fSZachary Turner PythonInteger::PythonInteger(PyRefType type, PyObject *py_obj) 449b9c1b51eSKate Stone : PythonObject() { 450f8b22f8fSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a integer type 4512c1f46dcSZachary Turner } 4522c1f46dcSZachary Turner 453f8b22f8fSZachary Turner PythonInteger::PythonInteger(const PythonInteger &object) 454b9c1b51eSKate Stone : PythonObject(object) {} 4552c1f46dcSZachary Turner 456b9c1b51eSKate Stone PythonInteger::PythonInteger(int64_t value) : PythonObject() { 4572c1f46dcSZachary Turner SetInteger(value); 4582c1f46dcSZachary Turner } 4592c1f46dcSZachary Turner 460b9c1b51eSKate Stone PythonInteger::~PythonInteger() {} 4612c1f46dcSZachary Turner 462b9c1b51eSKate Stone bool PythonInteger::Check(PyObject *py_obj) { 46322c8efcdSZachary Turner if (!py_obj) 46422c8efcdSZachary Turner return false; 46522c8efcdSZachary Turner 46622c8efcdSZachary Turner #if PY_MAJOR_VERSION >= 3 46705097246SAdrian Prantl // Python 3 does not have PyInt_Check. There is only one type of integral 46805097246SAdrian Prantl // value, long. 46922c8efcdSZachary Turner return PyLong_Check(py_obj); 47022c8efcdSZachary Turner #else 47122c8efcdSZachary Turner return PyLong_Check(py_obj) || PyInt_Check(py_obj); 47222c8efcdSZachary Turner #endif 4732c1f46dcSZachary Turner } 4742c1f46dcSZachary Turner 475b9c1b51eSKate Stone void PythonInteger::Reset(PyRefType type, PyObject *py_obj) { 47605097246SAdrian Prantl // Grab the desired reference type so that if we end up rejecting `py_obj` it 47705097246SAdrian Prantl // still gets decremented if necessary. 478f8b22f8fSZachary Turner PythonObject result(type, py_obj); 479f8b22f8fSZachary Turner 480b9c1b51eSKate Stone if (!PythonInteger::Check(py_obj)) { 481f8b22f8fSZachary Turner PythonObject::Reset(); 482f8b22f8fSZachary Turner return; 48322c8efcdSZachary Turner } 48422c8efcdSZachary Turner 48522c8efcdSZachary Turner #if PY_MAJOR_VERSION < 3 48605097246SAdrian Prantl // Always store this as a PyLong, which makes interoperability between Python 48705097246SAdrian Prantl // 2.x and Python 3.x easier. This is only necessary in 2.x, since 3.x 48805097246SAdrian Prantl // doesn't even have a PyInt. 489b9c1b51eSKate Stone if (PyInt_Check(py_obj)) { 490f8b22f8fSZachary Turner // Since we converted the original object to a different type, the new 49105097246SAdrian Prantl // object is an owned object regardless of the ownership semantics 49205097246SAdrian Prantl // requested by the user. 493f8b22f8fSZachary Turner result.Reset(PyRefType::Owned, PyLong_FromLongLong(PyInt_AsLong(py_obj))); 49422c8efcdSZachary Turner } 49522c8efcdSZachary Turner #endif 49622c8efcdSZachary Turner 497b9c1b51eSKate Stone assert(PyLong_Check(result.get()) && 498b9c1b51eSKate Stone "Couldn't get a PyLong from this PyObject"); 49922c8efcdSZachary Turner 500b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 50105097246SAdrian Prantl // overflow since it calls back into the virtual implementation. 502f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 5032c1f46dcSZachary Turner } 5042c1f46dcSZachary Turner 505b9c1b51eSKate Stone int64_t PythonInteger::GetInteger() const { 506b9c1b51eSKate Stone if (m_py_obj) { 507b9c1b51eSKate Stone assert(PyLong_Check(m_py_obj) && 508b9c1b51eSKate Stone "PythonInteger::GetInteger has a PyObject that isn't a PyLong"); 50922c8efcdSZachary Turner 510008ec446SGreg Clayton int overflow = 0; 511008ec446SGreg Clayton int64_t result = PyLong_AsLongLongAndOverflow(m_py_obj, &overflow); 512b9c1b51eSKate Stone if (overflow != 0) { 51305097246SAdrian Prantl // We got an integer that overflows, like 18446744072853913392L we can't 51405097246SAdrian Prantl // use PyLong_AsLongLong() as it will return 0xffffffffffffffff. If we 51505097246SAdrian Prantl // use the unsigned long long it will work as expected. 516008ec446SGreg Clayton const uint64_t uval = PyLong_AsUnsignedLongLong(m_py_obj); 5174f730dc7SIlia K result = static_cast<int64_t>(uval); 518008ec446SGreg Clayton } 519008ec446SGreg Clayton return result; 5202c1f46dcSZachary Turner } 5212c1f46dcSZachary Turner return UINT64_MAX; 5222c1f46dcSZachary Turner } 5232c1f46dcSZachary Turner 524b9c1b51eSKate Stone void PythonInteger::SetInteger(int64_t value) { 525f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Owned, PyLong_FromLongLong(value)); 5262c1f46dcSZachary Turner } 5272c1f46dcSZachary Turner 528b9c1b51eSKate Stone StructuredData::IntegerSP PythonInteger::CreateStructuredInteger() const { 5292c1f46dcSZachary Turner StructuredData::IntegerSP result(new StructuredData::Integer); 5302c1f46dcSZachary Turner result->SetValue(GetInteger()); 5312c1f46dcSZachary Turner return result; 5322c1f46dcSZachary Turner } 5332c1f46dcSZachary Turner 5342c1f46dcSZachary Turner //---------------------------------------------------------------------- 535b81d715cSTatyana Krasnukha // PythonBoolean 536b81d715cSTatyana Krasnukha //---------------------------------------------------------------------- 537b81d715cSTatyana Krasnukha 538b81d715cSTatyana Krasnukha PythonBoolean::PythonBoolean(PyRefType type, PyObject *py_obj) 539b81d715cSTatyana Krasnukha : PythonObject() { 540b81d715cSTatyana Krasnukha Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a boolean type 541b81d715cSTatyana Krasnukha } 542b81d715cSTatyana Krasnukha 543b81d715cSTatyana Krasnukha PythonBoolean::PythonBoolean(const PythonBoolean &object) 544b81d715cSTatyana Krasnukha : PythonObject(object) {} 545b81d715cSTatyana Krasnukha 546b81d715cSTatyana Krasnukha PythonBoolean::PythonBoolean(bool value) { 547b81d715cSTatyana Krasnukha SetValue(value); 548b81d715cSTatyana Krasnukha } 549b81d715cSTatyana Krasnukha 550b81d715cSTatyana Krasnukha bool PythonBoolean::Check(PyObject *py_obj) { 551b81d715cSTatyana Krasnukha return py_obj ? PyBool_Check(py_obj) : false; 552b81d715cSTatyana Krasnukha } 553b81d715cSTatyana Krasnukha 554b81d715cSTatyana Krasnukha void PythonBoolean::Reset(PyRefType type, PyObject *py_obj) { 555b81d715cSTatyana Krasnukha // Grab the desired reference type so that if we end up rejecting `py_obj` it 556b81d715cSTatyana Krasnukha // still gets decremented if necessary. 557b81d715cSTatyana Krasnukha PythonObject result(type, py_obj); 558b81d715cSTatyana Krasnukha 559b81d715cSTatyana Krasnukha if (!PythonBoolean::Check(py_obj)) { 560b81d715cSTatyana Krasnukha PythonObject::Reset(); 561b81d715cSTatyana Krasnukha return; 562b81d715cSTatyana Krasnukha } 563b81d715cSTatyana Krasnukha 564b81d715cSTatyana Krasnukha // Calling PythonObject::Reset(const PythonObject&) will lead to stack 565b81d715cSTatyana Krasnukha // overflow since it calls back into the virtual implementation. 566b81d715cSTatyana Krasnukha PythonObject::Reset(PyRefType::Borrowed, result.get()); 567b81d715cSTatyana Krasnukha } 568b81d715cSTatyana Krasnukha 569b81d715cSTatyana Krasnukha bool PythonBoolean::GetValue() const { 570b81d715cSTatyana Krasnukha return m_py_obj ? PyObject_IsTrue(m_py_obj) : false; 571b81d715cSTatyana Krasnukha } 572b81d715cSTatyana Krasnukha 573b81d715cSTatyana Krasnukha void PythonBoolean::SetValue(bool value) { 574b81d715cSTatyana Krasnukha PythonObject::Reset(PyRefType::Owned, PyBool_FromLong(value)); 575b81d715cSTatyana Krasnukha } 576b81d715cSTatyana Krasnukha 577b81d715cSTatyana Krasnukha StructuredData::BooleanSP PythonBoolean::CreateStructuredBoolean() const { 578b81d715cSTatyana Krasnukha StructuredData::BooleanSP result(new StructuredData::Boolean); 579b81d715cSTatyana Krasnukha result->SetValue(GetValue()); 580b81d715cSTatyana Krasnukha return result; 581b81d715cSTatyana Krasnukha } 582b81d715cSTatyana Krasnukha 583b81d715cSTatyana Krasnukha //---------------------------------------------------------------------- 5842c1f46dcSZachary Turner // PythonList 5852c1f46dcSZachary Turner //---------------------------------------------------------------------- 5862c1f46dcSZachary Turner 587b9c1b51eSKate Stone PythonList::PythonList(PyInitialValue value) : PythonObject() { 588f8b22f8fSZachary Turner if (value == PyInitialValue::Empty) 589f8b22f8fSZachary Turner Reset(PyRefType::Owned, PyList_New(0)); 5902c1f46dcSZachary Turner } 5912c1f46dcSZachary Turner 592b9c1b51eSKate Stone PythonList::PythonList(int list_size) : PythonObject() { 59387f47729SZachary Turner Reset(PyRefType::Owned, PyList_New(list_size)); 59487f47729SZachary Turner } 59587f47729SZachary Turner 596b9c1b51eSKate Stone PythonList::PythonList(PyRefType type, PyObject *py_obj) : PythonObject() { 597f8b22f8fSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a list 5982c1f46dcSZachary Turner } 5992c1f46dcSZachary Turner 600b9c1b51eSKate Stone PythonList::PythonList(const PythonList &list) : PythonObject(list) {} 6012c1f46dcSZachary Turner 602b9c1b51eSKate Stone PythonList::~PythonList() {} 6032c1f46dcSZachary Turner 604b9c1b51eSKate Stone bool PythonList::Check(PyObject *py_obj) { 60522c8efcdSZachary Turner if (!py_obj) 60622c8efcdSZachary Turner return false; 60722c8efcdSZachary Turner return PyList_Check(py_obj); 60822c8efcdSZachary Turner } 60922c8efcdSZachary Turner 610b9c1b51eSKate Stone void PythonList::Reset(PyRefType type, PyObject *py_obj) { 61105097246SAdrian Prantl // Grab the desired reference type so that if we end up rejecting `py_obj` it 61205097246SAdrian Prantl // still gets decremented if necessary. 613f8b22f8fSZachary Turner PythonObject result(type, py_obj); 614f8b22f8fSZachary Turner 615b9c1b51eSKate Stone if (!PythonList::Check(py_obj)) { 616f8b22f8fSZachary Turner PythonObject::Reset(); 617f8b22f8fSZachary Turner return; 61822c8efcdSZachary Turner } 61922c8efcdSZachary Turner 620b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 62105097246SAdrian Prantl // overflow since it calls back into the virtual implementation. 622f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 6232c1f46dcSZachary Turner } 6242c1f46dcSZachary Turner 625b9c1b51eSKate Stone uint32_t PythonList::GetSize() const { 626f8b22f8fSZachary Turner if (IsValid()) 6272c1f46dcSZachary Turner return PyList_GET_SIZE(m_py_obj); 6282c1f46dcSZachary Turner return 0; 6292c1f46dcSZachary Turner } 6302c1f46dcSZachary Turner 631b9c1b51eSKate Stone PythonObject PythonList::GetItemAtIndex(uint32_t index) const { 632f8b22f8fSZachary Turner if (IsValid()) 633f8b22f8fSZachary Turner return PythonObject(PyRefType::Borrowed, PyList_GetItem(m_py_obj, index)); 6342c1f46dcSZachary Turner return PythonObject(); 6352c1f46dcSZachary Turner } 6362c1f46dcSZachary Turner 637b9c1b51eSKate Stone void PythonList::SetItemAtIndex(uint32_t index, const PythonObject &object) { 638b9c1b51eSKate Stone if (IsAllocated() && object.IsValid()) { 639f8b22f8fSZachary Turner // PyList_SetItem is documented to "steal" a reference, so we need to 640f8b22f8fSZachary Turner // convert it to an owned reference by incrementing it. 641f8b22f8fSZachary Turner Py_INCREF(object.get()); 6422c1f46dcSZachary Turner PyList_SetItem(m_py_obj, index, object.get()); 6432c1f46dcSZachary Turner } 644f8b22f8fSZachary Turner } 6452c1f46dcSZachary Turner 646b9c1b51eSKate Stone void PythonList::AppendItem(const PythonObject &object) { 647b9c1b51eSKate Stone if (IsAllocated() && object.IsValid()) { 648f8b22f8fSZachary Turner // `PyList_Append` does *not* steal a reference, so do not call `Py_INCREF` 649f8b22f8fSZachary Turner // here like we do with `PyList_SetItem`. 6502c1f46dcSZachary Turner PyList_Append(m_py_obj, object.get()); 6512c1f46dcSZachary Turner } 652f8b22f8fSZachary Turner } 6532c1f46dcSZachary Turner 654b9c1b51eSKate Stone StructuredData::ArraySP PythonList::CreateStructuredArray() const { 6552c1f46dcSZachary Turner StructuredData::ArraySP result(new StructuredData::Array); 6562c1f46dcSZachary Turner uint32_t count = GetSize(); 657b9c1b51eSKate Stone for (uint32_t i = 0; i < count; ++i) { 6582c1f46dcSZachary Turner PythonObject obj = GetItemAtIndex(i); 6592c1f46dcSZachary Turner result->AddItem(obj.CreateStructuredObject()); 6602c1f46dcSZachary Turner } 6612c1f46dcSZachary Turner return result; 6622c1f46dcSZachary Turner } 6632c1f46dcSZachary Turner 6642c1f46dcSZachary Turner //---------------------------------------------------------------------- 665a1405147SZachary Turner // PythonTuple 666a1405147SZachary Turner //---------------------------------------------------------------------- 667a1405147SZachary Turner 668b9c1b51eSKate Stone PythonTuple::PythonTuple(PyInitialValue value) : PythonObject() { 669a1405147SZachary Turner if (value == PyInitialValue::Empty) 670a1405147SZachary Turner Reset(PyRefType::Owned, PyTuple_New(0)); 671a1405147SZachary Turner } 672a1405147SZachary Turner 673b9c1b51eSKate Stone PythonTuple::PythonTuple(int tuple_size) : PythonObject() { 674a1405147SZachary Turner Reset(PyRefType::Owned, PyTuple_New(tuple_size)); 675a1405147SZachary Turner } 676a1405147SZachary Turner 677b9c1b51eSKate Stone PythonTuple::PythonTuple(PyRefType type, PyObject *py_obj) : PythonObject() { 678a1405147SZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a tuple 679a1405147SZachary Turner } 680a1405147SZachary Turner 681b9c1b51eSKate Stone PythonTuple::PythonTuple(const PythonTuple &tuple) : PythonObject(tuple) {} 682a1405147SZachary Turner 683b9c1b51eSKate Stone PythonTuple::PythonTuple(std::initializer_list<PythonObject> objects) { 684a1405147SZachary Turner m_py_obj = PyTuple_New(objects.size()); 685a1405147SZachary Turner 686a1405147SZachary Turner uint32_t idx = 0; 687b9c1b51eSKate Stone for (auto object : objects) { 688a1405147SZachary Turner if (object.IsValid()) 689a1405147SZachary Turner SetItemAtIndex(idx, object); 690a1405147SZachary Turner idx++; 691a1405147SZachary Turner } 692a1405147SZachary Turner } 693a1405147SZachary Turner 694b9c1b51eSKate Stone PythonTuple::PythonTuple(std::initializer_list<PyObject *> objects) { 695a1405147SZachary Turner m_py_obj = PyTuple_New(objects.size()); 696a1405147SZachary Turner 697a1405147SZachary Turner uint32_t idx = 0; 698b9c1b51eSKate Stone for (auto py_object : objects) { 699a1405147SZachary Turner PythonObject object(PyRefType::Borrowed, py_object); 700a1405147SZachary Turner if (object.IsValid()) 701a1405147SZachary Turner SetItemAtIndex(idx, object); 702a1405147SZachary Turner idx++; 703a1405147SZachary Turner } 704a1405147SZachary Turner } 705a1405147SZachary Turner 706b9c1b51eSKate Stone PythonTuple::~PythonTuple() {} 707a1405147SZachary Turner 708b9c1b51eSKate Stone bool PythonTuple::Check(PyObject *py_obj) { 709a1405147SZachary Turner if (!py_obj) 710a1405147SZachary Turner return false; 711a1405147SZachary Turner return PyTuple_Check(py_obj); 712a1405147SZachary Turner } 713a1405147SZachary Turner 714b9c1b51eSKate Stone void PythonTuple::Reset(PyRefType type, PyObject *py_obj) { 71505097246SAdrian Prantl // Grab the desired reference type so that if we end up rejecting `py_obj` it 71605097246SAdrian Prantl // still gets decremented if necessary. 717a1405147SZachary Turner PythonObject result(type, py_obj); 718a1405147SZachary Turner 719b9c1b51eSKate Stone if (!PythonTuple::Check(py_obj)) { 720a1405147SZachary Turner PythonObject::Reset(); 721a1405147SZachary Turner return; 722a1405147SZachary Turner } 723a1405147SZachary Turner 724b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 72505097246SAdrian Prantl // overflow since it calls back into the virtual implementation. 726a1405147SZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 727a1405147SZachary Turner } 728a1405147SZachary Turner 729b9c1b51eSKate Stone uint32_t PythonTuple::GetSize() const { 730a1405147SZachary Turner if (IsValid()) 731a1405147SZachary Turner return PyTuple_GET_SIZE(m_py_obj); 732a1405147SZachary Turner return 0; 733a1405147SZachary Turner } 734a1405147SZachary Turner 735b9c1b51eSKate Stone PythonObject PythonTuple::GetItemAtIndex(uint32_t index) const { 736a1405147SZachary Turner if (IsValid()) 737a1405147SZachary Turner return PythonObject(PyRefType::Borrowed, PyTuple_GetItem(m_py_obj, index)); 738a1405147SZachary Turner return PythonObject(); 739a1405147SZachary Turner } 740a1405147SZachary Turner 741b9c1b51eSKate Stone void PythonTuple::SetItemAtIndex(uint32_t index, const PythonObject &object) { 742b9c1b51eSKate Stone if (IsAllocated() && object.IsValid()) { 743a1405147SZachary Turner // PyTuple_SetItem is documented to "steal" a reference, so we need to 744a1405147SZachary Turner // convert it to an owned reference by incrementing it. 745a1405147SZachary Turner Py_INCREF(object.get()); 746a1405147SZachary Turner PyTuple_SetItem(m_py_obj, index, object.get()); 747a1405147SZachary Turner } 748a1405147SZachary Turner } 749a1405147SZachary Turner 750b9c1b51eSKate Stone StructuredData::ArraySP PythonTuple::CreateStructuredArray() const { 751a1405147SZachary Turner StructuredData::ArraySP result(new StructuredData::Array); 752a1405147SZachary Turner uint32_t count = GetSize(); 753b9c1b51eSKate Stone for (uint32_t i = 0; i < count; ++i) { 754a1405147SZachary Turner PythonObject obj = GetItemAtIndex(i); 755a1405147SZachary Turner result->AddItem(obj.CreateStructuredObject()); 756a1405147SZachary Turner } 757a1405147SZachary Turner return result; 758a1405147SZachary Turner } 759a1405147SZachary Turner 760a1405147SZachary Turner //---------------------------------------------------------------------- 7612c1f46dcSZachary Turner // PythonDictionary 7622c1f46dcSZachary Turner //---------------------------------------------------------------------- 7632c1f46dcSZachary Turner 764b9c1b51eSKate Stone PythonDictionary::PythonDictionary(PyInitialValue value) : PythonObject() { 765f8b22f8fSZachary Turner if (value == PyInitialValue::Empty) 766f8b22f8fSZachary Turner Reset(PyRefType::Owned, PyDict_New()); 7672c1f46dcSZachary Turner } 7682c1f46dcSZachary Turner 769f8b22f8fSZachary Turner PythonDictionary::PythonDictionary(PyRefType type, PyObject *py_obj) 770b9c1b51eSKate Stone : PythonObject() { 771f8b22f8fSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a dictionary 7722c1f46dcSZachary Turner } 7732c1f46dcSZachary Turner 774f8b22f8fSZachary Turner PythonDictionary::PythonDictionary(const PythonDictionary &object) 775b9c1b51eSKate Stone : PythonObject(object) {} 7762c1f46dcSZachary Turner 777b9c1b51eSKate Stone PythonDictionary::~PythonDictionary() {} 7782c1f46dcSZachary Turner 779b9c1b51eSKate Stone bool PythonDictionary::Check(PyObject *py_obj) { 78022c8efcdSZachary Turner if (!py_obj) 78122c8efcdSZachary Turner return false; 78222c8efcdSZachary Turner 78322c8efcdSZachary Turner return PyDict_Check(py_obj); 78422c8efcdSZachary Turner } 78522c8efcdSZachary Turner 786b9c1b51eSKate Stone void PythonDictionary::Reset(PyRefType type, PyObject *py_obj) { 78705097246SAdrian Prantl // Grab the desired reference type so that if we end up rejecting `py_obj` it 78805097246SAdrian Prantl // still gets decremented if necessary. 789f8b22f8fSZachary Turner PythonObject result(type, py_obj); 790f8b22f8fSZachary Turner 791b9c1b51eSKate Stone if (!PythonDictionary::Check(py_obj)) { 792f8b22f8fSZachary Turner PythonObject::Reset(); 793f8b22f8fSZachary Turner return; 79422c8efcdSZachary Turner } 79522c8efcdSZachary Turner 796b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 79705097246SAdrian Prantl // overflow since it calls back into the virtual implementation. 798f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 7992c1f46dcSZachary Turner } 8002c1f46dcSZachary Turner 801b9c1b51eSKate Stone uint32_t PythonDictionary::GetSize() const { 802f8b22f8fSZachary Turner if (IsValid()) 8032c1f46dcSZachary Turner return PyDict_Size(m_py_obj); 8042c1f46dcSZachary Turner return 0; 8052c1f46dcSZachary Turner } 8062c1f46dcSZachary Turner 807b9c1b51eSKate Stone PythonList PythonDictionary::GetKeys() const { 808f8b22f8fSZachary Turner if (IsValid()) 809f8b22f8fSZachary Turner return PythonList(PyRefType::Owned, PyDict_Keys(m_py_obj)); 810f8b22f8fSZachary Turner return PythonList(PyInitialValue::Invalid); 8112c1f46dcSZachary Turner } 8122c1f46dcSZachary Turner 813b9c1b51eSKate Stone PythonObject PythonDictionary::GetItemForKey(const PythonObject &key) const { 814f8b22f8fSZachary Turner if (IsAllocated() && key.IsValid()) 815b9c1b51eSKate Stone return PythonObject(PyRefType::Borrowed, 816b9c1b51eSKate Stone PyDict_GetItem(m_py_obj, key.get())); 8172c1f46dcSZachary Turner return PythonObject(); 8182c1f46dcSZachary Turner } 8192c1f46dcSZachary Turner 820b9c1b51eSKate Stone void PythonDictionary::SetItemForKey(const PythonObject &key, 821b9c1b51eSKate Stone const PythonObject &value) { 822f8b22f8fSZachary Turner if (IsAllocated() && key.IsValid() && value.IsValid()) 8232c1f46dcSZachary Turner PyDict_SetItem(m_py_obj, key.get(), value.get()); 8242c1f46dcSZachary Turner } 8252c1f46dcSZachary Turner 8262c1f46dcSZachary Turner StructuredData::DictionarySP 827b9c1b51eSKate Stone PythonDictionary::CreateStructuredDictionary() const { 8282c1f46dcSZachary Turner StructuredData::DictionarySP result(new StructuredData::Dictionary); 8292c1f46dcSZachary Turner PythonList keys(GetKeys()); 8302c1f46dcSZachary Turner uint32_t num_keys = keys.GetSize(); 831b9c1b51eSKate Stone for (uint32_t i = 0; i < num_keys; ++i) { 8322c1f46dcSZachary Turner PythonObject key = keys.GetItemAtIndex(i); 8332c1f46dcSZachary Turner PythonObject value = GetItemForKey(key); 8342c1f46dcSZachary Turner StructuredData::ObjectSP structured_value = value.CreateStructuredObject(); 835f8b22f8fSZachary Turner result->AddItem(key.Str().GetString(), structured_value); 8362c1f46dcSZachary Turner } 8372c1f46dcSZachary Turner return result; 8382c1f46dcSZachary Turner } 8392c1f46dcSZachary Turner 840b9c1b51eSKate Stone PythonModule::PythonModule() : PythonObject() {} 8417841efbbSZachary Turner 842b9c1b51eSKate Stone PythonModule::PythonModule(PyRefType type, PyObject *py_obj) { 8437841efbbSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a module 8447841efbbSZachary Turner } 8457841efbbSZachary Turner 846b9c1b51eSKate Stone PythonModule::PythonModule(const PythonModule &dict) : PythonObject(dict) {} 8477841efbbSZachary Turner 848b9c1b51eSKate Stone PythonModule::~PythonModule() {} 8497841efbbSZachary Turner 850b9c1b51eSKate Stone PythonModule PythonModule::BuiltinsModule() { 851a1405147SZachary Turner #if PY_MAJOR_VERSION >= 3 852a1405147SZachary Turner return AddModule("builtins"); 853a1405147SZachary Turner #else 854a1405147SZachary Turner return AddModule("__builtin__"); 855a1405147SZachary Turner #endif 856a1405147SZachary Turner } 857a1405147SZachary Turner 858b9c1b51eSKate Stone PythonModule PythonModule::MainModule() { return AddModule("__main__"); } 859a1405147SZachary Turner 860b9c1b51eSKate Stone PythonModule PythonModule::AddModule(llvm::StringRef module) { 861a1405147SZachary Turner std::string str = module.str(); 862a1405147SZachary Turner return PythonModule(PyRefType::Borrowed, PyImport_AddModule(str.c_str())); 8637841efbbSZachary Turner } 8647841efbbSZachary Turner 865b9c1b51eSKate Stone PythonModule PythonModule::ImportModule(llvm::StringRef module) { 8662419f1d5SZachary Turner std::string str = module.str(); 8672419f1d5SZachary Turner return PythonModule(PyRefType::Owned, PyImport_ImportModule(str.c_str())); 8682419f1d5SZachary Turner } 8692419f1d5SZachary Turner 870b9c1b51eSKate Stone bool PythonModule::Check(PyObject *py_obj) { 8717841efbbSZachary Turner if (!py_obj) 8727841efbbSZachary Turner return false; 8737841efbbSZachary Turner 8747841efbbSZachary Turner return PyModule_Check(py_obj); 8757841efbbSZachary Turner } 8767841efbbSZachary Turner 877b9c1b51eSKate Stone void PythonModule::Reset(PyRefType type, PyObject *py_obj) { 87805097246SAdrian Prantl // Grab the desired reference type so that if we end up rejecting `py_obj` it 87905097246SAdrian Prantl // still gets decremented if necessary. 8807841efbbSZachary Turner PythonObject result(type, py_obj); 8817841efbbSZachary Turner 882b9c1b51eSKate Stone if (!PythonModule::Check(py_obj)) { 8837841efbbSZachary Turner PythonObject::Reset(); 8847841efbbSZachary Turner return; 8857841efbbSZachary Turner } 8867841efbbSZachary Turner 887b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 88805097246SAdrian Prantl // overflow since it calls back into the virtual implementation. 8897841efbbSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 8907841efbbSZachary Turner } 8917841efbbSZachary Turner 892b9c1b51eSKate Stone PythonDictionary PythonModule::GetDictionary() const { 8937841efbbSZachary Turner return PythonDictionary(PyRefType::Borrowed, PyModule_GetDict(m_py_obj)); 8947841efbbSZachary Turner } 8957841efbbSZachary Turner 896b9c1b51eSKate Stone PythonCallable::PythonCallable() : PythonObject() {} 897a1405147SZachary Turner 898b9c1b51eSKate Stone PythonCallable::PythonCallable(PyRefType type, PyObject *py_obj) { 899a1405147SZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a callable 900a1405147SZachary Turner } 901a1405147SZachary Turner 902a1405147SZachary Turner PythonCallable::PythonCallable(const PythonCallable &callable) 903b9c1b51eSKate Stone : PythonObject(callable) {} 904a1405147SZachary Turner 905b9c1b51eSKate Stone PythonCallable::~PythonCallable() {} 906a1405147SZachary Turner 907b9c1b51eSKate Stone bool PythonCallable::Check(PyObject *py_obj) { 908a1405147SZachary Turner if (!py_obj) 909a1405147SZachary Turner return false; 910a1405147SZachary Turner 911a1405147SZachary Turner return PyCallable_Check(py_obj); 912a1405147SZachary Turner } 913a1405147SZachary Turner 914b9c1b51eSKate Stone void PythonCallable::Reset(PyRefType type, PyObject *py_obj) { 91505097246SAdrian Prantl // Grab the desired reference type so that if we end up rejecting `py_obj` it 91605097246SAdrian Prantl // still gets decremented if necessary. 917a1405147SZachary Turner PythonObject result(type, py_obj); 918a1405147SZachary Turner 919b9c1b51eSKate Stone if (!PythonCallable::Check(py_obj)) { 920a1405147SZachary Turner PythonObject::Reset(); 921a1405147SZachary Turner return; 922a1405147SZachary Turner } 923a1405147SZachary Turner 924b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 92505097246SAdrian Prantl // overflow since it calls back into the virtual implementation. 926a1405147SZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 927a1405147SZachary Turner } 928a1405147SZachary Turner 929b9c1b51eSKate Stone PythonCallable::ArgInfo PythonCallable::GetNumArguments() const { 930a5d6765cSEnrico Granata ArgInfo result = {0, false, false, false}; 931a1405147SZachary Turner if (!IsValid()) 932b58fb2f4SZachary Turner return result; 933a1405147SZachary Turner 934a1405147SZachary Turner PyObject *py_func_obj = m_py_obj; 935b9c1b51eSKate Stone if (PyMethod_Check(py_func_obj)) { 936a1405147SZachary Turner py_func_obj = PyMethod_GET_FUNCTION(py_func_obj); 937a5d6765cSEnrico Granata PythonObject im_self = GetAttributeValue("im_self"); 938a5d6765cSEnrico Granata if (im_self.IsValid() && !im_self.IsNone()) 939a5d6765cSEnrico Granata result.is_bound_method = true; 940b9c1b51eSKate Stone } else { 941a5d6765cSEnrico Granata // see if this is a callable object with an __call__ method 942b9c1b51eSKate Stone if (!PyFunction_Check(py_func_obj)) { 943a5d6765cSEnrico Granata PythonObject __call__ = GetAttributeValue("__call__"); 944b9c1b51eSKate Stone if (__call__.IsValid()) { 945a5d6765cSEnrico Granata auto __callable__ = __call__.AsType<PythonCallable>(); 946b9c1b51eSKate Stone if (__callable__.IsValid()) { 947a5d6765cSEnrico Granata py_func_obj = PyMethod_GET_FUNCTION(__callable__.get()); 948a5d6765cSEnrico Granata PythonObject im_self = GetAttributeValue("im_self"); 949a5d6765cSEnrico Granata if (im_self.IsValid() && !im_self.IsNone()) 950a5d6765cSEnrico Granata result.is_bound_method = true; 951a5d6765cSEnrico Granata } 952a5d6765cSEnrico Granata } 953a5d6765cSEnrico Granata } 954a5d6765cSEnrico Granata } 955a1405147SZachary Turner 956a1405147SZachary Turner if (!py_func_obj) 957b58fb2f4SZachary Turner return result; 958a1405147SZachary Turner 959a1405147SZachary Turner PyCodeObject *code = (PyCodeObject *)PyFunction_GET_CODE(py_func_obj); 960a1405147SZachary Turner if (!code) 961b58fb2f4SZachary Turner return result; 962a1405147SZachary Turner 963b58fb2f4SZachary Turner result.count = code->co_argcount; 964b58fb2f4SZachary Turner result.has_varargs = !!(code->co_flags & CO_VARARGS); 965b58fb2f4SZachary Turner result.has_kwargs = !!(code->co_flags & CO_VARKEYWORDS); 966b58fb2f4SZachary Turner return result; 967b58fb2f4SZachary Turner } 968b58fb2f4SZachary Turner 969b9c1b51eSKate Stone PythonObject PythonCallable::operator()() { 970b9c1b51eSKate Stone return PythonObject(PyRefType::Owned, PyObject_CallObject(m_py_obj, nullptr)); 971a1405147SZachary Turner } 972a1405147SZachary Turner 973b9c1b51eSKate Stone PythonObject PythonCallable:: 974b9c1b51eSKate Stone operator()(std::initializer_list<PyObject *> args) { 975a1405147SZachary Turner PythonTuple arg_tuple(args); 976a1405147SZachary Turner return PythonObject(PyRefType::Owned, 977a1405147SZachary Turner PyObject_CallObject(m_py_obj, arg_tuple.get())); 978a1405147SZachary Turner } 979a1405147SZachary Turner 980b9c1b51eSKate Stone PythonObject PythonCallable:: 981b9c1b51eSKate Stone operator()(std::initializer_list<PythonObject> args) { 982a1405147SZachary Turner PythonTuple arg_tuple(args); 983a1405147SZachary Turner return PythonObject(PyRefType::Owned, 984a1405147SZachary Turner PyObject_CallObject(m_py_obj, arg_tuple.get())); 985a1405147SZachary Turner } 986a1405147SZachary Turner 987b9c1b51eSKate Stone PythonFile::PythonFile() : PythonObject() {} 98832064024SZachary Turner 989b9c1b51eSKate Stone PythonFile::PythonFile(File &file, const char *mode) { Reset(file, mode); } 9909c40264fSZachary Turner 991b9c1b51eSKate Stone PythonFile::PythonFile(const char *path, const char *mode) { 99250bc1ed2SJonas Devlieghere lldb_private::File file; 99350bc1ed2SJonas Devlieghere FileSystem::Instance().Open(file, FileSpec(path), GetOptionsFromMode(mode)); 994eda01c31SZachary Turner Reset(file, mode); 995eda01c31SZachary Turner } 996eda01c31SZachary Turner 997b9c1b51eSKate Stone PythonFile::PythonFile(PyRefType type, PyObject *o) { Reset(type, o); } 9989c40264fSZachary Turner 999b9c1b51eSKate Stone PythonFile::~PythonFile() {} 10009c40264fSZachary Turner 1001b9c1b51eSKate Stone bool PythonFile::Check(PyObject *py_obj) { 10029c40264fSZachary Turner #if PY_MAJOR_VERSION < 3 100323502721SJason Molenda return PyFile_Check(py_obj); 100423502721SJason Molenda #else 10059c40264fSZachary Turner // In Python 3, there is no `PyFile_Check`, and in fact PyFile is not even a 10069c40264fSZachary Turner // first-class object type anymore. `PyFile_FromFd` is just a thin wrapper 100705097246SAdrian Prantl // over `io.open()`, which returns some object derived from `io.IOBase`. As a 100805097246SAdrian Prantl // result, the only way to detect a file in Python 3 is to check whether it 100905097246SAdrian Prantl // inherits from `io.IOBase`. Since it is possible for non-files to also 10109c40264fSZachary Turner // inherit from `io.IOBase`, we additionally verify that it has the `fileno` 10119c40264fSZachary Turner // attribute, which should guarantee that it is backed by the file system. 10129c40264fSZachary Turner PythonObject io_module(PyRefType::Owned, PyImport_ImportModule("io")); 1013b9c1b51eSKate Stone PythonDictionary io_dict(PyRefType::Borrowed, 1014b9c1b51eSKate Stone PyModule_GetDict(io_module.get())); 10159c40264fSZachary Turner PythonObject io_base_class = io_dict.GetItemForKey(PythonString("IOBase")); 10169c40264fSZachary Turner 10179c40264fSZachary Turner PythonObject object_type(PyRefType::Owned, PyObject_Type(py_obj)); 10189c40264fSZachary Turner 10199c40264fSZachary Turner if (1 != PyObject_IsSubclass(object_type.get(), io_base_class.get())) 10209c40264fSZachary Turner return false; 10219c40264fSZachary Turner if (!object_type.HasAttribute("fileno")) 10229c40264fSZachary Turner return false; 10239c40264fSZachary Turner 10249c40264fSZachary Turner return true; 102523502721SJason Molenda #endif 10269c40264fSZachary Turner } 10279c40264fSZachary Turner 1028b9c1b51eSKate Stone void PythonFile::Reset(PyRefType type, PyObject *py_obj) { 102905097246SAdrian Prantl // Grab the desired reference type so that if we end up rejecting `py_obj` it 103005097246SAdrian Prantl // still gets decremented if necessary. 10319c40264fSZachary Turner PythonObject result(type, py_obj); 10329c40264fSZachary Turner 103323502721SJason Molenda if (!PythonFile::Check(py_obj)) { 10349c40264fSZachary Turner PythonObject::Reset(); 10359c40264fSZachary Turner return; 10369c40264fSZachary Turner } 10379c40264fSZachary Turner 10389c40264fSZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack 10399c40264fSZachary Turner // overflow since it calls back into the virtual implementation. 10409c40264fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 10419c40264fSZachary Turner } 10429c40264fSZachary Turner 1043b9c1b51eSKate Stone void PythonFile::Reset(File &file, const char *mode) { 1044b9c1b51eSKate Stone if (!file.IsValid()) { 104532ac147bSZachary Turner Reset(); 104632ac147bSZachary Turner return; 104732ac147bSZachary Turner } 104832ac147bSZachary Turner 10499c40264fSZachary Turner char *cmode = const_cast<char *>(mode); 10509c40264fSZachary Turner #if PY_MAJOR_VERSION >= 3 1051b9c1b51eSKate Stone Reset(PyRefType::Owned, PyFile_FromFd(file.GetDescriptor(), nullptr, cmode, 1052b9c1b51eSKate Stone -1, nullptr, "ignore", nullptr, 0)); 10539c40264fSZachary Turner #else 10549c40264fSZachary Turner // Read through the Python source, doesn't seem to modify these strings 10559c40264fSZachary Turner Reset(PyRefType::Owned, 1056b9c1b51eSKate Stone PyFile_FromFile(file.GetStream(), const_cast<char *>(""), cmode, 1057b9c1b51eSKate Stone nullptr)); 10589c40264fSZachary Turner #endif 10599c40264fSZachary Turner } 10609c40264fSZachary Turner 1061b9c1b51eSKate Stone uint32_t PythonFile::GetOptionsFromMode(llvm::StringRef mode) { 1062744959b9SEnrico Granata if (mode.empty()) 1063744959b9SEnrico Granata return 0; 1064744959b9SEnrico Granata 1065771ef6d4SMalcolm Parsons return llvm::StringSwitch<uint32_t>(mode.str()) 1066744959b9SEnrico Granata .Case("r", File::eOpenOptionRead) 1067744959b9SEnrico Granata .Case("w", File::eOpenOptionWrite) 1068b9c1b51eSKate Stone .Case("a", File::eOpenOptionWrite | File::eOpenOptionAppend | 1069b9c1b51eSKate Stone File::eOpenOptionCanCreate) 1070744959b9SEnrico Granata .Case("r+", File::eOpenOptionRead | File::eOpenOptionWrite) 1071b9c1b51eSKate Stone .Case("w+", File::eOpenOptionRead | File::eOpenOptionWrite | 1072b9c1b51eSKate Stone File::eOpenOptionCanCreate | File::eOpenOptionTruncate) 1073b9c1b51eSKate Stone .Case("a+", File::eOpenOptionRead | File::eOpenOptionWrite | 1074b9c1b51eSKate Stone File::eOpenOptionAppend | File::eOpenOptionCanCreate) 1075744959b9SEnrico Granata .Default(0); 1076744959b9SEnrico Granata } 1077744959b9SEnrico Granata 1078b9c1b51eSKate Stone bool PythonFile::GetUnderlyingFile(File &file) const { 1079eda01c31SZachary Turner if (!IsValid()) 1080eda01c31SZachary Turner return false; 1081eda01c31SZachary Turner 1082eda01c31SZachary Turner file.Close(); 1083eda01c31SZachary Turner // We don't own the file descriptor returned by this function, make sure the 1084eda01c31SZachary Turner // File object knows about that. 1085eda01c31SZachary Turner file.SetDescriptor(PyObject_AsFileDescriptor(m_py_obj), false); 1086744959b9SEnrico Granata PythonString py_mode = GetAttributeValue("mode").AsType<PythonString>(); 1087744959b9SEnrico Granata file.SetOptions(PythonFile::GetOptionsFromMode(py_mode.GetString())); 1088eda01c31SZachary Turner return file.IsValid(); 1089eda01c31SZachary Turner } 1090d68983e3SPavel Labath 1091d68983e3SPavel Labath #endif 1092