12c1f46dcSZachary Turner //===-- PythonDataObjects.cpp ------------------------------------*- C++ -*-===// 22c1f46dcSZachary Turner // 32c1f46dcSZachary Turner // The LLVM Compiler Infrastructure 42c1f46dcSZachary Turner // 52c1f46dcSZachary Turner // This file is distributed under the University of Illinois Open Source 62c1f46dcSZachary Turner // License. See LICENSE.TXT for details. 72c1f46dcSZachary Turner // 82c1f46dcSZachary Turner //===----------------------------------------------------------------------===// 92c1f46dcSZachary Turner 102c1f46dcSZachary Turner #ifdef LLDB_DISABLE_PYTHON 112c1f46dcSZachary Turner 122c1f46dcSZachary Turner // Python is disabled in this build 132c1f46dcSZachary Turner 142c1f46dcSZachary Turner #else 152c1f46dcSZachary Turner 162c1f46dcSZachary Turner #include "lldb-python.h" 172c1f46dcSZachary Turner #include "PythonDataObjects.h" 182c1f46dcSZachary Turner #include "ScriptInterpreterPython.h" 192c1f46dcSZachary Turner 202c1f46dcSZachary Turner #include "lldb/Core/Stream.h" 212c1f46dcSZachary Turner #include "lldb/Host/File.h" 222c1f46dcSZachary Turner #include "lldb/Interpreter/ScriptInterpreter.h" 232c1f46dcSZachary Turner 242c1f46dcSZachary Turner #include <stdio.h> 252c1f46dcSZachary Turner 262c1f46dcSZachary Turner using namespace lldb_private; 272c1f46dcSZachary Turner using namespace lldb; 282c1f46dcSZachary Turner 292c1f46dcSZachary Turner void 302c1f46dcSZachary Turner StructuredPythonObject::Dump(Stream &s) const 312c1f46dcSZachary Turner { 322c1f46dcSZachary Turner s << "Python Obj: 0x" << GetValue(); 332c1f46dcSZachary Turner } 342c1f46dcSZachary Turner 352c1f46dcSZachary Turner //---------------------------------------------------------------------- 362c1f46dcSZachary Turner // PythonObject 372c1f46dcSZachary Turner //---------------------------------------------------------------------- 382c1f46dcSZachary Turner 392c1f46dcSZachary Turner void 402c1f46dcSZachary Turner PythonObject::Dump(Stream &strm) const 412c1f46dcSZachary Turner { 422c1f46dcSZachary Turner if (m_py_obj) 432c1f46dcSZachary Turner { 442c1f46dcSZachary Turner FILE *file = ::tmpfile(); 452c1f46dcSZachary Turner if (file) 462c1f46dcSZachary Turner { 472c1f46dcSZachary Turner ::PyObject_Print (m_py_obj, file, 0); 482c1f46dcSZachary Turner const long length = ftell (file); 492c1f46dcSZachary Turner if (length) 502c1f46dcSZachary Turner { 512c1f46dcSZachary Turner ::rewind(file); 522c1f46dcSZachary Turner std::vector<char> file_contents (length,'\0'); 532c1f46dcSZachary Turner const size_t length_read = ::fread (file_contents.data(), 1, file_contents.size(), file); 542c1f46dcSZachary Turner if (length_read > 0) 552c1f46dcSZachary Turner strm.Write (file_contents.data(), length_read); 562c1f46dcSZachary Turner } 572c1f46dcSZachary Turner ::fclose (file); 582c1f46dcSZachary Turner } 592c1f46dcSZachary Turner } 602c1f46dcSZachary Turner else 612c1f46dcSZachary Turner strm.PutCString ("NULL"); 622c1f46dcSZachary Turner } 632c1f46dcSZachary Turner 642c1f46dcSZachary Turner PyObjectType 652c1f46dcSZachary Turner PythonObject::GetObjectType() const 662c1f46dcSZachary Turner { 67f8b22f8fSZachary Turner if (!IsAllocated()) 682c1f46dcSZachary Turner return PyObjectType::None; 692c1f46dcSZachary Turner 70*7841efbbSZachary Turner if (PythonModule::Check(m_py_obj)) 71*7841efbbSZachary Turner return PyObjectType::Module; 7218426935SZachary Turner if (PythonList::Check(m_py_obj)) 732c1f46dcSZachary Turner return PyObjectType::List; 7418426935SZachary Turner if (PythonDictionary::Check(m_py_obj)) 752c1f46dcSZachary Turner return PyObjectType::Dictionary; 7618426935SZachary Turner if (PythonString::Check(m_py_obj)) 7722c8efcdSZachary Turner return PyObjectType::String; 7818426935SZachary Turner if (PythonInteger::Check(m_py_obj)) 7922c8efcdSZachary Turner return PyObjectType::Integer; 809c40264fSZachary Turner if (PythonFile::Check(m_py_obj)) 819c40264fSZachary Turner return PyObjectType::File; 822c1f46dcSZachary Turner return PyObjectType::Unknown; 832c1f46dcSZachary Turner } 842c1f46dcSZachary Turner 852c1f46dcSZachary Turner PythonString 86*7841efbbSZachary Turner PythonObject::Repr() const 872c1f46dcSZachary Turner { 882c1f46dcSZachary Turner if (!m_py_obj) 892c1f46dcSZachary Turner return PythonString(); 902c1f46dcSZachary Turner PyObject *repr = PyObject_Repr(m_py_obj); 912c1f46dcSZachary Turner if (!repr) 922c1f46dcSZachary Turner return PythonString(); 93f8b22f8fSZachary Turner return PythonString(PyRefType::Owned, repr); 942c1f46dcSZachary Turner } 952c1f46dcSZachary Turner 962c1f46dcSZachary Turner PythonString 97*7841efbbSZachary Turner PythonObject::Str() const 982c1f46dcSZachary Turner { 992c1f46dcSZachary Turner if (!m_py_obj) 1002c1f46dcSZachary Turner return PythonString(); 1012c1f46dcSZachary Turner PyObject *str = PyObject_Str(m_py_obj); 1022c1f46dcSZachary Turner if (!str) 1032c1f46dcSZachary Turner return PythonString(); 104f8b22f8fSZachary Turner return PythonString(PyRefType::Owned, str); 1052c1f46dcSZachary Turner } 1062c1f46dcSZachary Turner 107*7841efbbSZachary Turner PythonObject 108*7841efbbSZachary Turner PythonObject::ResolveNameGlobal(llvm::StringRef name) 109*7841efbbSZachary Turner { 110*7841efbbSZachary Turner return PythonModule::MainModule().ResolveName(name); 111*7841efbbSZachary Turner } 112*7841efbbSZachary Turner 113*7841efbbSZachary Turner PythonObject 114*7841efbbSZachary Turner PythonObject::ResolveName(llvm::StringRef name) const 115*7841efbbSZachary Turner { 116*7841efbbSZachary Turner // Resolve the name in the context of the specified object. If, 117*7841efbbSZachary Turner // for example, `this` refers to a PyModule, then this will look for 118*7841efbbSZachary Turner // `name` in this module. If `this` refers to a PyType, then it will 119*7841efbbSZachary Turner // resolve `name` as an attribute of that type. If `this` refers to 120*7841efbbSZachary Turner // an instance of an object, then it will resolve `name` as the value 121*7841efbbSZachary Turner // of the specified field. 122*7841efbbSZachary Turner // 123*7841efbbSZachary Turner // This function handles dotted names so that, for example, if `m_py_obj` 124*7841efbbSZachary Turner // refers to the `sys` module, and `name` == "path.append", then it 125*7841efbbSZachary Turner // will find the function `sys.path.append`. 126*7841efbbSZachary Turner 127*7841efbbSZachary Turner size_t dot_pos = name.find_first_of('.'); 128*7841efbbSZachary Turner if (dot_pos == llvm::StringRef::npos) 129*7841efbbSZachary Turner { 130*7841efbbSZachary Turner // No dots in the name, we should be able to find the value immediately 131*7841efbbSZachary Turner // as an attribute of `use_object`. 132*7841efbbSZachary Turner return GetAttributeValue(name); 133*7841efbbSZachary Turner } 134*7841efbbSZachary Turner 135*7841efbbSZachary Turner // Look up the first piece of the name, and resolve the rest as a child of that. 136*7841efbbSZachary Turner PythonObject parent = ResolveName(name.substr(0, dot_pos)); 137*7841efbbSZachary Turner if (!parent.IsAllocated()) 138*7841efbbSZachary Turner return PythonObject(); 139*7841efbbSZachary Turner 140*7841efbbSZachary Turner // Tail recursion.. should be optimized by the compiler 141*7841efbbSZachary Turner return parent.ResolveName(name.substr(dot_pos + 1)); 142*7841efbbSZachary Turner } 143*7841efbbSZachary Turner 1442c1f46dcSZachary Turner bool 1459c40264fSZachary Turner PythonObject::HasAttribute(llvm::StringRef attr) const 1469c40264fSZachary Turner { 1479c40264fSZachary Turner if (!IsValid()) 1489c40264fSZachary Turner return false; 1499c40264fSZachary Turner PythonString py_attr(attr); 1509c40264fSZachary Turner return !!PyObject_HasAttr(m_py_obj, py_attr.get()); 1519c40264fSZachary Turner } 1529c40264fSZachary Turner 1537d6d218eSZachary Turner PythonObject 1547d6d218eSZachary Turner PythonObject::GetAttributeValue(llvm::StringRef attr) const 1557d6d218eSZachary Turner { 1567d6d218eSZachary Turner if (!IsValid()) 1577d6d218eSZachary Turner return PythonObject(); 1587d6d218eSZachary Turner 1597d6d218eSZachary Turner PythonString py_attr(attr); 1607d6d218eSZachary Turner if (!PyObject_HasAttr(m_py_obj, py_attr.get())) 1617d6d218eSZachary Turner return PythonObject(); 1627d6d218eSZachary Turner 1637d6d218eSZachary Turner return PythonObject(PyRefType::Owned, 1647d6d218eSZachary Turner PyObject_GetAttr(m_py_obj, py_attr.get())); 1657d6d218eSZachary Turner } 1667d6d218eSZachary Turner 1679c40264fSZachary Turner bool 168f8b22f8fSZachary Turner PythonObject::IsNone() const 1692c1f46dcSZachary Turner { 170f8b22f8fSZachary Turner return m_py_obj == Py_None; 171f8b22f8fSZachary Turner } 172f8b22f8fSZachary Turner 173f8b22f8fSZachary Turner bool 174f8b22f8fSZachary Turner PythonObject::IsValid() const 175f8b22f8fSZachary Turner { 176f8b22f8fSZachary Turner return m_py_obj != nullptr; 177f8b22f8fSZachary Turner } 178f8b22f8fSZachary Turner 179f8b22f8fSZachary Turner bool 180f8b22f8fSZachary Turner PythonObject::IsAllocated() const 181f8b22f8fSZachary Turner { 182f8b22f8fSZachary Turner return IsValid() && !IsNone(); 1832c1f46dcSZachary Turner } 1842c1f46dcSZachary Turner 1852c1f46dcSZachary Turner StructuredData::ObjectSP 1862c1f46dcSZachary Turner PythonObject::CreateStructuredObject() const 1872c1f46dcSZachary Turner { 1882c1f46dcSZachary Turner switch (GetObjectType()) 1892c1f46dcSZachary Turner { 1902c1f46dcSZachary Turner case PyObjectType::Dictionary: 191f8b22f8fSZachary Turner return PythonDictionary(PyRefType::Borrowed, m_py_obj).CreateStructuredDictionary(); 1922c1f46dcSZachary Turner case PyObjectType::Integer: 193f8b22f8fSZachary Turner return PythonInteger(PyRefType::Borrowed, m_py_obj).CreateStructuredInteger(); 1942c1f46dcSZachary Turner case PyObjectType::List: 195f8b22f8fSZachary Turner return PythonList(PyRefType::Borrowed, m_py_obj).CreateStructuredArray(); 1962c1f46dcSZachary Turner case PyObjectType::String: 197f8b22f8fSZachary Turner return PythonString(PyRefType::Borrowed, m_py_obj).CreateStructuredString(); 1982c1f46dcSZachary Turner case PyObjectType::None: 1992c1f46dcSZachary Turner return StructuredData::ObjectSP(); 2002c1f46dcSZachary Turner default: 2012c1f46dcSZachary Turner return StructuredData::ObjectSP(new StructuredPythonObject(m_py_obj)); 2022c1f46dcSZachary Turner } 2032c1f46dcSZachary Turner } 2042c1f46dcSZachary Turner 2052c1f46dcSZachary Turner //---------------------------------------------------------------------- 2062c1f46dcSZachary Turner // PythonString 2072c1f46dcSZachary Turner //---------------------------------------------------------------------- 2082c1f46dcSZachary Turner 209f8b22f8fSZachary Turner PythonString::PythonString(PyRefType type, PyObject *py_obj) 210f8b22f8fSZachary Turner : PythonObject() 2112c1f46dcSZachary Turner { 212f8b22f8fSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string 2132c1f46dcSZachary Turner } 2142c1f46dcSZachary Turner 215f8b22f8fSZachary Turner PythonString::PythonString(const PythonString &object) 216f8b22f8fSZachary Turner : PythonObject(object) 2172c1f46dcSZachary Turner { 2182c1f46dcSZachary Turner } 2192c1f46dcSZachary Turner 22022c8efcdSZachary Turner PythonString::PythonString(llvm::StringRef string) 22122c8efcdSZachary Turner : PythonObject() 2222c1f46dcSZachary Turner { 22322c8efcdSZachary Turner SetString(string); 2242c1f46dcSZachary Turner } 2252c1f46dcSZachary Turner 22622c8efcdSZachary Turner PythonString::PythonString(const char *string) 22722c8efcdSZachary Turner : PythonObject() 2282c1f46dcSZachary Turner { 22922c8efcdSZachary Turner SetString(llvm::StringRef(string)); 2302c1f46dcSZachary Turner } 2312c1f46dcSZachary Turner 232f8b22f8fSZachary Turner PythonString::PythonString() 233f8b22f8fSZachary Turner : PythonObject() 2342c1f46dcSZachary Turner { 2352c1f46dcSZachary Turner } 2362c1f46dcSZachary Turner 2372c1f46dcSZachary Turner PythonString::~PythonString () 2382c1f46dcSZachary Turner { 2392c1f46dcSZachary Turner } 2402c1f46dcSZachary Turner 2412c1f46dcSZachary Turner bool 24222c8efcdSZachary Turner PythonString::Check(PyObject *py_obj) 24322c8efcdSZachary Turner { 24422c8efcdSZachary Turner if (!py_obj) 24522c8efcdSZachary Turner return false; 24618426935SZachary Turner 2477d6d218eSZachary Turner if (PyUnicode_Check(py_obj)) 2487d6d218eSZachary Turner return true; 2497d6d218eSZachary Turner #if PY_MAJOR_VERSION < 3 2507d6d218eSZachary Turner if (PyString_Check(py_obj)) 2517d6d218eSZachary Turner return true; 25222c8efcdSZachary Turner #endif 2537d6d218eSZachary Turner return false; 25422c8efcdSZachary Turner } 25522c8efcdSZachary Turner 256f8b22f8fSZachary Turner void 257f8b22f8fSZachary Turner PythonString::Reset(PyRefType type, PyObject *py_obj) 2582c1f46dcSZachary Turner { 259f8b22f8fSZachary Turner // Grab the desired reference type so that if we end up rejecting 260f8b22f8fSZachary Turner // `py_obj` it still gets decremented if necessary. 261f8b22f8fSZachary Turner PythonObject result(type, py_obj); 262f8b22f8fSZachary Turner 26322c8efcdSZachary Turner if (!PythonString::Check(py_obj)) 26422c8efcdSZachary Turner { 265f8b22f8fSZachary Turner PythonObject::Reset(); 266f8b22f8fSZachary Turner return; 26722c8efcdSZachary Turner } 2687d6d218eSZachary Turner #if PY_MAJOR_VERSION < 3 2697d6d218eSZachary Turner // In Python 2, Don't store PyUnicode objects directly, because we need 2707d6d218eSZachary Turner // access to their underlying character buffers which Python 2 doesn't 2717d6d218eSZachary Turner // provide. 2727d6d218eSZachary Turner if (PyUnicode_Check(py_obj)) 2737d6d218eSZachary Turner result.Reset(PyRefType::Owned, PyUnicode_AsUTF8String(result.get())); 2747d6d218eSZachary Turner #endif 275f8b22f8fSZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls 276f8b22f8fSZachary Turner // back into the virtual implementation. 277f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 2782c1f46dcSZachary Turner } 2792c1f46dcSZachary Turner 2802c1f46dcSZachary Turner llvm::StringRef 2812c1f46dcSZachary Turner PythonString::GetString() const 2822c1f46dcSZachary Turner { 28318426935SZachary Turner if (!IsValid()) 28418426935SZachary Turner return llvm::StringRef(); 28518426935SZachary Turner 28622c8efcdSZachary Turner Py_ssize_t size; 28722c8efcdSZachary Turner char *c; 28818426935SZachary Turner 28918426935SZachary Turner #if PY_MAJOR_VERSION >= 3 29018426935SZachary Turner c = PyUnicode_AsUTF8AndSize(m_py_obj, &size); 29118426935SZachary Turner #else 29218426935SZachary Turner PyString_AsStringAndSize(m_py_obj, &c, &size); 29318426935SZachary Turner #endif 29422c8efcdSZachary Turner return llvm::StringRef(c, size); 29522c8efcdSZachary Turner } 2962c1f46dcSZachary Turner 2972c1f46dcSZachary Turner size_t 2982c1f46dcSZachary Turner PythonString::GetSize() const 2992c1f46dcSZachary Turner { 300f8b22f8fSZachary Turner if (IsValid()) 30118426935SZachary Turner { 30218426935SZachary Turner #if PY_MAJOR_VERSION >= 3 30318426935SZachary Turner return PyUnicode_GetSize(m_py_obj); 30418426935SZachary Turner #else 30518426935SZachary Turner return PyString_Size(m_py_obj); 30618426935SZachary Turner #endif 30718426935SZachary Turner } 3082c1f46dcSZachary Turner return 0; 3092c1f46dcSZachary Turner } 3102c1f46dcSZachary Turner 3112c1f46dcSZachary Turner void 3122c1f46dcSZachary Turner PythonString::SetString (llvm::StringRef string) 3132c1f46dcSZachary Turner { 31422c8efcdSZachary Turner #if PY_MAJOR_VERSION >= 3 31522c8efcdSZachary Turner PyObject *unicode = PyUnicode_FromStringAndSize(string.data(), string.size()); 31618426935SZachary Turner PythonObject::Reset(PyRefType::Owned, unicode); 31722c8efcdSZachary Turner #else 31818426935SZachary Turner PyObject *str = PyString_FromStringAndSize(string.data(), string.size()); 31918426935SZachary Turner PythonObject::Reset(PyRefType::Owned, str); 32022c8efcdSZachary Turner #endif 3212c1f46dcSZachary Turner } 3222c1f46dcSZachary Turner 3232c1f46dcSZachary Turner StructuredData::StringSP 3242c1f46dcSZachary Turner PythonString::CreateStructuredString() const 3252c1f46dcSZachary Turner { 3262c1f46dcSZachary Turner StructuredData::StringSP result(new StructuredData::String); 3272c1f46dcSZachary Turner result->SetValue(GetString()); 3282c1f46dcSZachary Turner return result; 3292c1f46dcSZachary Turner } 3302c1f46dcSZachary Turner 3312c1f46dcSZachary Turner //---------------------------------------------------------------------- 3322c1f46dcSZachary Turner // PythonInteger 3332c1f46dcSZachary Turner //---------------------------------------------------------------------- 3342c1f46dcSZachary Turner 3357d6d218eSZachary Turner PythonInteger::PythonInteger() 3367d6d218eSZachary Turner : PythonObject() 3377d6d218eSZachary Turner { 3387d6d218eSZachary Turner 3397d6d218eSZachary Turner } 3407d6d218eSZachary Turner 341f8b22f8fSZachary Turner PythonInteger::PythonInteger(PyRefType type, PyObject *py_obj) 342f8b22f8fSZachary Turner : PythonObject() 3432c1f46dcSZachary Turner { 344f8b22f8fSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a integer type 3452c1f46dcSZachary Turner } 3462c1f46dcSZachary Turner 347f8b22f8fSZachary Turner PythonInteger::PythonInteger(const PythonInteger &object) 348f8b22f8fSZachary Turner : PythonObject(object) 3492c1f46dcSZachary Turner { 3502c1f46dcSZachary Turner } 3512c1f46dcSZachary Turner 352f8b22f8fSZachary Turner PythonInteger::PythonInteger(int64_t value) 353f8b22f8fSZachary Turner : PythonObject() 3542c1f46dcSZachary Turner { 3552c1f46dcSZachary Turner SetInteger(value); 3562c1f46dcSZachary Turner } 3572c1f46dcSZachary Turner 3582c1f46dcSZachary Turner 3592c1f46dcSZachary Turner PythonInteger::~PythonInteger () 3602c1f46dcSZachary Turner { 3612c1f46dcSZachary Turner } 3622c1f46dcSZachary Turner 3632c1f46dcSZachary Turner bool 36422c8efcdSZachary Turner PythonInteger::Check(PyObject *py_obj) 3652c1f46dcSZachary Turner { 36622c8efcdSZachary Turner if (!py_obj) 36722c8efcdSZachary Turner return false; 36822c8efcdSZachary Turner 36922c8efcdSZachary Turner #if PY_MAJOR_VERSION >= 3 37022c8efcdSZachary Turner // Python 3 does not have PyInt_Check. There is only one type of 37122c8efcdSZachary Turner // integral value, long. 37222c8efcdSZachary Turner return PyLong_Check(py_obj); 37322c8efcdSZachary Turner #else 37422c8efcdSZachary Turner return PyLong_Check(py_obj) || PyInt_Check(py_obj); 37522c8efcdSZachary Turner #endif 3762c1f46dcSZachary Turner } 3772c1f46dcSZachary Turner 378f8b22f8fSZachary Turner void 379f8b22f8fSZachary Turner PythonInteger::Reset(PyRefType type, PyObject *py_obj) 38022c8efcdSZachary Turner { 381f8b22f8fSZachary Turner // Grab the desired reference type so that if we end up rejecting 382f8b22f8fSZachary Turner // `py_obj` it still gets decremented if necessary. 383f8b22f8fSZachary Turner PythonObject result(type, py_obj); 384f8b22f8fSZachary Turner 38522c8efcdSZachary Turner if (!PythonInteger::Check(py_obj)) 38622c8efcdSZachary Turner { 387f8b22f8fSZachary Turner PythonObject::Reset(); 388f8b22f8fSZachary Turner return; 38922c8efcdSZachary Turner } 39022c8efcdSZachary Turner 39122c8efcdSZachary Turner #if PY_MAJOR_VERSION < 3 39222c8efcdSZachary Turner // Always store this as a PyLong, which makes interoperability between 39322c8efcdSZachary Turner // Python 2.x and Python 3.x easier. This is only necessary in 2.x, 39422c8efcdSZachary Turner // since 3.x doesn't even have a PyInt. 39522c8efcdSZachary Turner if (PyInt_Check(py_obj)) 39622c8efcdSZachary Turner { 397f8b22f8fSZachary Turner // Since we converted the original object to a different type, the new 398f8b22f8fSZachary Turner // object is an owned object regardless of the ownership semantics requested 399f8b22f8fSZachary Turner // by the user. 400f8b22f8fSZachary Turner result.Reset(PyRefType::Owned, PyLong_FromLongLong(PyInt_AsLong(py_obj))); 40122c8efcdSZachary Turner } 40222c8efcdSZachary Turner #endif 40322c8efcdSZachary Turner 404f8b22f8fSZachary Turner assert(PyLong_Check(result.get()) && "Couldn't get a PyLong from this PyObject"); 40522c8efcdSZachary Turner 406f8b22f8fSZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls 407f8b22f8fSZachary Turner // back into the virtual implementation. 408f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 4092c1f46dcSZachary Turner } 4102c1f46dcSZachary Turner 4112c1f46dcSZachary Turner int64_t 4122c1f46dcSZachary Turner PythonInteger::GetInteger() const 4132c1f46dcSZachary Turner { 4142c1f46dcSZachary Turner if (m_py_obj) 4152c1f46dcSZachary Turner { 41622c8efcdSZachary Turner assert(PyLong_Check(m_py_obj) && "PythonInteger::GetInteger has a PyObject that isn't a PyLong"); 41722c8efcdSZachary Turner 4182c1f46dcSZachary Turner return PyLong_AsLongLong(m_py_obj); 4192c1f46dcSZachary Turner } 4202c1f46dcSZachary Turner return UINT64_MAX; 4212c1f46dcSZachary Turner } 4222c1f46dcSZachary Turner 4232c1f46dcSZachary Turner void 4242c1f46dcSZachary Turner PythonInteger::SetInteger(int64_t value) 4252c1f46dcSZachary Turner { 426f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Owned, PyLong_FromLongLong(value)); 4272c1f46dcSZachary Turner } 4282c1f46dcSZachary Turner 4292c1f46dcSZachary Turner StructuredData::IntegerSP 4302c1f46dcSZachary Turner PythonInteger::CreateStructuredInteger() const 4312c1f46dcSZachary Turner { 4322c1f46dcSZachary Turner StructuredData::IntegerSP result(new StructuredData::Integer); 4332c1f46dcSZachary Turner result->SetValue(GetInteger()); 4342c1f46dcSZachary Turner return result; 4352c1f46dcSZachary Turner } 4362c1f46dcSZachary Turner 4372c1f46dcSZachary Turner //---------------------------------------------------------------------- 4382c1f46dcSZachary Turner // PythonList 4392c1f46dcSZachary Turner //---------------------------------------------------------------------- 4402c1f46dcSZachary Turner 441f8b22f8fSZachary Turner PythonList::PythonList(PyInitialValue value) 442f8b22f8fSZachary Turner : PythonObject() 4432c1f46dcSZachary Turner { 444f8b22f8fSZachary Turner if (value == PyInitialValue::Empty) 445f8b22f8fSZachary Turner Reset(PyRefType::Owned, PyList_New(0)); 4462c1f46dcSZachary Turner } 4472c1f46dcSZachary Turner 44887f47729SZachary Turner PythonList::PythonList(int list_size) 44987f47729SZachary Turner : PythonObject() 45087f47729SZachary Turner { 45187f47729SZachary Turner Reset(PyRefType::Owned, PyList_New(list_size)); 45287f47729SZachary Turner } 45387f47729SZachary Turner 454f8b22f8fSZachary Turner PythonList::PythonList(PyRefType type, PyObject *py_obj) 455f8b22f8fSZachary Turner : PythonObject() 4562c1f46dcSZachary Turner { 457f8b22f8fSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a list 4582c1f46dcSZachary Turner } 4592c1f46dcSZachary Turner 460f8b22f8fSZachary Turner PythonList::PythonList(const PythonList &list) 461f8b22f8fSZachary Turner : PythonObject(list) 4622c1f46dcSZachary Turner { 4632c1f46dcSZachary Turner } 4642c1f46dcSZachary Turner 4652c1f46dcSZachary Turner PythonList::~PythonList () 4662c1f46dcSZachary Turner { 4672c1f46dcSZachary Turner } 4682c1f46dcSZachary Turner 4692c1f46dcSZachary Turner bool 47022c8efcdSZachary Turner PythonList::Check(PyObject *py_obj) 47122c8efcdSZachary Turner { 47222c8efcdSZachary Turner if (!py_obj) 47322c8efcdSZachary Turner return false; 47422c8efcdSZachary Turner return PyList_Check(py_obj); 47522c8efcdSZachary Turner } 47622c8efcdSZachary Turner 477f8b22f8fSZachary Turner void 478f8b22f8fSZachary Turner PythonList::Reset(PyRefType type, PyObject *py_obj) 4792c1f46dcSZachary Turner { 480f8b22f8fSZachary Turner // Grab the desired reference type so that if we end up rejecting 481f8b22f8fSZachary Turner // `py_obj` it still gets decremented if necessary. 482f8b22f8fSZachary Turner PythonObject result(type, py_obj); 483f8b22f8fSZachary Turner 48422c8efcdSZachary Turner if (!PythonList::Check(py_obj)) 48522c8efcdSZachary Turner { 486f8b22f8fSZachary Turner PythonObject::Reset(); 487f8b22f8fSZachary Turner return; 48822c8efcdSZachary Turner } 48922c8efcdSZachary Turner 490f8b22f8fSZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls 491f8b22f8fSZachary Turner // back into the virtual implementation. 492f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 4932c1f46dcSZachary Turner } 4942c1f46dcSZachary Turner 4952c1f46dcSZachary Turner uint32_t 4962c1f46dcSZachary Turner PythonList::GetSize() const 4972c1f46dcSZachary Turner { 498f8b22f8fSZachary Turner if (IsValid()) 4992c1f46dcSZachary Turner return PyList_GET_SIZE(m_py_obj); 5002c1f46dcSZachary Turner return 0; 5012c1f46dcSZachary Turner } 5022c1f46dcSZachary Turner 5032c1f46dcSZachary Turner PythonObject 5042c1f46dcSZachary Turner PythonList::GetItemAtIndex(uint32_t index) const 5052c1f46dcSZachary Turner { 506f8b22f8fSZachary Turner if (IsValid()) 507f8b22f8fSZachary Turner return PythonObject(PyRefType::Borrowed, PyList_GetItem(m_py_obj, index)); 5082c1f46dcSZachary Turner return PythonObject(); 5092c1f46dcSZachary Turner } 5102c1f46dcSZachary Turner 5112c1f46dcSZachary Turner void 5122c1f46dcSZachary Turner PythonList::SetItemAtIndex(uint32_t index, const PythonObject &object) 5132c1f46dcSZachary Turner { 514f8b22f8fSZachary Turner if (IsAllocated() && object.IsValid()) 515f8b22f8fSZachary Turner { 516f8b22f8fSZachary Turner // PyList_SetItem is documented to "steal" a reference, so we need to 517f8b22f8fSZachary Turner // convert it to an owned reference by incrementing it. 518f8b22f8fSZachary Turner Py_INCREF(object.get()); 5192c1f46dcSZachary Turner PyList_SetItem(m_py_obj, index, object.get()); 5202c1f46dcSZachary Turner } 521f8b22f8fSZachary Turner } 5222c1f46dcSZachary Turner 5232c1f46dcSZachary Turner void 5242c1f46dcSZachary Turner PythonList::AppendItem(const PythonObject &object) 5252c1f46dcSZachary Turner { 526f8b22f8fSZachary Turner if (IsAllocated() && object.IsValid()) 527f8b22f8fSZachary Turner { 528f8b22f8fSZachary Turner // `PyList_Append` does *not* steal a reference, so do not call `Py_INCREF` 529f8b22f8fSZachary Turner // here like we do with `PyList_SetItem`. 5302c1f46dcSZachary Turner PyList_Append(m_py_obj, object.get()); 5312c1f46dcSZachary Turner } 532f8b22f8fSZachary Turner } 5332c1f46dcSZachary Turner 5342c1f46dcSZachary Turner StructuredData::ArraySP 5352c1f46dcSZachary Turner PythonList::CreateStructuredArray() const 5362c1f46dcSZachary Turner { 5372c1f46dcSZachary Turner StructuredData::ArraySP result(new StructuredData::Array); 5382c1f46dcSZachary Turner uint32_t count = GetSize(); 5392c1f46dcSZachary Turner for (uint32_t i = 0; i < count; ++i) 5402c1f46dcSZachary Turner { 5412c1f46dcSZachary Turner PythonObject obj = GetItemAtIndex(i); 5422c1f46dcSZachary Turner result->AddItem(obj.CreateStructuredObject()); 5432c1f46dcSZachary Turner } 5442c1f46dcSZachary Turner return result; 5452c1f46dcSZachary Turner } 5462c1f46dcSZachary Turner 5472c1f46dcSZachary Turner //---------------------------------------------------------------------- 5482c1f46dcSZachary Turner // PythonDictionary 5492c1f46dcSZachary Turner //---------------------------------------------------------------------- 5502c1f46dcSZachary Turner 551f8b22f8fSZachary Turner PythonDictionary::PythonDictionary(PyInitialValue value) 552f8b22f8fSZachary Turner : PythonObject() 5532c1f46dcSZachary Turner { 554f8b22f8fSZachary Turner if (value == PyInitialValue::Empty) 555f8b22f8fSZachary Turner Reset(PyRefType::Owned, PyDict_New()); 5562c1f46dcSZachary Turner } 5572c1f46dcSZachary Turner 558f8b22f8fSZachary Turner PythonDictionary::PythonDictionary(PyRefType type, PyObject *py_obj) 559f8b22f8fSZachary Turner : PythonObject() 5602c1f46dcSZachary Turner { 561f8b22f8fSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a dictionary 5622c1f46dcSZachary Turner } 5632c1f46dcSZachary Turner 564f8b22f8fSZachary Turner PythonDictionary::PythonDictionary(const PythonDictionary &object) 565f8b22f8fSZachary Turner : PythonObject(object) 5662c1f46dcSZachary Turner { 5672c1f46dcSZachary Turner } 5682c1f46dcSZachary Turner 5692c1f46dcSZachary Turner PythonDictionary::~PythonDictionary () 5702c1f46dcSZachary Turner { 5712c1f46dcSZachary Turner } 5722c1f46dcSZachary Turner 5732c1f46dcSZachary Turner bool 57422c8efcdSZachary Turner PythonDictionary::Check(PyObject *py_obj) 57522c8efcdSZachary Turner { 57622c8efcdSZachary Turner if (!py_obj) 57722c8efcdSZachary Turner return false; 57822c8efcdSZachary Turner 57922c8efcdSZachary Turner return PyDict_Check(py_obj); 58022c8efcdSZachary Turner } 58122c8efcdSZachary Turner 582f8b22f8fSZachary Turner void 583f8b22f8fSZachary Turner PythonDictionary::Reset(PyRefType type, PyObject *py_obj) 5842c1f46dcSZachary Turner { 585f8b22f8fSZachary Turner // Grab the desired reference type so that if we end up rejecting 586f8b22f8fSZachary Turner // `py_obj` it still gets decremented if necessary. 587f8b22f8fSZachary Turner PythonObject result(type, py_obj); 588f8b22f8fSZachary Turner 58922c8efcdSZachary Turner if (!PythonDictionary::Check(py_obj)) 59022c8efcdSZachary Turner { 591f8b22f8fSZachary Turner PythonObject::Reset(); 592f8b22f8fSZachary Turner return; 59322c8efcdSZachary Turner } 59422c8efcdSZachary Turner 595f8b22f8fSZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls 596f8b22f8fSZachary Turner // back into the virtual implementation. 597f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 5982c1f46dcSZachary Turner } 5992c1f46dcSZachary Turner 6002c1f46dcSZachary Turner uint32_t 6012c1f46dcSZachary Turner PythonDictionary::GetSize() const 6022c1f46dcSZachary Turner { 603f8b22f8fSZachary Turner if (IsValid()) 6042c1f46dcSZachary Turner return PyDict_Size(m_py_obj); 6052c1f46dcSZachary Turner return 0; 6062c1f46dcSZachary Turner } 6072c1f46dcSZachary Turner 6082c1f46dcSZachary Turner PythonList 6092c1f46dcSZachary Turner PythonDictionary::GetKeys() const 6102c1f46dcSZachary Turner { 611f8b22f8fSZachary Turner if (IsValid()) 612f8b22f8fSZachary Turner return PythonList(PyRefType::Owned, PyDict_Keys(m_py_obj)); 613f8b22f8fSZachary Turner return PythonList(PyInitialValue::Invalid); 6142c1f46dcSZachary Turner } 6152c1f46dcSZachary Turner 6162c1f46dcSZachary Turner PythonObject 617f8b22f8fSZachary Turner PythonDictionary::GetItemForKey(const PythonObject &key) const 6182c1f46dcSZachary Turner { 619f8b22f8fSZachary Turner if (IsAllocated() && key.IsValid()) 620f8b22f8fSZachary Turner return PythonObject(PyRefType::Borrowed, PyDict_GetItem(m_py_obj, key.get())); 6212c1f46dcSZachary Turner return PythonObject(); 6222c1f46dcSZachary Turner } 6232c1f46dcSZachary Turner 6242c1f46dcSZachary Turner void 625f8b22f8fSZachary Turner PythonDictionary::SetItemForKey(const PythonObject &key, const PythonObject &value) 6262c1f46dcSZachary Turner { 627f8b22f8fSZachary Turner if (IsAllocated() && key.IsValid() && value.IsValid()) 6282c1f46dcSZachary Turner PyDict_SetItem(m_py_obj, key.get(), value.get()); 6292c1f46dcSZachary Turner } 6302c1f46dcSZachary Turner 6312c1f46dcSZachary Turner StructuredData::DictionarySP 6322c1f46dcSZachary Turner PythonDictionary::CreateStructuredDictionary() const 6332c1f46dcSZachary Turner { 6342c1f46dcSZachary Turner StructuredData::DictionarySP result(new StructuredData::Dictionary); 6352c1f46dcSZachary Turner PythonList keys(GetKeys()); 6362c1f46dcSZachary Turner uint32_t num_keys = keys.GetSize(); 6372c1f46dcSZachary Turner for (uint32_t i = 0; i < num_keys; ++i) 6382c1f46dcSZachary Turner { 6392c1f46dcSZachary Turner PythonObject key = keys.GetItemAtIndex(i); 6402c1f46dcSZachary Turner PythonObject value = GetItemForKey(key); 6412c1f46dcSZachary Turner StructuredData::ObjectSP structured_value = value.CreateStructuredObject(); 642f8b22f8fSZachary Turner result->AddItem(key.Str().GetString(), structured_value); 6432c1f46dcSZachary Turner } 6442c1f46dcSZachary Turner return result; 6452c1f46dcSZachary Turner } 6462c1f46dcSZachary Turner 647*7841efbbSZachary Turner PythonModule::PythonModule() : PythonObject() 648*7841efbbSZachary Turner { 649*7841efbbSZachary Turner } 650*7841efbbSZachary Turner 651*7841efbbSZachary Turner PythonModule::PythonModule(PyRefType type, PyObject *py_obj) 652*7841efbbSZachary Turner { 653*7841efbbSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a module 654*7841efbbSZachary Turner } 655*7841efbbSZachary Turner 656*7841efbbSZachary Turner PythonModule::PythonModule(const PythonModule &dict) : PythonObject(dict) 657*7841efbbSZachary Turner { 658*7841efbbSZachary Turner } 659*7841efbbSZachary Turner 660*7841efbbSZachary Turner PythonModule::~PythonModule() 661*7841efbbSZachary Turner { 662*7841efbbSZachary Turner } 663*7841efbbSZachary Turner 664*7841efbbSZachary Turner PythonModule 665*7841efbbSZachary Turner PythonModule::MainModule() 666*7841efbbSZachary Turner { 667*7841efbbSZachary Turner return PythonModule(PyRefType::Borrowed, PyImport_AddModule("__main__")); 668*7841efbbSZachary Turner } 669*7841efbbSZachary Turner 670*7841efbbSZachary Turner bool 671*7841efbbSZachary Turner PythonModule::Check(PyObject *py_obj) 672*7841efbbSZachary Turner { 673*7841efbbSZachary Turner if (!py_obj) 674*7841efbbSZachary Turner return false; 675*7841efbbSZachary Turner 676*7841efbbSZachary Turner return PyModule_Check(py_obj); 677*7841efbbSZachary Turner } 678*7841efbbSZachary Turner 679*7841efbbSZachary Turner void 680*7841efbbSZachary Turner PythonModule::Reset(PyRefType type, PyObject *py_obj) 681*7841efbbSZachary Turner { 682*7841efbbSZachary Turner // Grab the desired reference type so that if we end up rejecting 683*7841efbbSZachary Turner // `py_obj` it still gets decremented if necessary. 684*7841efbbSZachary Turner PythonObject result(type, py_obj); 685*7841efbbSZachary Turner 686*7841efbbSZachary Turner if (!PythonModule::Check(py_obj)) 687*7841efbbSZachary Turner { 688*7841efbbSZachary Turner PythonObject::Reset(); 689*7841efbbSZachary Turner return; 690*7841efbbSZachary Turner } 691*7841efbbSZachary Turner 692*7841efbbSZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls 693*7841efbbSZachary Turner // back into the virtual implementation. 694*7841efbbSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 695*7841efbbSZachary Turner } 696*7841efbbSZachary Turner 697*7841efbbSZachary Turner PythonDictionary 698*7841efbbSZachary Turner PythonModule::GetDictionary() const 699*7841efbbSZachary Turner { 700*7841efbbSZachary Turner return PythonDictionary(PyRefType::Borrowed, PyModule_GetDict(m_py_obj)); 701*7841efbbSZachary Turner } 702*7841efbbSZachary Turner 70332064024SZachary Turner PythonFile::PythonFile() 70432064024SZachary Turner : PythonObject() 70532064024SZachary Turner { 70632064024SZachary Turner } 70732064024SZachary Turner 7089c40264fSZachary Turner PythonFile::PythonFile(File &file, const char *mode) 7099c40264fSZachary Turner { 7109c40264fSZachary Turner Reset(file, mode); 7119c40264fSZachary Turner } 7129c40264fSZachary Turner 713eda01c31SZachary Turner PythonFile::PythonFile(const char *path, const char *mode) 714eda01c31SZachary Turner { 715eda01c31SZachary Turner FILE *fp = nullptr; 716eda01c31SZachary Turner fp = fopen(path, mode); 717eda01c31SZachary Turner lldb_private::File file(fp, true); 718eda01c31SZachary Turner Reset(file, mode); 719eda01c31SZachary Turner } 720eda01c31SZachary Turner 7219c40264fSZachary Turner PythonFile::PythonFile(PyRefType type, PyObject *o) 7229c40264fSZachary Turner { 7239c40264fSZachary Turner Reset(type, o); 7249c40264fSZachary Turner } 7259c40264fSZachary Turner 7269c40264fSZachary Turner PythonFile::~PythonFile() 7279c40264fSZachary Turner { 7289c40264fSZachary Turner } 7299c40264fSZachary Turner 7309c40264fSZachary Turner bool 7319c40264fSZachary Turner PythonFile::Check(PyObject *py_obj) 7329c40264fSZachary Turner { 7339c40264fSZachary Turner #if PY_MAJOR_VERSION < 3 7349c40264fSZachary Turner return PyFile_Check(py_obj); 7359c40264fSZachary Turner #else 7369c40264fSZachary Turner // In Python 3, there is no `PyFile_Check`, and in fact PyFile is not even a 7379c40264fSZachary Turner // first-class object type anymore. `PyFile_FromFd` is just a thin wrapper 7389c40264fSZachary Turner // over `io.open()`, which returns some object derived from `io.IOBase`. 7399c40264fSZachary Turner // As a result, the only way to detect a file in Python 3 is to check whether 7409c40264fSZachary Turner // it inherits from `io.IOBase`. Since it is possible for non-files to also 7419c40264fSZachary Turner // inherit from `io.IOBase`, we additionally verify that it has the `fileno` 7429c40264fSZachary Turner // attribute, which should guarantee that it is backed by the file system. 7439c40264fSZachary Turner PythonObject io_module(PyRefType::Owned, PyImport_ImportModule("io")); 7449c40264fSZachary Turner PythonDictionary io_dict(PyRefType::Borrowed, PyModule_GetDict(io_module.get())); 7459c40264fSZachary Turner PythonObject io_base_class = io_dict.GetItemForKey(PythonString("IOBase")); 7469c40264fSZachary Turner 7479c40264fSZachary Turner PythonObject object_type(PyRefType::Owned, PyObject_Type(py_obj)); 7489c40264fSZachary Turner 7499c40264fSZachary Turner if (1 != PyObject_IsSubclass(object_type.get(), io_base_class.get())) 7509c40264fSZachary Turner return false; 7519c40264fSZachary Turner if (!object_type.HasAttribute("fileno")) 7529c40264fSZachary Turner return false; 7539c40264fSZachary Turner 7549c40264fSZachary Turner return true; 7559c40264fSZachary Turner #endif 7569c40264fSZachary Turner } 7579c40264fSZachary Turner 7589c40264fSZachary Turner void 7599c40264fSZachary Turner PythonFile::Reset(PyRefType type, PyObject *py_obj) 7609c40264fSZachary Turner { 7619c40264fSZachary Turner // Grab the desired reference type so that if we end up rejecting 7629c40264fSZachary Turner // `py_obj` it still gets decremented if necessary. 7639c40264fSZachary Turner PythonObject result(type, py_obj); 7649c40264fSZachary Turner 7659c40264fSZachary Turner if (!PythonFile::Check(py_obj)) 7669c40264fSZachary Turner { 7679c40264fSZachary Turner PythonObject::Reset(); 7689c40264fSZachary Turner return; 7699c40264fSZachary Turner } 7709c40264fSZachary Turner 7719c40264fSZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack 7729c40264fSZachary Turner // overflow since it calls back into the virtual implementation. 7739c40264fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 7749c40264fSZachary Turner } 7759c40264fSZachary Turner 7769c40264fSZachary Turner void 7779c40264fSZachary Turner PythonFile::Reset(File &file, const char *mode) 7789c40264fSZachary Turner { 7799c40264fSZachary Turner char *cmode = const_cast<char *>(mode); 7809c40264fSZachary Turner #if PY_MAJOR_VERSION >= 3 7819c40264fSZachary Turner Reset(PyRefType::Owned, 7829c40264fSZachary Turner PyFile_FromFd(file.GetDescriptor(), nullptr, cmode, -1, nullptr, "ignore", nullptr, 0)); 7839c40264fSZachary Turner #else 7849c40264fSZachary Turner // Read through the Python source, doesn't seem to modify these strings 7859c40264fSZachary Turner Reset(PyRefType::Owned, 7869c40264fSZachary Turner PyFile_FromFile(file.GetStream(), const_cast<char *>(""), cmode, nullptr)); 7879c40264fSZachary Turner #endif 7889c40264fSZachary Turner } 7899c40264fSZachary Turner 790eda01c31SZachary Turner bool 791eda01c31SZachary Turner PythonFile::GetUnderlyingFile(File &file) const 792eda01c31SZachary Turner { 793eda01c31SZachary Turner if (!IsValid()) 794eda01c31SZachary Turner return false; 795eda01c31SZachary Turner 796eda01c31SZachary Turner file.Close(); 797eda01c31SZachary Turner // We don't own the file descriptor returned by this function, make sure the 798eda01c31SZachary Turner // File object knows about that. 799eda01c31SZachary Turner file.SetDescriptor(PyObject_AsFileDescriptor(m_py_obj), false); 800eda01c31SZachary Turner return file.IsValid(); 801eda01c31SZachary Turner } 802eda01c31SZachary Turner 803eda01c31SZachary Turner 8042c1f46dcSZachary Turner #endif 805