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 7018426935SZachary Turner if (PythonList::Check(m_py_obj)) 712c1f46dcSZachary Turner return PyObjectType::List; 7218426935SZachary Turner if (PythonDictionary::Check(m_py_obj)) 732c1f46dcSZachary Turner return PyObjectType::Dictionary; 7418426935SZachary Turner if (PythonString::Check(m_py_obj)) 7522c8efcdSZachary Turner return PyObjectType::String; 7618426935SZachary Turner if (PythonInteger::Check(m_py_obj)) 7722c8efcdSZachary Turner return PyObjectType::Integer; 789c40264fSZachary Turner if (PythonFile::Check(m_py_obj)) 799c40264fSZachary Turner return PyObjectType::File; 802c1f46dcSZachary Turner return PyObjectType::Unknown; 812c1f46dcSZachary Turner } 822c1f46dcSZachary Turner 832c1f46dcSZachary Turner PythonString 842c1f46dcSZachary Turner PythonObject::Repr() 852c1f46dcSZachary Turner { 862c1f46dcSZachary Turner if (!m_py_obj) 872c1f46dcSZachary Turner return PythonString(); 882c1f46dcSZachary Turner PyObject *repr = PyObject_Repr(m_py_obj); 892c1f46dcSZachary Turner if (!repr) 902c1f46dcSZachary Turner return PythonString(); 91f8b22f8fSZachary Turner return PythonString(PyRefType::Owned, repr); 922c1f46dcSZachary Turner } 932c1f46dcSZachary Turner 942c1f46dcSZachary Turner PythonString 952c1f46dcSZachary Turner PythonObject::Str() 962c1f46dcSZachary Turner { 972c1f46dcSZachary Turner if (!m_py_obj) 982c1f46dcSZachary Turner return PythonString(); 992c1f46dcSZachary Turner PyObject *str = PyObject_Str(m_py_obj); 1002c1f46dcSZachary Turner if (!str) 1012c1f46dcSZachary Turner return PythonString(); 102f8b22f8fSZachary Turner return PythonString(PyRefType::Owned, str); 1032c1f46dcSZachary Turner } 1042c1f46dcSZachary Turner 1052c1f46dcSZachary Turner bool 1069c40264fSZachary Turner PythonObject::HasAttribute(llvm::StringRef attr) const 1079c40264fSZachary Turner { 1089c40264fSZachary Turner if (!IsValid()) 1099c40264fSZachary Turner return false; 1109c40264fSZachary Turner PythonString py_attr(attr); 1119c40264fSZachary Turner return !!PyObject_HasAttr(m_py_obj, py_attr.get()); 1129c40264fSZachary Turner } 1139c40264fSZachary Turner 1149c40264fSZachary Turner bool 115f8b22f8fSZachary Turner PythonObject::IsNone() const 1162c1f46dcSZachary Turner { 117f8b22f8fSZachary Turner return m_py_obj == Py_None; 118f8b22f8fSZachary Turner } 119f8b22f8fSZachary Turner 120f8b22f8fSZachary Turner bool 121f8b22f8fSZachary Turner PythonObject::IsValid() const 122f8b22f8fSZachary Turner { 123f8b22f8fSZachary Turner return m_py_obj != nullptr; 124f8b22f8fSZachary Turner } 125f8b22f8fSZachary Turner 126f8b22f8fSZachary Turner bool 127f8b22f8fSZachary Turner PythonObject::IsAllocated() const 128f8b22f8fSZachary Turner { 129f8b22f8fSZachary Turner return IsValid() && !IsNone(); 1302c1f46dcSZachary Turner } 1312c1f46dcSZachary Turner 1322c1f46dcSZachary Turner StructuredData::ObjectSP 1332c1f46dcSZachary Turner PythonObject::CreateStructuredObject() const 1342c1f46dcSZachary Turner { 1352c1f46dcSZachary Turner switch (GetObjectType()) 1362c1f46dcSZachary Turner { 1372c1f46dcSZachary Turner case PyObjectType::Dictionary: 138f8b22f8fSZachary Turner return PythonDictionary(PyRefType::Borrowed, m_py_obj).CreateStructuredDictionary(); 1392c1f46dcSZachary Turner case PyObjectType::Integer: 140f8b22f8fSZachary Turner return PythonInteger(PyRefType::Borrowed, m_py_obj).CreateStructuredInteger(); 1412c1f46dcSZachary Turner case PyObjectType::List: 142f8b22f8fSZachary Turner return PythonList(PyRefType::Borrowed, m_py_obj).CreateStructuredArray(); 1432c1f46dcSZachary Turner case PyObjectType::String: 144f8b22f8fSZachary Turner return PythonString(PyRefType::Borrowed, m_py_obj).CreateStructuredString(); 1452c1f46dcSZachary Turner case PyObjectType::None: 1462c1f46dcSZachary Turner return StructuredData::ObjectSP(); 1472c1f46dcSZachary Turner default: 1482c1f46dcSZachary Turner return StructuredData::ObjectSP(new StructuredPythonObject(m_py_obj)); 1492c1f46dcSZachary Turner } 1502c1f46dcSZachary Turner } 1512c1f46dcSZachary Turner 1522c1f46dcSZachary Turner //---------------------------------------------------------------------- 1532c1f46dcSZachary Turner // PythonString 1542c1f46dcSZachary Turner //---------------------------------------------------------------------- 1552c1f46dcSZachary Turner 156f8b22f8fSZachary Turner PythonString::PythonString(PyRefType type, PyObject *py_obj) 157f8b22f8fSZachary Turner : PythonObject() 1582c1f46dcSZachary Turner { 159f8b22f8fSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string 1602c1f46dcSZachary Turner } 1612c1f46dcSZachary Turner 162f8b22f8fSZachary Turner PythonString::PythonString(const PythonString &object) 163f8b22f8fSZachary Turner : PythonObject(object) 1642c1f46dcSZachary Turner { 1652c1f46dcSZachary Turner } 1662c1f46dcSZachary Turner 16722c8efcdSZachary Turner PythonString::PythonString(llvm::StringRef string) 16822c8efcdSZachary Turner : PythonObject() 1692c1f46dcSZachary Turner { 17022c8efcdSZachary Turner SetString(string); 1712c1f46dcSZachary Turner } 1722c1f46dcSZachary Turner 17322c8efcdSZachary Turner PythonString::PythonString(const char *string) 17422c8efcdSZachary Turner : PythonObject() 1752c1f46dcSZachary Turner { 17622c8efcdSZachary Turner SetString(llvm::StringRef(string)); 1772c1f46dcSZachary Turner } 1782c1f46dcSZachary Turner 179f8b22f8fSZachary Turner PythonString::PythonString() 180f8b22f8fSZachary Turner : PythonObject() 1812c1f46dcSZachary Turner { 1822c1f46dcSZachary Turner } 1832c1f46dcSZachary Turner 1842c1f46dcSZachary Turner PythonString::~PythonString () 1852c1f46dcSZachary Turner { 1862c1f46dcSZachary Turner } 1872c1f46dcSZachary Turner 1882c1f46dcSZachary Turner bool 18922c8efcdSZachary Turner PythonString::Check(PyObject *py_obj) 19022c8efcdSZachary Turner { 19122c8efcdSZachary Turner if (!py_obj) 19222c8efcdSZachary Turner return false; 19318426935SZachary Turner 19422c8efcdSZachary Turner #if PY_MAJOR_VERSION >= 3 19522c8efcdSZachary Turner return PyUnicode_Check(py_obj); 19622c8efcdSZachary Turner #else 19718426935SZachary Turner return PyString_Check(py_obj); 19822c8efcdSZachary Turner #endif 19922c8efcdSZachary Turner } 20022c8efcdSZachary Turner 201f8b22f8fSZachary Turner void 202f8b22f8fSZachary Turner PythonString::Reset(PyRefType type, PyObject *py_obj) 2032c1f46dcSZachary Turner { 204f8b22f8fSZachary Turner // Grab the desired reference type so that if we end up rejecting 205f8b22f8fSZachary Turner // `py_obj` it still gets decremented if necessary. 206f8b22f8fSZachary Turner PythonObject result(type, py_obj); 207f8b22f8fSZachary Turner 20822c8efcdSZachary Turner if (!PythonString::Check(py_obj)) 20922c8efcdSZachary Turner { 210f8b22f8fSZachary Turner PythonObject::Reset(); 211f8b22f8fSZachary Turner return; 21222c8efcdSZachary Turner } 21322c8efcdSZachary Turner 214f8b22f8fSZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls 215f8b22f8fSZachary Turner // back into the virtual implementation. 216f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 2172c1f46dcSZachary Turner } 2182c1f46dcSZachary Turner 2192c1f46dcSZachary Turner llvm::StringRef 2202c1f46dcSZachary Turner PythonString::GetString() const 2212c1f46dcSZachary Turner { 22218426935SZachary Turner if (!IsValid()) 22318426935SZachary Turner return llvm::StringRef(); 22418426935SZachary Turner 22522c8efcdSZachary Turner Py_ssize_t size; 22622c8efcdSZachary Turner char *c; 22718426935SZachary Turner 22818426935SZachary Turner #if PY_MAJOR_VERSION >= 3 22918426935SZachary Turner c = PyUnicode_AsUTF8AndSize(m_py_obj, &size); 23018426935SZachary Turner #else 23118426935SZachary Turner PyString_AsStringAndSize(m_py_obj, &c, &size); 23218426935SZachary Turner #endif 23322c8efcdSZachary Turner return llvm::StringRef(c, size); 23422c8efcdSZachary Turner } 2352c1f46dcSZachary Turner 2362c1f46dcSZachary Turner size_t 2372c1f46dcSZachary Turner PythonString::GetSize() const 2382c1f46dcSZachary Turner { 239f8b22f8fSZachary Turner if (IsValid()) 24018426935SZachary Turner { 24118426935SZachary Turner #if PY_MAJOR_VERSION >= 3 24218426935SZachary Turner return PyUnicode_GetSize(m_py_obj); 24318426935SZachary Turner #else 24418426935SZachary Turner return PyString_Size(m_py_obj); 24518426935SZachary Turner #endif 24618426935SZachary Turner } 2472c1f46dcSZachary Turner return 0; 2482c1f46dcSZachary Turner } 2492c1f46dcSZachary Turner 2502c1f46dcSZachary Turner void 2512c1f46dcSZachary Turner PythonString::SetString (llvm::StringRef string) 2522c1f46dcSZachary Turner { 25322c8efcdSZachary Turner #if PY_MAJOR_VERSION >= 3 25422c8efcdSZachary Turner PyObject *unicode = PyUnicode_FromStringAndSize(string.data(), string.size()); 25518426935SZachary Turner PythonObject::Reset(PyRefType::Owned, unicode); 25622c8efcdSZachary Turner #else 25718426935SZachary Turner PyObject *str = PyString_FromStringAndSize(string.data(), string.size()); 25818426935SZachary Turner PythonObject::Reset(PyRefType::Owned, str); 25922c8efcdSZachary Turner #endif 2602c1f46dcSZachary Turner } 2612c1f46dcSZachary Turner 2622c1f46dcSZachary Turner StructuredData::StringSP 2632c1f46dcSZachary Turner PythonString::CreateStructuredString() const 2642c1f46dcSZachary Turner { 2652c1f46dcSZachary Turner StructuredData::StringSP result(new StructuredData::String); 2662c1f46dcSZachary Turner result->SetValue(GetString()); 2672c1f46dcSZachary Turner return result; 2682c1f46dcSZachary Turner } 2692c1f46dcSZachary Turner 2702c1f46dcSZachary Turner //---------------------------------------------------------------------- 2712c1f46dcSZachary Turner // PythonInteger 2722c1f46dcSZachary Turner //---------------------------------------------------------------------- 2732c1f46dcSZachary Turner 274f8b22f8fSZachary Turner PythonInteger::PythonInteger(PyRefType type, PyObject *py_obj) 275f8b22f8fSZachary Turner : PythonObject() 2762c1f46dcSZachary Turner { 277f8b22f8fSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a integer type 2782c1f46dcSZachary Turner } 2792c1f46dcSZachary Turner 280f8b22f8fSZachary Turner PythonInteger::PythonInteger(const PythonInteger &object) 281f8b22f8fSZachary Turner : PythonObject(object) 2822c1f46dcSZachary Turner { 2832c1f46dcSZachary Turner } 2842c1f46dcSZachary Turner 285f8b22f8fSZachary Turner PythonInteger::PythonInteger(int64_t value) 286f8b22f8fSZachary Turner : PythonObject() 2872c1f46dcSZachary Turner { 2882c1f46dcSZachary Turner SetInteger(value); 2892c1f46dcSZachary Turner } 2902c1f46dcSZachary Turner 2912c1f46dcSZachary Turner 2922c1f46dcSZachary Turner PythonInteger::~PythonInteger () 2932c1f46dcSZachary Turner { 2942c1f46dcSZachary Turner } 2952c1f46dcSZachary Turner 2962c1f46dcSZachary Turner bool 29722c8efcdSZachary Turner PythonInteger::Check(PyObject *py_obj) 2982c1f46dcSZachary Turner { 29922c8efcdSZachary Turner if (!py_obj) 30022c8efcdSZachary Turner return false; 30122c8efcdSZachary Turner 30222c8efcdSZachary Turner #if PY_MAJOR_VERSION >= 3 30322c8efcdSZachary Turner // Python 3 does not have PyInt_Check. There is only one type of 30422c8efcdSZachary Turner // integral value, long. 30522c8efcdSZachary Turner return PyLong_Check(py_obj); 30622c8efcdSZachary Turner #else 30722c8efcdSZachary Turner return PyLong_Check(py_obj) || PyInt_Check(py_obj); 30822c8efcdSZachary Turner #endif 3092c1f46dcSZachary Turner } 3102c1f46dcSZachary Turner 311f8b22f8fSZachary Turner void 312f8b22f8fSZachary Turner PythonInteger::Reset(PyRefType type, PyObject *py_obj) 31322c8efcdSZachary Turner { 314f8b22f8fSZachary Turner // Grab the desired reference type so that if we end up rejecting 315f8b22f8fSZachary Turner // `py_obj` it still gets decremented if necessary. 316f8b22f8fSZachary Turner PythonObject result(type, py_obj); 317f8b22f8fSZachary Turner 31822c8efcdSZachary Turner if (!PythonInteger::Check(py_obj)) 31922c8efcdSZachary Turner { 320f8b22f8fSZachary Turner PythonObject::Reset(); 321f8b22f8fSZachary Turner return; 32222c8efcdSZachary Turner } 32322c8efcdSZachary Turner 32422c8efcdSZachary Turner #if PY_MAJOR_VERSION < 3 32522c8efcdSZachary Turner // Always store this as a PyLong, which makes interoperability between 32622c8efcdSZachary Turner // Python 2.x and Python 3.x easier. This is only necessary in 2.x, 32722c8efcdSZachary Turner // since 3.x doesn't even have a PyInt. 32822c8efcdSZachary Turner if (PyInt_Check(py_obj)) 32922c8efcdSZachary Turner { 330f8b22f8fSZachary Turner // Since we converted the original object to a different type, the new 331f8b22f8fSZachary Turner // object is an owned object regardless of the ownership semantics requested 332f8b22f8fSZachary Turner // by the user. 333f8b22f8fSZachary Turner result.Reset(PyRefType::Owned, PyLong_FromLongLong(PyInt_AsLong(py_obj))); 33422c8efcdSZachary Turner } 33522c8efcdSZachary Turner #endif 33622c8efcdSZachary Turner 337f8b22f8fSZachary Turner assert(PyLong_Check(result.get()) && "Couldn't get a PyLong from this PyObject"); 33822c8efcdSZachary Turner 339f8b22f8fSZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls 340f8b22f8fSZachary Turner // back into the virtual implementation. 341f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 3422c1f46dcSZachary Turner } 3432c1f46dcSZachary Turner 3442c1f46dcSZachary Turner int64_t 3452c1f46dcSZachary Turner PythonInteger::GetInteger() const 3462c1f46dcSZachary Turner { 3472c1f46dcSZachary Turner if (m_py_obj) 3482c1f46dcSZachary Turner { 34922c8efcdSZachary Turner assert(PyLong_Check(m_py_obj) && "PythonInteger::GetInteger has a PyObject that isn't a PyLong"); 35022c8efcdSZachary Turner 3512c1f46dcSZachary Turner return PyLong_AsLongLong(m_py_obj); 3522c1f46dcSZachary Turner } 3532c1f46dcSZachary Turner return UINT64_MAX; 3542c1f46dcSZachary Turner } 3552c1f46dcSZachary Turner 3562c1f46dcSZachary Turner void 3572c1f46dcSZachary Turner PythonInteger::SetInteger(int64_t value) 3582c1f46dcSZachary Turner { 359f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Owned, PyLong_FromLongLong(value)); 3602c1f46dcSZachary Turner } 3612c1f46dcSZachary Turner 3622c1f46dcSZachary Turner StructuredData::IntegerSP 3632c1f46dcSZachary Turner PythonInteger::CreateStructuredInteger() const 3642c1f46dcSZachary Turner { 3652c1f46dcSZachary Turner StructuredData::IntegerSP result(new StructuredData::Integer); 3662c1f46dcSZachary Turner result->SetValue(GetInteger()); 3672c1f46dcSZachary Turner return result; 3682c1f46dcSZachary Turner } 3692c1f46dcSZachary Turner 3702c1f46dcSZachary Turner //---------------------------------------------------------------------- 3712c1f46dcSZachary Turner // PythonList 3722c1f46dcSZachary Turner //---------------------------------------------------------------------- 3732c1f46dcSZachary Turner 374f8b22f8fSZachary Turner PythonList::PythonList(PyInitialValue value) 375f8b22f8fSZachary Turner : PythonObject() 3762c1f46dcSZachary Turner { 377f8b22f8fSZachary Turner if (value == PyInitialValue::Empty) 378f8b22f8fSZachary Turner Reset(PyRefType::Owned, PyList_New(0)); 3792c1f46dcSZachary Turner } 3802c1f46dcSZachary Turner 38187f47729SZachary Turner PythonList::PythonList(int list_size) 38287f47729SZachary Turner : PythonObject() 38387f47729SZachary Turner { 38487f47729SZachary Turner Reset(PyRefType::Owned, PyList_New(list_size)); 38587f47729SZachary Turner } 38687f47729SZachary Turner 387f8b22f8fSZachary Turner PythonList::PythonList(PyRefType type, PyObject *py_obj) 388f8b22f8fSZachary Turner : PythonObject() 3892c1f46dcSZachary Turner { 390f8b22f8fSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a list 3912c1f46dcSZachary Turner } 3922c1f46dcSZachary Turner 393f8b22f8fSZachary Turner PythonList::PythonList(const PythonList &list) 394f8b22f8fSZachary Turner : PythonObject(list) 3952c1f46dcSZachary Turner { 3962c1f46dcSZachary Turner } 3972c1f46dcSZachary Turner 3982c1f46dcSZachary Turner PythonList::~PythonList () 3992c1f46dcSZachary Turner { 4002c1f46dcSZachary Turner } 4012c1f46dcSZachary Turner 4022c1f46dcSZachary Turner bool 40322c8efcdSZachary Turner PythonList::Check(PyObject *py_obj) 40422c8efcdSZachary Turner { 40522c8efcdSZachary Turner if (!py_obj) 40622c8efcdSZachary Turner return false; 40722c8efcdSZachary Turner return PyList_Check(py_obj); 40822c8efcdSZachary Turner } 40922c8efcdSZachary Turner 410f8b22f8fSZachary Turner void 411f8b22f8fSZachary Turner PythonList::Reset(PyRefType type, PyObject *py_obj) 4122c1f46dcSZachary Turner { 413f8b22f8fSZachary Turner // Grab the desired reference type so that if we end up rejecting 414f8b22f8fSZachary Turner // `py_obj` it still gets decremented if necessary. 415f8b22f8fSZachary Turner PythonObject result(type, py_obj); 416f8b22f8fSZachary Turner 41722c8efcdSZachary Turner if (!PythonList::Check(py_obj)) 41822c8efcdSZachary Turner { 419f8b22f8fSZachary Turner PythonObject::Reset(); 420f8b22f8fSZachary Turner return; 42122c8efcdSZachary Turner } 42222c8efcdSZachary Turner 423f8b22f8fSZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls 424f8b22f8fSZachary Turner // back into the virtual implementation. 425f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 4262c1f46dcSZachary Turner } 4272c1f46dcSZachary Turner 4282c1f46dcSZachary Turner uint32_t 4292c1f46dcSZachary Turner PythonList::GetSize() const 4302c1f46dcSZachary Turner { 431f8b22f8fSZachary Turner if (IsValid()) 4322c1f46dcSZachary Turner return PyList_GET_SIZE(m_py_obj); 4332c1f46dcSZachary Turner return 0; 4342c1f46dcSZachary Turner } 4352c1f46dcSZachary Turner 4362c1f46dcSZachary Turner PythonObject 4372c1f46dcSZachary Turner PythonList::GetItemAtIndex(uint32_t index) const 4382c1f46dcSZachary Turner { 439f8b22f8fSZachary Turner if (IsValid()) 440f8b22f8fSZachary Turner return PythonObject(PyRefType::Borrowed, PyList_GetItem(m_py_obj, index)); 4412c1f46dcSZachary Turner return PythonObject(); 4422c1f46dcSZachary Turner } 4432c1f46dcSZachary Turner 4442c1f46dcSZachary Turner void 4452c1f46dcSZachary Turner PythonList::SetItemAtIndex(uint32_t index, const PythonObject &object) 4462c1f46dcSZachary Turner { 447f8b22f8fSZachary Turner if (IsAllocated() && object.IsValid()) 448f8b22f8fSZachary Turner { 449f8b22f8fSZachary Turner // PyList_SetItem is documented to "steal" a reference, so we need to 450f8b22f8fSZachary Turner // convert it to an owned reference by incrementing it. 451f8b22f8fSZachary Turner Py_INCREF(object.get()); 4522c1f46dcSZachary Turner PyList_SetItem(m_py_obj, index, object.get()); 4532c1f46dcSZachary Turner } 454f8b22f8fSZachary Turner } 4552c1f46dcSZachary Turner 4562c1f46dcSZachary Turner void 4572c1f46dcSZachary Turner PythonList::AppendItem(const PythonObject &object) 4582c1f46dcSZachary Turner { 459f8b22f8fSZachary Turner if (IsAllocated() && object.IsValid()) 460f8b22f8fSZachary Turner { 461f8b22f8fSZachary Turner // `PyList_Append` does *not* steal a reference, so do not call `Py_INCREF` 462f8b22f8fSZachary Turner // here like we do with `PyList_SetItem`. 4632c1f46dcSZachary Turner PyList_Append(m_py_obj, object.get()); 4642c1f46dcSZachary Turner } 465f8b22f8fSZachary Turner } 4662c1f46dcSZachary Turner 4672c1f46dcSZachary Turner StructuredData::ArraySP 4682c1f46dcSZachary Turner PythonList::CreateStructuredArray() const 4692c1f46dcSZachary Turner { 4702c1f46dcSZachary Turner StructuredData::ArraySP result(new StructuredData::Array); 4712c1f46dcSZachary Turner uint32_t count = GetSize(); 4722c1f46dcSZachary Turner for (uint32_t i = 0; i < count; ++i) 4732c1f46dcSZachary Turner { 4742c1f46dcSZachary Turner PythonObject obj = GetItemAtIndex(i); 4752c1f46dcSZachary Turner result->AddItem(obj.CreateStructuredObject()); 4762c1f46dcSZachary Turner } 4772c1f46dcSZachary Turner return result; 4782c1f46dcSZachary Turner } 4792c1f46dcSZachary Turner 4802c1f46dcSZachary Turner //---------------------------------------------------------------------- 4812c1f46dcSZachary Turner // PythonDictionary 4822c1f46dcSZachary Turner //---------------------------------------------------------------------- 4832c1f46dcSZachary Turner 484f8b22f8fSZachary Turner PythonDictionary::PythonDictionary(PyInitialValue value) 485f8b22f8fSZachary Turner : PythonObject() 4862c1f46dcSZachary Turner { 487f8b22f8fSZachary Turner if (value == PyInitialValue::Empty) 488f8b22f8fSZachary Turner Reset(PyRefType::Owned, PyDict_New()); 4892c1f46dcSZachary Turner } 4902c1f46dcSZachary Turner 491f8b22f8fSZachary Turner PythonDictionary::PythonDictionary(PyRefType type, PyObject *py_obj) 492f8b22f8fSZachary Turner : PythonObject() 4932c1f46dcSZachary Turner { 494f8b22f8fSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a dictionary 4952c1f46dcSZachary Turner } 4962c1f46dcSZachary Turner 497f8b22f8fSZachary Turner PythonDictionary::PythonDictionary(const PythonDictionary &object) 498f8b22f8fSZachary Turner : PythonObject(object) 4992c1f46dcSZachary Turner { 5002c1f46dcSZachary Turner } 5012c1f46dcSZachary Turner 5022c1f46dcSZachary Turner PythonDictionary::~PythonDictionary () 5032c1f46dcSZachary Turner { 5042c1f46dcSZachary Turner } 5052c1f46dcSZachary Turner 5062c1f46dcSZachary Turner bool 50722c8efcdSZachary Turner PythonDictionary::Check(PyObject *py_obj) 50822c8efcdSZachary Turner { 50922c8efcdSZachary Turner if (!py_obj) 51022c8efcdSZachary Turner return false; 51122c8efcdSZachary Turner 51222c8efcdSZachary Turner return PyDict_Check(py_obj); 51322c8efcdSZachary Turner } 51422c8efcdSZachary Turner 515f8b22f8fSZachary Turner void 516f8b22f8fSZachary Turner PythonDictionary::Reset(PyRefType type, PyObject *py_obj) 5172c1f46dcSZachary Turner { 518f8b22f8fSZachary Turner // Grab the desired reference type so that if we end up rejecting 519f8b22f8fSZachary Turner // `py_obj` it still gets decremented if necessary. 520f8b22f8fSZachary Turner PythonObject result(type, py_obj); 521f8b22f8fSZachary Turner 52222c8efcdSZachary Turner if (!PythonDictionary::Check(py_obj)) 52322c8efcdSZachary Turner { 524f8b22f8fSZachary Turner PythonObject::Reset(); 525f8b22f8fSZachary Turner return; 52622c8efcdSZachary Turner } 52722c8efcdSZachary Turner 528f8b22f8fSZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls 529f8b22f8fSZachary Turner // back into the virtual implementation. 530f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 5312c1f46dcSZachary Turner } 5322c1f46dcSZachary Turner 5332c1f46dcSZachary Turner uint32_t 5342c1f46dcSZachary Turner PythonDictionary::GetSize() const 5352c1f46dcSZachary Turner { 536f8b22f8fSZachary Turner if (IsValid()) 5372c1f46dcSZachary Turner return PyDict_Size(m_py_obj); 5382c1f46dcSZachary Turner return 0; 5392c1f46dcSZachary Turner } 5402c1f46dcSZachary Turner 5412c1f46dcSZachary Turner PythonList 5422c1f46dcSZachary Turner PythonDictionary::GetKeys() const 5432c1f46dcSZachary Turner { 544f8b22f8fSZachary Turner if (IsValid()) 545f8b22f8fSZachary Turner return PythonList(PyRefType::Owned, PyDict_Keys(m_py_obj)); 546f8b22f8fSZachary Turner return PythonList(PyInitialValue::Invalid); 5472c1f46dcSZachary Turner } 5482c1f46dcSZachary Turner 5492c1f46dcSZachary Turner PythonObject 550f8b22f8fSZachary Turner PythonDictionary::GetItemForKey(const PythonObject &key) const 5512c1f46dcSZachary Turner { 552f8b22f8fSZachary Turner if (IsAllocated() && key.IsValid()) 553f8b22f8fSZachary Turner return PythonObject(PyRefType::Borrowed, PyDict_GetItem(m_py_obj, key.get())); 5542c1f46dcSZachary Turner return PythonObject(); 5552c1f46dcSZachary Turner } 5562c1f46dcSZachary Turner 5572c1f46dcSZachary Turner void 558f8b22f8fSZachary Turner PythonDictionary::SetItemForKey(const PythonObject &key, const PythonObject &value) 5592c1f46dcSZachary Turner { 560f8b22f8fSZachary Turner if (IsAllocated() && key.IsValid() && value.IsValid()) 5612c1f46dcSZachary Turner PyDict_SetItem(m_py_obj, key.get(), value.get()); 5622c1f46dcSZachary Turner } 5632c1f46dcSZachary Turner 5642c1f46dcSZachary Turner StructuredData::DictionarySP 5652c1f46dcSZachary Turner PythonDictionary::CreateStructuredDictionary() const 5662c1f46dcSZachary Turner { 5672c1f46dcSZachary Turner StructuredData::DictionarySP result(new StructuredData::Dictionary); 5682c1f46dcSZachary Turner PythonList keys(GetKeys()); 5692c1f46dcSZachary Turner uint32_t num_keys = keys.GetSize(); 5702c1f46dcSZachary Turner for (uint32_t i = 0; i < num_keys; ++i) 5712c1f46dcSZachary Turner { 5722c1f46dcSZachary Turner PythonObject key = keys.GetItemAtIndex(i); 5732c1f46dcSZachary Turner PythonObject value = GetItemForKey(key); 5742c1f46dcSZachary Turner StructuredData::ObjectSP structured_value = value.CreateStructuredObject(); 575f8b22f8fSZachary Turner result->AddItem(key.Str().GetString(), structured_value); 5762c1f46dcSZachary Turner } 5772c1f46dcSZachary Turner return result; 5782c1f46dcSZachary Turner } 5792c1f46dcSZachary Turner 5809c40264fSZachary Turner PythonFile::PythonFile(File &file, const char *mode) 5819c40264fSZachary Turner { 5829c40264fSZachary Turner Reset(file, mode); 5839c40264fSZachary Turner } 5849c40264fSZachary Turner 585*eda01c31SZachary Turner PythonFile::PythonFile(const char *path, const char *mode) 586*eda01c31SZachary Turner { 587*eda01c31SZachary Turner FILE *fp = nullptr; 588*eda01c31SZachary Turner fp = fopen(path, mode); 589*eda01c31SZachary Turner lldb_private::File file(fp, true); 590*eda01c31SZachary Turner Reset(file, mode); 591*eda01c31SZachary Turner } 592*eda01c31SZachary Turner 5939c40264fSZachary Turner PythonFile::PythonFile(PyRefType type, PyObject *o) 5949c40264fSZachary Turner { 5959c40264fSZachary Turner Reset(type, o); 5969c40264fSZachary Turner } 5979c40264fSZachary Turner 5989c40264fSZachary Turner PythonFile::~PythonFile() 5999c40264fSZachary Turner { 6009c40264fSZachary Turner } 6019c40264fSZachary Turner 6029c40264fSZachary Turner bool 6039c40264fSZachary Turner PythonFile::Check(PyObject *py_obj) 6049c40264fSZachary Turner { 6059c40264fSZachary Turner #if PY_MAJOR_VERSION < 3 6069c40264fSZachary Turner return PyFile_Check(py_obj); 6079c40264fSZachary Turner #else 6089c40264fSZachary Turner // In Python 3, there is no `PyFile_Check`, and in fact PyFile is not even a 6099c40264fSZachary Turner // first-class object type anymore. `PyFile_FromFd` is just a thin wrapper 6109c40264fSZachary Turner // over `io.open()`, which returns some object derived from `io.IOBase`. 6119c40264fSZachary Turner // As a result, the only way to detect a file in Python 3 is to check whether 6129c40264fSZachary Turner // it inherits from `io.IOBase`. Since it is possible for non-files to also 6139c40264fSZachary Turner // inherit from `io.IOBase`, we additionally verify that it has the `fileno` 6149c40264fSZachary Turner // attribute, which should guarantee that it is backed by the file system. 6159c40264fSZachary Turner PythonObject io_module(PyRefType::Owned, PyImport_ImportModule("io")); 6169c40264fSZachary Turner PythonDictionary io_dict(PyRefType::Borrowed, PyModule_GetDict(io_module.get())); 6179c40264fSZachary Turner PythonObject io_base_class = io_dict.GetItemForKey(PythonString("IOBase")); 6189c40264fSZachary Turner 6199c40264fSZachary Turner PythonObject object_type(PyRefType::Owned, PyObject_Type(py_obj)); 6209c40264fSZachary Turner 6219c40264fSZachary Turner if (1 != PyObject_IsSubclass(object_type.get(), io_base_class.get())) 6229c40264fSZachary Turner return false; 6239c40264fSZachary Turner if (!object_type.HasAttribute("fileno")) 6249c40264fSZachary Turner return false; 6259c40264fSZachary Turner 6269c40264fSZachary Turner return true; 6279c40264fSZachary Turner #endif 6289c40264fSZachary Turner } 6299c40264fSZachary Turner 6309c40264fSZachary Turner void 6319c40264fSZachary Turner PythonFile::Reset(PyRefType type, PyObject *py_obj) 6329c40264fSZachary Turner { 6339c40264fSZachary Turner // Grab the desired reference type so that if we end up rejecting 6349c40264fSZachary Turner // `py_obj` it still gets decremented if necessary. 6359c40264fSZachary Turner PythonObject result(type, py_obj); 6369c40264fSZachary Turner 6379c40264fSZachary Turner if (!PythonFile::Check(py_obj)) 6389c40264fSZachary Turner { 6399c40264fSZachary Turner PythonObject::Reset(); 6409c40264fSZachary Turner return; 6419c40264fSZachary Turner } 6429c40264fSZachary Turner 6439c40264fSZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack 6449c40264fSZachary Turner // overflow since it calls back into the virtual implementation. 6459c40264fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 6469c40264fSZachary Turner } 6479c40264fSZachary Turner 6489c40264fSZachary Turner void 6499c40264fSZachary Turner PythonFile::Reset(File &file, const char *mode) 6509c40264fSZachary Turner { 6519c40264fSZachary Turner char *cmode = const_cast<char *>(mode); 6529c40264fSZachary Turner #if PY_MAJOR_VERSION >= 3 6539c40264fSZachary Turner Reset(PyRefType::Owned, 6549c40264fSZachary Turner PyFile_FromFd(file.GetDescriptor(), nullptr, cmode, -1, nullptr, "ignore", nullptr, 0)); 6559c40264fSZachary Turner #else 6569c40264fSZachary Turner // Read through the Python source, doesn't seem to modify these strings 6579c40264fSZachary Turner Reset(PyRefType::Owned, 6589c40264fSZachary Turner PyFile_FromFile(file.GetStream(), const_cast<char *>(""), cmode, nullptr)); 6599c40264fSZachary Turner #endif 6609c40264fSZachary Turner } 6619c40264fSZachary Turner 662*eda01c31SZachary Turner bool 663*eda01c31SZachary Turner PythonFile::GetUnderlyingFile(File &file) const 664*eda01c31SZachary Turner { 665*eda01c31SZachary Turner if (!IsValid()) 666*eda01c31SZachary Turner return false; 667*eda01c31SZachary Turner 668*eda01c31SZachary Turner file.Close(); 669*eda01c31SZachary Turner // We don't own the file descriptor returned by this function, make sure the 670*eda01c31SZachary Turner // File object knows about that. 671*eda01c31SZachary Turner file.SetDescriptor(PyObject_AsFileDescriptor(m_py_obj), false); 672*eda01c31SZachary Turner return file.IsValid(); 673*eda01c31SZachary Turner } 674*eda01c31SZachary Turner 675*eda01c31SZachary Turner 6762c1f46dcSZachary Turner #endif 677