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 26*744959b9SEnrico Granata #include "llvm/ADT/StringSwitch.h" 27*744959b9SEnrico Granata 282c1f46dcSZachary Turner using namespace lldb_private; 292c1f46dcSZachary Turner using namespace lldb; 302c1f46dcSZachary Turner 312c1f46dcSZachary Turner void 322c1f46dcSZachary Turner StructuredPythonObject::Dump(Stream &s) const 332c1f46dcSZachary Turner { 342c1f46dcSZachary Turner s << "Python Obj: 0x" << GetValue(); 352c1f46dcSZachary Turner } 362c1f46dcSZachary Turner 372c1f46dcSZachary Turner //---------------------------------------------------------------------- 382c1f46dcSZachary Turner // PythonObject 392c1f46dcSZachary Turner //---------------------------------------------------------------------- 402c1f46dcSZachary Turner 412c1f46dcSZachary Turner void 422c1f46dcSZachary Turner PythonObject::Dump(Stream &strm) const 432c1f46dcSZachary Turner { 442c1f46dcSZachary Turner if (m_py_obj) 452c1f46dcSZachary Turner { 462c1f46dcSZachary Turner FILE *file = ::tmpfile(); 472c1f46dcSZachary Turner if (file) 482c1f46dcSZachary Turner { 492c1f46dcSZachary Turner ::PyObject_Print (m_py_obj, file, 0); 502c1f46dcSZachary Turner const long length = ftell (file); 512c1f46dcSZachary Turner if (length) 522c1f46dcSZachary Turner { 532c1f46dcSZachary Turner ::rewind(file); 542c1f46dcSZachary Turner std::vector<char> file_contents (length,'\0'); 552c1f46dcSZachary Turner const size_t length_read = ::fread (file_contents.data(), 1, file_contents.size(), file); 562c1f46dcSZachary Turner if (length_read > 0) 572c1f46dcSZachary Turner strm.Write (file_contents.data(), length_read); 582c1f46dcSZachary Turner } 592c1f46dcSZachary Turner ::fclose (file); 602c1f46dcSZachary Turner } 612c1f46dcSZachary Turner } 622c1f46dcSZachary Turner else 632c1f46dcSZachary Turner strm.PutCString ("NULL"); 642c1f46dcSZachary Turner } 652c1f46dcSZachary Turner 662c1f46dcSZachary Turner PyObjectType 672c1f46dcSZachary Turner PythonObject::GetObjectType() const 682c1f46dcSZachary Turner { 69f8b22f8fSZachary Turner if (!IsAllocated()) 702c1f46dcSZachary Turner return PyObjectType::None; 712c1f46dcSZachary Turner 727841efbbSZachary Turner if (PythonModule::Check(m_py_obj)) 737841efbbSZachary Turner return PyObjectType::Module; 7418426935SZachary Turner if (PythonList::Check(m_py_obj)) 752c1f46dcSZachary Turner return PyObjectType::List; 76a1405147SZachary Turner if (PythonTuple::Check(m_py_obj)) 77a1405147SZachary Turner return PyObjectType::Tuple; 7818426935SZachary Turner if (PythonDictionary::Check(m_py_obj)) 792c1f46dcSZachary Turner return PyObjectType::Dictionary; 8018426935SZachary Turner if (PythonString::Check(m_py_obj)) 8122c8efcdSZachary Turner return PyObjectType::String; 825a72c02bSZachary Turner #if PY_MAJOR_VERSION >= 3 835a72c02bSZachary Turner if (PythonBytes::Check(m_py_obj)) 845a72c02bSZachary Turner return PyObjectType::Bytes; 855a72c02bSZachary Turner #endif 8618426935SZachary Turner if (PythonInteger::Check(m_py_obj)) 8722c8efcdSZachary Turner return PyObjectType::Integer; 889c40264fSZachary Turner if (PythonFile::Check(m_py_obj)) 899c40264fSZachary Turner return PyObjectType::File; 90a1405147SZachary Turner if (PythonCallable::Check(m_py_obj)) 91a1405147SZachary Turner return PyObjectType::Callable; 922c1f46dcSZachary Turner return PyObjectType::Unknown; 932c1f46dcSZachary Turner } 942c1f46dcSZachary Turner 952c1f46dcSZachary Turner PythonString 967841efbbSZachary Turner PythonObject::Repr() const 972c1f46dcSZachary Turner { 982c1f46dcSZachary Turner if (!m_py_obj) 992c1f46dcSZachary Turner return PythonString(); 1002c1f46dcSZachary Turner PyObject *repr = PyObject_Repr(m_py_obj); 1012c1f46dcSZachary Turner if (!repr) 1022c1f46dcSZachary Turner return PythonString(); 103f8b22f8fSZachary Turner return PythonString(PyRefType::Owned, repr); 1042c1f46dcSZachary Turner } 1052c1f46dcSZachary Turner 1062c1f46dcSZachary Turner PythonString 1077841efbbSZachary Turner PythonObject::Str() const 1082c1f46dcSZachary Turner { 1092c1f46dcSZachary Turner if (!m_py_obj) 1102c1f46dcSZachary Turner return PythonString(); 1112c1f46dcSZachary Turner PyObject *str = PyObject_Str(m_py_obj); 1122c1f46dcSZachary Turner if (!str) 1132c1f46dcSZachary Turner return PythonString(); 114f8b22f8fSZachary Turner return PythonString(PyRefType::Owned, str); 1152c1f46dcSZachary Turner } 1162c1f46dcSZachary Turner 1177841efbbSZachary Turner PythonObject 11802bf92d2SZachary Turner PythonObject::ResolveNameWithDictionary(llvm::StringRef name, const PythonDictionary &dict) 1197841efbbSZachary Turner { 120a1405147SZachary Turner size_t dot_pos = name.find_first_of('.'); 121a1405147SZachary Turner llvm::StringRef piece = name.substr(0, dot_pos); 122a1405147SZachary Turner PythonObject result = dict.GetItemForKey(PythonString(piece)); 123a1405147SZachary Turner if (dot_pos == llvm::StringRef::npos) 124a1405147SZachary Turner { 125a1405147SZachary Turner // There was no dot, we're done. 126a1405147SZachary Turner return result; 127a1405147SZachary Turner } 128a1405147SZachary Turner 129a1405147SZachary Turner // There was a dot. The remaining portion of the name should be looked up in 130a1405147SZachary Turner // the context of the object that was found in the dictionary. 131a1405147SZachary Turner return result.ResolveName(name.substr(dot_pos + 1)); 1327841efbbSZachary Turner } 1337841efbbSZachary Turner 1347841efbbSZachary Turner PythonObject 1357841efbbSZachary Turner PythonObject::ResolveName(llvm::StringRef name) const 1367841efbbSZachary Turner { 1377841efbbSZachary Turner // Resolve the name in the context of the specified object. If, 1387841efbbSZachary Turner // for example, `this` refers to a PyModule, then this will look for 1397841efbbSZachary Turner // `name` in this module. If `this` refers to a PyType, then it will 1407841efbbSZachary Turner // resolve `name` as an attribute of that type. If `this` refers to 1417841efbbSZachary Turner // an instance of an object, then it will resolve `name` as the value 1427841efbbSZachary Turner // of the specified field. 1437841efbbSZachary Turner // 1447841efbbSZachary Turner // This function handles dotted names so that, for example, if `m_py_obj` 1457841efbbSZachary Turner // refers to the `sys` module, and `name` == "path.append", then it 1467841efbbSZachary Turner // will find the function `sys.path.append`. 1477841efbbSZachary Turner 1487841efbbSZachary Turner size_t dot_pos = name.find_first_of('.'); 1497841efbbSZachary Turner if (dot_pos == llvm::StringRef::npos) 1507841efbbSZachary Turner { 1517841efbbSZachary Turner // No dots in the name, we should be able to find the value immediately 152a1405147SZachary Turner // as an attribute of `m_py_obj`. 1537841efbbSZachary Turner return GetAttributeValue(name); 1547841efbbSZachary Turner } 1557841efbbSZachary Turner 1567841efbbSZachary Turner // Look up the first piece of the name, and resolve the rest as a child of that. 1577841efbbSZachary Turner PythonObject parent = ResolveName(name.substr(0, dot_pos)); 1587841efbbSZachary Turner if (!parent.IsAllocated()) 1597841efbbSZachary Turner return PythonObject(); 1607841efbbSZachary Turner 1617841efbbSZachary Turner // Tail recursion.. should be optimized by the compiler 1627841efbbSZachary Turner return parent.ResolveName(name.substr(dot_pos + 1)); 1637841efbbSZachary Turner } 1647841efbbSZachary Turner 1652c1f46dcSZachary Turner bool 1669c40264fSZachary Turner PythonObject::HasAttribute(llvm::StringRef attr) const 1679c40264fSZachary Turner { 1689c40264fSZachary Turner if (!IsValid()) 1699c40264fSZachary Turner return false; 1709c40264fSZachary Turner PythonString py_attr(attr); 1719c40264fSZachary Turner return !!PyObject_HasAttr(m_py_obj, py_attr.get()); 1729c40264fSZachary Turner } 1739c40264fSZachary Turner 1747d6d218eSZachary Turner PythonObject 1757d6d218eSZachary Turner PythonObject::GetAttributeValue(llvm::StringRef attr) const 1767d6d218eSZachary Turner { 1777d6d218eSZachary Turner if (!IsValid()) 1787d6d218eSZachary Turner return PythonObject(); 1797d6d218eSZachary Turner 1807d6d218eSZachary Turner PythonString py_attr(attr); 1817d6d218eSZachary Turner if (!PyObject_HasAttr(m_py_obj, py_attr.get())) 1827d6d218eSZachary Turner return PythonObject(); 1837d6d218eSZachary Turner 1847d6d218eSZachary Turner return PythonObject(PyRefType::Owned, 1857d6d218eSZachary Turner PyObject_GetAttr(m_py_obj, py_attr.get())); 1867d6d218eSZachary Turner } 1877d6d218eSZachary Turner 1889c40264fSZachary Turner bool 189f8b22f8fSZachary Turner PythonObject::IsNone() const 1902c1f46dcSZachary Turner { 191f8b22f8fSZachary Turner return m_py_obj == Py_None; 192f8b22f8fSZachary Turner } 193f8b22f8fSZachary Turner 194f8b22f8fSZachary Turner bool 195f8b22f8fSZachary Turner PythonObject::IsValid() const 196f8b22f8fSZachary Turner { 197f8b22f8fSZachary Turner return m_py_obj != nullptr; 198f8b22f8fSZachary Turner } 199f8b22f8fSZachary Turner 200f8b22f8fSZachary Turner bool 201f8b22f8fSZachary Turner PythonObject::IsAllocated() const 202f8b22f8fSZachary Turner { 203f8b22f8fSZachary Turner return IsValid() && !IsNone(); 2042c1f46dcSZachary Turner } 2052c1f46dcSZachary Turner 2062c1f46dcSZachary Turner StructuredData::ObjectSP 2072c1f46dcSZachary Turner PythonObject::CreateStructuredObject() const 2082c1f46dcSZachary Turner { 2092c1f46dcSZachary Turner switch (GetObjectType()) 2102c1f46dcSZachary Turner { 2112c1f46dcSZachary Turner case PyObjectType::Dictionary: 212f8b22f8fSZachary Turner return PythonDictionary(PyRefType::Borrowed, m_py_obj).CreateStructuredDictionary(); 2132c1f46dcSZachary Turner case PyObjectType::Integer: 214f8b22f8fSZachary Turner return PythonInteger(PyRefType::Borrowed, m_py_obj).CreateStructuredInteger(); 2152c1f46dcSZachary Turner case PyObjectType::List: 216f8b22f8fSZachary Turner return PythonList(PyRefType::Borrowed, m_py_obj).CreateStructuredArray(); 2172c1f46dcSZachary Turner case PyObjectType::String: 218f8b22f8fSZachary Turner return PythonString(PyRefType::Borrowed, m_py_obj).CreateStructuredString(); 2195a72c02bSZachary Turner case PyObjectType::Bytes: 2205a72c02bSZachary Turner return PythonBytes(PyRefType::Borrowed, m_py_obj).CreateStructuredString(); 2212c1f46dcSZachary Turner case PyObjectType::None: 2222c1f46dcSZachary Turner return StructuredData::ObjectSP(); 2232c1f46dcSZachary Turner default: 2242c1f46dcSZachary Turner return StructuredData::ObjectSP(new StructuredPythonObject(m_py_obj)); 2252c1f46dcSZachary Turner } 2262c1f46dcSZachary Turner } 2272c1f46dcSZachary Turner 2282c1f46dcSZachary Turner //---------------------------------------------------------------------- 2292c1f46dcSZachary Turner // PythonString 2302c1f46dcSZachary Turner //---------------------------------------------------------------------- 2315a72c02bSZachary Turner PythonBytes::PythonBytes() : PythonObject() 2325a72c02bSZachary Turner { 2335a72c02bSZachary Turner } 2345a72c02bSZachary Turner 2355a72c02bSZachary Turner PythonBytes::PythonBytes(llvm::ArrayRef<uint8_t> bytes) : PythonObject() 2365a72c02bSZachary Turner { 2375a72c02bSZachary Turner SetBytes(bytes); 2385a72c02bSZachary Turner } 2395a72c02bSZachary Turner 2405a72c02bSZachary Turner PythonBytes::PythonBytes(const uint8_t *bytes, size_t length) : PythonObject() 2415a72c02bSZachary Turner { 2425a72c02bSZachary Turner SetBytes(llvm::ArrayRef<uint8_t>(bytes, length)); 2435a72c02bSZachary Turner } 2445a72c02bSZachary Turner 2455a72c02bSZachary Turner PythonBytes::PythonBytes(PyRefType type, PyObject *py_obj) : PythonObject() 2465a72c02bSZachary Turner { 2475a72c02bSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string 2485a72c02bSZachary Turner } 2495a72c02bSZachary Turner 2505a72c02bSZachary Turner PythonBytes::PythonBytes(const PythonBytes &object) : PythonObject(object) 2515a72c02bSZachary Turner { 2525a72c02bSZachary Turner } 2535a72c02bSZachary Turner 2545a72c02bSZachary Turner PythonBytes::~PythonBytes() 2555a72c02bSZachary Turner { 2565a72c02bSZachary Turner } 2575a72c02bSZachary Turner 2585a72c02bSZachary Turner bool 2595a72c02bSZachary Turner PythonBytes::Check(PyObject *py_obj) 2605a72c02bSZachary Turner { 2615a72c02bSZachary Turner if (!py_obj) 2625a72c02bSZachary Turner return false; 2635a72c02bSZachary Turner if (PyBytes_Check(py_obj)) 2645a72c02bSZachary Turner return true; 2655a72c02bSZachary Turner return false; 2665a72c02bSZachary Turner } 2675a72c02bSZachary Turner 2685a72c02bSZachary Turner void 2695a72c02bSZachary Turner PythonBytes::Reset(PyRefType type, PyObject *py_obj) 2705a72c02bSZachary Turner { 2715a72c02bSZachary Turner // Grab the desired reference type so that if we end up rejecting 2725a72c02bSZachary Turner // `py_obj` it still gets decremented if necessary. 2735a72c02bSZachary Turner PythonObject result(type, py_obj); 2745a72c02bSZachary Turner 2755a72c02bSZachary Turner if (!PythonBytes::Check(py_obj)) 2765a72c02bSZachary Turner { 2775a72c02bSZachary Turner PythonObject::Reset(); 2785a72c02bSZachary Turner return; 2795a72c02bSZachary Turner } 2805a72c02bSZachary Turner 2815a72c02bSZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls 2825a72c02bSZachary Turner // back into the virtual implementation. 2835a72c02bSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 2845a72c02bSZachary Turner } 2855a72c02bSZachary Turner 2865a72c02bSZachary Turner llvm::ArrayRef<uint8_t> 2875a72c02bSZachary Turner PythonBytes::GetBytes() const 2885a72c02bSZachary Turner { 2895a72c02bSZachary Turner if (!IsValid()) 2905a72c02bSZachary Turner return llvm::ArrayRef<uint8_t>(); 2915a72c02bSZachary Turner 2925a72c02bSZachary Turner Py_ssize_t size; 2935a72c02bSZachary Turner char *c; 2945a72c02bSZachary Turner 2955a72c02bSZachary Turner PyBytes_AsStringAndSize(m_py_obj, &c, &size); 2965a72c02bSZachary Turner return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size); 2975a72c02bSZachary Turner } 2985a72c02bSZachary Turner 2995a72c02bSZachary Turner size_t 3005a72c02bSZachary Turner PythonBytes::GetSize() const 3015a72c02bSZachary Turner { 3025a72c02bSZachary Turner if (!IsValid()) 3035a72c02bSZachary Turner return 0; 3045a72c02bSZachary Turner return PyBytes_Size(m_py_obj); 3055a72c02bSZachary Turner } 3065a72c02bSZachary Turner 3075a72c02bSZachary Turner void 3085a72c02bSZachary Turner PythonBytes::SetBytes(llvm::ArrayRef<uint8_t> bytes) 3095a72c02bSZachary Turner { 3105a72c02bSZachary Turner const char *data = reinterpret_cast<const char *>(bytes.data()); 3115a72c02bSZachary Turner PyObject *py_bytes = PyBytes_FromStringAndSize(data, bytes.size()); 3125a72c02bSZachary Turner PythonObject::Reset(PyRefType::Owned, py_bytes); 3135a72c02bSZachary Turner } 3145a72c02bSZachary Turner 3155a72c02bSZachary Turner StructuredData::StringSP 3165a72c02bSZachary Turner PythonBytes::CreateStructuredString() const 3175a72c02bSZachary Turner { 3185a72c02bSZachary Turner StructuredData::StringSP result(new StructuredData::String); 3195a72c02bSZachary Turner Py_ssize_t size; 3205a72c02bSZachary Turner char *c; 3215a72c02bSZachary Turner PyBytes_AsStringAndSize(m_py_obj, &c, &size); 3225a72c02bSZachary Turner result->SetValue(std::string(c, size)); 3235a72c02bSZachary Turner return result; 3245a72c02bSZachary Turner } 3255a72c02bSZachary Turner 3265a72c02bSZachary Turner //---------------------------------------------------------------------- 3275a72c02bSZachary Turner // PythonString 3285a72c02bSZachary Turner //---------------------------------------------------------------------- 3292c1f46dcSZachary Turner 330f8b22f8fSZachary Turner PythonString::PythonString(PyRefType type, PyObject *py_obj) 331f8b22f8fSZachary Turner : PythonObject() 3322c1f46dcSZachary Turner { 333f8b22f8fSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string 3342c1f46dcSZachary Turner } 3352c1f46dcSZachary Turner 336f8b22f8fSZachary Turner PythonString::PythonString(const PythonString &object) 337f8b22f8fSZachary Turner : PythonObject(object) 3382c1f46dcSZachary Turner { 3392c1f46dcSZachary Turner } 3402c1f46dcSZachary Turner 34122c8efcdSZachary Turner PythonString::PythonString(llvm::StringRef string) 34222c8efcdSZachary Turner : PythonObject() 3432c1f46dcSZachary Turner { 34422c8efcdSZachary Turner SetString(string); 3452c1f46dcSZachary Turner } 3462c1f46dcSZachary Turner 34722c8efcdSZachary Turner PythonString::PythonString(const char *string) 34822c8efcdSZachary Turner : PythonObject() 3492c1f46dcSZachary Turner { 35022c8efcdSZachary Turner SetString(llvm::StringRef(string)); 3512c1f46dcSZachary Turner } 3522c1f46dcSZachary Turner 353f8b22f8fSZachary Turner PythonString::PythonString() 354f8b22f8fSZachary Turner : PythonObject() 3552c1f46dcSZachary Turner { 3562c1f46dcSZachary Turner } 3572c1f46dcSZachary Turner 3582c1f46dcSZachary Turner PythonString::~PythonString () 3592c1f46dcSZachary Turner { 3602c1f46dcSZachary Turner } 3612c1f46dcSZachary Turner 3622c1f46dcSZachary Turner bool 36322c8efcdSZachary Turner PythonString::Check(PyObject *py_obj) 36422c8efcdSZachary Turner { 36522c8efcdSZachary Turner if (!py_obj) 36622c8efcdSZachary Turner return false; 36718426935SZachary Turner 3687d6d218eSZachary Turner if (PyUnicode_Check(py_obj)) 3697d6d218eSZachary Turner return true; 3707d6d218eSZachary Turner #if PY_MAJOR_VERSION < 3 3717d6d218eSZachary Turner if (PyString_Check(py_obj)) 3727d6d218eSZachary Turner return true; 37322c8efcdSZachary Turner #endif 3747d6d218eSZachary Turner return false; 37522c8efcdSZachary Turner } 37622c8efcdSZachary Turner 377f8b22f8fSZachary Turner void 378f8b22f8fSZachary Turner PythonString::Reset(PyRefType type, PyObject *py_obj) 3792c1f46dcSZachary Turner { 380f8b22f8fSZachary Turner // Grab the desired reference type so that if we end up rejecting 381f8b22f8fSZachary Turner // `py_obj` it still gets decremented if necessary. 382f8b22f8fSZachary Turner PythonObject result(type, py_obj); 383f8b22f8fSZachary Turner 38422c8efcdSZachary Turner if (!PythonString::Check(py_obj)) 38522c8efcdSZachary Turner { 386f8b22f8fSZachary Turner PythonObject::Reset(); 387f8b22f8fSZachary Turner return; 38822c8efcdSZachary Turner } 3897d6d218eSZachary Turner #if PY_MAJOR_VERSION < 3 3907d6d218eSZachary Turner // In Python 2, Don't store PyUnicode objects directly, because we need 3917d6d218eSZachary Turner // access to their underlying character buffers which Python 2 doesn't 3927d6d218eSZachary Turner // provide. 3937d6d218eSZachary Turner if (PyUnicode_Check(py_obj)) 3947d6d218eSZachary Turner result.Reset(PyRefType::Owned, PyUnicode_AsUTF8String(result.get())); 3957d6d218eSZachary Turner #endif 396f8b22f8fSZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls 397f8b22f8fSZachary Turner // back into the virtual implementation. 398f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 3992c1f46dcSZachary Turner } 4002c1f46dcSZachary Turner 4012c1f46dcSZachary Turner llvm::StringRef 4022c1f46dcSZachary Turner PythonString::GetString() const 4032c1f46dcSZachary Turner { 40418426935SZachary Turner if (!IsValid()) 40518426935SZachary Turner return llvm::StringRef(); 40618426935SZachary Turner 40722c8efcdSZachary Turner Py_ssize_t size; 40822c8efcdSZachary Turner char *c; 40918426935SZachary Turner 41018426935SZachary Turner #if PY_MAJOR_VERSION >= 3 41118426935SZachary Turner c = PyUnicode_AsUTF8AndSize(m_py_obj, &size); 41218426935SZachary Turner #else 41318426935SZachary Turner PyString_AsStringAndSize(m_py_obj, &c, &size); 41418426935SZachary Turner #endif 41522c8efcdSZachary Turner return llvm::StringRef(c, size); 41622c8efcdSZachary Turner } 4172c1f46dcSZachary Turner 4182c1f46dcSZachary Turner size_t 4192c1f46dcSZachary Turner PythonString::GetSize() const 4202c1f46dcSZachary Turner { 421f8b22f8fSZachary Turner if (IsValid()) 42218426935SZachary Turner { 42318426935SZachary Turner #if PY_MAJOR_VERSION >= 3 42418426935SZachary Turner return PyUnicode_GetSize(m_py_obj); 42518426935SZachary Turner #else 42618426935SZachary Turner return PyString_Size(m_py_obj); 42718426935SZachary Turner #endif 42818426935SZachary Turner } 4292c1f46dcSZachary Turner return 0; 4302c1f46dcSZachary Turner } 4312c1f46dcSZachary Turner 4322c1f46dcSZachary Turner void 4332c1f46dcSZachary Turner PythonString::SetString (llvm::StringRef string) 4342c1f46dcSZachary Turner { 43522c8efcdSZachary Turner #if PY_MAJOR_VERSION >= 3 43622c8efcdSZachary Turner PyObject *unicode = PyUnicode_FromStringAndSize(string.data(), string.size()); 43718426935SZachary Turner PythonObject::Reset(PyRefType::Owned, unicode); 43822c8efcdSZachary Turner #else 43918426935SZachary Turner PyObject *str = PyString_FromStringAndSize(string.data(), string.size()); 44018426935SZachary Turner PythonObject::Reset(PyRefType::Owned, str); 44122c8efcdSZachary Turner #endif 4422c1f46dcSZachary Turner } 4432c1f46dcSZachary Turner 4442c1f46dcSZachary Turner StructuredData::StringSP 4452c1f46dcSZachary Turner PythonString::CreateStructuredString() const 4462c1f46dcSZachary Turner { 4472c1f46dcSZachary Turner StructuredData::StringSP result(new StructuredData::String); 4482c1f46dcSZachary Turner result->SetValue(GetString()); 4492c1f46dcSZachary Turner return result; 4502c1f46dcSZachary Turner } 4512c1f46dcSZachary Turner 4522c1f46dcSZachary Turner //---------------------------------------------------------------------- 4532c1f46dcSZachary Turner // PythonInteger 4542c1f46dcSZachary Turner //---------------------------------------------------------------------- 4552c1f46dcSZachary Turner 4567d6d218eSZachary Turner PythonInteger::PythonInteger() 4577d6d218eSZachary Turner : PythonObject() 4587d6d218eSZachary Turner { 4597d6d218eSZachary Turner 4607d6d218eSZachary Turner } 4617d6d218eSZachary Turner 462f8b22f8fSZachary Turner PythonInteger::PythonInteger(PyRefType type, PyObject *py_obj) 463f8b22f8fSZachary Turner : PythonObject() 4642c1f46dcSZachary Turner { 465f8b22f8fSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a integer type 4662c1f46dcSZachary Turner } 4672c1f46dcSZachary Turner 468f8b22f8fSZachary Turner PythonInteger::PythonInteger(const PythonInteger &object) 469f8b22f8fSZachary Turner : PythonObject(object) 4702c1f46dcSZachary Turner { 4712c1f46dcSZachary Turner } 4722c1f46dcSZachary Turner 473f8b22f8fSZachary Turner PythonInteger::PythonInteger(int64_t value) 474f8b22f8fSZachary Turner : PythonObject() 4752c1f46dcSZachary Turner { 4762c1f46dcSZachary Turner SetInteger(value); 4772c1f46dcSZachary Turner } 4782c1f46dcSZachary Turner 4792c1f46dcSZachary Turner 4802c1f46dcSZachary Turner PythonInteger::~PythonInteger () 4812c1f46dcSZachary Turner { 4822c1f46dcSZachary Turner } 4832c1f46dcSZachary Turner 4842c1f46dcSZachary Turner bool 48522c8efcdSZachary Turner PythonInteger::Check(PyObject *py_obj) 4862c1f46dcSZachary Turner { 48722c8efcdSZachary Turner if (!py_obj) 48822c8efcdSZachary Turner return false; 48922c8efcdSZachary Turner 49022c8efcdSZachary Turner #if PY_MAJOR_VERSION >= 3 49122c8efcdSZachary Turner // Python 3 does not have PyInt_Check. There is only one type of 49222c8efcdSZachary Turner // integral value, long. 49322c8efcdSZachary Turner return PyLong_Check(py_obj); 49422c8efcdSZachary Turner #else 49522c8efcdSZachary Turner return PyLong_Check(py_obj) || PyInt_Check(py_obj); 49622c8efcdSZachary Turner #endif 4972c1f46dcSZachary Turner } 4982c1f46dcSZachary Turner 499f8b22f8fSZachary Turner void 500f8b22f8fSZachary Turner PythonInteger::Reset(PyRefType type, PyObject *py_obj) 50122c8efcdSZachary Turner { 502f8b22f8fSZachary Turner // Grab the desired reference type so that if we end up rejecting 503f8b22f8fSZachary Turner // `py_obj` it still gets decremented if necessary. 504f8b22f8fSZachary Turner PythonObject result(type, py_obj); 505f8b22f8fSZachary Turner 50622c8efcdSZachary Turner if (!PythonInteger::Check(py_obj)) 50722c8efcdSZachary Turner { 508f8b22f8fSZachary Turner PythonObject::Reset(); 509f8b22f8fSZachary Turner return; 51022c8efcdSZachary Turner } 51122c8efcdSZachary Turner 51222c8efcdSZachary Turner #if PY_MAJOR_VERSION < 3 51322c8efcdSZachary Turner // Always store this as a PyLong, which makes interoperability between 51422c8efcdSZachary Turner // Python 2.x and Python 3.x easier. This is only necessary in 2.x, 51522c8efcdSZachary Turner // since 3.x doesn't even have a PyInt. 51622c8efcdSZachary Turner if (PyInt_Check(py_obj)) 51722c8efcdSZachary Turner { 518f8b22f8fSZachary Turner // Since we converted the original object to a different type, the new 519f8b22f8fSZachary Turner // object is an owned object regardless of the ownership semantics requested 520f8b22f8fSZachary Turner // by the user. 521f8b22f8fSZachary Turner result.Reset(PyRefType::Owned, PyLong_FromLongLong(PyInt_AsLong(py_obj))); 52222c8efcdSZachary Turner } 52322c8efcdSZachary Turner #endif 52422c8efcdSZachary Turner 525f8b22f8fSZachary Turner assert(PyLong_Check(result.get()) && "Couldn't get a PyLong from this PyObject"); 52622c8efcdSZachary Turner 527f8b22f8fSZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls 528f8b22f8fSZachary Turner // back into the virtual implementation. 529f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 5302c1f46dcSZachary Turner } 5312c1f46dcSZachary Turner 5322c1f46dcSZachary Turner int64_t 5332c1f46dcSZachary Turner PythonInteger::GetInteger() const 5342c1f46dcSZachary Turner { 5352c1f46dcSZachary Turner if (m_py_obj) 5362c1f46dcSZachary Turner { 53722c8efcdSZachary Turner assert(PyLong_Check(m_py_obj) && "PythonInteger::GetInteger has a PyObject that isn't a PyLong"); 53822c8efcdSZachary Turner 5392c1f46dcSZachary Turner return PyLong_AsLongLong(m_py_obj); 5402c1f46dcSZachary Turner } 5412c1f46dcSZachary Turner return UINT64_MAX; 5422c1f46dcSZachary Turner } 5432c1f46dcSZachary Turner 5442c1f46dcSZachary Turner void 5452c1f46dcSZachary Turner PythonInteger::SetInteger(int64_t value) 5462c1f46dcSZachary Turner { 547f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Owned, PyLong_FromLongLong(value)); 5482c1f46dcSZachary Turner } 5492c1f46dcSZachary Turner 5502c1f46dcSZachary Turner StructuredData::IntegerSP 5512c1f46dcSZachary Turner PythonInteger::CreateStructuredInteger() const 5522c1f46dcSZachary Turner { 5532c1f46dcSZachary Turner StructuredData::IntegerSP result(new StructuredData::Integer); 5542c1f46dcSZachary Turner result->SetValue(GetInteger()); 5552c1f46dcSZachary Turner return result; 5562c1f46dcSZachary Turner } 5572c1f46dcSZachary Turner 5582c1f46dcSZachary Turner //---------------------------------------------------------------------- 5592c1f46dcSZachary Turner // PythonList 5602c1f46dcSZachary Turner //---------------------------------------------------------------------- 5612c1f46dcSZachary Turner 562f8b22f8fSZachary Turner PythonList::PythonList(PyInitialValue value) 563f8b22f8fSZachary Turner : PythonObject() 5642c1f46dcSZachary Turner { 565f8b22f8fSZachary Turner if (value == PyInitialValue::Empty) 566f8b22f8fSZachary Turner Reset(PyRefType::Owned, PyList_New(0)); 5672c1f46dcSZachary Turner } 5682c1f46dcSZachary Turner 56987f47729SZachary Turner PythonList::PythonList(int list_size) 57087f47729SZachary Turner : PythonObject() 57187f47729SZachary Turner { 57287f47729SZachary Turner Reset(PyRefType::Owned, PyList_New(list_size)); 57387f47729SZachary Turner } 57487f47729SZachary Turner 575f8b22f8fSZachary Turner PythonList::PythonList(PyRefType type, PyObject *py_obj) 576f8b22f8fSZachary Turner : PythonObject() 5772c1f46dcSZachary Turner { 578f8b22f8fSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a list 5792c1f46dcSZachary Turner } 5802c1f46dcSZachary Turner 581f8b22f8fSZachary Turner PythonList::PythonList(const PythonList &list) 582f8b22f8fSZachary Turner : PythonObject(list) 5832c1f46dcSZachary Turner { 5842c1f46dcSZachary Turner } 5852c1f46dcSZachary Turner 5862c1f46dcSZachary Turner PythonList::~PythonList () 5872c1f46dcSZachary Turner { 5882c1f46dcSZachary Turner } 5892c1f46dcSZachary Turner 5902c1f46dcSZachary Turner bool 59122c8efcdSZachary Turner PythonList::Check(PyObject *py_obj) 59222c8efcdSZachary Turner { 59322c8efcdSZachary Turner if (!py_obj) 59422c8efcdSZachary Turner return false; 59522c8efcdSZachary Turner return PyList_Check(py_obj); 59622c8efcdSZachary Turner } 59722c8efcdSZachary Turner 598f8b22f8fSZachary Turner void 599f8b22f8fSZachary Turner PythonList::Reset(PyRefType type, PyObject *py_obj) 6002c1f46dcSZachary Turner { 601f8b22f8fSZachary Turner // Grab the desired reference type so that if we end up rejecting 602f8b22f8fSZachary Turner // `py_obj` it still gets decremented if necessary. 603f8b22f8fSZachary Turner PythonObject result(type, py_obj); 604f8b22f8fSZachary Turner 60522c8efcdSZachary Turner if (!PythonList::Check(py_obj)) 60622c8efcdSZachary Turner { 607f8b22f8fSZachary Turner PythonObject::Reset(); 608f8b22f8fSZachary Turner return; 60922c8efcdSZachary Turner } 61022c8efcdSZachary Turner 611f8b22f8fSZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls 612f8b22f8fSZachary Turner // back into the virtual implementation. 613f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 6142c1f46dcSZachary Turner } 6152c1f46dcSZachary Turner 6162c1f46dcSZachary Turner uint32_t 6172c1f46dcSZachary Turner PythonList::GetSize() const 6182c1f46dcSZachary Turner { 619f8b22f8fSZachary Turner if (IsValid()) 6202c1f46dcSZachary Turner return PyList_GET_SIZE(m_py_obj); 6212c1f46dcSZachary Turner return 0; 6222c1f46dcSZachary Turner } 6232c1f46dcSZachary Turner 6242c1f46dcSZachary Turner PythonObject 6252c1f46dcSZachary Turner PythonList::GetItemAtIndex(uint32_t index) const 6262c1f46dcSZachary Turner { 627f8b22f8fSZachary Turner if (IsValid()) 628f8b22f8fSZachary Turner return PythonObject(PyRefType::Borrowed, PyList_GetItem(m_py_obj, index)); 6292c1f46dcSZachary Turner return PythonObject(); 6302c1f46dcSZachary Turner } 6312c1f46dcSZachary Turner 6322c1f46dcSZachary Turner void 6332c1f46dcSZachary Turner PythonList::SetItemAtIndex(uint32_t index, const PythonObject &object) 6342c1f46dcSZachary Turner { 635f8b22f8fSZachary Turner if (IsAllocated() && object.IsValid()) 636f8b22f8fSZachary Turner { 637f8b22f8fSZachary Turner // PyList_SetItem is documented to "steal" a reference, so we need to 638f8b22f8fSZachary Turner // convert it to an owned reference by incrementing it. 639f8b22f8fSZachary Turner Py_INCREF(object.get()); 6402c1f46dcSZachary Turner PyList_SetItem(m_py_obj, index, object.get()); 6412c1f46dcSZachary Turner } 642f8b22f8fSZachary Turner } 6432c1f46dcSZachary Turner 6442c1f46dcSZachary Turner void 6452c1f46dcSZachary Turner PythonList::AppendItem(const PythonObject &object) 6462c1f46dcSZachary Turner { 647f8b22f8fSZachary Turner if (IsAllocated() && object.IsValid()) 648f8b22f8fSZachary Turner { 649f8b22f8fSZachary Turner // `PyList_Append` does *not* steal a reference, so do not call `Py_INCREF` 650f8b22f8fSZachary Turner // here like we do with `PyList_SetItem`. 6512c1f46dcSZachary Turner PyList_Append(m_py_obj, object.get()); 6522c1f46dcSZachary Turner } 653f8b22f8fSZachary Turner } 6542c1f46dcSZachary Turner 6552c1f46dcSZachary Turner StructuredData::ArraySP 6562c1f46dcSZachary Turner PythonList::CreateStructuredArray() const 6572c1f46dcSZachary Turner { 6582c1f46dcSZachary Turner StructuredData::ArraySP result(new StructuredData::Array); 6592c1f46dcSZachary Turner uint32_t count = GetSize(); 6602c1f46dcSZachary Turner for (uint32_t i = 0; i < count; ++i) 6612c1f46dcSZachary Turner { 6622c1f46dcSZachary Turner PythonObject obj = GetItemAtIndex(i); 6632c1f46dcSZachary Turner result->AddItem(obj.CreateStructuredObject()); 6642c1f46dcSZachary Turner } 6652c1f46dcSZachary Turner return result; 6662c1f46dcSZachary Turner } 6672c1f46dcSZachary Turner 6682c1f46dcSZachary Turner //---------------------------------------------------------------------- 669a1405147SZachary Turner // PythonTuple 670a1405147SZachary Turner //---------------------------------------------------------------------- 671a1405147SZachary Turner 672a1405147SZachary Turner PythonTuple::PythonTuple(PyInitialValue value) 673a1405147SZachary Turner : PythonObject() 674a1405147SZachary Turner { 675a1405147SZachary Turner if (value == PyInitialValue::Empty) 676a1405147SZachary Turner Reset(PyRefType::Owned, PyTuple_New(0)); 677a1405147SZachary Turner } 678a1405147SZachary Turner 679a1405147SZachary Turner PythonTuple::PythonTuple(int tuple_size) 680a1405147SZachary Turner : PythonObject() 681a1405147SZachary Turner { 682a1405147SZachary Turner Reset(PyRefType::Owned, PyTuple_New(tuple_size)); 683a1405147SZachary Turner } 684a1405147SZachary Turner 685a1405147SZachary Turner PythonTuple::PythonTuple(PyRefType type, PyObject *py_obj) 686a1405147SZachary Turner : PythonObject() 687a1405147SZachary Turner { 688a1405147SZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a tuple 689a1405147SZachary Turner } 690a1405147SZachary Turner 691a1405147SZachary Turner PythonTuple::PythonTuple(const PythonTuple &tuple) 692a1405147SZachary Turner : PythonObject(tuple) 693a1405147SZachary Turner { 694a1405147SZachary Turner } 695a1405147SZachary Turner 696a1405147SZachary Turner PythonTuple::PythonTuple(std::initializer_list<PythonObject> objects) 697a1405147SZachary Turner { 698a1405147SZachary Turner m_py_obj = PyTuple_New(objects.size()); 699a1405147SZachary Turner 700a1405147SZachary Turner uint32_t idx = 0; 701a1405147SZachary Turner for (auto object : objects) 702a1405147SZachary Turner { 703a1405147SZachary Turner if (object.IsValid()) 704a1405147SZachary Turner SetItemAtIndex(idx, object); 705a1405147SZachary Turner idx++; 706a1405147SZachary Turner } 707a1405147SZachary Turner } 708a1405147SZachary Turner 709a1405147SZachary Turner PythonTuple::PythonTuple(std::initializer_list<PyObject*> objects) 710a1405147SZachary Turner { 711a1405147SZachary Turner m_py_obj = PyTuple_New(objects.size()); 712a1405147SZachary Turner 713a1405147SZachary Turner uint32_t idx = 0; 714a1405147SZachary Turner for (auto py_object : objects) 715a1405147SZachary Turner { 716a1405147SZachary Turner PythonObject object(PyRefType::Borrowed, py_object); 717a1405147SZachary Turner if (object.IsValid()) 718a1405147SZachary Turner SetItemAtIndex(idx, object); 719a1405147SZachary Turner idx++; 720a1405147SZachary Turner } 721a1405147SZachary Turner } 722a1405147SZachary Turner 723a1405147SZachary Turner PythonTuple::~PythonTuple() 724a1405147SZachary Turner { 725a1405147SZachary Turner } 726a1405147SZachary Turner 727a1405147SZachary Turner bool 728a1405147SZachary Turner PythonTuple::Check(PyObject *py_obj) 729a1405147SZachary Turner { 730a1405147SZachary Turner if (!py_obj) 731a1405147SZachary Turner return false; 732a1405147SZachary Turner return PyTuple_Check(py_obj); 733a1405147SZachary Turner } 734a1405147SZachary Turner 735a1405147SZachary Turner void 736a1405147SZachary Turner PythonTuple::Reset(PyRefType type, PyObject *py_obj) 737a1405147SZachary Turner { 738a1405147SZachary Turner // Grab the desired reference type so that if we end up rejecting 739a1405147SZachary Turner // `py_obj` it still gets decremented if necessary. 740a1405147SZachary Turner PythonObject result(type, py_obj); 741a1405147SZachary Turner 742a1405147SZachary Turner if (!PythonTuple::Check(py_obj)) 743a1405147SZachary Turner { 744a1405147SZachary Turner PythonObject::Reset(); 745a1405147SZachary Turner return; 746a1405147SZachary Turner } 747a1405147SZachary Turner 748a1405147SZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls 749a1405147SZachary Turner // back into the virtual implementation. 750a1405147SZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 751a1405147SZachary Turner } 752a1405147SZachary Turner 753a1405147SZachary Turner uint32_t 754a1405147SZachary Turner PythonTuple::GetSize() const 755a1405147SZachary Turner { 756a1405147SZachary Turner if (IsValid()) 757a1405147SZachary Turner return PyTuple_GET_SIZE(m_py_obj); 758a1405147SZachary Turner return 0; 759a1405147SZachary Turner } 760a1405147SZachary Turner 761a1405147SZachary Turner PythonObject 762a1405147SZachary Turner PythonTuple::GetItemAtIndex(uint32_t index) const 763a1405147SZachary Turner { 764a1405147SZachary Turner if (IsValid()) 765a1405147SZachary Turner return PythonObject(PyRefType::Borrowed, PyTuple_GetItem(m_py_obj, index)); 766a1405147SZachary Turner return PythonObject(); 767a1405147SZachary Turner } 768a1405147SZachary Turner 769a1405147SZachary Turner void 770a1405147SZachary Turner PythonTuple::SetItemAtIndex(uint32_t index, const PythonObject &object) 771a1405147SZachary Turner { 772a1405147SZachary Turner if (IsAllocated() && object.IsValid()) 773a1405147SZachary Turner { 774a1405147SZachary Turner // PyTuple_SetItem is documented to "steal" a reference, so we need to 775a1405147SZachary Turner // convert it to an owned reference by incrementing it. 776a1405147SZachary Turner Py_INCREF(object.get()); 777a1405147SZachary Turner PyTuple_SetItem(m_py_obj, index, object.get()); 778a1405147SZachary Turner } 779a1405147SZachary Turner } 780a1405147SZachary Turner 781a1405147SZachary Turner StructuredData::ArraySP 782a1405147SZachary Turner PythonTuple::CreateStructuredArray() const 783a1405147SZachary Turner { 784a1405147SZachary Turner StructuredData::ArraySP result(new StructuredData::Array); 785a1405147SZachary Turner uint32_t count = GetSize(); 786a1405147SZachary Turner for (uint32_t i = 0; i < count; ++i) 787a1405147SZachary Turner { 788a1405147SZachary Turner PythonObject obj = GetItemAtIndex(i); 789a1405147SZachary Turner result->AddItem(obj.CreateStructuredObject()); 790a1405147SZachary Turner } 791a1405147SZachary Turner return result; 792a1405147SZachary Turner } 793a1405147SZachary Turner 794a1405147SZachary Turner //---------------------------------------------------------------------- 7952c1f46dcSZachary Turner // PythonDictionary 7962c1f46dcSZachary Turner //---------------------------------------------------------------------- 7972c1f46dcSZachary Turner 798f8b22f8fSZachary Turner PythonDictionary::PythonDictionary(PyInitialValue value) 799f8b22f8fSZachary Turner : PythonObject() 8002c1f46dcSZachary Turner { 801f8b22f8fSZachary Turner if (value == PyInitialValue::Empty) 802f8b22f8fSZachary Turner Reset(PyRefType::Owned, PyDict_New()); 8032c1f46dcSZachary Turner } 8042c1f46dcSZachary Turner 805f8b22f8fSZachary Turner PythonDictionary::PythonDictionary(PyRefType type, PyObject *py_obj) 806f8b22f8fSZachary Turner : PythonObject() 8072c1f46dcSZachary Turner { 808f8b22f8fSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a dictionary 8092c1f46dcSZachary Turner } 8102c1f46dcSZachary Turner 811f8b22f8fSZachary Turner PythonDictionary::PythonDictionary(const PythonDictionary &object) 812f8b22f8fSZachary Turner : PythonObject(object) 8132c1f46dcSZachary Turner { 8142c1f46dcSZachary Turner } 8152c1f46dcSZachary Turner 8162c1f46dcSZachary Turner PythonDictionary::~PythonDictionary () 8172c1f46dcSZachary Turner { 8182c1f46dcSZachary Turner } 8192c1f46dcSZachary Turner 8202c1f46dcSZachary Turner bool 82122c8efcdSZachary Turner PythonDictionary::Check(PyObject *py_obj) 82222c8efcdSZachary Turner { 82322c8efcdSZachary Turner if (!py_obj) 82422c8efcdSZachary Turner return false; 82522c8efcdSZachary Turner 82622c8efcdSZachary Turner return PyDict_Check(py_obj); 82722c8efcdSZachary Turner } 82822c8efcdSZachary Turner 829f8b22f8fSZachary Turner void 830f8b22f8fSZachary Turner PythonDictionary::Reset(PyRefType type, PyObject *py_obj) 8312c1f46dcSZachary Turner { 832f8b22f8fSZachary Turner // Grab the desired reference type so that if we end up rejecting 833f8b22f8fSZachary Turner // `py_obj` it still gets decremented if necessary. 834f8b22f8fSZachary Turner PythonObject result(type, py_obj); 835f8b22f8fSZachary Turner 83622c8efcdSZachary Turner if (!PythonDictionary::Check(py_obj)) 83722c8efcdSZachary Turner { 838f8b22f8fSZachary Turner PythonObject::Reset(); 839f8b22f8fSZachary Turner return; 84022c8efcdSZachary Turner } 84122c8efcdSZachary Turner 842f8b22f8fSZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls 843f8b22f8fSZachary Turner // back into the virtual implementation. 844f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 8452c1f46dcSZachary Turner } 8462c1f46dcSZachary Turner 8472c1f46dcSZachary Turner uint32_t 8482c1f46dcSZachary Turner PythonDictionary::GetSize() const 8492c1f46dcSZachary Turner { 850f8b22f8fSZachary Turner if (IsValid()) 8512c1f46dcSZachary Turner return PyDict_Size(m_py_obj); 8522c1f46dcSZachary Turner return 0; 8532c1f46dcSZachary Turner } 8542c1f46dcSZachary Turner 8552c1f46dcSZachary Turner PythonList 8562c1f46dcSZachary Turner PythonDictionary::GetKeys() const 8572c1f46dcSZachary Turner { 858f8b22f8fSZachary Turner if (IsValid()) 859f8b22f8fSZachary Turner return PythonList(PyRefType::Owned, PyDict_Keys(m_py_obj)); 860f8b22f8fSZachary Turner return PythonList(PyInitialValue::Invalid); 8612c1f46dcSZachary Turner } 8622c1f46dcSZachary Turner 8632c1f46dcSZachary Turner PythonObject 864f8b22f8fSZachary Turner PythonDictionary::GetItemForKey(const PythonObject &key) const 8652c1f46dcSZachary Turner { 866f8b22f8fSZachary Turner if (IsAllocated() && key.IsValid()) 867f8b22f8fSZachary Turner return PythonObject(PyRefType::Borrowed, PyDict_GetItem(m_py_obj, key.get())); 8682c1f46dcSZachary Turner return PythonObject(); 8692c1f46dcSZachary Turner } 8702c1f46dcSZachary Turner 8712c1f46dcSZachary Turner void 872f8b22f8fSZachary Turner PythonDictionary::SetItemForKey(const PythonObject &key, const PythonObject &value) 8732c1f46dcSZachary Turner { 874f8b22f8fSZachary Turner if (IsAllocated() && key.IsValid() && value.IsValid()) 8752c1f46dcSZachary Turner PyDict_SetItem(m_py_obj, key.get(), value.get()); 8762c1f46dcSZachary Turner } 8772c1f46dcSZachary Turner 8782c1f46dcSZachary Turner StructuredData::DictionarySP 8792c1f46dcSZachary Turner PythonDictionary::CreateStructuredDictionary() const 8802c1f46dcSZachary Turner { 8812c1f46dcSZachary Turner StructuredData::DictionarySP result(new StructuredData::Dictionary); 8822c1f46dcSZachary Turner PythonList keys(GetKeys()); 8832c1f46dcSZachary Turner uint32_t num_keys = keys.GetSize(); 8842c1f46dcSZachary Turner for (uint32_t i = 0; i < num_keys; ++i) 8852c1f46dcSZachary Turner { 8862c1f46dcSZachary Turner PythonObject key = keys.GetItemAtIndex(i); 8872c1f46dcSZachary Turner PythonObject value = GetItemForKey(key); 8882c1f46dcSZachary Turner StructuredData::ObjectSP structured_value = value.CreateStructuredObject(); 889f8b22f8fSZachary Turner result->AddItem(key.Str().GetString(), structured_value); 8902c1f46dcSZachary Turner } 8912c1f46dcSZachary Turner return result; 8922c1f46dcSZachary Turner } 8932c1f46dcSZachary Turner 8947841efbbSZachary Turner PythonModule::PythonModule() : PythonObject() 8957841efbbSZachary Turner { 8967841efbbSZachary Turner } 8977841efbbSZachary Turner 8987841efbbSZachary Turner PythonModule::PythonModule(PyRefType type, PyObject *py_obj) 8997841efbbSZachary Turner { 9007841efbbSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a module 9017841efbbSZachary Turner } 9027841efbbSZachary Turner 9037841efbbSZachary Turner PythonModule::PythonModule(const PythonModule &dict) : PythonObject(dict) 9047841efbbSZachary Turner { 9057841efbbSZachary Turner } 9067841efbbSZachary Turner 9077841efbbSZachary Turner PythonModule::~PythonModule() 9087841efbbSZachary Turner { 9097841efbbSZachary Turner } 9107841efbbSZachary Turner 9117841efbbSZachary Turner PythonModule 912a1405147SZachary Turner PythonModule::BuiltinsModule() 913a1405147SZachary Turner { 914a1405147SZachary Turner #if PY_MAJOR_VERSION >= 3 915a1405147SZachary Turner return AddModule("builtins"); 916a1405147SZachary Turner #else 917a1405147SZachary Turner return AddModule("__builtin__"); 918a1405147SZachary Turner #endif 919a1405147SZachary Turner } 920a1405147SZachary Turner 921a1405147SZachary Turner PythonModule 9227841efbbSZachary Turner PythonModule::MainModule() 9237841efbbSZachary Turner { 924a1405147SZachary Turner return AddModule("__main__"); 925a1405147SZachary Turner } 926a1405147SZachary Turner 927a1405147SZachary Turner PythonModule 928a1405147SZachary Turner PythonModule::AddModule(llvm::StringRef module) 929a1405147SZachary Turner { 930a1405147SZachary Turner std::string str = module.str(); 931a1405147SZachary Turner return PythonModule(PyRefType::Borrowed, PyImport_AddModule(str.c_str())); 9327841efbbSZachary Turner } 9337841efbbSZachary Turner 9342419f1d5SZachary Turner 9352419f1d5SZachary Turner PythonModule 9362419f1d5SZachary Turner PythonModule::ImportModule(llvm::StringRef module) 9372419f1d5SZachary Turner { 9382419f1d5SZachary Turner std::string str = module.str(); 9392419f1d5SZachary Turner return PythonModule(PyRefType::Owned, PyImport_ImportModule(str.c_str())); 9402419f1d5SZachary Turner } 9412419f1d5SZachary Turner 9427841efbbSZachary Turner bool 9437841efbbSZachary Turner PythonModule::Check(PyObject *py_obj) 9447841efbbSZachary Turner { 9457841efbbSZachary Turner if (!py_obj) 9467841efbbSZachary Turner return false; 9477841efbbSZachary Turner 9487841efbbSZachary Turner return PyModule_Check(py_obj); 9497841efbbSZachary Turner } 9507841efbbSZachary Turner 9517841efbbSZachary Turner void 9527841efbbSZachary Turner PythonModule::Reset(PyRefType type, PyObject *py_obj) 9537841efbbSZachary Turner { 9547841efbbSZachary Turner // Grab the desired reference type so that if we end up rejecting 9557841efbbSZachary Turner // `py_obj` it still gets decremented if necessary. 9567841efbbSZachary Turner PythonObject result(type, py_obj); 9577841efbbSZachary Turner 9587841efbbSZachary Turner if (!PythonModule::Check(py_obj)) 9597841efbbSZachary Turner { 9607841efbbSZachary Turner PythonObject::Reset(); 9617841efbbSZachary Turner return; 9627841efbbSZachary Turner } 9637841efbbSZachary Turner 9647841efbbSZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls 9657841efbbSZachary Turner // back into the virtual implementation. 9667841efbbSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 9677841efbbSZachary Turner } 9687841efbbSZachary Turner 9697841efbbSZachary Turner PythonDictionary 9707841efbbSZachary Turner PythonModule::GetDictionary() const 9717841efbbSZachary Turner { 9727841efbbSZachary Turner return PythonDictionary(PyRefType::Borrowed, PyModule_GetDict(m_py_obj)); 9737841efbbSZachary Turner } 9747841efbbSZachary Turner 975a1405147SZachary Turner PythonCallable::PythonCallable() : PythonObject() 976a1405147SZachary Turner { 977a1405147SZachary Turner } 978a1405147SZachary Turner 979a1405147SZachary Turner PythonCallable::PythonCallable(PyRefType type, PyObject *py_obj) 980a1405147SZachary Turner { 981a1405147SZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a callable 982a1405147SZachary Turner } 983a1405147SZachary Turner 984a1405147SZachary Turner PythonCallable::PythonCallable(const PythonCallable &callable) 985a1405147SZachary Turner : PythonObject(callable) 986a1405147SZachary Turner { 987a1405147SZachary Turner } 988a1405147SZachary Turner 989a1405147SZachary Turner PythonCallable::~PythonCallable() 990a1405147SZachary Turner { 991a1405147SZachary Turner } 992a1405147SZachary Turner 993a1405147SZachary Turner bool 994a1405147SZachary Turner PythonCallable::Check(PyObject *py_obj) 995a1405147SZachary Turner { 996a1405147SZachary Turner if (!py_obj) 997a1405147SZachary Turner return false; 998a1405147SZachary Turner 999a1405147SZachary Turner return PyCallable_Check(py_obj); 1000a1405147SZachary Turner } 1001a1405147SZachary Turner 1002a1405147SZachary Turner void 1003a1405147SZachary Turner PythonCallable::Reset(PyRefType type, PyObject *py_obj) 1004a1405147SZachary Turner { 1005a1405147SZachary Turner // Grab the desired reference type so that if we end up rejecting 1006a1405147SZachary Turner // `py_obj` it still gets decremented if necessary. 1007a1405147SZachary Turner PythonObject result(type, py_obj); 1008a1405147SZachary Turner 1009a1405147SZachary Turner if (!PythonCallable::Check(py_obj)) 1010a1405147SZachary Turner { 1011a1405147SZachary Turner PythonObject::Reset(); 1012a1405147SZachary Turner return; 1013a1405147SZachary Turner } 1014a1405147SZachary Turner 1015a1405147SZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls 1016a1405147SZachary Turner // back into the virtual implementation. 1017a1405147SZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 1018a1405147SZachary Turner } 1019a1405147SZachary Turner 1020a1405147SZachary Turner 1021b58fb2f4SZachary Turner PythonCallable::ArgInfo 1022b58fb2f4SZachary Turner PythonCallable::GetNumArguments() const 1023a1405147SZachary Turner { 1024b58fb2f4SZachary Turner ArgInfo result = { 0, false, false }; 1025a1405147SZachary Turner if (!IsValid()) 1026b58fb2f4SZachary Turner return result; 1027a1405147SZachary Turner 1028a1405147SZachary Turner PyObject *py_func_obj = m_py_obj; 1029a1405147SZachary Turner if (PyMethod_Check(py_func_obj)) 1030a1405147SZachary Turner py_func_obj = PyMethod_GET_FUNCTION(py_func_obj); 1031a1405147SZachary Turner 1032a1405147SZachary Turner if (!py_func_obj) 1033b58fb2f4SZachary Turner return result; 1034a1405147SZachary Turner 1035a1405147SZachary Turner PyCodeObject* code = (PyCodeObject*)PyFunction_GET_CODE(py_func_obj); 1036a1405147SZachary Turner if (!code) 1037b58fb2f4SZachary Turner return result; 1038a1405147SZachary Turner 1039b58fb2f4SZachary Turner result.count = code->co_argcount; 1040b58fb2f4SZachary Turner result.has_varargs = !!(code->co_flags & CO_VARARGS); 1041b58fb2f4SZachary Turner result.has_kwargs = !!(code->co_flags & CO_VARKEYWORDS); 1042b58fb2f4SZachary Turner return result; 1043b58fb2f4SZachary Turner } 1044b58fb2f4SZachary Turner 1045b58fb2f4SZachary Turner PythonObject 1046b58fb2f4SZachary Turner PythonCallable::operator ()() 1047b58fb2f4SZachary Turner { 1048b58fb2f4SZachary Turner return PythonObject(PyRefType::Owned, 1049b58fb2f4SZachary Turner PyObject_CallObject(m_py_obj, nullptr)); 1050a1405147SZachary Turner } 1051a1405147SZachary Turner 1052a1405147SZachary Turner PythonObject 1053a1405147SZachary Turner PythonCallable::operator ()(std::initializer_list<PyObject*> args) 1054a1405147SZachary Turner { 1055a1405147SZachary Turner PythonTuple arg_tuple(args); 1056a1405147SZachary Turner return PythonObject(PyRefType::Owned, 1057a1405147SZachary Turner PyObject_CallObject(m_py_obj, arg_tuple.get())); 1058a1405147SZachary Turner } 1059a1405147SZachary Turner 1060a1405147SZachary Turner PythonObject 1061a1405147SZachary Turner PythonCallable::operator ()(std::initializer_list<PythonObject> args) 1062a1405147SZachary Turner { 1063a1405147SZachary Turner PythonTuple arg_tuple(args); 1064a1405147SZachary Turner return PythonObject(PyRefType::Owned, 1065a1405147SZachary Turner PyObject_CallObject(m_py_obj, arg_tuple.get())); 1066a1405147SZachary Turner } 1067a1405147SZachary Turner 106832064024SZachary Turner PythonFile::PythonFile() 106932064024SZachary Turner : PythonObject() 107032064024SZachary Turner { 107132064024SZachary Turner } 107232064024SZachary Turner 10739c40264fSZachary Turner PythonFile::PythonFile(File &file, const char *mode) 10749c40264fSZachary Turner { 10759c40264fSZachary Turner Reset(file, mode); 10769c40264fSZachary Turner } 10779c40264fSZachary Turner 1078eda01c31SZachary Turner PythonFile::PythonFile(const char *path, const char *mode) 1079eda01c31SZachary Turner { 1080eda01c31SZachary Turner FILE *fp = nullptr; 1081eda01c31SZachary Turner fp = fopen(path, mode); 1082eda01c31SZachary Turner lldb_private::File file(fp, true); 1083eda01c31SZachary Turner Reset(file, mode); 1084eda01c31SZachary Turner } 1085eda01c31SZachary Turner 10869c40264fSZachary Turner PythonFile::PythonFile(PyRefType type, PyObject *o) 10879c40264fSZachary Turner { 10889c40264fSZachary Turner Reset(type, o); 10899c40264fSZachary Turner } 10909c40264fSZachary Turner 10919c40264fSZachary Turner PythonFile::~PythonFile() 10929c40264fSZachary Turner { 10939c40264fSZachary Turner } 10949c40264fSZachary Turner 10959c40264fSZachary Turner bool 10969c40264fSZachary Turner PythonFile::Check(PyObject *py_obj) 10979c40264fSZachary Turner { 10989c40264fSZachary Turner #if PY_MAJOR_VERSION < 3 10999c40264fSZachary Turner return PyFile_Check(py_obj); 11009c40264fSZachary Turner #else 11019c40264fSZachary Turner // In Python 3, there is no `PyFile_Check`, and in fact PyFile is not even a 11029c40264fSZachary Turner // first-class object type anymore. `PyFile_FromFd` is just a thin wrapper 11039c40264fSZachary Turner // over `io.open()`, which returns some object derived from `io.IOBase`. 11049c40264fSZachary Turner // As a result, the only way to detect a file in Python 3 is to check whether 11059c40264fSZachary Turner // it inherits from `io.IOBase`. Since it is possible for non-files to also 11069c40264fSZachary Turner // inherit from `io.IOBase`, we additionally verify that it has the `fileno` 11079c40264fSZachary Turner // attribute, which should guarantee that it is backed by the file system. 11089c40264fSZachary Turner PythonObject io_module(PyRefType::Owned, PyImport_ImportModule("io")); 11099c40264fSZachary Turner PythonDictionary io_dict(PyRefType::Borrowed, PyModule_GetDict(io_module.get())); 11109c40264fSZachary Turner PythonObject io_base_class = io_dict.GetItemForKey(PythonString("IOBase")); 11119c40264fSZachary Turner 11129c40264fSZachary Turner PythonObject object_type(PyRefType::Owned, PyObject_Type(py_obj)); 11139c40264fSZachary Turner 11149c40264fSZachary Turner if (1 != PyObject_IsSubclass(object_type.get(), io_base_class.get())) 11159c40264fSZachary Turner return false; 11169c40264fSZachary Turner if (!object_type.HasAttribute("fileno")) 11179c40264fSZachary Turner return false; 11189c40264fSZachary Turner 11199c40264fSZachary Turner return true; 11209c40264fSZachary Turner #endif 11219c40264fSZachary Turner } 11229c40264fSZachary Turner 11239c40264fSZachary Turner void 11249c40264fSZachary Turner PythonFile::Reset(PyRefType type, PyObject *py_obj) 11259c40264fSZachary Turner { 11269c40264fSZachary Turner // Grab the desired reference type so that if we end up rejecting 11279c40264fSZachary Turner // `py_obj` it still gets decremented if necessary. 11289c40264fSZachary Turner PythonObject result(type, py_obj); 11299c40264fSZachary Turner 11309c40264fSZachary Turner if (!PythonFile::Check(py_obj)) 11319c40264fSZachary Turner { 11329c40264fSZachary Turner PythonObject::Reset(); 11339c40264fSZachary Turner return; 11349c40264fSZachary Turner } 11359c40264fSZachary Turner 11369c40264fSZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack 11379c40264fSZachary Turner // overflow since it calls back into the virtual implementation. 11389c40264fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 11399c40264fSZachary Turner } 11409c40264fSZachary Turner 11419c40264fSZachary Turner void 11429c40264fSZachary Turner PythonFile::Reset(File &file, const char *mode) 11439c40264fSZachary Turner { 114432ac147bSZachary Turner if (!file.IsValid()) 114532ac147bSZachary Turner { 114632ac147bSZachary Turner Reset(); 114732ac147bSZachary Turner return; 114832ac147bSZachary Turner } 114932ac147bSZachary Turner 11509c40264fSZachary Turner char *cmode = const_cast<char *>(mode); 11519c40264fSZachary Turner #if PY_MAJOR_VERSION >= 3 11529c40264fSZachary Turner Reset(PyRefType::Owned, 11539c40264fSZachary Turner PyFile_FromFd(file.GetDescriptor(), nullptr, cmode, -1, nullptr, "ignore", nullptr, 0)); 11549c40264fSZachary Turner #else 11559c40264fSZachary Turner // Read through the Python source, doesn't seem to modify these strings 11569c40264fSZachary Turner Reset(PyRefType::Owned, 11579c40264fSZachary Turner PyFile_FromFile(file.GetStream(), const_cast<char *>(""), cmode, nullptr)); 11589c40264fSZachary Turner #endif 11599c40264fSZachary Turner } 11609c40264fSZachary Turner 1161*744959b9SEnrico Granata uint32_t 1162*744959b9SEnrico Granata PythonFile::GetOptionsFromMode(llvm::StringRef mode) 1163*744959b9SEnrico Granata { 1164*744959b9SEnrico Granata if (mode.empty()) 1165*744959b9SEnrico Granata return 0; 1166*744959b9SEnrico Granata 1167*744959b9SEnrico Granata return llvm::StringSwitch<uint32_t>(mode.str().c_str()) 1168*744959b9SEnrico Granata .Case("r", File::eOpenOptionRead) 1169*744959b9SEnrico Granata .Case("w", File::eOpenOptionWrite) 1170*744959b9SEnrico Granata .Case("a", File::eOpenOptionAppend|File::eOpenOptionCanCreate) 1171*744959b9SEnrico Granata .Case("r+", File::eOpenOptionRead|File::eOpenOptionWrite) 1172*744959b9SEnrico Granata .Case("w+", File::eOpenOptionRead|File::eOpenOptionWrite|File::eOpenOptionCanCreate|File::eOpenOptionTruncate) 1173*744959b9SEnrico Granata .Case("a+", File::eOpenOptionRead|File::eOpenOptionWrite|File::eOpenOptionCanCreate) 1174*744959b9SEnrico Granata .Default(0); 1175*744959b9SEnrico Granata } 1176*744959b9SEnrico Granata 1177eda01c31SZachary Turner bool 1178eda01c31SZachary Turner PythonFile::GetUnderlyingFile(File &file) const 1179eda01c31SZachary Turner { 1180eda01c31SZachary Turner if (!IsValid()) 1181eda01c31SZachary Turner return false; 1182eda01c31SZachary Turner 1183eda01c31SZachary Turner file.Close(); 1184eda01c31SZachary Turner // We don't own the file descriptor returned by this function, make sure the 1185eda01c31SZachary Turner // File object knows about that. 1186eda01c31SZachary Turner file.SetDescriptor(PyObject_AsFileDescriptor(m_py_obj), false); 1187*744959b9SEnrico Granata PythonString py_mode = GetAttributeValue("mode").AsType<PythonString>(); 1188*744959b9SEnrico Granata file.SetOptions(PythonFile::GetOptionsFromMode(py_mode.GetString())); 1189eda01c31SZachary Turner return file.IsValid(); 1190eda01c31SZachary Turner } 1191eda01c31SZachary Turner 1192eda01c31SZachary Turner 11932c1f46dcSZachary Turner #endif 1194