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 707841efbbSZachary Turner if (PythonModule::Check(m_py_obj)) 717841efbbSZachary Turner return PyObjectType::Module; 7218426935SZachary Turner if (PythonList::Check(m_py_obj)) 732c1f46dcSZachary Turner return PyObjectType::List; 74a1405147SZachary Turner if (PythonTuple::Check(m_py_obj)) 75a1405147SZachary Turner return PyObjectType::Tuple; 7618426935SZachary Turner if (PythonDictionary::Check(m_py_obj)) 772c1f46dcSZachary Turner return PyObjectType::Dictionary; 7818426935SZachary Turner if (PythonString::Check(m_py_obj)) 7922c8efcdSZachary Turner return PyObjectType::String; 8018426935SZachary Turner if (PythonInteger::Check(m_py_obj)) 8122c8efcdSZachary Turner return PyObjectType::Integer; 829c40264fSZachary Turner if (PythonFile::Check(m_py_obj)) 839c40264fSZachary Turner return PyObjectType::File; 84a1405147SZachary Turner if (PythonCallable::Check(m_py_obj)) 85a1405147SZachary Turner return PyObjectType::Callable; 862c1f46dcSZachary Turner return PyObjectType::Unknown; 872c1f46dcSZachary Turner } 882c1f46dcSZachary Turner 892c1f46dcSZachary Turner PythonString 907841efbbSZachary Turner PythonObject::Repr() const 912c1f46dcSZachary Turner { 922c1f46dcSZachary Turner if (!m_py_obj) 932c1f46dcSZachary Turner return PythonString(); 942c1f46dcSZachary Turner PyObject *repr = PyObject_Repr(m_py_obj); 952c1f46dcSZachary Turner if (!repr) 962c1f46dcSZachary Turner return PythonString(); 97f8b22f8fSZachary Turner return PythonString(PyRefType::Owned, repr); 982c1f46dcSZachary Turner } 992c1f46dcSZachary Turner 1002c1f46dcSZachary Turner PythonString 1017841efbbSZachary Turner PythonObject::Str() const 1022c1f46dcSZachary Turner { 1032c1f46dcSZachary Turner if (!m_py_obj) 1042c1f46dcSZachary Turner return PythonString(); 1052c1f46dcSZachary Turner PyObject *str = PyObject_Str(m_py_obj); 1062c1f46dcSZachary Turner if (!str) 1072c1f46dcSZachary Turner return PythonString(); 108f8b22f8fSZachary Turner return PythonString(PyRefType::Owned, str); 1092c1f46dcSZachary Turner } 1102c1f46dcSZachary Turner 1117841efbbSZachary Turner PythonObject 11202bf92d2SZachary Turner PythonObject::ResolveNameWithDictionary(llvm::StringRef name, const PythonDictionary &dict) 1137841efbbSZachary Turner { 114a1405147SZachary Turner size_t dot_pos = name.find_first_of('.'); 115a1405147SZachary Turner llvm::StringRef piece = name.substr(0, dot_pos); 116a1405147SZachary Turner PythonObject result = dict.GetItemForKey(PythonString(piece)); 117a1405147SZachary Turner if (dot_pos == llvm::StringRef::npos) 118a1405147SZachary Turner { 119a1405147SZachary Turner // There was no dot, we're done. 120a1405147SZachary Turner return result; 121a1405147SZachary Turner } 122a1405147SZachary Turner 123a1405147SZachary Turner // There was a dot. The remaining portion of the name should be looked up in 124a1405147SZachary Turner // the context of the object that was found in the dictionary. 125a1405147SZachary Turner return result.ResolveName(name.substr(dot_pos + 1)); 1267841efbbSZachary Turner } 1277841efbbSZachary Turner 1287841efbbSZachary Turner PythonObject 1297841efbbSZachary Turner PythonObject::ResolveName(llvm::StringRef name) const 1307841efbbSZachary Turner { 1317841efbbSZachary Turner // Resolve the name in the context of the specified object. If, 1327841efbbSZachary Turner // for example, `this` refers to a PyModule, then this will look for 1337841efbbSZachary Turner // `name` in this module. If `this` refers to a PyType, then it will 1347841efbbSZachary Turner // resolve `name` as an attribute of that type. If `this` refers to 1357841efbbSZachary Turner // an instance of an object, then it will resolve `name` as the value 1367841efbbSZachary Turner // of the specified field. 1377841efbbSZachary Turner // 1387841efbbSZachary Turner // This function handles dotted names so that, for example, if `m_py_obj` 1397841efbbSZachary Turner // refers to the `sys` module, and `name` == "path.append", then it 1407841efbbSZachary Turner // will find the function `sys.path.append`. 1417841efbbSZachary Turner 1427841efbbSZachary Turner size_t dot_pos = name.find_first_of('.'); 1437841efbbSZachary Turner if (dot_pos == llvm::StringRef::npos) 1447841efbbSZachary Turner { 1457841efbbSZachary Turner // No dots in the name, we should be able to find the value immediately 146a1405147SZachary Turner // as an attribute of `m_py_obj`. 1477841efbbSZachary Turner return GetAttributeValue(name); 1487841efbbSZachary Turner } 1497841efbbSZachary Turner 1507841efbbSZachary Turner // Look up the first piece of the name, and resolve the rest as a child of that. 1517841efbbSZachary Turner PythonObject parent = ResolveName(name.substr(0, dot_pos)); 1527841efbbSZachary Turner if (!parent.IsAllocated()) 1537841efbbSZachary Turner return PythonObject(); 1547841efbbSZachary Turner 1557841efbbSZachary Turner // Tail recursion.. should be optimized by the compiler 1567841efbbSZachary Turner return parent.ResolveName(name.substr(dot_pos + 1)); 1577841efbbSZachary Turner } 1587841efbbSZachary Turner 1592c1f46dcSZachary Turner bool 1609c40264fSZachary Turner PythonObject::HasAttribute(llvm::StringRef attr) const 1619c40264fSZachary Turner { 1629c40264fSZachary Turner if (!IsValid()) 1639c40264fSZachary Turner return false; 1649c40264fSZachary Turner PythonString py_attr(attr); 1659c40264fSZachary Turner return !!PyObject_HasAttr(m_py_obj, py_attr.get()); 1669c40264fSZachary Turner } 1679c40264fSZachary Turner 1687d6d218eSZachary Turner PythonObject 1697d6d218eSZachary Turner PythonObject::GetAttributeValue(llvm::StringRef attr) const 1707d6d218eSZachary Turner { 1717d6d218eSZachary Turner if (!IsValid()) 1727d6d218eSZachary Turner return PythonObject(); 1737d6d218eSZachary Turner 1747d6d218eSZachary Turner PythonString py_attr(attr); 1757d6d218eSZachary Turner if (!PyObject_HasAttr(m_py_obj, py_attr.get())) 1767d6d218eSZachary Turner return PythonObject(); 1777d6d218eSZachary Turner 1787d6d218eSZachary Turner return PythonObject(PyRefType::Owned, 1797d6d218eSZachary Turner PyObject_GetAttr(m_py_obj, py_attr.get())); 1807d6d218eSZachary Turner } 1817d6d218eSZachary Turner 1829c40264fSZachary Turner bool 183f8b22f8fSZachary Turner PythonObject::IsNone() const 1842c1f46dcSZachary Turner { 185f8b22f8fSZachary Turner return m_py_obj == Py_None; 186f8b22f8fSZachary Turner } 187f8b22f8fSZachary Turner 188f8b22f8fSZachary Turner bool 189f8b22f8fSZachary Turner PythonObject::IsValid() const 190f8b22f8fSZachary Turner { 191f8b22f8fSZachary Turner return m_py_obj != nullptr; 192f8b22f8fSZachary Turner } 193f8b22f8fSZachary Turner 194f8b22f8fSZachary Turner bool 195f8b22f8fSZachary Turner PythonObject::IsAllocated() const 196f8b22f8fSZachary Turner { 197f8b22f8fSZachary Turner return IsValid() && !IsNone(); 1982c1f46dcSZachary Turner } 1992c1f46dcSZachary Turner 2002c1f46dcSZachary Turner StructuredData::ObjectSP 2012c1f46dcSZachary Turner PythonObject::CreateStructuredObject() const 2022c1f46dcSZachary Turner { 2032c1f46dcSZachary Turner switch (GetObjectType()) 2042c1f46dcSZachary Turner { 2052c1f46dcSZachary Turner case PyObjectType::Dictionary: 206f8b22f8fSZachary Turner return PythonDictionary(PyRefType::Borrowed, m_py_obj).CreateStructuredDictionary(); 2072c1f46dcSZachary Turner case PyObjectType::Integer: 208f8b22f8fSZachary Turner return PythonInteger(PyRefType::Borrowed, m_py_obj).CreateStructuredInteger(); 2092c1f46dcSZachary Turner case PyObjectType::List: 210f8b22f8fSZachary Turner return PythonList(PyRefType::Borrowed, m_py_obj).CreateStructuredArray(); 2112c1f46dcSZachary Turner case PyObjectType::String: 212f8b22f8fSZachary Turner return PythonString(PyRefType::Borrowed, m_py_obj).CreateStructuredString(); 2132c1f46dcSZachary Turner case PyObjectType::None: 2142c1f46dcSZachary Turner return StructuredData::ObjectSP(); 2152c1f46dcSZachary Turner default: 2162c1f46dcSZachary Turner return StructuredData::ObjectSP(new StructuredPythonObject(m_py_obj)); 2172c1f46dcSZachary Turner } 2182c1f46dcSZachary Turner } 2192c1f46dcSZachary Turner 2202c1f46dcSZachary Turner //---------------------------------------------------------------------- 2212c1f46dcSZachary Turner // PythonString 2222c1f46dcSZachary Turner //---------------------------------------------------------------------- 2232c1f46dcSZachary Turner 224f8b22f8fSZachary Turner PythonString::PythonString(PyRefType type, PyObject *py_obj) 225f8b22f8fSZachary Turner : PythonObject() 2262c1f46dcSZachary Turner { 227f8b22f8fSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string 2282c1f46dcSZachary Turner } 2292c1f46dcSZachary Turner 230f8b22f8fSZachary Turner PythonString::PythonString(const PythonString &object) 231f8b22f8fSZachary Turner : PythonObject(object) 2322c1f46dcSZachary Turner { 2332c1f46dcSZachary Turner } 2342c1f46dcSZachary Turner 23522c8efcdSZachary Turner PythonString::PythonString(llvm::StringRef string) 23622c8efcdSZachary Turner : PythonObject() 2372c1f46dcSZachary Turner { 23822c8efcdSZachary Turner SetString(string); 2392c1f46dcSZachary Turner } 2402c1f46dcSZachary Turner 24122c8efcdSZachary Turner PythonString::PythonString(const char *string) 24222c8efcdSZachary Turner : PythonObject() 2432c1f46dcSZachary Turner { 24422c8efcdSZachary Turner SetString(llvm::StringRef(string)); 2452c1f46dcSZachary Turner } 2462c1f46dcSZachary Turner 247f8b22f8fSZachary Turner PythonString::PythonString() 248f8b22f8fSZachary Turner : PythonObject() 2492c1f46dcSZachary Turner { 2502c1f46dcSZachary Turner } 2512c1f46dcSZachary Turner 2522c1f46dcSZachary Turner PythonString::~PythonString () 2532c1f46dcSZachary Turner { 2542c1f46dcSZachary Turner } 2552c1f46dcSZachary Turner 2562c1f46dcSZachary Turner bool 25722c8efcdSZachary Turner PythonString::Check(PyObject *py_obj) 25822c8efcdSZachary Turner { 25922c8efcdSZachary Turner if (!py_obj) 26022c8efcdSZachary Turner return false; 26118426935SZachary Turner 2627d6d218eSZachary Turner if (PyUnicode_Check(py_obj)) 2637d6d218eSZachary Turner return true; 2647d6d218eSZachary Turner #if PY_MAJOR_VERSION < 3 2657d6d218eSZachary Turner if (PyString_Check(py_obj)) 2667d6d218eSZachary Turner return true; 26722c8efcdSZachary Turner #endif 2687d6d218eSZachary Turner return false; 26922c8efcdSZachary Turner } 27022c8efcdSZachary Turner 271f8b22f8fSZachary Turner void 272f8b22f8fSZachary Turner PythonString::Reset(PyRefType type, PyObject *py_obj) 2732c1f46dcSZachary Turner { 274f8b22f8fSZachary Turner // Grab the desired reference type so that if we end up rejecting 275f8b22f8fSZachary Turner // `py_obj` it still gets decremented if necessary. 276f8b22f8fSZachary Turner PythonObject result(type, py_obj); 277f8b22f8fSZachary Turner 27822c8efcdSZachary Turner if (!PythonString::Check(py_obj)) 27922c8efcdSZachary Turner { 280f8b22f8fSZachary Turner PythonObject::Reset(); 281f8b22f8fSZachary Turner return; 28222c8efcdSZachary Turner } 2837d6d218eSZachary Turner #if PY_MAJOR_VERSION < 3 2847d6d218eSZachary Turner // In Python 2, Don't store PyUnicode objects directly, because we need 2857d6d218eSZachary Turner // access to their underlying character buffers which Python 2 doesn't 2867d6d218eSZachary Turner // provide. 2877d6d218eSZachary Turner if (PyUnicode_Check(py_obj)) 2887d6d218eSZachary Turner result.Reset(PyRefType::Owned, PyUnicode_AsUTF8String(result.get())); 2897d6d218eSZachary Turner #endif 290f8b22f8fSZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls 291f8b22f8fSZachary Turner // back into the virtual implementation. 292f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 2932c1f46dcSZachary Turner } 2942c1f46dcSZachary Turner 2952c1f46dcSZachary Turner llvm::StringRef 2962c1f46dcSZachary Turner PythonString::GetString() const 2972c1f46dcSZachary Turner { 29818426935SZachary Turner if (!IsValid()) 29918426935SZachary Turner return llvm::StringRef(); 30018426935SZachary Turner 30122c8efcdSZachary Turner Py_ssize_t size; 30222c8efcdSZachary Turner char *c; 30318426935SZachary Turner 30418426935SZachary Turner #if PY_MAJOR_VERSION >= 3 30518426935SZachary Turner c = PyUnicode_AsUTF8AndSize(m_py_obj, &size); 30618426935SZachary Turner #else 30718426935SZachary Turner PyString_AsStringAndSize(m_py_obj, &c, &size); 30818426935SZachary Turner #endif 30922c8efcdSZachary Turner return llvm::StringRef(c, size); 31022c8efcdSZachary Turner } 3112c1f46dcSZachary Turner 3122c1f46dcSZachary Turner size_t 3132c1f46dcSZachary Turner PythonString::GetSize() const 3142c1f46dcSZachary Turner { 315f8b22f8fSZachary Turner if (IsValid()) 31618426935SZachary Turner { 31718426935SZachary Turner #if PY_MAJOR_VERSION >= 3 31818426935SZachary Turner return PyUnicode_GetSize(m_py_obj); 31918426935SZachary Turner #else 32018426935SZachary Turner return PyString_Size(m_py_obj); 32118426935SZachary Turner #endif 32218426935SZachary Turner } 3232c1f46dcSZachary Turner return 0; 3242c1f46dcSZachary Turner } 3252c1f46dcSZachary Turner 3262c1f46dcSZachary Turner void 3272c1f46dcSZachary Turner PythonString::SetString (llvm::StringRef string) 3282c1f46dcSZachary Turner { 32922c8efcdSZachary Turner #if PY_MAJOR_VERSION >= 3 33022c8efcdSZachary Turner PyObject *unicode = PyUnicode_FromStringAndSize(string.data(), string.size()); 33118426935SZachary Turner PythonObject::Reset(PyRefType::Owned, unicode); 33222c8efcdSZachary Turner #else 33318426935SZachary Turner PyObject *str = PyString_FromStringAndSize(string.data(), string.size()); 33418426935SZachary Turner PythonObject::Reset(PyRefType::Owned, str); 33522c8efcdSZachary Turner #endif 3362c1f46dcSZachary Turner } 3372c1f46dcSZachary Turner 3382c1f46dcSZachary Turner StructuredData::StringSP 3392c1f46dcSZachary Turner PythonString::CreateStructuredString() const 3402c1f46dcSZachary Turner { 3412c1f46dcSZachary Turner StructuredData::StringSP result(new StructuredData::String); 3422c1f46dcSZachary Turner result->SetValue(GetString()); 3432c1f46dcSZachary Turner return result; 3442c1f46dcSZachary Turner } 3452c1f46dcSZachary Turner 3462c1f46dcSZachary Turner //---------------------------------------------------------------------- 3472c1f46dcSZachary Turner // PythonInteger 3482c1f46dcSZachary Turner //---------------------------------------------------------------------- 3492c1f46dcSZachary Turner 3507d6d218eSZachary Turner PythonInteger::PythonInteger() 3517d6d218eSZachary Turner : PythonObject() 3527d6d218eSZachary Turner { 3537d6d218eSZachary Turner 3547d6d218eSZachary Turner } 3557d6d218eSZachary Turner 356f8b22f8fSZachary Turner PythonInteger::PythonInteger(PyRefType type, PyObject *py_obj) 357f8b22f8fSZachary Turner : PythonObject() 3582c1f46dcSZachary Turner { 359f8b22f8fSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a integer type 3602c1f46dcSZachary Turner } 3612c1f46dcSZachary Turner 362f8b22f8fSZachary Turner PythonInteger::PythonInteger(const PythonInteger &object) 363f8b22f8fSZachary Turner : PythonObject(object) 3642c1f46dcSZachary Turner { 3652c1f46dcSZachary Turner } 3662c1f46dcSZachary Turner 367f8b22f8fSZachary Turner PythonInteger::PythonInteger(int64_t value) 368f8b22f8fSZachary Turner : PythonObject() 3692c1f46dcSZachary Turner { 3702c1f46dcSZachary Turner SetInteger(value); 3712c1f46dcSZachary Turner } 3722c1f46dcSZachary Turner 3732c1f46dcSZachary Turner 3742c1f46dcSZachary Turner PythonInteger::~PythonInteger () 3752c1f46dcSZachary Turner { 3762c1f46dcSZachary Turner } 3772c1f46dcSZachary Turner 3782c1f46dcSZachary Turner bool 37922c8efcdSZachary Turner PythonInteger::Check(PyObject *py_obj) 3802c1f46dcSZachary Turner { 38122c8efcdSZachary Turner if (!py_obj) 38222c8efcdSZachary Turner return false; 38322c8efcdSZachary Turner 38422c8efcdSZachary Turner #if PY_MAJOR_VERSION >= 3 38522c8efcdSZachary Turner // Python 3 does not have PyInt_Check. There is only one type of 38622c8efcdSZachary Turner // integral value, long. 38722c8efcdSZachary Turner return PyLong_Check(py_obj); 38822c8efcdSZachary Turner #else 38922c8efcdSZachary Turner return PyLong_Check(py_obj) || PyInt_Check(py_obj); 39022c8efcdSZachary Turner #endif 3912c1f46dcSZachary Turner } 3922c1f46dcSZachary Turner 393f8b22f8fSZachary Turner void 394f8b22f8fSZachary Turner PythonInteger::Reset(PyRefType type, PyObject *py_obj) 39522c8efcdSZachary Turner { 396f8b22f8fSZachary Turner // Grab the desired reference type so that if we end up rejecting 397f8b22f8fSZachary Turner // `py_obj` it still gets decremented if necessary. 398f8b22f8fSZachary Turner PythonObject result(type, py_obj); 399f8b22f8fSZachary Turner 40022c8efcdSZachary Turner if (!PythonInteger::Check(py_obj)) 40122c8efcdSZachary Turner { 402f8b22f8fSZachary Turner PythonObject::Reset(); 403f8b22f8fSZachary Turner return; 40422c8efcdSZachary Turner } 40522c8efcdSZachary Turner 40622c8efcdSZachary Turner #if PY_MAJOR_VERSION < 3 40722c8efcdSZachary Turner // Always store this as a PyLong, which makes interoperability between 40822c8efcdSZachary Turner // Python 2.x and Python 3.x easier. This is only necessary in 2.x, 40922c8efcdSZachary Turner // since 3.x doesn't even have a PyInt. 41022c8efcdSZachary Turner if (PyInt_Check(py_obj)) 41122c8efcdSZachary Turner { 412f8b22f8fSZachary Turner // Since we converted the original object to a different type, the new 413f8b22f8fSZachary Turner // object is an owned object regardless of the ownership semantics requested 414f8b22f8fSZachary Turner // by the user. 415f8b22f8fSZachary Turner result.Reset(PyRefType::Owned, PyLong_FromLongLong(PyInt_AsLong(py_obj))); 41622c8efcdSZachary Turner } 41722c8efcdSZachary Turner #endif 41822c8efcdSZachary Turner 419f8b22f8fSZachary Turner assert(PyLong_Check(result.get()) && "Couldn't get a PyLong from this PyObject"); 42022c8efcdSZachary Turner 421f8b22f8fSZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls 422f8b22f8fSZachary Turner // back into the virtual implementation. 423f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 4242c1f46dcSZachary Turner } 4252c1f46dcSZachary Turner 4262c1f46dcSZachary Turner int64_t 4272c1f46dcSZachary Turner PythonInteger::GetInteger() const 4282c1f46dcSZachary Turner { 4292c1f46dcSZachary Turner if (m_py_obj) 4302c1f46dcSZachary Turner { 43122c8efcdSZachary Turner assert(PyLong_Check(m_py_obj) && "PythonInteger::GetInteger has a PyObject that isn't a PyLong"); 43222c8efcdSZachary Turner 4332c1f46dcSZachary Turner return PyLong_AsLongLong(m_py_obj); 4342c1f46dcSZachary Turner } 4352c1f46dcSZachary Turner return UINT64_MAX; 4362c1f46dcSZachary Turner } 4372c1f46dcSZachary Turner 4382c1f46dcSZachary Turner void 4392c1f46dcSZachary Turner PythonInteger::SetInteger(int64_t value) 4402c1f46dcSZachary Turner { 441f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Owned, PyLong_FromLongLong(value)); 4422c1f46dcSZachary Turner } 4432c1f46dcSZachary Turner 4442c1f46dcSZachary Turner StructuredData::IntegerSP 4452c1f46dcSZachary Turner PythonInteger::CreateStructuredInteger() const 4462c1f46dcSZachary Turner { 4472c1f46dcSZachary Turner StructuredData::IntegerSP result(new StructuredData::Integer); 4482c1f46dcSZachary Turner result->SetValue(GetInteger()); 4492c1f46dcSZachary Turner return result; 4502c1f46dcSZachary Turner } 4512c1f46dcSZachary Turner 4522c1f46dcSZachary Turner //---------------------------------------------------------------------- 4532c1f46dcSZachary Turner // PythonList 4542c1f46dcSZachary Turner //---------------------------------------------------------------------- 4552c1f46dcSZachary Turner 456f8b22f8fSZachary Turner PythonList::PythonList(PyInitialValue value) 457f8b22f8fSZachary Turner : PythonObject() 4582c1f46dcSZachary Turner { 459f8b22f8fSZachary Turner if (value == PyInitialValue::Empty) 460f8b22f8fSZachary Turner Reset(PyRefType::Owned, PyList_New(0)); 4612c1f46dcSZachary Turner } 4622c1f46dcSZachary Turner 46387f47729SZachary Turner PythonList::PythonList(int list_size) 46487f47729SZachary Turner : PythonObject() 46587f47729SZachary Turner { 46687f47729SZachary Turner Reset(PyRefType::Owned, PyList_New(list_size)); 46787f47729SZachary Turner } 46887f47729SZachary Turner 469f8b22f8fSZachary Turner PythonList::PythonList(PyRefType type, PyObject *py_obj) 470f8b22f8fSZachary Turner : PythonObject() 4712c1f46dcSZachary Turner { 472f8b22f8fSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a list 4732c1f46dcSZachary Turner } 4742c1f46dcSZachary Turner 475f8b22f8fSZachary Turner PythonList::PythonList(const PythonList &list) 476f8b22f8fSZachary Turner : PythonObject(list) 4772c1f46dcSZachary Turner { 4782c1f46dcSZachary Turner } 4792c1f46dcSZachary Turner 4802c1f46dcSZachary Turner PythonList::~PythonList () 4812c1f46dcSZachary Turner { 4822c1f46dcSZachary Turner } 4832c1f46dcSZachary Turner 4842c1f46dcSZachary Turner bool 48522c8efcdSZachary Turner PythonList::Check(PyObject *py_obj) 48622c8efcdSZachary Turner { 48722c8efcdSZachary Turner if (!py_obj) 48822c8efcdSZachary Turner return false; 48922c8efcdSZachary Turner return PyList_Check(py_obj); 49022c8efcdSZachary Turner } 49122c8efcdSZachary Turner 492f8b22f8fSZachary Turner void 493f8b22f8fSZachary Turner PythonList::Reset(PyRefType type, PyObject *py_obj) 4942c1f46dcSZachary Turner { 495f8b22f8fSZachary Turner // Grab the desired reference type so that if we end up rejecting 496f8b22f8fSZachary Turner // `py_obj` it still gets decremented if necessary. 497f8b22f8fSZachary Turner PythonObject result(type, py_obj); 498f8b22f8fSZachary Turner 49922c8efcdSZachary Turner if (!PythonList::Check(py_obj)) 50022c8efcdSZachary Turner { 501f8b22f8fSZachary Turner PythonObject::Reset(); 502f8b22f8fSZachary Turner return; 50322c8efcdSZachary Turner } 50422c8efcdSZachary Turner 505f8b22f8fSZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls 506f8b22f8fSZachary Turner // back into the virtual implementation. 507f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 5082c1f46dcSZachary Turner } 5092c1f46dcSZachary Turner 5102c1f46dcSZachary Turner uint32_t 5112c1f46dcSZachary Turner PythonList::GetSize() const 5122c1f46dcSZachary Turner { 513f8b22f8fSZachary Turner if (IsValid()) 5142c1f46dcSZachary Turner return PyList_GET_SIZE(m_py_obj); 5152c1f46dcSZachary Turner return 0; 5162c1f46dcSZachary Turner } 5172c1f46dcSZachary Turner 5182c1f46dcSZachary Turner PythonObject 5192c1f46dcSZachary Turner PythonList::GetItemAtIndex(uint32_t index) const 5202c1f46dcSZachary Turner { 521f8b22f8fSZachary Turner if (IsValid()) 522f8b22f8fSZachary Turner return PythonObject(PyRefType::Borrowed, PyList_GetItem(m_py_obj, index)); 5232c1f46dcSZachary Turner return PythonObject(); 5242c1f46dcSZachary Turner } 5252c1f46dcSZachary Turner 5262c1f46dcSZachary Turner void 5272c1f46dcSZachary Turner PythonList::SetItemAtIndex(uint32_t index, const PythonObject &object) 5282c1f46dcSZachary Turner { 529f8b22f8fSZachary Turner if (IsAllocated() && object.IsValid()) 530f8b22f8fSZachary Turner { 531f8b22f8fSZachary Turner // PyList_SetItem is documented to "steal" a reference, so we need to 532f8b22f8fSZachary Turner // convert it to an owned reference by incrementing it. 533f8b22f8fSZachary Turner Py_INCREF(object.get()); 5342c1f46dcSZachary Turner PyList_SetItem(m_py_obj, index, object.get()); 5352c1f46dcSZachary Turner } 536f8b22f8fSZachary Turner } 5372c1f46dcSZachary Turner 5382c1f46dcSZachary Turner void 5392c1f46dcSZachary Turner PythonList::AppendItem(const PythonObject &object) 5402c1f46dcSZachary Turner { 541f8b22f8fSZachary Turner if (IsAllocated() && object.IsValid()) 542f8b22f8fSZachary Turner { 543f8b22f8fSZachary Turner // `PyList_Append` does *not* steal a reference, so do not call `Py_INCREF` 544f8b22f8fSZachary Turner // here like we do with `PyList_SetItem`. 5452c1f46dcSZachary Turner PyList_Append(m_py_obj, object.get()); 5462c1f46dcSZachary Turner } 547f8b22f8fSZachary Turner } 5482c1f46dcSZachary Turner 5492c1f46dcSZachary Turner StructuredData::ArraySP 5502c1f46dcSZachary Turner PythonList::CreateStructuredArray() const 5512c1f46dcSZachary Turner { 5522c1f46dcSZachary Turner StructuredData::ArraySP result(new StructuredData::Array); 5532c1f46dcSZachary Turner uint32_t count = GetSize(); 5542c1f46dcSZachary Turner for (uint32_t i = 0; i < count; ++i) 5552c1f46dcSZachary Turner { 5562c1f46dcSZachary Turner PythonObject obj = GetItemAtIndex(i); 5572c1f46dcSZachary Turner result->AddItem(obj.CreateStructuredObject()); 5582c1f46dcSZachary Turner } 5592c1f46dcSZachary Turner return result; 5602c1f46dcSZachary Turner } 5612c1f46dcSZachary Turner 5622c1f46dcSZachary Turner //---------------------------------------------------------------------- 563a1405147SZachary Turner // PythonTuple 564a1405147SZachary Turner //---------------------------------------------------------------------- 565a1405147SZachary Turner 566a1405147SZachary Turner PythonTuple::PythonTuple(PyInitialValue value) 567a1405147SZachary Turner : PythonObject() 568a1405147SZachary Turner { 569a1405147SZachary Turner if (value == PyInitialValue::Empty) 570a1405147SZachary Turner Reset(PyRefType::Owned, PyTuple_New(0)); 571a1405147SZachary Turner } 572a1405147SZachary Turner 573a1405147SZachary Turner PythonTuple::PythonTuple(int tuple_size) 574a1405147SZachary Turner : PythonObject() 575a1405147SZachary Turner { 576a1405147SZachary Turner Reset(PyRefType::Owned, PyTuple_New(tuple_size)); 577a1405147SZachary Turner } 578a1405147SZachary Turner 579a1405147SZachary Turner PythonTuple::PythonTuple(PyRefType type, PyObject *py_obj) 580a1405147SZachary Turner : PythonObject() 581a1405147SZachary Turner { 582a1405147SZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a tuple 583a1405147SZachary Turner } 584a1405147SZachary Turner 585a1405147SZachary Turner PythonTuple::PythonTuple(const PythonTuple &tuple) 586a1405147SZachary Turner : PythonObject(tuple) 587a1405147SZachary Turner { 588a1405147SZachary Turner } 589a1405147SZachary Turner 590a1405147SZachary Turner PythonTuple::PythonTuple(std::initializer_list<PythonObject> objects) 591a1405147SZachary Turner { 592a1405147SZachary Turner m_py_obj = PyTuple_New(objects.size()); 593a1405147SZachary Turner 594a1405147SZachary Turner uint32_t idx = 0; 595a1405147SZachary Turner for (auto object : objects) 596a1405147SZachary Turner { 597a1405147SZachary Turner if (object.IsValid()) 598a1405147SZachary Turner SetItemAtIndex(idx, object); 599a1405147SZachary Turner idx++; 600a1405147SZachary Turner } 601a1405147SZachary Turner } 602a1405147SZachary Turner 603a1405147SZachary Turner PythonTuple::PythonTuple(std::initializer_list<PyObject*> objects) 604a1405147SZachary Turner { 605a1405147SZachary Turner m_py_obj = PyTuple_New(objects.size()); 606a1405147SZachary Turner 607a1405147SZachary Turner uint32_t idx = 0; 608a1405147SZachary Turner for (auto py_object : objects) 609a1405147SZachary Turner { 610a1405147SZachary Turner PythonObject object(PyRefType::Borrowed, py_object); 611a1405147SZachary Turner if (object.IsValid()) 612a1405147SZachary Turner SetItemAtIndex(idx, object); 613a1405147SZachary Turner idx++; 614a1405147SZachary Turner } 615a1405147SZachary Turner } 616a1405147SZachary Turner 617a1405147SZachary Turner PythonTuple::~PythonTuple() 618a1405147SZachary Turner { 619a1405147SZachary Turner } 620a1405147SZachary Turner 621a1405147SZachary Turner bool 622a1405147SZachary Turner PythonTuple::Check(PyObject *py_obj) 623a1405147SZachary Turner { 624a1405147SZachary Turner if (!py_obj) 625a1405147SZachary Turner return false; 626a1405147SZachary Turner return PyTuple_Check(py_obj); 627a1405147SZachary Turner } 628a1405147SZachary Turner 629a1405147SZachary Turner void 630a1405147SZachary Turner PythonTuple::Reset(PyRefType type, PyObject *py_obj) 631a1405147SZachary Turner { 632a1405147SZachary Turner // Grab the desired reference type so that if we end up rejecting 633a1405147SZachary Turner // `py_obj` it still gets decremented if necessary. 634a1405147SZachary Turner PythonObject result(type, py_obj); 635a1405147SZachary Turner 636a1405147SZachary Turner if (!PythonTuple::Check(py_obj)) 637a1405147SZachary Turner { 638a1405147SZachary Turner PythonObject::Reset(); 639a1405147SZachary Turner return; 640a1405147SZachary Turner } 641a1405147SZachary Turner 642a1405147SZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls 643a1405147SZachary Turner // back into the virtual implementation. 644a1405147SZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 645a1405147SZachary Turner } 646a1405147SZachary Turner 647a1405147SZachary Turner uint32_t 648a1405147SZachary Turner PythonTuple::GetSize() const 649a1405147SZachary Turner { 650a1405147SZachary Turner if (IsValid()) 651a1405147SZachary Turner return PyTuple_GET_SIZE(m_py_obj); 652a1405147SZachary Turner return 0; 653a1405147SZachary Turner } 654a1405147SZachary Turner 655a1405147SZachary Turner PythonObject 656a1405147SZachary Turner PythonTuple::GetItemAtIndex(uint32_t index) const 657a1405147SZachary Turner { 658a1405147SZachary Turner if (IsValid()) 659a1405147SZachary Turner return PythonObject(PyRefType::Borrowed, PyTuple_GetItem(m_py_obj, index)); 660a1405147SZachary Turner return PythonObject(); 661a1405147SZachary Turner } 662a1405147SZachary Turner 663a1405147SZachary Turner void 664a1405147SZachary Turner PythonTuple::SetItemAtIndex(uint32_t index, const PythonObject &object) 665a1405147SZachary Turner { 666a1405147SZachary Turner if (IsAllocated() && object.IsValid()) 667a1405147SZachary Turner { 668a1405147SZachary Turner // PyTuple_SetItem is documented to "steal" a reference, so we need to 669a1405147SZachary Turner // convert it to an owned reference by incrementing it. 670a1405147SZachary Turner Py_INCREF(object.get()); 671a1405147SZachary Turner PyTuple_SetItem(m_py_obj, index, object.get()); 672a1405147SZachary Turner } 673a1405147SZachary Turner } 674a1405147SZachary Turner 675a1405147SZachary Turner StructuredData::ArraySP 676a1405147SZachary Turner PythonTuple::CreateStructuredArray() const 677a1405147SZachary Turner { 678a1405147SZachary Turner StructuredData::ArraySP result(new StructuredData::Array); 679a1405147SZachary Turner uint32_t count = GetSize(); 680a1405147SZachary Turner for (uint32_t i = 0; i < count; ++i) 681a1405147SZachary Turner { 682a1405147SZachary Turner PythonObject obj = GetItemAtIndex(i); 683a1405147SZachary Turner result->AddItem(obj.CreateStructuredObject()); 684a1405147SZachary Turner } 685a1405147SZachary Turner return result; 686a1405147SZachary Turner } 687a1405147SZachary Turner 688a1405147SZachary Turner //---------------------------------------------------------------------- 6892c1f46dcSZachary Turner // PythonDictionary 6902c1f46dcSZachary Turner //---------------------------------------------------------------------- 6912c1f46dcSZachary Turner 692f8b22f8fSZachary Turner PythonDictionary::PythonDictionary(PyInitialValue value) 693f8b22f8fSZachary Turner : PythonObject() 6942c1f46dcSZachary Turner { 695f8b22f8fSZachary Turner if (value == PyInitialValue::Empty) 696f8b22f8fSZachary Turner Reset(PyRefType::Owned, PyDict_New()); 6972c1f46dcSZachary Turner } 6982c1f46dcSZachary Turner 699f8b22f8fSZachary Turner PythonDictionary::PythonDictionary(PyRefType type, PyObject *py_obj) 700f8b22f8fSZachary Turner : PythonObject() 7012c1f46dcSZachary Turner { 702f8b22f8fSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a dictionary 7032c1f46dcSZachary Turner } 7042c1f46dcSZachary Turner 705f8b22f8fSZachary Turner PythonDictionary::PythonDictionary(const PythonDictionary &object) 706f8b22f8fSZachary Turner : PythonObject(object) 7072c1f46dcSZachary Turner { 7082c1f46dcSZachary Turner } 7092c1f46dcSZachary Turner 7102c1f46dcSZachary Turner PythonDictionary::~PythonDictionary () 7112c1f46dcSZachary Turner { 7122c1f46dcSZachary Turner } 7132c1f46dcSZachary Turner 7142c1f46dcSZachary Turner bool 71522c8efcdSZachary Turner PythonDictionary::Check(PyObject *py_obj) 71622c8efcdSZachary Turner { 71722c8efcdSZachary Turner if (!py_obj) 71822c8efcdSZachary Turner return false; 71922c8efcdSZachary Turner 72022c8efcdSZachary Turner return PyDict_Check(py_obj); 72122c8efcdSZachary Turner } 72222c8efcdSZachary Turner 723f8b22f8fSZachary Turner void 724f8b22f8fSZachary Turner PythonDictionary::Reset(PyRefType type, PyObject *py_obj) 7252c1f46dcSZachary Turner { 726f8b22f8fSZachary Turner // Grab the desired reference type so that if we end up rejecting 727f8b22f8fSZachary Turner // `py_obj` it still gets decremented if necessary. 728f8b22f8fSZachary Turner PythonObject result(type, py_obj); 729f8b22f8fSZachary Turner 73022c8efcdSZachary Turner if (!PythonDictionary::Check(py_obj)) 73122c8efcdSZachary Turner { 732f8b22f8fSZachary Turner PythonObject::Reset(); 733f8b22f8fSZachary Turner return; 73422c8efcdSZachary Turner } 73522c8efcdSZachary Turner 736f8b22f8fSZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls 737f8b22f8fSZachary Turner // back into the virtual implementation. 738f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 7392c1f46dcSZachary Turner } 7402c1f46dcSZachary Turner 7412c1f46dcSZachary Turner uint32_t 7422c1f46dcSZachary Turner PythonDictionary::GetSize() const 7432c1f46dcSZachary Turner { 744f8b22f8fSZachary Turner if (IsValid()) 7452c1f46dcSZachary Turner return PyDict_Size(m_py_obj); 7462c1f46dcSZachary Turner return 0; 7472c1f46dcSZachary Turner } 7482c1f46dcSZachary Turner 7492c1f46dcSZachary Turner PythonList 7502c1f46dcSZachary Turner PythonDictionary::GetKeys() const 7512c1f46dcSZachary Turner { 752f8b22f8fSZachary Turner if (IsValid()) 753f8b22f8fSZachary Turner return PythonList(PyRefType::Owned, PyDict_Keys(m_py_obj)); 754f8b22f8fSZachary Turner return PythonList(PyInitialValue::Invalid); 7552c1f46dcSZachary Turner } 7562c1f46dcSZachary Turner 7572c1f46dcSZachary Turner PythonObject 758f8b22f8fSZachary Turner PythonDictionary::GetItemForKey(const PythonObject &key) const 7592c1f46dcSZachary Turner { 760f8b22f8fSZachary Turner if (IsAllocated() && key.IsValid()) 761f8b22f8fSZachary Turner return PythonObject(PyRefType::Borrowed, PyDict_GetItem(m_py_obj, key.get())); 7622c1f46dcSZachary Turner return PythonObject(); 7632c1f46dcSZachary Turner } 7642c1f46dcSZachary Turner 7652c1f46dcSZachary Turner void 766f8b22f8fSZachary Turner PythonDictionary::SetItemForKey(const PythonObject &key, const PythonObject &value) 7672c1f46dcSZachary Turner { 768f8b22f8fSZachary Turner if (IsAllocated() && key.IsValid() && value.IsValid()) 7692c1f46dcSZachary Turner PyDict_SetItem(m_py_obj, key.get(), value.get()); 7702c1f46dcSZachary Turner } 7712c1f46dcSZachary Turner 7722c1f46dcSZachary Turner StructuredData::DictionarySP 7732c1f46dcSZachary Turner PythonDictionary::CreateStructuredDictionary() const 7742c1f46dcSZachary Turner { 7752c1f46dcSZachary Turner StructuredData::DictionarySP result(new StructuredData::Dictionary); 7762c1f46dcSZachary Turner PythonList keys(GetKeys()); 7772c1f46dcSZachary Turner uint32_t num_keys = keys.GetSize(); 7782c1f46dcSZachary Turner for (uint32_t i = 0; i < num_keys; ++i) 7792c1f46dcSZachary Turner { 7802c1f46dcSZachary Turner PythonObject key = keys.GetItemAtIndex(i); 7812c1f46dcSZachary Turner PythonObject value = GetItemForKey(key); 7822c1f46dcSZachary Turner StructuredData::ObjectSP structured_value = value.CreateStructuredObject(); 783f8b22f8fSZachary Turner result->AddItem(key.Str().GetString(), structured_value); 7842c1f46dcSZachary Turner } 7852c1f46dcSZachary Turner return result; 7862c1f46dcSZachary Turner } 7872c1f46dcSZachary Turner 7887841efbbSZachary Turner PythonModule::PythonModule() : PythonObject() 7897841efbbSZachary Turner { 7907841efbbSZachary Turner } 7917841efbbSZachary Turner 7927841efbbSZachary Turner PythonModule::PythonModule(PyRefType type, PyObject *py_obj) 7937841efbbSZachary Turner { 7947841efbbSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a module 7957841efbbSZachary Turner } 7967841efbbSZachary Turner 7977841efbbSZachary Turner PythonModule::PythonModule(const PythonModule &dict) : PythonObject(dict) 7987841efbbSZachary Turner { 7997841efbbSZachary Turner } 8007841efbbSZachary Turner 8017841efbbSZachary Turner PythonModule::~PythonModule() 8027841efbbSZachary Turner { 8037841efbbSZachary Turner } 8047841efbbSZachary Turner 8057841efbbSZachary Turner PythonModule 806a1405147SZachary Turner PythonModule::BuiltinsModule() 807a1405147SZachary Turner { 808a1405147SZachary Turner #if PY_MAJOR_VERSION >= 3 809a1405147SZachary Turner return AddModule("builtins"); 810a1405147SZachary Turner #else 811a1405147SZachary Turner return AddModule("__builtin__"); 812a1405147SZachary Turner #endif 813a1405147SZachary Turner } 814a1405147SZachary Turner 815a1405147SZachary Turner PythonModule 8167841efbbSZachary Turner PythonModule::MainModule() 8177841efbbSZachary Turner { 818a1405147SZachary Turner return AddModule("__main__"); 819a1405147SZachary Turner } 820a1405147SZachary Turner 821a1405147SZachary Turner PythonModule 822a1405147SZachary Turner PythonModule::AddModule(llvm::StringRef module) 823a1405147SZachary Turner { 824a1405147SZachary Turner std::string str = module.str(); 825a1405147SZachary Turner return PythonModule(PyRefType::Borrowed, PyImport_AddModule(str.c_str())); 8267841efbbSZachary Turner } 8277841efbbSZachary Turner 828*2419f1d5SZachary Turner 829*2419f1d5SZachary Turner PythonModule 830*2419f1d5SZachary Turner PythonModule::ImportModule(llvm::StringRef module) 831*2419f1d5SZachary Turner { 832*2419f1d5SZachary Turner std::string str = module.str(); 833*2419f1d5SZachary Turner return PythonModule(PyRefType::Owned, PyImport_ImportModule(str.c_str())); 834*2419f1d5SZachary Turner } 835*2419f1d5SZachary Turner 8367841efbbSZachary Turner bool 8377841efbbSZachary Turner PythonModule::Check(PyObject *py_obj) 8387841efbbSZachary Turner { 8397841efbbSZachary Turner if (!py_obj) 8407841efbbSZachary Turner return false; 8417841efbbSZachary Turner 8427841efbbSZachary Turner return PyModule_Check(py_obj); 8437841efbbSZachary Turner } 8447841efbbSZachary Turner 8457841efbbSZachary Turner void 8467841efbbSZachary Turner PythonModule::Reset(PyRefType type, PyObject *py_obj) 8477841efbbSZachary Turner { 8487841efbbSZachary Turner // Grab the desired reference type so that if we end up rejecting 8497841efbbSZachary Turner // `py_obj` it still gets decremented if necessary. 8507841efbbSZachary Turner PythonObject result(type, py_obj); 8517841efbbSZachary Turner 8527841efbbSZachary Turner if (!PythonModule::Check(py_obj)) 8537841efbbSZachary Turner { 8547841efbbSZachary Turner PythonObject::Reset(); 8557841efbbSZachary Turner return; 8567841efbbSZachary Turner } 8577841efbbSZachary Turner 8587841efbbSZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls 8597841efbbSZachary Turner // back into the virtual implementation. 8607841efbbSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 8617841efbbSZachary Turner } 8627841efbbSZachary Turner 8637841efbbSZachary Turner PythonDictionary 8647841efbbSZachary Turner PythonModule::GetDictionary() const 8657841efbbSZachary Turner { 8667841efbbSZachary Turner return PythonDictionary(PyRefType::Borrowed, PyModule_GetDict(m_py_obj)); 8677841efbbSZachary Turner } 8687841efbbSZachary Turner 869a1405147SZachary Turner PythonCallable::PythonCallable() : PythonObject() 870a1405147SZachary Turner { 871a1405147SZachary Turner } 872a1405147SZachary Turner 873a1405147SZachary Turner PythonCallable::PythonCallable(PyRefType type, PyObject *py_obj) 874a1405147SZachary Turner { 875a1405147SZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a callable 876a1405147SZachary Turner } 877a1405147SZachary Turner 878a1405147SZachary Turner PythonCallable::PythonCallable(const PythonCallable &callable) 879a1405147SZachary Turner : PythonObject(callable) 880a1405147SZachary Turner { 881a1405147SZachary Turner } 882a1405147SZachary Turner 883a1405147SZachary Turner PythonCallable::~PythonCallable() 884a1405147SZachary Turner { 885a1405147SZachary Turner } 886a1405147SZachary Turner 887a1405147SZachary Turner bool 888a1405147SZachary Turner PythonCallable::Check(PyObject *py_obj) 889a1405147SZachary Turner { 890a1405147SZachary Turner if (!py_obj) 891a1405147SZachary Turner return false; 892a1405147SZachary Turner 893a1405147SZachary Turner return PyCallable_Check(py_obj); 894a1405147SZachary Turner } 895a1405147SZachary Turner 896a1405147SZachary Turner void 897a1405147SZachary Turner PythonCallable::Reset(PyRefType type, PyObject *py_obj) 898a1405147SZachary Turner { 899a1405147SZachary Turner // Grab the desired reference type so that if we end up rejecting 900a1405147SZachary Turner // `py_obj` it still gets decremented if necessary. 901a1405147SZachary Turner PythonObject result(type, py_obj); 902a1405147SZachary Turner 903a1405147SZachary Turner if (!PythonCallable::Check(py_obj)) 904a1405147SZachary Turner { 905a1405147SZachary Turner PythonObject::Reset(); 906a1405147SZachary Turner return; 907a1405147SZachary Turner } 908a1405147SZachary Turner 909a1405147SZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls 910a1405147SZachary Turner // back into the virtual implementation. 911a1405147SZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 912a1405147SZachary Turner } 913a1405147SZachary Turner 914a1405147SZachary Turner 915b58fb2f4SZachary Turner PythonCallable::ArgInfo 916b58fb2f4SZachary Turner PythonCallable::GetNumArguments() const 917a1405147SZachary Turner { 918b58fb2f4SZachary Turner ArgInfo result = { 0, false, false }; 919a1405147SZachary Turner if (!IsValid()) 920b58fb2f4SZachary Turner return result; 921a1405147SZachary Turner 922a1405147SZachary Turner PyObject *py_func_obj = m_py_obj; 923a1405147SZachary Turner if (PyMethod_Check(py_func_obj)) 924a1405147SZachary Turner py_func_obj = PyMethod_GET_FUNCTION(py_func_obj); 925a1405147SZachary Turner 926a1405147SZachary Turner if (!py_func_obj) 927b58fb2f4SZachary Turner return result; 928a1405147SZachary Turner 929a1405147SZachary Turner PyCodeObject* code = (PyCodeObject*)PyFunction_GET_CODE(py_func_obj); 930a1405147SZachary Turner if (!code) 931b58fb2f4SZachary Turner return result; 932a1405147SZachary Turner 933b58fb2f4SZachary Turner result.count = code->co_argcount; 934b58fb2f4SZachary Turner result.has_varargs = !!(code->co_flags & CO_VARARGS); 935b58fb2f4SZachary Turner result.has_kwargs = !!(code->co_flags & CO_VARKEYWORDS); 936b58fb2f4SZachary Turner return result; 937b58fb2f4SZachary Turner } 938b58fb2f4SZachary Turner 939b58fb2f4SZachary Turner PythonObject 940b58fb2f4SZachary Turner PythonCallable::operator ()() 941b58fb2f4SZachary Turner { 942b58fb2f4SZachary Turner return PythonObject(PyRefType::Owned, 943b58fb2f4SZachary Turner PyObject_CallObject(m_py_obj, nullptr)); 944a1405147SZachary Turner } 945a1405147SZachary Turner 946a1405147SZachary Turner PythonObject 947a1405147SZachary Turner PythonCallable::operator ()(std::initializer_list<PyObject*> args) 948a1405147SZachary Turner { 949a1405147SZachary Turner PythonTuple arg_tuple(args); 950a1405147SZachary Turner return PythonObject(PyRefType::Owned, 951a1405147SZachary Turner PyObject_CallObject(m_py_obj, arg_tuple.get())); 952a1405147SZachary Turner } 953a1405147SZachary Turner 954a1405147SZachary Turner PythonObject 955a1405147SZachary Turner PythonCallable::operator ()(std::initializer_list<PythonObject> args) 956a1405147SZachary Turner { 957a1405147SZachary Turner PythonTuple arg_tuple(args); 958a1405147SZachary Turner return PythonObject(PyRefType::Owned, 959a1405147SZachary Turner PyObject_CallObject(m_py_obj, arg_tuple.get())); 960a1405147SZachary Turner } 961a1405147SZachary Turner 96232064024SZachary Turner PythonFile::PythonFile() 96332064024SZachary Turner : PythonObject() 96432064024SZachary Turner { 96532064024SZachary Turner } 96632064024SZachary Turner 9679c40264fSZachary Turner PythonFile::PythonFile(File &file, const char *mode) 9689c40264fSZachary Turner { 9699c40264fSZachary Turner Reset(file, mode); 9709c40264fSZachary Turner } 9719c40264fSZachary Turner 972eda01c31SZachary Turner PythonFile::PythonFile(const char *path, const char *mode) 973eda01c31SZachary Turner { 974eda01c31SZachary Turner FILE *fp = nullptr; 975eda01c31SZachary Turner fp = fopen(path, mode); 976eda01c31SZachary Turner lldb_private::File file(fp, true); 977eda01c31SZachary Turner Reset(file, mode); 978eda01c31SZachary Turner } 979eda01c31SZachary Turner 9809c40264fSZachary Turner PythonFile::PythonFile(PyRefType type, PyObject *o) 9819c40264fSZachary Turner { 9829c40264fSZachary Turner Reset(type, o); 9839c40264fSZachary Turner } 9849c40264fSZachary Turner 9859c40264fSZachary Turner PythonFile::~PythonFile() 9869c40264fSZachary Turner { 9879c40264fSZachary Turner } 9889c40264fSZachary Turner 9899c40264fSZachary Turner bool 9909c40264fSZachary Turner PythonFile::Check(PyObject *py_obj) 9919c40264fSZachary Turner { 9929c40264fSZachary Turner #if PY_MAJOR_VERSION < 3 9939c40264fSZachary Turner return PyFile_Check(py_obj); 9949c40264fSZachary Turner #else 9959c40264fSZachary Turner // In Python 3, there is no `PyFile_Check`, and in fact PyFile is not even a 9969c40264fSZachary Turner // first-class object type anymore. `PyFile_FromFd` is just a thin wrapper 9979c40264fSZachary Turner // over `io.open()`, which returns some object derived from `io.IOBase`. 9989c40264fSZachary Turner // As a result, the only way to detect a file in Python 3 is to check whether 9999c40264fSZachary Turner // it inherits from `io.IOBase`. Since it is possible for non-files to also 10009c40264fSZachary Turner // inherit from `io.IOBase`, we additionally verify that it has the `fileno` 10019c40264fSZachary Turner // attribute, which should guarantee that it is backed by the file system. 10029c40264fSZachary Turner PythonObject io_module(PyRefType::Owned, PyImport_ImportModule("io")); 10039c40264fSZachary Turner PythonDictionary io_dict(PyRefType::Borrowed, PyModule_GetDict(io_module.get())); 10049c40264fSZachary Turner PythonObject io_base_class = io_dict.GetItemForKey(PythonString("IOBase")); 10059c40264fSZachary Turner 10069c40264fSZachary Turner PythonObject object_type(PyRefType::Owned, PyObject_Type(py_obj)); 10079c40264fSZachary Turner 10089c40264fSZachary Turner if (1 != PyObject_IsSubclass(object_type.get(), io_base_class.get())) 10099c40264fSZachary Turner return false; 10109c40264fSZachary Turner if (!object_type.HasAttribute("fileno")) 10119c40264fSZachary Turner return false; 10129c40264fSZachary Turner 10139c40264fSZachary Turner return true; 10149c40264fSZachary Turner #endif 10159c40264fSZachary Turner } 10169c40264fSZachary Turner 10179c40264fSZachary Turner void 10189c40264fSZachary Turner PythonFile::Reset(PyRefType type, PyObject *py_obj) 10199c40264fSZachary Turner { 10209c40264fSZachary Turner // Grab the desired reference type so that if we end up rejecting 10219c40264fSZachary Turner // `py_obj` it still gets decremented if necessary. 10229c40264fSZachary Turner PythonObject result(type, py_obj); 10239c40264fSZachary Turner 10249c40264fSZachary Turner if (!PythonFile::Check(py_obj)) 10259c40264fSZachary Turner { 10269c40264fSZachary Turner PythonObject::Reset(); 10279c40264fSZachary Turner return; 10289c40264fSZachary Turner } 10299c40264fSZachary Turner 10309c40264fSZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack 10319c40264fSZachary Turner // overflow since it calls back into the virtual implementation. 10329c40264fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 10339c40264fSZachary Turner } 10349c40264fSZachary Turner 10359c40264fSZachary Turner void 10369c40264fSZachary Turner PythonFile::Reset(File &file, const char *mode) 10379c40264fSZachary Turner { 10389c40264fSZachary Turner char *cmode = const_cast<char *>(mode); 10399c40264fSZachary Turner #if PY_MAJOR_VERSION >= 3 10409c40264fSZachary Turner Reset(PyRefType::Owned, 10419c40264fSZachary Turner PyFile_FromFd(file.GetDescriptor(), nullptr, cmode, -1, nullptr, "ignore", nullptr, 0)); 10429c40264fSZachary Turner #else 10439c40264fSZachary Turner // Read through the Python source, doesn't seem to modify these strings 10449c40264fSZachary Turner Reset(PyRefType::Owned, 10459c40264fSZachary Turner PyFile_FromFile(file.GetStream(), const_cast<char *>(""), cmode, nullptr)); 10469c40264fSZachary Turner #endif 10479c40264fSZachary Turner } 10489c40264fSZachary Turner 1049eda01c31SZachary Turner bool 1050eda01c31SZachary Turner PythonFile::GetUnderlyingFile(File &file) const 1051eda01c31SZachary Turner { 1052eda01c31SZachary Turner if (!IsValid()) 1053eda01c31SZachary Turner return false; 1054eda01c31SZachary Turner 1055eda01c31SZachary Turner file.Close(); 1056eda01c31SZachary Turner // We don't own the file descriptor returned by this function, make sure the 1057eda01c31SZachary Turner // File object knows about that. 1058eda01c31SZachary Turner file.SetDescriptor(PyObject_AsFileDescriptor(m_py_obj), false); 1059eda01c31SZachary Turner return file.IsValid(); 1060eda01c31SZachary Turner } 1061eda01c31SZachary Turner 1062eda01c31SZachary Turner 10632c1f46dcSZachary Turner #endif 1064