1bcadb5a3SPavel Labath //===-- 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 10d68983e3SPavel Labath #ifdef LLDB_DISABLE_PYTHON 11d68983e3SPavel Labath 12d68983e3SPavel Labath // Python is disabled in this build 13d68983e3SPavel Labath 14d68983e3SPavel Labath #else 15d68983e3SPavel Labath 162c1f46dcSZachary Turner #include "PythonDataObjects.h" 172c1f46dcSZachary Turner #include "ScriptInterpreterPython.h" 182c1f46dcSZachary Turner 192c1f46dcSZachary Turner #include "lldb/Host/File.h" 20190fadcdSZachary Turner #include "lldb/Host/FileSystem.h" 212c1f46dcSZachary Turner #include "lldb/Interpreter/ScriptInterpreter.h" 22bf9a7730SZachary Turner #include "lldb/Utility/Stream.h" 232c1f46dcSZachary Turner 24190fadcdSZachary Turner #include "llvm/Support/ConvertUTF.h" 25190fadcdSZachary Turner 262c1f46dcSZachary Turner #include <stdio.h> 272c1f46dcSZachary Turner 28744959b9SEnrico Granata #include "llvm/ADT/StringSwitch.h" 29744959b9SEnrico Granata 302c1f46dcSZachary Turner using namespace lldb_private; 312c1f46dcSZachary Turner using namespace lldb; 322c1f46dcSZachary Turner 33b9c1b51eSKate Stone void StructuredPythonObject::Dump(Stream &s, bool pretty_print) const { 342c1f46dcSZachary Turner s << "Python Obj: 0x" << GetValue(); 352c1f46dcSZachary Turner } 362c1f46dcSZachary Turner 372c1f46dcSZachary Turner //---------------------------------------------------------------------- 382c1f46dcSZachary Turner // PythonObject 392c1f46dcSZachary Turner //---------------------------------------------------------------------- 402c1f46dcSZachary Turner 41b9c1b51eSKate Stone void PythonObject::Dump(Stream &strm) const { 42b9c1b51eSKate Stone if (m_py_obj) { 432c1f46dcSZachary Turner FILE *file = ::tmpfile(); 44b9c1b51eSKate Stone if (file) { 452c1f46dcSZachary Turner ::PyObject_Print(m_py_obj, file, 0); 462c1f46dcSZachary Turner const long length = ftell(file); 47b9c1b51eSKate Stone if (length) { 482c1f46dcSZachary Turner ::rewind(file); 492c1f46dcSZachary Turner std::vector<char> file_contents(length, '\0'); 50b9c1b51eSKate Stone const size_t length_read = 51b9c1b51eSKate Stone ::fread(file_contents.data(), 1, file_contents.size(), file); 522c1f46dcSZachary Turner if (length_read > 0) 532c1f46dcSZachary Turner strm.Write(file_contents.data(), length_read); 542c1f46dcSZachary Turner } 552c1f46dcSZachary Turner ::fclose(file); 562c1f46dcSZachary Turner } 57b9c1b51eSKate Stone } else 582c1f46dcSZachary Turner strm.PutCString("NULL"); 592c1f46dcSZachary Turner } 602c1f46dcSZachary Turner 61b9c1b51eSKate Stone PyObjectType PythonObject::GetObjectType() const { 62f8b22f8fSZachary Turner if (!IsAllocated()) 632c1f46dcSZachary Turner return PyObjectType::None; 642c1f46dcSZachary Turner 657841efbbSZachary Turner if (PythonModule::Check(m_py_obj)) 667841efbbSZachary Turner return PyObjectType::Module; 6718426935SZachary Turner if (PythonList::Check(m_py_obj)) 682c1f46dcSZachary Turner return PyObjectType::List; 69a1405147SZachary Turner if (PythonTuple::Check(m_py_obj)) 70a1405147SZachary Turner return PyObjectType::Tuple; 7118426935SZachary Turner if (PythonDictionary::Check(m_py_obj)) 722c1f46dcSZachary Turner return PyObjectType::Dictionary; 7318426935SZachary Turner if (PythonString::Check(m_py_obj)) 7422c8efcdSZachary Turner return PyObjectType::String; 755a72c02bSZachary Turner #if PY_MAJOR_VERSION >= 3 765a72c02bSZachary Turner if (PythonBytes::Check(m_py_obj)) 775a72c02bSZachary Turner return PyObjectType::Bytes; 785a72c02bSZachary Turner #endif 79f9d6d204SZachary Turner if (PythonByteArray::Check(m_py_obj)) 80f9d6d204SZachary Turner return PyObjectType::ByteArray; 8118426935SZachary Turner if (PythonInteger::Check(m_py_obj)) 8222c8efcdSZachary Turner return PyObjectType::Integer; 839c40264fSZachary Turner if (PythonFile::Check(m_py_obj)) 849c40264fSZachary Turner return PyObjectType::File; 85a1405147SZachary Turner if (PythonCallable::Check(m_py_obj)) 86a1405147SZachary Turner return PyObjectType::Callable; 872c1f46dcSZachary Turner return PyObjectType::Unknown; 882c1f46dcSZachary Turner } 892c1f46dcSZachary Turner 90b9c1b51eSKate Stone PythonString PythonObject::Repr() const { 912c1f46dcSZachary Turner if (!m_py_obj) 922c1f46dcSZachary Turner return PythonString(); 932c1f46dcSZachary Turner PyObject *repr = PyObject_Repr(m_py_obj); 942c1f46dcSZachary Turner if (!repr) 952c1f46dcSZachary Turner return PythonString(); 96f8b22f8fSZachary Turner return PythonString(PyRefType::Owned, repr); 972c1f46dcSZachary Turner } 982c1f46dcSZachary Turner 99b9c1b51eSKate Stone PythonString PythonObject::Str() const { 1002c1f46dcSZachary Turner if (!m_py_obj) 1012c1f46dcSZachary Turner return PythonString(); 1022c1f46dcSZachary Turner PyObject *str = PyObject_Str(m_py_obj); 1032c1f46dcSZachary Turner if (!str) 1042c1f46dcSZachary Turner return PythonString(); 105f8b22f8fSZachary Turner return PythonString(PyRefType::Owned, str); 1062c1f46dcSZachary Turner } 1072c1f46dcSZachary Turner 1087841efbbSZachary Turner PythonObject 109b9c1b51eSKate Stone PythonObject::ResolveNameWithDictionary(llvm::StringRef name, 110b9c1b51eSKate Stone const PythonDictionary &dict) { 111a1405147SZachary Turner size_t dot_pos = name.find_first_of('.'); 112a1405147SZachary Turner llvm::StringRef piece = name.substr(0, dot_pos); 113a1405147SZachary Turner PythonObject result = dict.GetItemForKey(PythonString(piece)); 114b9c1b51eSKate Stone if (dot_pos == llvm::StringRef::npos) { 115a1405147SZachary Turner // There was no dot, we're done. 116a1405147SZachary Turner return result; 117a1405147SZachary Turner } 118a1405147SZachary Turner 119a1405147SZachary Turner // There was a dot. The remaining portion of the name should be looked up in 120a1405147SZachary Turner // the context of the object that was found in the dictionary. 121a1405147SZachary Turner return result.ResolveName(name.substr(dot_pos + 1)); 1227841efbbSZachary Turner } 1237841efbbSZachary Turner 124b9c1b51eSKate Stone PythonObject PythonObject::ResolveName(llvm::StringRef name) const { 12505097246SAdrian Prantl // Resolve the name in the context of the specified object. If, for example, 12605097246SAdrian Prantl // `this` refers to a PyModule, then this will look for `name` in this 12705097246SAdrian Prantl // module. If `this` refers to a PyType, then it will resolve `name` as an 12805097246SAdrian Prantl // attribute of that type. If `this` refers to an instance of an object, 12905097246SAdrian Prantl // then it will resolve `name` as the value of the specified field. 1307841efbbSZachary Turner // 1317841efbbSZachary Turner // This function handles dotted names so that, for example, if `m_py_obj` 13205097246SAdrian Prantl // refers to the `sys` module, and `name` == "path.append", then it will find 13305097246SAdrian Prantl // the function `sys.path.append`. 1347841efbbSZachary Turner 1357841efbbSZachary Turner size_t dot_pos = name.find_first_of('.'); 136b9c1b51eSKate Stone if (dot_pos == llvm::StringRef::npos) { 13705097246SAdrian Prantl // No dots in the name, we should be able to find the value immediately as 13805097246SAdrian Prantl // an attribute of `m_py_obj`. 1397841efbbSZachary Turner return GetAttributeValue(name); 1407841efbbSZachary Turner } 1417841efbbSZachary Turner 142b9c1b51eSKate Stone // Look up the first piece of the name, and resolve the rest as a child of 143b9c1b51eSKate Stone // that. 1447841efbbSZachary Turner PythonObject parent = ResolveName(name.substr(0, dot_pos)); 1457841efbbSZachary Turner if (!parent.IsAllocated()) 1467841efbbSZachary Turner return PythonObject(); 1477841efbbSZachary Turner 1487841efbbSZachary Turner // Tail recursion.. should be optimized by the compiler 1497841efbbSZachary Turner return parent.ResolveName(name.substr(dot_pos + 1)); 1507841efbbSZachary Turner } 1517841efbbSZachary Turner 152b9c1b51eSKate Stone bool PythonObject::HasAttribute(llvm::StringRef attr) const { 1539c40264fSZachary Turner if (!IsValid()) 1549c40264fSZachary Turner return false; 1559c40264fSZachary Turner PythonString py_attr(attr); 1569c40264fSZachary Turner return !!PyObject_HasAttr(m_py_obj, py_attr.get()); 1579c40264fSZachary Turner } 1589c40264fSZachary Turner 159b9c1b51eSKate Stone PythonObject PythonObject::GetAttributeValue(llvm::StringRef attr) const { 1607d6d218eSZachary Turner if (!IsValid()) 1617d6d218eSZachary Turner return PythonObject(); 1627d6d218eSZachary Turner 1637d6d218eSZachary Turner PythonString py_attr(attr); 1647d6d218eSZachary Turner if (!PyObject_HasAttr(m_py_obj, py_attr.get())) 1657d6d218eSZachary Turner return PythonObject(); 1667d6d218eSZachary Turner 1677d6d218eSZachary Turner return PythonObject(PyRefType::Owned, 1687d6d218eSZachary Turner PyObject_GetAttr(m_py_obj, py_attr.get())); 1697d6d218eSZachary Turner } 1707d6d218eSZachary Turner 171b9c1b51eSKate Stone bool PythonObject::IsNone() const { return m_py_obj == Py_None; } 172f8b22f8fSZachary Turner 173b9c1b51eSKate Stone bool PythonObject::IsValid() const { return m_py_obj != nullptr; } 174f8b22f8fSZachary Turner 175b9c1b51eSKate Stone bool PythonObject::IsAllocated() const { return IsValid() && !IsNone(); } 1762c1f46dcSZachary Turner 177b9c1b51eSKate Stone StructuredData::ObjectSP PythonObject::CreateStructuredObject() const { 178b9c1b51eSKate Stone switch (GetObjectType()) { 1792c1f46dcSZachary Turner case PyObjectType::Dictionary: 180b9c1b51eSKate Stone return PythonDictionary(PyRefType::Borrowed, m_py_obj) 181b9c1b51eSKate Stone .CreateStructuredDictionary(); 1822c1f46dcSZachary Turner case PyObjectType::Integer: 183b9c1b51eSKate Stone return PythonInteger(PyRefType::Borrowed, m_py_obj) 184b9c1b51eSKate Stone .CreateStructuredInteger(); 1852c1f46dcSZachary Turner case PyObjectType::List: 186f8b22f8fSZachary Turner return PythonList(PyRefType::Borrowed, m_py_obj).CreateStructuredArray(); 1872c1f46dcSZachary Turner case PyObjectType::String: 188f8b22f8fSZachary Turner return PythonString(PyRefType::Borrowed, m_py_obj).CreateStructuredString(); 1895a72c02bSZachary Turner case PyObjectType::Bytes: 1905a72c02bSZachary Turner return PythonBytes(PyRefType::Borrowed, m_py_obj).CreateStructuredString(); 191f9d6d204SZachary Turner case PyObjectType::ByteArray: 192b9c1b51eSKate Stone return PythonByteArray(PyRefType::Borrowed, m_py_obj) 193b9c1b51eSKate Stone .CreateStructuredString(); 1942c1f46dcSZachary Turner case PyObjectType::None: 1952c1f46dcSZachary Turner return StructuredData::ObjectSP(); 1962c1f46dcSZachary Turner default: 1972c1f46dcSZachary Turner return StructuredData::ObjectSP(new StructuredPythonObject(m_py_obj)); 1982c1f46dcSZachary Turner } 1992c1f46dcSZachary Turner } 2002c1f46dcSZachary Turner 2012c1f46dcSZachary Turner //---------------------------------------------------------------------- 2022c1f46dcSZachary Turner // PythonString 2032c1f46dcSZachary Turner //---------------------------------------------------------------------- 204b9c1b51eSKate Stone PythonBytes::PythonBytes() : PythonObject() {} 2055a72c02bSZachary Turner 206b9c1b51eSKate Stone PythonBytes::PythonBytes(llvm::ArrayRef<uint8_t> bytes) : PythonObject() { 2075a72c02bSZachary Turner SetBytes(bytes); 2085a72c02bSZachary Turner } 2095a72c02bSZachary Turner 210b9c1b51eSKate Stone PythonBytes::PythonBytes(const uint8_t *bytes, size_t length) : PythonObject() { 2115a72c02bSZachary Turner SetBytes(llvm::ArrayRef<uint8_t>(bytes, length)); 2125a72c02bSZachary Turner } 2135a72c02bSZachary Turner 214b9c1b51eSKate Stone PythonBytes::PythonBytes(PyRefType type, PyObject *py_obj) : PythonObject() { 2155a72c02bSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string 2165a72c02bSZachary Turner } 2175a72c02bSZachary Turner 218b9c1b51eSKate Stone PythonBytes::PythonBytes(const PythonBytes &object) : PythonObject(object) {} 2195a72c02bSZachary Turner 220b9c1b51eSKate Stone PythonBytes::~PythonBytes() {} 2215a72c02bSZachary Turner 222b9c1b51eSKate Stone bool PythonBytes::Check(PyObject *py_obj) { 2235a72c02bSZachary Turner if (!py_obj) 2245a72c02bSZachary Turner return false; 225*a6682a41SJonas Devlieghere return PyBytes_Check(py_obj); 2265a72c02bSZachary Turner } 2275a72c02bSZachary Turner 228b9c1b51eSKate Stone void PythonBytes::Reset(PyRefType type, PyObject *py_obj) { 22905097246SAdrian Prantl // Grab the desired reference type so that if we end up rejecting `py_obj` it 23005097246SAdrian Prantl // still gets decremented if necessary. 2315a72c02bSZachary Turner PythonObject result(type, py_obj); 2325a72c02bSZachary Turner 233b9c1b51eSKate Stone if (!PythonBytes::Check(py_obj)) { 2345a72c02bSZachary Turner PythonObject::Reset(); 2355a72c02bSZachary Turner return; 2365a72c02bSZachary Turner } 2375a72c02bSZachary Turner 238b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 23905097246SAdrian Prantl // overflow since it calls back into the virtual implementation. 2405a72c02bSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 2415a72c02bSZachary Turner } 2425a72c02bSZachary Turner 243b9c1b51eSKate Stone llvm::ArrayRef<uint8_t> PythonBytes::GetBytes() const { 2445a72c02bSZachary Turner if (!IsValid()) 2455a72c02bSZachary Turner return llvm::ArrayRef<uint8_t>(); 2465a72c02bSZachary Turner 2475a72c02bSZachary Turner Py_ssize_t size; 2485a72c02bSZachary Turner char *c; 2495a72c02bSZachary Turner 2505a72c02bSZachary Turner PyBytes_AsStringAndSize(m_py_obj, &c, &size); 2515a72c02bSZachary Turner return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size); 2525a72c02bSZachary Turner } 2535a72c02bSZachary Turner 254b9c1b51eSKate Stone size_t PythonBytes::GetSize() const { 2555a72c02bSZachary Turner if (!IsValid()) 2565a72c02bSZachary Turner return 0; 2575a72c02bSZachary Turner return PyBytes_Size(m_py_obj); 2585a72c02bSZachary Turner } 2595a72c02bSZachary Turner 260b9c1b51eSKate Stone void PythonBytes::SetBytes(llvm::ArrayRef<uint8_t> bytes) { 2615a72c02bSZachary Turner const char *data = reinterpret_cast<const char *>(bytes.data()); 2625a72c02bSZachary Turner PyObject *py_bytes = PyBytes_FromStringAndSize(data, bytes.size()); 2635a72c02bSZachary Turner PythonObject::Reset(PyRefType::Owned, py_bytes); 2645a72c02bSZachary Turner } 2655a72c02bSZachary Turner 266b9c1b51eSKate Stone StructuredData::StringSP PythonBytes::CreateStructuredString() const { 2675a72c02bSZachary Turner StructuredData::StringSP result(new StructuredData::String); 2685a72c02bSZachary Turner Py_ssize_t size; 2695a72c02bSZachary Turner char *c; 2705a72c02bSZachary Turner PyBytes_AsStringAndSize(m_py_obj, &c, &size); 2715a72c02bSZachary Turner result->SetValue(std::string(c, size)); 2725a72c02bSZachary Turner return result; 2735a72c02bSZachary Turner } 2745a72c02bSZachary Turner 275b9c1b51eSKate Stone PythonByteArray::PythonByteArray(llvm::ArrayRef<uint8_t> bytes) 276b9c1b51eSKate Stone : PythonByteArray(bytes.data(), bytes.size()) {} 277f9d6d204SZachary Turner 278b9c1b51eSKate Stone PythonByteArray::PythonByteArray(const uint8_t *bytes, size_t length) { 279f9d6d204SZachary Turner const char *str = reinterpret_cast<const char *>(bytes); 280f9d6d204SZachary Turner Reset(PyRefType::Owned, PyByteArray_FromStringAndSize(str, length)); 281f9d6d204SZachary Turner } 282f9d6d204SZachary Turner 283b9c1b51eSKate Stone PythonByteArray::PythonByteArray(PyRefType type, PyObject *o) { 284f9d6d204SZachary Turner Reset(type, o); 285f9d6d204SZachary Turner } 286f9d6d204SZachary Turner 287b9c1b51eSKate Stone PythonByteArray::PythonByteArray(const PythonBytes &object) 288b9c1b51eSKate Stone : PythonObject(object) {} 289f9d6d204SZachary Turner 290b9c1b51eSKate Stone PythonByteArray::~PythonByteArray() {} 291f9d6d204SZachary Turner 292b9c1b51eSKate Stone bool PythonByteArray::Check(PyObject *py_obj) { 293f9d6d204SZachary Turner if (!py_obj) 294f9d6d204SZachary Turner return false; 295*a6682a41SJonas Devlieghere return PyByteArray_Check(py_obj); 296f9d6d204SZachary Turner } 297f9d6d204SZachary Turner 298b9c1b51eSKate Stone void PythonByteArray::Reset(PyRefType type, PyObject *py_obj) { 29905097246SAdrian Prantl // Grab the desired reference type so that if we end up rejecting `py_obj` it 30005097246SAdrian Prantl // still gets decremented if necessary. 301f9d6d204SZachary Turner PythonObject result(type, py_obj); 302f9d6d204SZachary Turner 303b9c1b51eSKate Stone if (!PythonByteArray::Check(py_obj)) { 304f9d6d204SZachary Turner PythonObject::Reset(); 305f9d6d204SZachary Turner return; 306f9d6d204SZachary Turner } 307f9d6d204SZachary Turner 308b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 30905097246SAdrian Prantl // overflow since it calls back into the virtual implementation. 310f9d6d204SZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 311f9d6d204SZachary Turner } 312f9d6d204SZachary Turner 313b9c1b51eSKate Stone llvm::ArrayRef<uint8_t> PythonByteArray::GetBytes() const { 314f9d6d204SZachary Turner if (!IsValid()) 315f9d6d204SZachary Turner return llvm::ArrayRef<uint8_t>(); 316f9d6d204SZachary Turner 317f9d6d204SZachary Turner char *c = PyByteArray_AsString(m_py_obj); 318f9d6d204SZachary Turner size_t size = GetSize(); 319f9d6d204SZachary Turner return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size); 320f9d6d204SZachary Turner } 321f9d6d204SZachary Turner 322b9c1b51eSKate Stone size_t PythonByteArray::GetSize() const { 323f9d6d204SZachary Turner if (!IsValid()) 324f9d6d204SZachary Turner return 0; 325f9d6d204SZachary Turner 326f9d6d204SZachary Turner return PyByteArray_Size(m_py_obj); 327f9d6d204SZachary Turner } 328f9d6d204SZachary Turner 329b9c1b51eSKate Stone StructuredData::StringSP PythonByteArray::CreateStructuredString() const { 330f9d6d204SZachary Turner StructuredData::StringSP result(new StructuredData::String); 331f9d6d204SZachary Turner llvm::ArrayRef<uint8_t> bytes = GetBytes(); 332f9d6d204SZachary Turner const char *str = reinterpret_cast<const char *>(bytes.data()); 333f9d6d204SZachary Turner result->SetValue(std::string(str, bytes.size())); 334f9d6d204SZachary Turner return result; 335f9d6d204SZachary Turner } 336f9d6d204SZachary Turner 3375a72c02bSZachary Turner //---------------------------------------------------------------------- 3385a72c02bSZachary Turner // PythonString 3395a72c02bSZachary Turner //---------------------------------------------------------------------- 3402c1f46dcSZachary Turner 341b9c1b51eSKate Stone PythonString::PythonString(PyRefType type, PyObject *py_obj) : PythonObject() { 342f8b22f8fSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string 3432c1f46dcSZachary Turner } 3442c1f46dcSZachary Turner 345b9c1b51eSKate Stone PythonString::PythonString(const PythonString &object) : PythonObject(object) {} 3462c1f46dcSZachary Turner 347b9c1b51eSKate Stone PythonString::PythonString(llvm::StringRef string) : PythonObject() { 34822c8efcdSZachary Turner SetString(string); 3492c1f46dcSZachary Turner } 3502c1f46dcSZachary Turner 351b9c1b51eSKate Stone PythonString::PythonString(const char *string) : PythonObject() { 35222c8efcdSZachary Turner SetString(llvm::StringRef(string)); 3532c1f46dcSZachary Turner } 3542c1f46dcSZachary Turner 355b9c1b51eSKate Stone PythonString::PythonString() : PythonObject() {} 3562c1f46dcSZachary Turner 357b9c1b51eSKate Stone PythonString::~PythonString() {} 3582c1f46dcSZachary Turner 359b9c1b51eSKate Stone bool PythonString::Check(PyObject *py_obj) { 36022c8efcdSZachary Turner if (!py_obj) 36122c8efcdSZachary Turner return false; 36218426935SZachary Turner 3637d6d218eSZachary Turner if (PyUnicode_Check(py_obj)) 3647d6d218eSZachary Turner return true; 3657d6d218eSZachary Turner #if PY_MAJOR_VERSION < 3 3667d6d218eSZachary Turner if (PyString_Check(py_obj)) 3677d6d218eSZachary Turner return true; 36822c8efcdSZachary Turner #endif 3697d6d218eSZachary Turner return false; 37022c8efcdSZachary Turner } 37122c8efcdSZachary Turner 372b9c1b51eSKate Stone void PythonString::Reset(PyRefType type, PyObject *py_obj) { 37305097246SAdrian Prantl // Grab the desired reference type so that if we end up rejecting `py_obj` it 37405097246SAdrian Prantl // still gets decremented if necessary. 375f8b22f8fSZachary Turner PythonObject result(type, py_obj); 376f8b22f8fSZachary Turner 377b9c1b51eSKate Stone if (!PythonString::Check(py_obj)) { 378f8b22f8fSZachary Turner PythonObject::Reset(); 379f8b22f8fSZachary Turner return; 38022c8efcdSZachary Turner } 3817d6d218eSZachary Turner #if PY_MAJOR_VERSION < 3 3827d6d218eSZachary Turner // In Python 2, Don't store PyUnicode objects directly, because we need 3837d6d218eSZachary Turner // access to their underlying character buffers which Python 2 doesn't 3847d6d218eSZachary Turner // provide. 3857d6d218eSZachary Turner if (PyUnicode_Check(py_obj)) 3867d6d218eSZachary Turner result.Reset(PyRefType::Owned, PyUnicode_AsUTF8String(result.get())); 3877d6d218eSZachary Turner #endif 388b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 38905097246SAdrian Prantl // overflow since it calls back into the virtual implementation. 390f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 3912c1f46dcSZachary Turner } 3922c1f46dcSZachary Turner 393b9c1b51eSKate Stone llvm::StringRef PythonString::GetString() const { 39418426935SZachary Turner if (!IsValid()) 39518426935SZachary Turner return llvm::StringRef(); 39618426935SZachary Turner 39722c8efcdSZachary Turner Py_ssize_t size; 3985457b426SPavel Labath const char *data; 39918426935SZachary Turner 40018426935SZachary Turner #if PY_MAJOR_VERSION >= 3 4015457b426SPavel Labath data = PyUnicode_AsUTF8AndSize(m_py_obj, &size); 40218426935SZachary Turner #else 4035457b426SPavel Labath char *c; 40418426935SZachary Turner PyString_AsStringAndSize(m_py_obj, &c, &size); 4055457b426SPavel Labath data = c; 40618426935SZachary Turner #endif 4075457b426SPavel Labath return llvm::StringRef(data, size); 40822c8efcdSZachary Turner } 4092c1f46dcSZachary Turner 410b9c1b51eSKate Stone size_t PythonString::GetSize() const { 411b9c1b51eSKate Stone if (IsValid()) { 41218426935SZachary Turner #if PY_MAJOR_VERSION >= 3 41318426935SZachary Turner return PyUnicode_GetSize(m_py_obj); 41418426935SZachary Turner #else 41518426935SZachary Turner return PyString_Size(m_py_obj); 41618426935SZachary Turner #endif 41718426935SZachary Turner } 4182c1f46dcSZachary Turner return 0; 4192c1f46dcSZachary Turner } 4202c1f46dcSZachary Turner 421b9c1b51eSKate Stone void PythonString::SetString(llvm::StringRef string) { 42222c8efcdSZachary Turner #if PY_MAJOR_VERSION >= 3 42322c8efcdSZachary Turner PyObject *unicode = PyUnicode_FromStringAndSize(string.data(), string.size()); 42418426935SZachary Turner PythonObject::Reset(PyRefType::Owned, unicode); 42522c8efcdSZachary Turner #else 42618426935SZachary Turner PyObject *str = PyString_FromStringAndSize(string.data(), string.size()); 42718426935SZachary Turner PythonObject::Reset(PyRefType::Owned, str); 42822c8efcdSZachary Turner #endif 4292c1f46dcSZachary Turner } 4302c1f46dcSZachary Turner 431b9c1b51eSKate Stone StructuredData::StringSP PythonString::CreateStructuredString() const { 4322c1f46dcSZachary Turner StructuredData::StringSP result(new StructuredData::String); 4332c1f46dcSZachary Turner result->SetValue(GetString()); 4342c1f46dcSZachary Turner return result; 4352c1f46dcSZachary Turner } 4362c1f46dcSZachary Turner 4372c1f46dcSZachary Turner //---------------------------------------------------------------------- 4382c1f46dcSZachary Turner // PythonInteger 4392c1f46dcSZachary Turner //---------------------------------------------------------------------- 4402c1f46dcSZachary Turner 441b9c1b51eSKate Stone PythonInteger::PythonInteger() : PythonObject() {} 4427d6d218eSZachary Turner 443f8b22f8fSZachary Turner PythonInteger::PythonInteger(PyRefType type, PyObject *py_obj) 444b9c1b51eSKate Stone : PythonObject() { 445f8b22f8fSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a integer type 4462c1f46dcSZachary Turner } 4472c1f46dcSZachary Turner 448f8b22f8fSZachary Turner PythonInteger::PythonInteger(const PythonInteger &object) 449b9c1b51eSKate Stone : PythonObject(object) {} 4502c1f46dcSZachary Turner 451b9c1b51eSKate Stone PythonInteger::PythonInteger(int64_t value) : PythonObject() { 4522c1f46dcSZachary Turner SetInteger(value); 4532c1f46dcSZachary Turner } 4542c1f46dcSZachary Turner 455b9c1b51eSKate Stone PythonInteger::~PythonInteger() {} 4562c1f46dcSZachary Turner 457b9c1b51eSKate Stone bool PythonInteger::Check(PyObject *py_obj) { 45822c8efcdSZachary Turner if (!py_obj) 45922c8efcdSZachary Turner return false; 46022c8efcdSZachary Turner 46122c8efcdSZachary Turner #if PY_MAJOR_VERSION >= 3 46205097246SAdrian Prantl // Python 3 does not have PyInt_Check. There is only one type of integral 46305097246SAdrian Prantl // value, long. 46422c8efcdSZachary Turner return PyLong_Check(py_obj); 46522c8efcdSZachary Turner #else 46622c8efcdSZachary Turner return PyLong_Check(py_obj) || PyInt_Check(py_obj); 46722c8efcdSZachary Turner #endif 4682c1f46dcSZachary Turner } 4692c1f46dcSZachary Turner 470b9c1b51eSKate Stone void PythonInteger::Reset(PyRefType type, PyObject *py_obj) { 47105097246SAdrian Prantl // Grab the desired reference type so that if we end up rejecting `py_obj` it 47205097246SAdrian Prantl // still gets decremented if necessary. 473f8b22f8fSZachary Turner PythonObject result(type, py_obj); 474f8b22f8fSZachary Turner 475b9c1b51eSKate Stone if (!PythonInteger::Check(py_obj)) { 476f8b22f8fSZachary Turner PythonObject::Reset(); 477f8b22f8fSZachary Turner return; 47822c8efcdSZachary Turner } 47922c8efcdSZachary Turner 48022c8efcdSZachary Turner #if PY_MAJOR_VERSION < 3 48105097246SAdrian Prantl // Always store this as a PyLong, which makes interoperability between Python 48205097246SAdrian Prantl // 2.x and Python 3.x easier. This is only necessary in 2.x, since 3.x 48305097246SAdrian Prantl // doesn't even have a PyInt. 484b9c1b51eSKate Stone if (PyInt_Check(py_obj)) { 485f8b22f8fSZachary Turner // Since we converted the original object to a different type, the new 48605097246SAdrian Prantl // object is an owned object regardless of the ownership semantics 48705097246SAdrian Prantl // requested by the user. 488f8b22f8fSZachary Turner result.Reset(PyRefType::Owned, PyLong_FromLongLong(PyInt_AsLong(py_obj))); 48922c8efcdSZachary Turner } 49022c8efcdSZachary Turner #endif 49122c8efcdSZachary Turner 492b9c1b51eSKate Stone assert(PyLong_Check(result.get()) && 493b9c1b51eSKate Stone "Couldn't get a PyLong from this PyObject"); 49422c8efcdSZachary Turner 495b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 49605097246SAdrian Prantl // overflow since it calls back into the virtual implementation. 497f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 4982c1f46dcSZachary Turner } 4992c1f46dcSZachary Turner 500b9c1b51eSKate Stone int64_t PythonInteger::GetInteger() const { 501b9c1b51eSKate Stone if (m_py_obj) { 502b9c1b51eSKate Stone assert(PyLong_Check(m_py_obj) && 503b9c1b51eSKate Stone "PythonInteger::GetInteger has a PyObject that isn't a PyLong"); 50422c8efcdSZachary Turner 505008ec446SGreg Clayton int overflow = 0; 506008ec446SGreg Clayton int64_t result = PyLong_AsLongLongAndOverflow(m_py_obj, &overflow); 507b9c1b51eSKate Stone if (overflow != 0) { 50805097246SAdrian Prantl // We got an integer that overflows, like 18446744072853913392L we can't 50905097246SAdrian Prantl // use PyLong_AsLongLong() as it will return 0xffffffffffffffff. If we 51005097246SAdrian Prantl // use the unsigned long long it will work as expected. 511008ec446SGreg Clayton const uint64_t uval = PyLong_AsUnsignedLongLong(m_py_obj); 5124f730dc7SIlia K result = static_cast<int64_t>(uval); 513008ec446SGreg Clayton } 514008ec446SGreg Clayton return result; 5152c1f46dcSZachary Turner } 5162c1f46dcSZachary Turner return UINT64_MAX; 5172c1f46dcSZachary Turner } 5182c1f46dcSZachary Turner 519b9c1b51eSKate Stone void PythonInteger::SetInteger(int64_t value) { 520f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Owned, PyLong_FromLongLong(value)); 5212c1f46dcSZachary Turner } 5222c1f46dcSZachary Turner 523b9c1b51eSKate Stone StructuredData::IntegerSP PythonInteger::CreateStructuredInteger() const { 5242c1f46dcSZachary Turner StructuredData::IntegerSP result(new StructuredData::Integer); 5252c1f46dcSZachary Turner result->SetValue(GetInteger()); 5262c1f46dcSZachary Turner return result; 5272c1f46dcSZachary Turner } 5282c1f46dcSZachary Turner 5292c1f46dcSZachary Turner //---------------------------------------------------------------------- 5302c1f46dcSZachary Turner // PythonList 5312c1f46dcSZachary Turner //---------------------------------------------------------------------- 5322c1f46dcSZachary Turner 533b9c1b51eSKate Stone PythonList::PythonList(PyInitialValue value) : PythonObject() { 534f8b22f8fSZachary Turner if (value == PyInitialValue::Empty) 535f8b22f8fSZachary Turner Reset(PyRefType::Owned, PyList_New(0)); 5362c1f46dcSZachary Turner } 5372c1f46dcSZachary Turner 538b9c1b51eSKate Stone PythonList::PythonList(int list_size) : PythonObject() { 53987f47729SZachary Turner Reset(PyRefType::Owned, PyList_New(list_size)); 54087f47729SZachary Turner } 54187f47729SZachary Turner 542b9c1b51eSKate Stone PythonList::PythonList(PyRefType type, PyObject *py_obj) : PythonObject() { 543f8b22f8fSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a list 5442c1f46dcSZachary Turner } 5452c1f46dcSZachary Turner 546b9c1b51eSKate Stone PythonList::PythonList(const PythonList &list) : PythonObject(list) {} 5472c1f46dcSZachary Turner 548b9c1b51eSKate Stone PythonList::~PythonList() {} 5492c1f46dcSZachary Turner 550b9c1b51eSKate Stone bool PythonList::Check(PyObject *py_obj) { 55122c8efcdSZachary Turner if (!py_obj) 55222c8efcdSZachary Turner return false; 55322c8efcdSZachary Turner return PyList_Check(py_obj); 55422c8efcdSZachary Turner } 55522c8efcdSZachary Turner 556b9c1b51eSKate Stone void PythonList::Reset(PyRefType type, PyObject *py_obj) { 55705097246SAdrian Prantl // Grab the desired reference type so that if we end up rejecting `py_obj` it 55805097246SAdrian Prantl // still gets decremented if necessary. 559f8b22f8fSZachary Turner PythonObject result(type, py_obj); 560f8b22f8fSZachary Turner 561b9c1b51eSKate Stone if (!PythonList::Check(py_obj)) { 562f8b22f8fSZachary Turner PythonObject::Reset(); 563f8b22f8fSZachary Turner return; 56422c8efcdSZachary Turner } 56522c8efcdSZachary Turner 566b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 56705097246SAdrian Prantl // overflow since it calls back into the virtual implementation. 568f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 5692c1f46dcSZachary Turner } 5702c1f46dcSZachary Turner 571b9c1b51eSKate Stone uint32_t PythonList::GetSize() const { 572f8b22f8fSZachary Turner if (IsValid()) 5732c1f46dcSZachary Turner return PyList_GET_SIZE(m_py_obj); 5742c1f46dcSZachary Turner return 0; 5752c1f46dcSZachary Turner } 5762c1f46dcSZachary Turner 577b9c1b51eSKate Stone PythonObject PythonList::GetItemAtIndex(uint32_t index) const { 578f8b22f8fSZachary Turner if (IsValid()) 579f8b22f8fSZachary Turner return PythonObject(PyRefType::Borrowed, PyList_GetItem(m_py_obj, index)); 5802c1f46dcSZachary Turner return PythonObject(); 5812c1f46dcSZachary Turner } 5822c1f46dcSZachary Turner 583b9c1b51eSKate Stone void PythonList::SetItemAtIndex(uint32_t index, const PythonObject &object) { 584b9c1b51eSKate Stone if (IsAllocated() && object.IsValid()) { 585f8b22f8fSZachary Turner // PyList_SetItem is documented to "steal" a reference, so we need to 586f8b22f8fSZachary Turner // convert it to an owned reference by incrementing it. 587f8b22f8fSZachary Turner Py_INCREF(object.get()); 5882c1f46dcSZachary Turner PyList_SetItem(m_py_obj, index, object.get()); 5892c1f46dcSZachary Turner } 590f8b22f8fSZachary Turner } 5912c1f46dcSZachary Turner 592b9c1b51eSKate Stone void PythonList::AppendItem(const PythonObject &object) { 593b9c1b51eSKate Stone if (IsAllocated() && object.IsValid()) { 594f8b22f8fSZachary Turner // `PyList_Append` does *not* steal a reference, so do not call `Py_INCREF` 595f8b22f8fSZachary Turner // here like we do with `PyList_SetItem`. 5962c1f46dcSZachary Turner PyList_Append(m_py_obj, object.get()); 5972c1f46dcSZachary Turner } 598f8b22f8fSZachary Turner } 5992c1f46dcSZachary Turner 600b9c1b51eSKate Stone StructuredData::ArraySP PythonList::CreateStructuredArray() const { 6012c1f46dcSZachary Turner StructuredData::ArraySP result(new StructuredData::Array); 6022c1f46dcSZachary Turner uint32_t count = GetSize(); 603b9c1b51eSKate Stone for (uint32_t i = 0; i < count; ++i) { 6042c1f46dcSZachary Turner PythonObject obj = GetItemAtIndex(i); 6052c1f46dcSZachary Turner result->AddItem(obj.CreateStructuredObject()); 6062c1f46dcSZachary Turner } 6072c1f46dcSZachary Turner return result; 6082c1f46dcSZachary Turner } 6092c1f46dcSZachary Turner 6102c1f46dcSZachary Turner //---------------------------------------------------------------------- 611a1405147SZachary Turner // PythonTuple 612a1405147SZachary Turner //---------------------------------------------------------------------- 613a1405147SZachary Turner 614b9c1b51eSKate Stone PythonTuple::PythonTuple(PyInitialValue value) : PythonObject() { 615a1405147SZachary Turner if (value == PyInitialValue::Empty) 616a1405147SZachary Turner Reset(PyRefType::Owned, PyTuple_New(0)); 617a1405147SZachary Turner } 618a1405147SZachary Turner 619b9c1b51eSKate Stone PythonTuple::PythonTuple(int tuple_size) : PythonObject() { 620a1405147SZachary Turner Reset(PyRefType::Owned, PyTuple_New(tuple_size)); 621a1405147SZachary Turner } 622a1405147SZachary Turner 623b9c1b51eSKate Stone PythonTuple::PythonTuple(PyRefType type, PyObject *py_obj) : PythonObject() { 624a1405147SZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a tuple 625a1405147SZachary Turner } 626a1405147SZachary Turner 627b9c1b51eSKate Stone PythonTuple::PythonTuple(const PythonTuple &tuple) : PythonObject(tuple) {} 628a1405147SZachary Turner 629b9c1b51eSKate Stone PythonTuple::PythonTuple(std::initializer_list<PythonObject> objects) { 630a1405147SZachary Turner m_py_obj = PyTuple_New(objects.size()); 631a1405147SZachary Turner 632a1405147SZachary Turner uint32_t idx = 0; 633b9c1b51eSKate Stone for (auto object : objects) { 634a1405147SZachary Turner if (object.IsValid()) 635a1405147SZachary Turner SetItemAtIndex(idx, object); 636a1405147SZachary Turner idx++; 637a1405147SZachary Turner } 638a1405147SZachary Turner } 639a1405147SZachary Turner 640b9c1b51eSKate Stone PythonTuple::PythonTuple(std::initializer_list<PyObject *> objects) { 641a1405147SZachary Turner m_py_obj = PyTuple_New(objects.size()); 642a1405147SZachary Turner 643a1405147SZachary Turner uint32_t idx = 0; 644b9c1b51eSKate Stone for (auto py_object : objects) { 645a1405147SZachary Turner PythonObject object(PyRefType::Borrowed, py_object); 646a1405147SZachary Turner if (object.IsValid()) 647a1405147SZachary Turner SetItemAtIndex(idx, object); 648a1405147SZachary Turner idx++; 649a1405147SZachary Turner } 650a1405147SZachary Turner } 651a1405147SZachary Turner 652b9c1b51eSKate Stone PythonTuple::~PythonTuple() {} 653a1405147SZachary Turner 654b9c1b51eSKate Stone bool PythonTuple::Check(PyObject *py_obj) { 655a1405147SZachary Turner if (!py_obj) 656a1405147SZachary Turner return false; 657a1405147SZachary Turner return PyTuple_Check(py_obj); 658a1405147SZachary Turner } 659a1405147SZachary Turner 660b9c1b51eSKate Stone void PythonTuple::Reset(PyRefType type, PyObject *py_obj) { 66105097246SAdrian Prantl // Grab the desired reference type so that if we end up rejecting `py_obj` it 66205097246SAdrian Prantl // still gets decremented if necessary. 663a1405147SZachary Turner PythonObject result(type, py_obj); 664a1405147SZachary Turner 665b9c1b51eSKate Stone if (!PythonTuple::Check(py_obj)) { 666a1405147SZachary Turner PythonObject::Reset(); 667a1405147SZachary Turner return; 668a1405147SZachary Turner } 669a1405147SZachary Turner 670b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 67105097246SAdrian Prantl // overflow since it calls back into the virtual implementation. 672a1405147SZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 673a1405147SZachary Turner } 674a1405147SZachary Turner 675b9c1b51eSKate Stone uint32_t PythonTuple::GetSize() const { 676a1405147SZachary Turner if (IsValid()) 677a1405147SZachary Turner return PyTuple_GET_SIZE(m_py_obj); 678a1405147SZachary Turner return 0; 679a1405147SZachary Turner } 680a1405147SZachary Turner 681b9c1b51eSKate Stone PythonObject PythonTuple::GetItemAtIndex(uint32_t index) const { 682a1405147SZachary Turner if (IsValid()) 683a1405147SZachary Turner return PythonObject(PyRefType::Borrowed, PyTuple_GetItem(m_py_obj, index)); 684a1405147SZachary Turner return PythonObject(); 685a1405147SZachary Turner } 686a1405147SZachary Turner 687b9c1b51eSKate Stone void PythonTuple::SetItemAtIndex(uint32_t index, const PythonObject &object) { 688b9c1b51eSKate Stone if (IsAllocated() && object.IsValid()) { 689a1405147SZachary Turner // PyTuple_SetItem is documented to "steal" a reference, so we need to 690a1405147SZachary Turner // convert it to an owned reference by incrementing it. 691a1405147SZachary Turner Py_INCREF(object.get()); 692a1405147SZachary Turner PyTuple_SetItem(m_py_obj, index, object.get()); 693a1405147SZachary Turner } 694a1405147SZachary Turner } 695a1405147SZachary Turner 696b9c1b51eSKate Stone StructuredData::ArraySP PythonTuple::CreateStructuredArray() const { 697a1405147SZachary Turner StructuredData::ArraySP result(new StructuredData::Array); 698a1405147SZachary Turner uint32_t count = GetSize(); 699b9c1b51eSKate Stone for (uint32_t i = 0; i < count; ++i) { 700a1405147SZachary Turner PythonObject obj = GetItemAtIndex(i); 701a1405147SZachary Turner result->AddItem(obj.CreateStructuredObject()); 702a1405147SZachary Turner } 703a1405147SZachary Turner return result; 704a1405147SZachary Turner } 705a1405147SZachary Turner 706a1405147SZachary Turner //---------------------------------------------------------------------- 7072c1f46dcSZachary Turner // PythonDictionary 7082c1f46dcSZachary Turner //---------------------------------------------------------------------- 7092c1f46dcSZachary Turner 710b9c1b51eSKate Stone PythonDictionary::PythonDictionary(PyInitialValue value) : PythonObject() { 711f8b22f8fSZachary Turner if (value == PyInitialValue::Empty) 712f8b22f8fSZachary Turner Reset(PyRefType::Owned, PyDict_New()); 7132c1f46dcSZachary Turner } 7142c1f46dcSZachary Turner 715f8b22f8fSZachary Turner PythonDictionary::PythonDictionary(PyRefType type, PyObject *py_obj) 716b9c1b51eSKate Stone : PythonObject() { 717f8b22f8fSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a dictionary 7182c1f46dcSZachary Turner } 7192c1f46dcSZachary Turner 720f8b22f8fSZachary Turner PythonDictionary::PythonDictionary(const PythonDictionary &object) 721b9c1b51eSKate Stone : PythonObject(object) {} 7222c1f46dcSZachary Turner 723b9c1b51eSKate Stone PythonDictionary::~PythonDictionary() {} 7242c1f46dcSZachary Turner 725b9c1b51eSKate Stone bool PythonDictionary::Check(PyObject *py_obj) { 72622c8efcdSZachary Turner if (!py_obj) 72722c8efcdSZachary Turner return false; 72822c8efcdSZachary Turner 72922c8efcdSZachary Turner return PyDict_Check(py_obj); 73022c8efcdSZachary Turner } 73122c8efcdSZachary Turner 732b9c1b51eSKate Stone void PythonDictionary::Reset(PyRefType type, PyObject *py_obj) { 73305097246SAdrian Prantl // Grab the desired reference type so that if we end up rejecting `py_obj` it 73405097246SAdrian Prantl // still gets decremented if necessary. 735f8b22f8fSZachary Turner PythonObject result(type, py_obj); 736f8b22f8fSZachary Turner 737b9c1b51eSKate Stone if (!PythonDictionary::Check(py_obj)) { 738f8b22f8fSZachary Turner PythonObject::Reset(); 739f8b22f8fSZachary Turner return; 74022c8efcdSZachary Turner } 74122c8efcdSZachary Turner 742b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 74305097246SAdrian Prantl // overflow since it calls back into the virtual implementation. 744f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 7452c1f46dcSZachary Turner } 7462c1f46dcSZachary Turner 747b9c1b51eSKate Stone uint32_t PythonDictionary::GetSize() const { 748f8b22f8fSZachary Turner if (IsValid()) 7492c1f46dcSZachary Turner return PyDict_Size(m_py_obj); 7502c1f46dcSZachary Turner return 0; 7512c1f46dcSZachary Turner } 7522c1f46dcSZachary Turner 753b9c1b51eSKate Stone PythonList PythonDictionary::GetKeys() const { 754f8b22f8fSZachary Turner if (IsValid()) 755f8b22f8fSZachary Turner return PythonList(PyRefType::Owned, PyDict_Keys(m_py_obj)); 756f8b22f8fSZachary Turner return PythonList(PyInitialValue::Invalid); 7572c1f46dcSZachary Turner } 7582c1f46dcSZachary Turner 759b9c1b51eSKate Stone PythonObject PythonDictionary::GetItemForKey(const PythonObject &key) const { 760f8b22f8fSZachary Turner if (IsAllocated() && key.IsValid()) 761b9c1b51eSKate Stone return PythonObject(PyRefType::Borrowed, 762b9c1b51eSKate Stone PyDict_GetItem(m_py_obj, key.get())); 7632c1f46dcSZachary Turner return PythonObject(); 7642c1f46dcSZachary Turner } 7652c1f46dcSZachary Turner 766b9c1b51eSKate Stone void PythonDictionary::SetItemForKey(const PythonObject &key, 767b9c1b51eSKate Stone const PythonObject &value) { 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 773b9c1b51eSKate Stone PythonDictionary::CreateStructuredDictionary() const { 7742c1f46dcSZachary Turner StructuredData::DictionarySP result(new StructuredData::Dictionary); 7752c1f46dcSZachary Turner PythonList keys(GetKeys()); 7762c1f46dcSZachary Turner uint32_t num_keys = keys.GetSize(); 777b9c1b51eSKate Stone for (uint32_t i = 0; i < num_keys; ++i) { 7782c1f46dcSZachary Turner PythonObject key = keys.GetItemAtIndex(i); 7792c1f46dcSZachary Turner PythonObject value = GetItemForKey(key); 7802c1f46dcSZachary Turner StructuredData::ObjectSP structured_value = value.CreateStructuredObject(); 781f8b22f8fSZachary Turner result->AddItem(key.Str().GetString(), structured_value); 7822c1f46dcSZachary Turner } 7832c1f46dcSZachary Turner return result; 7842c1f46dcSZachary Turner } 7852c1f46dcSZachary Turner 786b9c1b51eSKate Stone PythonModule::PythonModule() : PythonObject() {} 7877841efbbSZachary Turner 788b9c1b51eSKate Stone PythonModule::PythonModule(PyRefType type, PyObject *py_obj) { 7897841efbbSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a module 7907841efbbSZachary Turner } 7917841efbbSZachary Turner 792b9c1b51eSKate Stone PythonModule::PythonModule(const PythonModule &dict) : PythonObject(dict) {} 7937841efbbSZachary Turner 794b9c1b51eSKate Stone PythonModule::~PythonModule() {} 7957841efbbSZachary Turner 796b9c1b51eSKate Stone PythonModule PythonModule::BuiltinsModule() { 797a1405147SZachary Turner #if PY_MAJOR_VERSION >= 3 798a1405147SZachary Turner return AddModule("builtins"); 799a1405147SZachary Turner #else 800a1405147SZachary Turner return AddModule("__builtin__"); 801a1405147SZachary Turner #endif 802a1405147SZachary Turner } 803a1405147SZachary Turner 804b9c1b51eSKate Stone PythonModule PythonModule::MainModule() { return AddModule("__main__"); } 805a1405147SZachary Turner 806b9c1b51eSKate Stone PythonModule PythonModule::AddModule(llvm::StringRef module) { 807a1405147SZachary Turner std::string str = module.str(); 808a1405147SZachary Turner return PythonModule(PyRefType::Borrowed, PyImport_AddModule(str.c_str())); 8097841efbbSZachary Turner } 8107841efbbSZachary Turner 811b9c1b51eSKate Stone PythonModule PythonModule::ImportModule(llvm::StringRef module) { 8122419f1d5SZachary Turner std::string str = module.str(); 8132419f1d5SZachary Turner return PythonModule(PyRefType::Owned, PyImport_ImportModule(str.c_str())); 8142419f1d5SZachary Turner } 8152419f1d5SZachary Turner 816b9c1b51eSKate Stone bool PythonModule::Check(PyObject *py_obj) { 8177841efbbSZachary Turner if (!py_obj) 8187841efbbSZachary Turner return false; 8197841efbbSZachary Turner 8207841efbbSZachary Turner return PyModule_Check(py_obj); 8217841efbbSZachary Turner } 8227841efbbSZachary Turner 823b9c1b51eSKate Stone void PythonModule::Reset(PyRefType type, PyObject *py_obj) { 82405097246SAdrian Prantl // Grab the desired reference type so that if we end up rejecting `py_obj` it 82505097246SAdrian Prantl // still gets decremented if necessary. 8267841efbbSZachary Turner PythonObject result(type, py_obj); 8277841efbbSZachary Turner 828b9c1b51eSKate Stone if (!PythonModule::Check(py_obj)) { 8297841efbbSZachary Turner PythonObject::Reset(); 8307841efbbSZachary Turner return; 8317841efbbSZachary Turner } 8327841efbbSZachary Turner 833b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 83405097246SAdrian Prantl // overflow since it calls back into the virtual implementation. 8357841efbbSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 8367841efbbSZachary Turner } 8377841efbbSZachary Turner 838b9c1b51eSKate Stone PythonDictionary PythonModule::GetDictionary() const { 8397841efbbSZachary Turner return PythonDictionary(PyRefType::Borrowed, PyModule_GetDict(m_py_obj)); 8407841efbbSZachary Turner } 8417841efbbSZachary Turner 842b9c1b51eSKate Stone PythonCallable::PythonCallable() : PythonObject() {} 843a1405147SZachary Turner 844b9c1b51eSKate Stone PythonCallable::PythonCallable(PyRefType type, PyObject *py_obj) { 845a1405147SZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a callable 846a1405147SZachary Turner } 847a1405147SZachary Turner 848a1405147SZachary Turner PythonCallable::PythonCallable(const PythonCallable &callable) 849b9c1b51eSKate Stone : PythonObject(callable) {} 850a1405147SZachary Turner 851b9c1b51eSKate Stone PythonCallable::~PythonCallable() {} 852a1405147SZachary Turner 853b9c1b51eSKate Stone bool PythonCallable::Check(PyObject *py_obj) { 854a1405147SZachary Turner if (!py_obj) 855a1405147SZachary Turner return false; 856a1405147SZachary Turner 857a1405147SZachary Turner return PyCallable_Check(py_obj); 858a1405147SZachary Turner } 859a1405147SZachary Turner 860b9c1b51eSKate Stone void PythonCallable::Reset(PyRefType type, PyObject *py_obj) { 86105097246SAdrian Prantl // Grab the desired reference type so that if we end up rejecting `py_obj` it 86205097246SAdrian Prantl // still gets decremented if necessary. 863a1405147SZachary Turner PythonObject result(type, py_obj); 864a1405147SZachary Turner 865b9c1b51eSKate Stone if (!PythonCallable::Check(py_obj)) { 866a1405147SZachary Turner PythonObject::Reset(); 867a1405147SZachary Turner return; 868a1405147SZachary Turner } 869a1405147SZachary Turner 870b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 87105097246SAdrian Prantl // overflow since it calls back into the virtual implementation. 872a1405147SZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 873a1405147SZachary Turner } 874a1405147SZachary Turner 875b9c1b51eSKate Stone PythonCallable::ArgInfo PythonCallable::GetNumArguments() const { 876a5d6765cSEnrico Granata ArgInfo result = {0, false, false, false}; 877a1405147SZachary Turner if (!IsValid()) 878b58fb2f4SZachary Turner return result; 879a1405147SZachary Turner 880a1405147SZachary Turner PyObject *py_func_obj = m_py_obj; 881b9c1b51eSKate Stone if (PyMethod_Check(py_func_obj)) { 882a1405147SZachary Turner py_func_obj = PyMethod_GET_FUNCTION(py_func_obj); 883a5d6765cSEnrico Granata PythonObject im_self = GetAttributeValue("im_self"); 884a5d6765cSEnrico Granata if (im_self.IsValid() && !im_self.IsNone()) 885a5d6765cSEnrico Granata result.is_bound_method = true; 886b9c1b51eSKate Stone } else { 887a5d6765cSEnrico Granata // see if this is a callable object with an __call__ method 888b9c1b51eSKate Stone if (!PyFunction_Check(py_func_obj)) { 889a5d6765cSEnrico Granata PythonObject __call__ = GetAttributeValue("__call__"); 890b9c1b51eSKate Stone if (__call__.IsValid()) { 891a5d6765cSEnrico Granata auto __callable__ = __call__.AsType<PythonCallable>(); 892b9c1b51eSKate Stone if (__callable__.IsValid()) { 893a5d6765cSEnrico Granata py_func_obj = PyMethod_GET_FUNCTION(__callable__.get()); 894a5d6765cSEnrico Granata PythonObject im_self = GetAttributeValue("im_self"); 895a5d6765cSEnrico Granata if (im_self.IsValid() && !im_self.IsNone()) 896a5d6765cSEnrico Granata result.is_bound_method = true; 897a5d6765cSEnrico Granata } 898a5d6765cSEnrico Granata } 899a5d6765cSEnrico Granata } 900a5d6765cSEnrico Granata } 901a1405147SZachary Turner 902a1405147SZachary Turner if (!py_func_obj) 903b58fb2f4SZachary Turner return result; 904a1405147SZachary Turner 905a1405147SZachary Turner PyCodeObject *code = (PyCodeObject *)PyFunction_GET_CODE(py_func_obj); 906a1405147SZachary Turner if (!code) 907b58fb2f4SZachary Turner return result; 908a1405147SZachary Turner 909b58fb2f4SZachary Turner result.count = code->co_argcount; 910b58fb2f4SZachary Turner result.has_varargs = !!(code->co_flags & CO_VARARGS); 911b58fb2f4SZachary Turner result.has_kwargs = !!(code->co_flags & CO_VARKEYWORDS); 912b58fb2f4SZachary Turner return result; 913b58fb2f4SZachary Turner } 914b58fb2f4SZachary Turner 915b9c1b51eSKate Stone PythonObject PythonCallable::operator()() { 916b9c1b51eSKate Stone return PythonObject(PyRefType::Owned, PyObject_CallObject(m_py_obj, nullptr)); 917a1405147SZachary Turner } 918a1405147SZachary Turner 919b9c1b51eSKate Stone PythonObject PythonCallable:: 920b9c1b51eSKate Stone operator()(std::initializer_list<PyObject *> args) { 921a1405147SZachary Turner PythonTuple arg_tuple(args); 922a1405147SZachary Turner return PythonObject(PyRefType::Owned, 923a1405147SZachary Turner PyObject_CallObject(m_py_obj, arg_tuple.get())); 924a1405147SZachary Turner } 925a1405147SZachary Turner 926b9c1b51eSKate Stone PythonObject PythonCallable:: 927b9c1b51eSKate Stone operator()(std::initializer_list<PythonObject> args) { 928a1405147SZachary Turner PythonTuple arg_tuple(args); 929a1405147SZachary Turner return PythonObject(PyRefType::Owned, 930a1405147SZachary Turner PyObject_CallObject(m_py_obj, arg_tuple.get())); 931a1405147SZachary Turner } 932a1405147SZachary Turner 933b9c1b51eSKate Stone PythonFile::PythonFile() : PythonObject() {} 93432064024SZachary Turner 935b9c1b51eSKate Stone PythonFile::PythonFile(File &file, const char *mode) { Reset(file, mode); } 9369c40264fSZachary Turner 937b9c1b51eSKate Stone PythonFile::PythonFile(const char *path, const char *mode) { 93850bc1ed2SJonas Devlieghere lldb_private::File file; 93950bc1ed2SJonas Devlieghere FileSystem::Instance().Open(file, FileSpec(path), GetOptionsFromMode(mode)); 940eda01c31SZachary Turner Reset(file, mode); 941eda01c31SZachary Turner } 942eda01c31SZachary Turner 943b9c1b51eSKate Stone PythonFile::PythonFile(PyRefType type, PyObject *o) { Reset(type, o); } 9449c40264fSZachary Turner 945b9c1b51eSKate Stone PythonFile::~PythonFile() {} 9469c40264fSZachary Turner 947b9c1b51eSKate Stone bool PythonFile::Check(PyObject *py_obj) { 9489c40264fSZachary Turner #if PY_MAJOR_VERSION < 3 94923502721SJason Molenda return PyFile_Check(py_obj); 95023502721SJason Molenda #else 9519c40264fSZachary Turner // In Python 3, there is no `PyFile_Check`, and in fact PyFile is not even a 9529c40264fSZachary Turner // first-class object type anymore. `PyFile_FromFd` is just a thin wrapper 95305097246SAdrian Prantl // over `io.open()`, which returns some object derived from `io.IOBase`. As a 95405097246SAdrian Prantl // result, the only way to detect a file in Python 3 is to check whether it 95505097246SAdrian Prantl // inherits from `io.IOBase`. Since it is possible for non-files to also 9569c40264fSZachary Turner // inherit from `io.IOBase`, we additionally verify that it has the `fileno` 9579c40264fSZachary Turner // attribute, which should guarantee that it is backed by the file system. 9589c40264fSZachary Turner PythonObject io_module(PyRefType::Owned, PyImport_ImportModule("io")); 959b9c1b51eSKate Stone PythonDictionary io_dict(PyRefType::Borrowed, 960b9c1b51eSKate Stone PyModule_GetDict(io_module.get())); 9619c40264fSZachary Turner PythonObject io_base_class = io_dict.GetItemForKey(PythonString("IOBase")); 9629c40264fSZachary Turner 9639c40264fSZachary Turner PythonObject object_type(PyRefType::Owned, PyObject_Type(py_obj)); 9649c40264fSZachary Turner 9659c40264fSZachary Turner if (1 != PyObject_IsSubclass(object_type.get(), io_base_class.get())) 9669c40264fSZachary Turner return false; 9679c40264fSZachary Turner if (!object_type.HasAttribute("fileno")) 9689c40264fSZachary Turner return false; 9699c40264fSZachary Turner 9709c40264fSZachary Turner return true; 97123502721SJason Molenda #endif 9729c40264fSZachary Turner } 9739c40264fSZachary Turner 974b9c1b51eSKate Stone void PythonFile::Reset(PyRefType type, PyObject *py_obj) { 97505097246SAdrian Prantl // Grab the desired reference type so that if we end up rejecting `py_obj` it 97605097246SAdrian Prantl // still gets decremented if necessary. 9779c40264fSZachary Turner PythonObject result(type, py_obj); 9789c40264fSZachary Turner 97923502721SJason Molenda if (!PythonFile::Check(py_obj)) { 9809c40264fSZachary Turner PythonObject::Reset(); 9819c40264fSZachary Turner return; 9829c40264fSZachary Turner } 9839c40264fSZachary Turner 9849c40264fSZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack 9859c40264fSZachary Turner // overflow since it calls back into the virtual implementation. 9869c40264fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 9879c40264fSZachary Turner } 9889c40264fSZachary Turner 989b9c1b51eSKate Stone void PythonFile::Reset(File &file, const char *mode) { 990b9c1b51eSKate Stone if (!file.IsValid()) { 99132ac147bSZachary Turner Reset(); 99232ac147bSZachary Turner return; 99332ac147bSZachary Turner } 99432ac147bSZachary Turner 9959c40264fSZachary Turner char *cmode = const_cast<char *>(mode); 9969c40264fSZachary Turner #if PY_MAJOR_VERSION >= 3 997b9c1b51eSKate Stone Reset(PyRefType::Owned, PyFile_FromFd(file.GetDescriptor(), nullptr, cmode, 998b9c1b51eSKate Stone -1, nullptr, "ignore", nullptr, 0)); 9999c40264fSZachary Turner #else 10009c40264fSZachary Turner // Read through the Python source, doesn't seem to modify these strings 10019c40264fSZachary Turner Reset(PyRefType::Owned, 1002b9c1b51eSKate Stone PyFile_FromFile(file.GetStream(), const_cast<char *>(""), cmode, 1003b9c1b51eSKate Stone nullptr)); 10049c40264fSZachary Turner #endif 10059c40264fSZachary Turner } 10069c40264fSZachary Turner 1007b9c1b51eSKate Stone uint32_t PythonFile::GetOptionsFromMode(llvm::StringRef mode) { 1008744959b9SEnrico Granata if (mode.empty()) 1009744959b9SEnrico Granata return 0; 1010744959b9SEnrico Granata 1011771ef6d4SMalcolm Parsons return llvm::StringSwitch<uint32_t>(mode.str()) 1012744959b9SEnrico Granata .Case("r", File::eOpenOptionRead) 1013744959b9SEnrico Granata .Case("w", File::eOpenOptionWrite) 1014b9c1b51eSKate Stone .Case("a", File::eOpenOptionWrite | File::eOpenOptionAppend | 1015b9c1b51eSKate Stone File::eOpenOptionCanCreate) 1016744959b9SEnrico Granata .Case("r+", File::eOpenOptionRead | File::eOpenOptionWrite) 1017b9c1b51eSKate Stone .Case("w+", File::eOpenOptionRead | File::eOpenOptionWrite | 1018b9c1b51eSKate Stone File::eOpenOptionCanCreate | File::eOpenOptionTruncate) 1019b9c1b51eSKate Stone .Case("a+", File::eOpenOptionRead | File::eOpenOptionWrite | 1020b9c1b51eSKate Stone File::eOpenOptionAppend | File::eOpenOptionCanCreate) 1021744959b9SEnrico Granata .Default(0); 1022744959b9SEnrico Granata } 1023744959b9SEnrico Granata 1024b9c1b51eSKate Stone bool PythonFile::GetUnderlyingFile(File &file) const { 1025eda01c31SZachary Turner if (!IsValid()) 1026eda01c31SZachary Turner return false; 1027eda01c31SZachary Turner 1028eda01c31SZachary Turner file.Close(); 1029eda01c31SZachary Turner // We don't own the file descriptor returned by this function, make sure the 1030eda01c31SZachary Turner // File object knows about that. 1031eda01c31SZachary Turner file.SetDescriptor(PyObject_AsFileDescriptor(m_py_obj), false); 1032744959b9SEnrico Granata PythonString py_mode = GetAttributeValue("mode").AsType<PythonString>(); 1033744959b9SEnrico Granata file.SetOptions(PythonFile::GetOptionsFromMode(py_mode.GetString())); 1034eda01c31SZachary Turner return file.IsValid(); 1035eda01c31SZachary Turner } 1036d68983e3SPavel Labath 1037d68983e3SPavel Labath #endif 1038