1*b9c1b51eSKate Stone //===-- PythonDataObjects.cpp ------------------------------------*- C++ 2*b9c1b51eSKate Stone //-*-===// 32c1f46dcSZachary Turner // 42c1f46dcSZachary Turner // The LLVM Compiler Infrastructure 52c1f46dcSZachary Turner // 62c1f46dcSZachary Turner // This file is distributed under the University of Illinois Open Source 72c1f46dcSZachary Turner // License. See LICENSE.TXT for details. 82c1f46dcSZachary Turner // 92c1f46dcSZachary Turner //===----------------------------------------------------------------------===// 102c1f46dcSZachary Turner 112c1f46dcSZachary Turner #ifdef LLDB_DISABLE_PYTHON 122c1f46dcSZachary Turner 132c1f46dcSZachary Turner // Python is disabled in this build 142c1f46dcSZachary Turner 152c1f46dcSZachary Turner #else 162c1f46dcSZachary Turner 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" 22190fadcdSZachary Turner #include "lldb/Host/FileSystem.h" 232c1f46dcSZachary Turner #include "lldb/Interpreter/ScriptInterpreter.h" 242c1f46dcSZachary Turner 25190fadcdSZachary Turner #include "llvm/Support/ConvertUTF.h" 26190fadcdSZachary Turner 272c1f46dcSZachary Turner #include <stdio.h> 282c1f46dcSZachary Turner 29744959b9SEnrico Granata #include "llvm/ADT/StringSwitch.h" 30744959b9SEnrico Granata 312c1f46dcSZachary Turner using namespace lldb_private; 322c1f46dcSZachary Turner using namespace lldb; 332c1f46dcSZachary Turner 34*b9c1b51eSKate Stone void StructuredPythonObject::Dump(Stream &s, bool pretty_print) const { 352c1f46dcSZachary Turner s << "Python Obj: 0x" << GetValue(); 362c1f46dcSZachary Turner } 372c1f46dcSZachary Turner 382c1f46dcSZachary Turner //---------------------------------------------------------------------- 392c1f46dcSZachary Turner // PythonObject 402c1f46dcSZachary Turner //---------------------------------------------------------------------- 412c1f46dcSZachary Turner 42*b9c1b51eSKate Stone void PythonObject::Dump(Stream &strm) const { 43*b9c1b51eSKate Stone if (m_py_obj) { 442c1f46dcSZachary Turner FILE *file = ::tmpfile(); 45*b9c1b51eSKate Stone if (file) { 462c1f46dcSZachary Turner ::PyObject_Print(m_py_obj, file, 0); 472c1f46dcSZachary Turner const long length = ftell(file); 48*b9c1b51eSKate Stone if (length) { 492c1f46dcSZachary Turner ::rewind(file); 502c1f46dcSZachary Turner std::vector<char> file_contents(length, '\0'); 51*b9c1b51eSKate Stone const size_t length_read = 52*b9c1b51eSKate Stone ::fread(file_contents.data(), 1, file_contents.size(), file); 532c1f46dcSZachary Turner if (length_read > 0) 542c1f46dcSZachary Turner strm.Write(file_contents.data(), length_read); 552c1f46dcSZachary Turner } 562c1f46dcSZachary Turner ::fclose(file); 572c1f46dcSZachary Turner } 58*b9c1b51eSKate Stone } else 592c1f46dcSZachary Turner strm.PutCString("NULL"); 602c1f46dcSZachary Turner } 612c1f46dcSZachary Turner 62*b9c1b51eSKate Stone PyObjectType PythonObject::GetObjectType() const { 63f8b22f8fSZachary Turner if (!IsAllocated()) 642c1f46dcSZachary Turner return PyObjectType::None; 652c1f46dcSZachary Turner 667841efbbSZachary Turner if (PythonModule::Check(m_py_obj)) 677841efbbSZachary Turner return PyObjectType::Module; 6818426935SZachary Turner if (PythonList::Check(m_py_obj)) 692c1f46dcSZachary Turner return PyObjectType::List; 70a1405147SZachary Turner if (PythonTuple::Check(m_py_obj)) 71a1405147SZachary Turner return PyObjectType::Tuple; 7218426935SZachary Turner if (PythonDictionary::Check(m_py_obj)) 732c1f46dcSZachary Turner return PyObjectType::Dictionary; 7418426935SZachary Turner if (PythonString::Check(m_py_obj)) 7522c8efcdSZachary Turner return PyObjectType::String; 765a72c02bSZachary Turner #if PY_MAJOR_VERSION >= 3 775a72c02bSZachary Turner if (PythonBytes::Check(m_py_obj)) 785a72c02bSZachary Turner return PyObjectType::Bytes; 795a72c02bSZachary Turner #endif 80f9d6d204SZachary Turner if (PythonByteArray::Check(m_py_obj)) 81f9d6d204SZachary Turner return PyObjectType::ByteArray; 8218426935SZachary Turner if (PythonInteger::Check(m_py_obj)) 8322c8efcdSZachary Turner return PyObjectType::Integer; 849c40264fSZachary Turner if (PythonFile::Check(m_py_obj)) 859c40264fSZachary Turner return PyObjectType::File; 86a1405147SZachary Turner if (PythonCallable::Check(m_py_obj)) 87a1405147SZachary Turner return PyObjectType::Callable; 882c1f46dcSZachary Turner return PyObjectType::Unknown; 892c1f46dcSZachary Turner } 902c1f46dcSZachary Turner 91*b9c1b51eSKate Stone PythonString PythonObject::Repr() const { 922c1f46dcSZachary Turner if (!m_py_obj) 932c1f46dcSZachary Turner return PythonString(); 942c1f46dcSZachary Turner PyObject *repr = PyObject_Repr(m_py_obj); 952c1f46dcSZachary Turner if (!repr) 962c1f46dcSZachary Turner return PythonString(); 97f8b22f8fSZachary Turner return PythonString(PyRefType::Owned, repr); 982c1f46dcSZachary Turner } 992c1f46dcSZachary Turner 100*b9c1b51eSKate Stone PythonString PythonObject::Str() const { 1012c1f46dcSZachary Turner if (!m_py_obj) 1022c1f46dcSZachary Turner return PythonString(); 1032c1f46dcSZachary Turner PyObject *str = PyObject_Str(m_py_obj); 1042c1f46dcSZachary Turner if (!str) 1052c1f46dcSZachary Turner return PythonString(); 106f8b22f8fSZachary Turner return PythonString(PyRefType::Owned, str); 1072c1f46dcSZachary Turner } 1082c1f46dcSZachary Turner 1097841efbbSZachary Turner PythonObject 110*b9c1b51eSKate Stone PythonObject::ResolveNameWithDictionary(llvm::StringRef name, 111*b9c1b51eSKate Stone const PythonDictionary &dict) { 112a1405147SZachary Turner size_t dot_pos = name.find_first_of('.'); 113a1405147SZachary Turner llvm::StringRef piece = name.substr(0, dot_pos); 114a1405147SZachary Turner PythonObject result = dict.GetItemForKey(PythonString(piece)); 115*b9c1b51eSKate Stone if (dot_pos == llvm::StringRef::npos) { 116a1405147SZachary Turner // There was no dot, we're done. 117a1405147SZachary Turner return result; 118a1405147SZachary Turner } 119a1405147SZachary Turner 120a1405147SZachary Turner // There was a dot. The remaining portion of the name should be looked up in 121a1405147SZachary Turner // the context of the object that was found in the dictionary. 122a1405147SZachary Turner return result.ResolveName(name.substr(dot_pos + 1)); 1237841efbbSZachary Turner } 1247841efbbSZachary Turner 125*b9c1b51eSKate Stone PythonObject PythonObject::ResolveName(llvm::StringRef name) const { 1267841efbbSZachary Turner // Resolve the name in the context of the specified object. If, 1277841efbbSZachary Turner // for example, `this` refers to a PyModule, then this will look for 1287841efbbSZachary Turner // `name` in this module. If `this` refers to a PyType, then it will 1297841efbbSZachary Turner // resolve `name` as an attribute of that type. If `this` refers to 1307841efbbSZachary Turner // an instance of an object, then it will resolve `name` as the value 1317841efbbSZachary Turner // of the specified field. 1327841efbbSZachary Turner // 1337841efbbSZachary Turner // This function handles dotted names so that, for example, if `m_py_obj` 1347841efbbSZachary Turner // refers to the `sys` module, and `name` == "path.append", then it 1357841efbbSZachary Turner // will find the function `sys.path.append`. 1367841efbbSZachary Turner 1377841efbbSZachary Turner size_t dot_pos = name.find_first_of('.'); 138*b9c1b51eSKate Stone if (dot_pos == llvm::StringRef::npos) { 1397841efbbSZachary Turner // No dots in the name, we should be able to find the value immediately 140a1405147SZachary Turner // as an attribute of `m_py_obj`. 1417841efbbSZachary Turner return GetAttributeValue(name); 1427841efbbSZachary Turner } 1437841efbbSZachary Turner 144*b9c1b51eSKate Stone // Look up the first piece of the name, and resolve the rest as a child of 145*b9c1b51eSKate Stone // that. 1467841efbbSZachary Turner PythonObject parent = ResolveName(name.substr(0, dot_pos)); 1477841efbbSZachary Turner if (!parent.IsAllocated()) 1487841efbbSZachary Turner return PythonObject(); 1497841efbbSZachary Turner 1507841efbbSZachary Turner // Tail recursion.. should be optimized by the compiler 1517841efbbSZachary Turner return parent.ResolveName(name.substr(dot_pos + 1)); 1527841efbbSZachary Turner } 1537841efbbSZachary Turner 154*b9c1b51eSKate Stone bool PythonObject::HasAttribute(llvm::StringRef attr) const { 1559c40264fSZachary Turner if (!IsValid()) 1569c40264fSZachary Turner return false; 1579c40264fSZachary Turner PythonString py_attr(attr); 1589c40264fSZachary Turner return !!PyObject_HasAttr(m_py_obj, py_attr.get()); 1599c40264fSZachary Turner } 1609c40264fSZachary Turner 161*b9c1b51eSKate Stone PythonObject PythonObject::GetAttributeValue(llvm::StringRef attr) const { 1627d6d218eSZachary Turner if (!IsValid()) 1637d6d218eSZachary Turner return PythonObject(); 1647d6d218eSZachary Turner 1657d6d218eSZachary Turner PythonString py_attr(attr); 1667d6d218eSZachary Turner if (!PyObject_HasAttr(m_py_obj, py_attr.get())) 1677d6d218eSZachary Turner return PythonObject(); 1687d6d218eSZachary Turner 1697d6d218eSZachary Turner return PythonObject(PyRefType::Owned, 1707d6d218eSZachary Turner PyObject_GetAttr(m_py_obj, py_attr.get())); 1717d6d218eSZachary Turner } 1727d6d218eSZachary Turner 173*b9c1b51eSKate Stone bool PythonObject::IsNone() const { return m_py_obj == Py_None; } 174f8b22f8fSZachary Turner 175*b9c1b51eSKate Stone bool PythonObject::IsValid() const { return m_py_obj != nullptr; } 176f8b22f8fSZachary Turner 177*b9c1b51eSKate Stone bool PythonObject::IsAllocated() const { return IsValid() && !IsNone(); } 1782c1f46dcSZachary Turner 179*b9c1b51eSKate Stone StructuredData::ObjectSP PythonObject::CreateStructuredObject() const { 180*b9c1b51eSKate Stone switch (GetObjectType()) { 1812c1f46dcSZachary Turner case PyObjectType::Dictionary: 182*b9c1b51eSKate Stone return PythonDictionary(PyRefType::Borrowed, m_py_obj) 183*b9c1b51eSKate Stone .CreateStructuredDictionary(); 1842c1f46dcSZachary Turner case PyObjectType::Integer: 185*b9c1b51eSKate Stone return PythonInteger(PyRefType::Borrowed, m_py_obj) 186*b9c1b51eSKate Stone .CreateStructuredInteger(); 1872c1f46dcSZachary Turner case PyObjectType::List: 188f8b22f8fSZachary Turner return PythonList(PyRefType::Borrowed, m_py_obj).CreateStructuredArray(); 1892c1f46dcSZachary Turner case PyObjectType::String: 190f8b22f8fSZachary Turner return PythonString(PyRefType::Borrowed, m_py_obj).CreateStructuredString(); 1915a72c02bSZachary Turner case PyObjectType::Bytes: 1925a72c02bSZachary Turner return PythonBytes(PyRefType::Borrowed, m_py_obj).CreateStructuredString(); 193f9d6d204SZachary Turner case PyObjectType::ByteArray: 194*b9c1b51eSKate Stone return PythonByteArray(PyRefType::Borrowed, m_py_obj) 195*b9c1b51eSKate Stone .CreateStructuredString(); 1962c1f46dcSZachary Turner case PyObjectType::None: 1972c1f46dcSZachary Turner return StructuredData::ObjectSP(); 1982c1f46dcSZachary Turner default: 1992c1f46dcSZachary Turner return StructuredData::ObjectSP(new StructuredPythonObject(m_py_obj)); 2002c1f46dcSZachary Turner } 2012c1f46dcSZachary Turner } 2022c1f46dcSZachary Turner 2032c1f46dcSZachary Turner //---------------------------------------------------------------------- 2042c1f46dcSZachary Turner // PythonString 2052c1f46dcSZachary Turner //---------------------------------------------------------------------- 206*b9c1b51eSKate Stone PythonBytes::PythonBytes() : PythonObject() {} 2075a72c02bSZachary Turner 208*b9c1b51eSKate Stone PythonBytes::PythonBytes(llvm::ArrayRef<uint8_t> bytes) : PythonObject() { 2095a72c02bSZachary Turner SetBytes(bytes); 2105a72c02bSZachary Turner } 2115a72c02bSZachary Turner 212*b9c1b51eSKate Stone PythonBytes::PythonBytes(const uint8_t *bytes, size_t length) : PythonObject() { 2135a72c02bSZachary Turner SetBytes(llvm::ArrayRef<uint8_t>(bytes, length)); 2145a72c02bSZachary Turner } 2155a72c02bSZachary Turner 216*b9c1b51eSKate Stone PythonBytes::PythonBytes(PyRefType type, PyObject *py_obj) : PythonObject() { 2175a72c02bSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string 2185a72c02bSZachary Turner } 2195a72c02bSZachary Turner 220*b9c1b51eSKate Stone PythonBytes::PythonBytes(const PythonBytes &object) : PythonObject(object) {} 2215a72c02bSZachary Turner 222*b9c1b51eSKate Stone PythonBytes::~PythonBytes() {} 2235a72c02bSZachary Turner 224*b9c1b51eSKate Stone bool PythonBytes::Check(PyObject *py_obj) { 2255a72c02bSZachary Turner if (!py_obj) 2265a72c02bSZachary Turner return false; 2275a72c02bSZachary Turner if (PyBytes_Check(py_obj)) 2285a72c02bSZachary Turner return true; 2295a72c02bSZachary Turner return false; 2305a72c02bSZachary Turner } 2315a72c02bSZachary Turner 232*b9c1b51eSKate Stone void PythonBytes::Reset(PyRefType type, PyObject *py_obj) { 2335a72c02bSZachary Turner // Grab the desired reference type so that if we end up rejecting 2345a72c02bSZachary Turner // `py_obj` it still gets decremented if necessary. 2355a72c02bSZachary Turner PythonObject result(type, py_obj); 2365a72c02bSZachary Turner 237*b9c1b51eSKate Stone if (!PythonBytes::Check(py_obj)) { 2385a72c02bSZachary Turner PythonObject::Reset(); 2395a72c02bSZachary Turner return; 2405a72c02bSZachary Turner } 2415a72c02bSZachary Turner 242*b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 243*b9c1b51eSKate Stone // overflow since it calls 2445a72c02bSZachary Turner // back into the virtual implementation. 2455a72c02bSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 2465a72c02bSZachary Turner } 2475a72c02bSZachary Turner 248*b9c1b51eSKate Stone llvm::ArrayRef<uint8_t> PythonBytes::GetBytes() const { 2495a72c02bSZachary Turner if (!IsValid()) 2505a72c02bSZachary Turner return llvm::ArrayRef<uint8_t>(); 2515a72c02bSZachary Turner 2525a72c02bSZachary Turner Py_ssize_t size; 2535a72c02bSZachary Turner char *c; 2545a72c02bSZachary Turner 2555a72c02bSZachary Turner PyBytes_AsStringAndSize(m_py_obj, &c, &size); 2565a72c02bSZachary Turner return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size); 2575a72c02bSZachary Turner } 2585a72c02bSZachary Turner 259*b9c1b51eSKate Stone size_t PythonBytes::GetSize() const { 2605a72c02bSZachary Turner if (!IsValid()) 2615a72c02bSZachary Turner return 0; 2625a72c02bSZachary Turner return PyBytes_Size(m_py_obj); 2635a72c02bSZachary Turner } 2645a72c02bSZachary Turner 265*b9c1b51eSKate Stone void PythonBytes::SetBytes(llvm::ArrayRef<uint8_t> bytes) { 2665a72c02bSZachary Turner const char *data = reinterpret_cast<const char *>(bytes.data()); 2675a72c02bSZachary Turner PyObject *py_bytes = PyBytes_FromStringAndSize(data, bytes.size()); 2685a72c02bSZachary Turner PythonObject::Reset(PyRefType::Owned, py_bytes); 2695a72c02bSZachary Turner } 2705a72c02bSZachary Turner 271*b9c1b51eSKate Stone StructuredData::StringSP PythonBytes::CreateStructuredString() const { 2725a72c02bSZachary Turner StructuredData::StringSP result(new StructuredData::String); 2735a72c02bSZachary Turner Py_ssize_t size; 2745a72c02bSZachary Turner char *c; 2755a72c02bSZachary Turner PyBytes_AsStringAndSize(m_py_obj, &c, &size); 2765a72c02bSZachary Turner result->SetValue(std::string(c, size)); 2775a72c02bSZachary Turner return result; 2785a72c02bSZachary Turner } 2795a72c02bSZachary Turner 280*b9c1b51eSKate Stone PythonByteArray::PythonByteArray(llvm::ArrayRef<uint8_t> bytes) 281*b9c1b51eSKate Stone : PythonByteArray(bytes.data(), bytes.size()) {} 282f9d6d204SZachary Turner 283*b9c1b51eSKate Stone PythonByteArray::PythonByteArray(const uint8_t *bytes, size_t length) { 284f9d6d204SZachary Turner const char *str = reinterpret_cast<const char *>(bytes); 285f9d6d204SZachary Turner Reset(PyRefType::Owned, PyByteArray_FromStringAndSize(str, length)); 286f9d6d204SZachary Turner } 287f9d6d204SZachary Turner 288*b9c1b51eSKate Stone PythonByteArray::PythonByteArray(PyRefType type, PyObject *o) { 289f9d6d204SZachary Turner Reset(type, o); 290f9d6d204SZachary Turner } 291f9d6d204SZachary Turner 292*b9c1b51eSKate Stone PythonByteArray::PythonByteArray(const PythonBytes &object) 293*b9c1b51eSKate Stone : PythonObject(object) {} 294f9d6d204SZachary Turner 295*b9c1b51eSKate Stone PythonByteArray::~PythonByteArray() {} 296f9d6d204SZachary Turner 297*b9c1b51eSKate Stone bool PythonByteArray::Check(PyObject *py_obj) { 298f9d6d204SZachary Turner if (!py_obj) 299f9d6d204SZachary Turner return false; 300f9d6d204SZachary Turner if (PyByteArray_Check(py_obj)) 301f9d6d204SZachary Turner return true; 302f9d6d204SZachary Turner return false; 303f9d6d204SZachary Turner } 304f9d6d204SZachary Turner 305*b9c1b51eSKate Stone void PythonByteArray::Reset(PyRefType type, PyObject *py_obj) { 306f9d6d204SZachary Turner // Grab the desired reference type so that if we end up rejecting 307f9d6d204SZachary Turner // `py_obj` it still gets decremented if necessary. 308f9d6d204SZachary Turner PythonObject result(type, py_obj); 309f9d6d204SZachary Turner 310*b9c1b51eSKate Stone if (!PythonByteArray::Check(py_obj)) { 311f9d6d204SZachary Turner PythonObject::Reset(); 312f9d6d204SZachary Turner return; 313f9d6d204SZachary Turner } 314f9d6d204SZachary Turner 315*b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 316*b9c1b51eSKate Stone // overflow since it calls 317f9d6d204SZachary Turner // back into the virtual implementation. 318f9d6d204SZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 319f9d6d204SZachary Turner } 320f9d6d204SZachary Turner 321*b9c1b51eSKate Stone llvm::ArrayRef<uint8_t> PythonByteArray::GetBytes() const { 322f9d6d204SZachary Turner if (!IsValid()) 323f9d6d204SZachary Turner return llvm::ArrayRef<uint8_t>(); 324f9d6d204SZachary Turner 325f9d6d204SZachary Turner char *c = PyByteArray_AsString(m_py_obj); 326f9d6d204SZachary Turner size_t size = GetSize(); 327f9d6d204SZachary Turner return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size); 328f9d6d204SZachary Turner } 329f9d6d204SZachary Turner 330*b9c1b51eSKate Stone size_t PythonByteArray::GetSize() const { 331f9d6d204SZachary Turner if (!IsValid()) 332f9d6d204SZachary Turner return 0; 333f9d6d204SZachary Turner 334f9d6d204SZachary Turner return PyByteArray_Size(m_py_obj); 335f9d6d204SZachary Turner } 336f9d6d204SZachary Turner 337*b9c1b51eSKate Stone StructuredData::StringSP PythonByteArray::CreateStructuredString() const { 338f9d6d204SZachary Turner StructuredData::StringSP result(new StructuredData::String); 339f9d6d204SZachary Turner llvm::ArrayRef<uint8_t> bytes = GetBytes(); 340f9d6d204SZachary Turner const char *str = reinterpret_cast<const char *>(bytes.data()); 341f9d6d204SZachary Turner result->SetValue(std::string(str, bytes.size())); 342f9d6d204SZachary Turner return result; 343f9d6d204SZachary Turner } 344f9d6d204SZachary Turner 3455a72c02bSZachary Turner //---------------------------------------------------------------------- 3465a72c02bSZachary Turner // PythonString 3475a72c02bSZachary Turner //---------------------------------------------------------------------- 3482c1f46dcSZachary Turner 349*b9c1b51eSKate Stone PythonString::PythonString(PyRefType type, PyObject *py_obj) : PythonObject() { 350f8b22f8fSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string 3512c1f46dcSZachary Turner } 3522c1f46dcSZachary Turner 353*b9c1b51eSKate Stone PythonString::PythonString(const PythonString &object) : PythonObject(object) {} 3542c1f46dcSZachary Turner 355*b9c1b51eSKate Stone PythonString::PythonString(llvm::StringRef string) : PythonObject() { 35622c8efcdSZachary Turner SetString(string); 3572c1f46dcSZachary Turner } 3582c1f46dcSZachary Turner 359*b9c1b51eSKate Stone PythonString::PythonString(const char *string) : PythonObject() { 36022c8efcdSZachary Turner SetString(llvm::StringRef(string)); 3612c1f46dcSZachary Turner } 3622c1f46dcSZachary Turner 363*b9c1b51eSKate Stone PythonString::PythonString() : PythonObject() {} 3642c1f46dcSZachary Turner 365*b9c1b51eSKate Stone PythonString::~PythonString() {} 3662c1f46dcSZachary Turner 367*b9c1b51eSKate Stone bool PythonString::Check(PyObject *py_obj) { 36822c8efcdSZachary Turner if (!py_obj) 36922c8efcdSZachary Turner return false; 37018426935SZachary Turner 3717d6d218eSZachary Turner if (PyUnicode_Check(py_obj)) 3727d6d218eSZachary Turner return true; 3737d6d218eSZachary Turner #if PY_MAJOR_VERSION < 3 3747d6d218eSZachary Turner if (PyString_Check(py_obj)) 3757d6d218eSZachary Turner return true; 37622c8efcdSZachary Turner #endif 3777d6d218eSZachary Turner return false; 37822c8efcdSZachary Turner } 37922c8efcdSZachary Turner 380*b9c1b51eSKate Stone void PythonString::Reset(PyRefType type, PyObject *py_obj) { 381f8b22f8fSZachary Turner // Grab the desired reference type so that if we end up rejecting 382f8b22f8fSZachary Turner // `py_obj` it still gets decremented if necessary. 383f8b22f8fSZachary Turner PythonObject result(type, py_obj); 384f8b22f8fSZachary Turner 385*b9c1b51eSKate Stone if (!PythonString::Check(py_obj)) { 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 396*b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 397*b9c1b51eSKate Stone // overflow since it calls 398f8b22f8fSZachary Turner // back into the virtual implementation. 399f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 4002c1f46dcSZachary Turner } 4012c1f46dcSZachary Turner 402*b9c1b51eSKate Stone llvm::StringRef PythonString::GetString() const { 40318426935SZachary Turner if (!IsValid()) 40418426935SZachary Turner return llvm::StringRef(); 40518426935SZachary Turner 40622c8efcdSZachary Turner Py_ssize_t size; 40722c8efcdSZachary Turner char *c; 40818426935SZachary Turner 40918426935SZachary Turner #if PY_MAJOR_VERSION >= 3 41018426935SZachary Turner c = PyUnicode_AsUTF8AndSize(m_py_obj, &size); 41118426935SZachary Turner #else 41218426935SZachary Turner PyString_AsStringAndSize(m_py_obj, &c, &size); 41318426935SZachary Turner #endif 41422c8efcdSZachary Turner return llvm::StringRef(c, size); 41522c8efcdSZachary Turner } 4162c1f46dcSZachary Turner 417*b9c1b51eSKate Stone size_t PythonString::GetSize() const { 418*b9c1b51eSKate Stone if (IsValid()) { 41918426935SZachary Turner #if PY_MAJOR_VERSION >= 3 42018426935SZachary Turner return PyUnicode_GetSize(m_py_obj); 42118426935SZachary Turner #else 42218426935SZachary Turner return PyString_Size(m_py_obj); 42318426935SZachary Turner #endif 42418426935SZachary Turner } 4252c1f46dcSZachary Turner return 0; 4262c1f46dcSZachary Turner } 4272c1f46dcSZachary Turner 428*b9c1b51eSKate Stone void PythonString::SetString(llvm::StringRef string) { 42922c8efcdSZachary Turner #if PY_MAJOR_VERSION >= 3 43022c8efcdSZachary Turner PyObject *unicode = PyUnicode_FromStringAndSize(string.data(), string.size()); 43118426935SZachary Turner PythonObject::Reset(PyRefType::Owned, unicode); 43222c8efcdSZachary Turner #else 43318426935SZachary Turner PyObject *str = PyString_FromStringAndSize(string.data(), string.size()); 43418426935SZachary Turner PythonObject::Reset(PyRefType::Owned, str); 43522c8efcdSZachary Turner #endif 4362c1f46dcSZachary Turner } 4372c1f46dcSZachary Turner 438*b9c1b51eSKate Stone StructuredData::StringSP PythonString::CreateStructuredString() const { 4392c1f46dcSZachary Turner StructuredData::StringSP result(new StructuredData::String); 4402c1f46dcSZachary Turner result->SetValue(GetString()); 4412c1f46dcSZachary Turner return result; 4422c1f46dcSZachary Turner } 4432c1f46dcSZachary Turner 4442c1f46dcSZachary Turner //---------------------------------------------------------------------- 4452c1f46dcSZachary Turner // PythonInteger 4462c1f46dcSZachary Turner //---------------------------------------------------------------------- 4472c1f46dcSZachary Turner 448*b9c1b51eSKate Stone PythonInteger::PythonInteger() : PythonObject() {} 4497d6d218eSZachary Turner 450f8b22f8fSZachary Turner PythonInteger::PythonInteger(PyRefType type, PyObject *py_obj) 451*b9c1b51eSKate Stone : PythonObject() { 452f8b22f8fSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a integer type 4532c1f46dcSZachary Turner } 4542c1f46dcSZachary Turner 455f8b22f8fSZachary Turner PythonInteger::PythonInteger(const PythonInteger &object) 456*b9c1b51eSKate Stone : PythonObject(object) {} 4572c1f46dcSZachary Turner 458*b9c1b51eSKate Stone PythonInteger::PythonInteger(int64_t value) : PythonObject() { 4592c1f46dcSZachary Turner SetInteger(value); 4602c1f46dcSZachary Turner } 4612c1f46dcSZachary Turner 462*b9c1b51eSKate Stone PythonInteger::~PythonInteger() {} 4632c1f46dcSZachary Turner 464*b9c1b51eSKate Stone bool PythonInteger::Check(PyObject *py_obj) { 46522c8efcdSZachary Turner if (!py_obj) 46622c8efcdSZachary Turner return false; 46722c8efcdSZachary Turner 46822c8efcdSZachary Turner #if PY_MAJOR_VERSION >= 3 46922c8efcdSZachary Turner // Python 3 does not have PyInt_Check. There is only one type of 47022c8efcdSZachary Turner // integral value, long. 47122c8efcdSZachary Turner return PyLong_Check(py_obj); 47222c8efcdSZachary Turner #else 47322c8efcdSZachary Turner return PyLong_Check(py_obj) || PyInt_Check(py_obj); 47422c8efcdSZachary Turner #endif 4752c1f46dcSZachary Turner } 4762c1f46dcSZachary Turner 477*b9c1b51eSKate Stone void PythonInteger::Reset(PyRefType type, PyObject *py_obj) { 478f8b22f8fSZachary Turner // Grab the desired reference type so that if we end up rejecting 479f8b22f8fSZachary Turner // `py_obj` it still gets decremented if necessary. 480f8b22f8fSZachary Turner PythonObject result(type, py_obj); 481f8b22f8fSZachary Turner 482*b9c1b51eSKate Stone if (!PythonInteger::Check(py_obj)) { 483f8b22f8fSZachary Turner PythonObject::Reset(); 484f8b22f8fSZachary Turner return; 48522c8efcdSZachary Turner } 48622c8efcdSZachary Turner 48722c8efcdSZachary Turner #if PY_MAJOR_VERSION < 3 48822c8efcdSZachary Turner // Always store this as a PyLong, which makes interoperability between 48922c8efcdSZachary Turner // Python 2.x and Python 3.x easier. This is only necessary in 2.x, 49022c8efcdSZachary Turner // since 3.x doesn't even have a PyInt. 491*b9c1b51eSKate Stone if (PyInt_Check(py_obj)) { 492f8b22f8fSZachary Turner // Since we converted the original object to a different type, the new 493f8b22f8fSZachary Turner // object is an owned object regardless of the ownership semantics requested 494f8b22f8fSZachary Turner // by the user. 495f8b22f8fSZachary Turner result.Reset(PyRefType::Owned, PyLong_FromLongLong(PyInt_AsLong(py_obj))); 49622c8efcdSZachary Turner } 49722c8efcdSZachary Turner #endif 49822c8efcdSZachary Turner 499*b9c1b51eSKate Stone assert(PyLong_Check(result.get()) && 500*b9c1b51eSKate Stone "Couldn't get a PyLong from this PyObject"); 50122c8efcdSZachary Turner 502*b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 503*b9c1b51eSKate Stone // overflow since it calls 504f8b22f8fSZachary Turner // back into the virtual implementation. 505f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 5062c1f46dcSZachary Turner } 5072c1f46dcSZachary Turner 508*b9c1b51eSKate Stone int64_t PythonInteger::GetInteger() const { 509*b9c1b51eSKate Stone if (m_py_obj) { 510*b9c1b51eSKate Stone assert(PyLong_Check(m_py_obj) && 511*b9c1b51eSKate Stone "PythonInteger::GetInteger has a PyObject that isn't a PyLong"); 51222c8efcdSZachary Turner 513008ec446SGreg Clayton int overflow = 0; 514008ec446SGreg Clayton int64_t result = PyLong_AsLongLongAndOverflow(m_py_obj, &overflow); 515*b9c1b51eSKate Stone if (overflow != 0) { 516008ec446SGreg Clayton // We got an integer that overflows, like 18446744072853913392L 517008ec446SGreg Clayton // we can't use PyLong_AsLongLong() as it will return 518008ec446SGreg Clayton // 0xffffffffffffffff. If we use the unsigned long long 519008ec446SGreg Clayton // it will work as expected. 520008ec446SGreg Clayton const uint64_t uval = PyLong_AsUnsignedLongLong(m_py_obj); 521008ec446SGreg Clayton result = *((int64_t *)&uval); 522008ec446SGreg Clayton } 523008ec446SGreg Clayton return result; 5242c1f46dcSZachary Turner } 5252c1f46dcSZachary Turner return UINT64_MAX; 5262c1f46dcSZachary Turner } 5272c1f46dcSZachary Turner 528*b9c1b51eSKate Stone void PythonInteger::SetInteger(int64_t value) { 529f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Owned, PyLong_FromLongLong(value)); 5302c1f46dcSZachary Turner } 5312c1f46dcSZachary Turner 532*b9c1b51eSKate Stone StructuredData::IntegerSP PythonInteger::CreateStructuredInteger() const { 5332c1f46dcSZachary Turner StructuredData::IntegerSP result(new StructuredData::Integer); 5342c1f46dcSZachary Turner result->SetValue(GetInteger()); 5352c1f46dcSZachary Turner return result; 5362c1f46dcSZachary Turner } 5372c1f46dcSZachary Turner 5382c1f46dcSZachary Turner //---------------------------------------------------------------------- 5392c1f46dcSZachary Turner // PythonList 5402c1f46dcSZachary Turner //---------------------------------------------------------------------- 5412c1f46dcSZachary Turner 542*b9c1b51eSKate Stone PythonList::PythonList(PyInitialValue value) : PythonObject() { 543f8b22f8fSZachary Turner if (value == PyInitialValue::Empty) 544f8b22f8fSZachary Turner Reset(PyRefType::Owned, PyList_New(0)); 5452c1f46dcSZachary Turner } 5462c1f46dcSZachary Turner 547*b9c1b51eSKate Stone PythonList::PythonList(int list_size) : PythonObject() { 54887f47729SZachary Turner Reset(PyRefType::Owned, PyList_New(list_size)); 54987f47729SZachary Turner } 55087f47729SZachary Turner 551*b9c1b51eSKate Stone PythonList::PythonList(PyRefType type, PyObject *py_obj) : PythonObject() { 552f8b22f8fSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a list 5532c1f46dcSZachary Turner } 5542c1f46dcSZachary Turner 555*b9c1b51eSKate Stone PythonList::PythonList(const PythonList &list) : PythonObject(list) {} 5562c1f46dcSZachary Turner 557*b9c1b51eSKate Stone PythonList::~PythonList() {} 5582c1f46dcSZachary Turner 559*b9c1b51eSKate Stone bool PythonList::Check(PyObject *py_obj) { 56022c8efcdSZachary Turner if (!py_obj) 56122c8efcdSZachary Turner return false; 56222c8efcdSZachary Turner return PyList_Check(py_obj); 56322c8efcdSZachary Turner } 56422c8efcdSZachary Turner 565*b9c1b51eSKate Stone void PythonList::Reset(PyRefType type, PyObject *py_obj) { 566f8b22f8fSZachary Turner // Grab the desired reference type so that if we end up rejecting 567f8b22f8fSZachary Turner // `py_obj` it still gets decremented if necessary. 568f8b22f8fSZachary Turner PythonObject result(type, py_obj); 569f8b22f8fSZachary Turner 570*b9c1b51eSKate Stone if (!PythonList::Check(py_obj)) { 571f8b22f8fSZachary Turner PythonObject::Reset(); 572f8b22f8fSZachary Turner return; 57322c8efcdSZachary Turner } 57422c8efcdSZachary Turner 575*b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 576*b9c1b51eSKate Stone // overflow since it calls 577f8b22f8fSZachary Turner // back into the virtual implementation. 578f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 5792c1f46dcSZachary Turner } 5802c1f46dcSZachary Turner 581*b9c1b51eSKate Stone uint32_t PythonList::GetSize() const { 582f8b22f8fSZachary Turner if (IsValid()) 5832c1f46dcSZachary Turner return PyList_GET_SIZE(m_py_obj); 5842c1f46dcSZachary Turner return 0; 5852c1f46dcSZachary Turner } 5862c1f46dcSZachary Turner 587*b9c1b51eSKate Stone PythonObject PythonList::GetItemAtIndex(uint32_t index) const { 588f8b22f8fSZachary Turner if (IsValid()) 589f8b22f8fSZachary Turner return PythonObject(PyRefType::Borrowed, PyList_GetItem(m_py_obj, index)); 5902c1f46dcSZachary Turner return PythonObject(); 5912c1f46dcSZachary Turner } 5922c1f46dcSZachary Turner 593*b9c1b51eSKate Stone void PythonList::SetItemAtIndex(uint32_t index, const PythonObject &object) { 594*b9c1b51eSKate Stone if (IsAllocated() && object.IsValid()) { 595f8b22f8fSZachary Turner // PyList_SetItem is documented to "steal" a reference, so we need to 596f8b22f8fSZachary Turner // convert it to an owned reference by incrementing it. 597f8b22f8fSZachary Turner Py_INCREF(object.get()); 5982c1f46dcSZachary Turner PyList_SetItem(m_py_obj, index, object.get()); 5992c1f46dcSZachary Turner } 600f8b22f8fSZachary Turner } 6012c1f46dcSZachary Turner 602*b9c1b51eSKate Stone void PythonList::AppendItem(const PythonObject &object) { 603*b9c1b51eSKate Stone if (IsAllocated() && object.IsValid()) { 604f8b22f8fSZachary Turner // `PyList_Append` does *not* steal a reference, so do not call `Py_INCREF` 605f8b22f8fSZachary Turner // here like we do with `PyList_SetItem`. 6062c1f46dcSZachary Turner PyList_Append(m_py_obj, object.get()); 6072c1f46dcSZachary Turner } 608f8b22f8fSZachary Turner } 6092c1f46dcSZachary Turner 610*b9c1b51eSKate Stone StructuredData::ArraySP PythonList::CreateStructuredArray() const { 6112c1f46dcSZachary Turner StructuredData::ArraySP result(new StructuredData::Array); 6122c1f46dcSZachary Turner uint32_t count = GetSize(); 613*b9c1b51eSKate Stone for (uint32_t i = 0; i < count; ++i) { 6142c1f46dcSZachary Turner PythonObject obj = GetItemAtIndex(i); 6152c1f46dcSZachary Turner result->AddItem(obj.CreateStructuredObject()); 6162c1f46dcSZachary Turner } 6172c1f46dcSZachary Turner return result; 6182c1f46dcSZachary Turner } 6192c1f46dcSZachary Turner 6202c1f46dcSZachary Turner //---------------------------------------------------------------------- 621a1405147SZachary Turner // PythonTuple 622a1405147SZachary Turner //---------------------------------------------------------------------- 623a1405147SZachary Turner 624*b9c1b51eSKate Stone PythonTuple::PythonTuple(PyInitialValue value) : PythonObject() { 625a1405147SZachary Turner if (value == PyInitialValue::Empty) 626a1405147SZachary Turner Reset(PyRefType::Owned, PyTuple_New(0)); 627a1405147SZachary Turner } 628a1405147SZachary Turner 629*b9c1b51eSKate Stone PythonTuple::PythonTuple(int tuple_size) : PythonObject() { 630a1405147SZachary Turner Reset(PyRefType::Owned, PyTuple_New(tuple_size)); 631a1405147SZachary Turner } 632a1405147SZachary Turner 633*b9c1b51eSKate Stone PythonTuple::PythonTuple(PyRefType type, PyObject *py_obj) : PythonObject() { 634a1405147SZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a tuple 635a1405147SZachary Turner } 636a1405147SZachary Turner 637*b9c1b51eSKate Stone PythonTuple::PythonTuple(const PythonTuple &tuple) : PythonObject(tuple) {} 638a1405147SZachary Turner 639*b9c1b51eSKate Stone PythonTuple::PythonTuple(std::initializer_list<PythonObject> objects) { 640a1405147SZachary Turner m_py_obj = PyTuple_New(objects.size()); 641a1405147SZachary Turner 642a1405147SZachary Turner uint32_t idx = 0; 643*b9c1b51eSKate Stone for (auto object : objects) { 644a1405147SZachary Turner if (object.IsValid()) 645a1405147SZachary Turner SetItemAtIndex(idx, object); 646a1405147SZachary Turner idx++; 647a1405147SZachary Turner } 648a1405147SZachary Turner } 649a1405147SZachary Turner 650*b9c1b51eSKate Stone PythonTuple::PythonTuple(std::initializer_list<PyObject *> objects) { 651a1405147SZachary Turner m_py_obj = PyTuple_New(objects.size()); 652a1405147SZachary Turner 653a1405147SZachary Turner uint32_t idx = 0; 654*b9c1b51eSKate Stone for (auto py_object : objects) { 655a1405147SZachary Turner PythonObject object(PyRefType::Borrowed, py_object); 656a1405147SZachary Turner if (object.IsValid()) 657a1405147SZachary Turner SetItemAtIndex(idx, object); 658a1405147SZachary Turner idx++; 659a1405147SZachary Turner } 660a1405147SZachary Turner } 661a1405147SZachary Turner 662*b9c1b51eSKate Stone PythonTuple::~PythonTuple() {} 663a1405147SZachary Turner 664*b9c1b51eSKate Stone bool PythonTuple::Check(PyObject *py_obj) { 665a1405147SZachary Turner if (!py_obj) 666a1405147SZachary Turner return false; 667a1405147SZachary Turner return PyTuple_Check(py_obj); 668a1405147SZachary Turner } 669a1405147SZachary Turner 670*b9c1b51eSKate Stone void PythonTuple::Reset(PyRefType type, PyObject *py_obj) { 671a1405147SZachary Turner // Grab the desired reference type so that if we end up rejecting 672a1405147SZachary Turner // `py_obj` it still gets decremented if necessary. 673a1405147SZachary Turner PythonObject result(type, py_obj); 674a1405147SZachary Turner 675*b9c1b51eSKate Stone if (!PythonTuple::Check(py_obj)) { 676a1405147SZachary Turner PythonObject::Reset(); 677a1405147SZachary Turner return; 678a1405147SZachary Turner } 679a1405147SZachary Turner 680*b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 681*b9c1b51eSKate Stone // overflow since it calls 682a1405147SZachary Turner // back into the virtual implementation. 683a1405147SZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 684a1405147SZachary Turner } 685a1405147SZachary Turner 686*b9c1b51eSKate Stone uint32_t PythonTuple::GetSize() const { 687a1405147SZachary Turner if (IsValid()) 688a1405147SZachary Turner return PyTuple_GET_SIZE(m_py_obj); 689a1405147SZachary Turner return 0; 690a1405147SZachary Turner } 691a1405147SZachary Turner 692*b9c1b51eSKate Stone PythonObject PythonTuple::GetItemAtIndex(uint32_t index) const { 693a1405147SZachary Turner if (IsValid()) 694a1405147SZachary Turner return PythonObject(PyRefType::Borrowed, PyTuple_GetItem(m_py_obj, index)); 695a1405147SZachary Turner return PythonObject(); 696a1405147SZachary Turner } 697a1405147SZachary Turner 698*b9c1b51eSKate Stone void PythonTuple::SetItemAtIndex(uint32_t index, const PythonObject &object) { 699*b9c1b51eSKate Stone if (IsAllocated() && object.IsValid()) { 700a1405147SZachary Turner // PyTuple_SetItem is documented to "steal" a reference, so we need to 701a1405147SZachary Turner // convert it to an owned reference by incrementing it. 702a1405147SZachary Turner Py_INCREF(object.get()); 703a1405147SZachary Turner PyTuple_SetItem(m_py_obj, index, object.get()); 704a1405147SZachary Turner } 705a1405147SZachary Turner } 706a1405147SZachary Turner 707*b9c1b51eSKate Stone StructuredData::ArraySP PythonTuple::CreateStructuredArray() const { 708a1405147SZachary Turner StructuredData::ArraySP result(new StructuredData::Array); 709a1405147SZachary Turner uint32_t count = GetSize(); 710*b9c1b51eSKate Stone for (uint32_t i = 0; i < count; ++i) { 711a1405147SZachary Turner PythonObject obj = GetItemAtIndex(i); 712a1405147SZachary Turner result->AddItem(obj.CreateStructuredObject()); 713a1405147SZachary Turner } 714a1405147SZachary Turner return result; 715a1405147SZachary Turner } 716a1405147SZachary Turner 717a1405147SZachary Turner //---------------------------------------------------------------------- 7182c1f46dcSZachary Turner // PythonDictionary 7192c1f46dcSZachary Turner //---------------------------------------------------------------------- 7202c1f46dcSZachary Turner 721*b9c1b51eSKate Stone PythonDictionary::PythonDictionary(PyInitialValue value) : PythonObject() { 722f8b22f8fSZachary Turner if (value == PyInitialValue::Empty) 723f8b22f8fSZachary Turner Reset(PyRefType::Owned, PyDict_New()); 7242c1f46dcSZachary Turner } 7252c1f46dcSZachary Turner 726f8b22f8fSZachary Turner PythonDictionary::PythonDictionary(PyRefType type, PyObject *py_obj) 727*b9c1b51eSKate Stone : PythonObject() { 728f8b22f8fSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a dictionary 7292c1f46dcSZachary Turner } 7302c1f46dcSZachary Turner 731f8b22f8fSZachary Turner PythonDictionary::PythonDictionary(const PythonDictionary &object) 732*b9c1b51eSKate Stone : PythonObject(object) {} 7332c1f46dcSZachary Turner 734*b9c1b51eSKate Stone PythonDictionary::~PythonDictionary() {} 7352c1f46dcSZachary Turner 736*b9c1b51eSKate Stone bool PythonDictionary::Check(PyObject *py_obj) { 73722c8efcdSZachary Turner if (!py_obj) 73822c8efcdSZachary Turner return false; 73922c8efcdSZachary Turner 74022c8efcdSZachary Turner return PyDict_Check(py_obj); 74122c8efcdSZachary Turner } 74222c8efcdSZachary Turner 743*b9c1b51eSKate Stone void PythonDictionary::Reset(PyRefType type, PyObject *py_obj) { 744f8b22f8fSZachary Turner // Grab the desired reference type so that if we end up rejecting 745f8b22f8fSZachary Turner // `py_obj` it still gets decremented if necessary. 746f8b22f8fSZachary Turner PythonObject result(type, py_obj); 747f8b22f8fSZachary Turner 748*b9c1b51eSKate Stone if (!PythonDictionary::Check(py_obj)) { 749f8b22f8fSZachary Turner PythonObject::Reset(); 750f8b22f8fSZachary Turner return; 75122c8efcdSZachary Turner } 75222c8efcdSZachary Turner 753*b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 754*b9c1b51eSKate Stone // overflow since it calls 755f8b22f8fSZachary Turner // back into the virtual implementation. 756f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 7572c1f46dcSZachary Turner } 7582c1f46dcSZachary Turner 759*b9c1b51eSKate Stone uint32_t PythonDictionary::GetSize() const { 760f8b22f8fSZachary Turner if (IsValid()) 7612c1f46dcSZachary Turner return PyDict_Size(m_py_obj); 7622c1f46dcSZachary Turner return 0; 7632c1f46dcSZachary Turner } 7642c1f46dcSZachary Turner 765*b9c1b51eSKate Stone PythonList PythonDictionary::GetKeys() const { 766f8b22f8fSZachary Turner if (IsValid()) 767f8b22f8fSZachary Turner return PythonList(PyRefType::Owned, PyDict_Keys(m_py_obj)); 768f8b22f8fSZachary Turner return PythonList(PyInitialValue::Invalid); 7692c1f46dcSZachary Turner } 7702c1f46dcSZachary Turner 771*b9c1b51eSKate Stone PythonObject PythonDictionary::GetItemForKey(const PythonObject &key) const { 772f8b22f8fSZachary Turner if (IsAllocated() && key.IsValid()) 773*b9c1b51eSKate Stone return PythonObject(PyRefType::Borrowed, 774*b9c1b51eSKate Stone PyDict_GetItem(m_py_obj, key.get())); 7752c1f46dcSZachary Turner return PythonObject(); 7762c1f46dcSZachary Turner } 7772c1f46dcSZachary Turner 778*b9c1b51eSKate Stone void PythonDictionary::SetItemForKey(const PythonObject &key, 779*b9c1b51eSKate Stone const PythonObject &value) { 780f8b22f8fSZachary Turner if (IsAllocated() && key.IsValid() && value.IsValid()) 7812c1f46dcSZachary Turner PyDict_SetItem(m_py_obj, key.get(), value.get()); 7822c1f46dcSZachary Turner } 7832c1f46dcSZachary Turner 7842c1f46dcSZachary Turner StructuredData::DictionarySP 785*b9c1b51eSKate Stone PythonDictionary::CreateStructuredDictionary() const { 7862c1f46dcSZachary Turner StructuredData::DictionarySP result(new StructuredData::Dictionary); 7872c1f46dcSZachary Turner PythonList keys(GetKeys()); 7882c1f46dcSZachary Turner uint32_t num_keys = keys.GetSize(); 789*b9c1b51eSKate Stone for (uint32_t i = 0; i < num_keys; ++i) { 7902c1f46dcSZachary Turner PythonObject key = keys.GetItemAtIndex(i); 7912c1f46dcSZachary Turner PythonObject value = GetItemForKey(key); 7922c1f46dcSZachary Turner StructuredData::ObjectSP structured_value = value.CreateStructuredObject(); 793f8b22f8fSZachary Turner result->AddItem(key.Str().GetString(), structured_value); 7942c1f46dcSZachary Turner } 7952c1f46dcSZachary Turner return result; 7962c1f46dcSZachary Turner } 7972c1f46dcSZachary Turner 798*b9c1b51eSKate Stone PythonModule::PythonModule() : PythonObject() {} 7997841efbbSZachary Turner 800*b9c1b51eSKate Stone PythonModule::PythonModule(PyRefType type, PyObject *py_obj) { 8017841efbbSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a module 8027841efbbSZachary Turner } 8037841efbbSZachary Turner 804*b9c1b51eSKate Stone PythonModule::PythonModule(const PythonModule &dict) : PythonObject(dict) {} 8057841efbbSZachary Turner 806*b9c1b51eSKate Stone PythonModule::~PythonModule() {} 8077841efbbSZachary Turner 808*b9c1b51eSKate Stone PythonModule PythonModule::BuiltinsModule() { 809a1405147SZachary Turner #if PY_MAJOR_VERSION >= 3 810a1405147SZachary Turner return AddModule("builtins"); 811a1405147SZachary Turner #else 812a1405147SZachary Turner return AddModule("__builtin__"); 813a1405147SZachary Turner #endif 814a1405147SZachary Turner } 815a1405147SZachary Turner 816*b9c1b51eSKate Stone PythonModule PythonModule::MainModule() { return AddModule("__main__"); } 817a1405147SZachary Turner 818*b9c1b51eSKate Stone PythonModule PythonModule::AddModule(llvm::StringRef module) { 819a1405147SZachary Turner std::string str = module.str(); 820a1405147SZachary Turner return PythonModule(PyRefType::Borrowed, PyImport_AddModule(str.c_str())); 8217841efbbSZachary Turner } 8227841efbbSZachary Turner 823*b9c1b51eSKate Stone PythonModule PythonModule::ImportModule(llvm::StringRef module) { 8242419f1d5SZachary Turner std::string str = module.str(); 8252419f1d5SZachary Turner return PythonModule(PyRefType::Owned, PyImport_ImportModule(str.c_str())); 8262419f1d5SZachary Turner } 8272419f1d5SZachary Turner 828*b9c1b51eSKate Stone bool PythonModule::Check(PyObject *py_obj) { 8297841efbbSZachary Turner if (!py_obj) 8307841efbbSZachary Turner return false; 8317841efbbSZachary Turner 8327841efbbSZachary Turner return PyModule_Check(py_obj); 8337841efbbSZachary Turner } 8347841efbbSZachary Turner 835*b9c1b51eSKate Stone void PythonModule::Reset(PyRefType type, PyObject *py_obj) { 8367841efbbSZachary Turner // Grab the desired reference type so that if we end up rejecting 8377841efbbSZachary Turner // `py_obj` it still gets decremented if necessary. 8387841efbbSZachary Turner PythonObject result(type, py_obj); 8397841efbbSZachary Turner 840*b9c1b51eSKate Stone if (!PythonModule::Check(py_obj)) { 8417841efbbSZachary Turner PythonObject::Reset(); 8427841efbbSZachary Turner return; 8437841efbbSZachary Turner } 8447841efbbSZachary Turner 845*b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 846*b9c1b51eSKate Stone // overflow since it calls 8477841efbbSZachary Turner // back into the virtual implementation. 8487841efbbSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 8497841efbbSZachary Turner } 8507841efbbSZachary Turner 851*b9c1b51eSKate Stone PythonDictionary PythonModule::GetDictionary() const { 8527841efbbSZachary Turner return PythonDictionary(PyRefType::Borrowed, PyModule_GetDict(m_py_obj)); 8537841efbbSZachary Turner } 8547841efbbSZachary Turner 855*b9c1b51eSKate Stone PythonCallable::PythonCallable() : PythonObject() {} 856a1405147SZachary Turner 857*b9c1b51eSKate Stone PythonCallable::PythonCallable(PyRefType type, PyObject *py_obj) { 858a1405147SZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a callable 859a1405147SZachary Turner } 860a1405147SZachary Turner 861a1405147SZachary Turner PythonCallable::PythonCallable(const PythonCallable &callable) 862*b9c1b51eSKate Stone : PythonObject(callable) {} 863a1405147SZachary Turner 864*b9c1b51eSKate Stone PythonCallable::~PythonCallable() {} 865a1405147SZachary Turner 866*b9c1b51eSKate Stone bool PythonCallable::Check(PyObject *py_obj) { 867a1405147SZachary Turner if (!py_obj) 868a1405147SZachary Turner return false; 869a1405147SZachary Turner 870a1405147SZachary Turner return PyCallable_Check(py_obj); 871a1405147SZachary Turner } 872a1405147SZachary Turner 873*b9c1b51eSKate Stone void PythonCallable::Reset(PyRefType type, PyObject *py_obj) { 874a1405147SZachary Turner // Grab the desired reference type so that if we end up rejecting 875a1405147SZachary Turner // `py_obj` it still gets decremented if necessary. 876a1405147SZachary Turner PythonObject result(type, py_obj); 877a1405147SZachary Turner 878*b9c1b51eSKate Stone if (!PythonCallable::Check(py_obj)) { 879a1405147SZachary Turner PythonObject::Reset(); 880a1405147SZachary Turner return; 881a1405147SZachary Turner } 882a1405147SZachary Turner 883*b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 884*b9c1b51eSKate Stone // overflow since it calls 885a1405147SZachary Turner // back into the virtual implementation. 886a1405147SZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 887a1405147SZachary Turner } 888a1405147SZachary Turner 889*b9c1b51eSKate Stone PythonCallable::ArgInfo PythonCallable::GetNumArguments() const { 890a5d6765cSEnrico Granata ArgInfo result = {0, false, false, false}; 891a1405147SZachary Turner if (!IsValid()) 892b58fb2f4SZachary Turner return result; 893a1405147SZachary Turner 894a1405147SZachary Turner PyObject *py_func_obj = m_py_obj; 895*b9c1b51eSKate Stone if (PyMethod_Check(py_func_obj)) { 896a1405147SZachary Turner py_func_obj = PyMethod_GET_FUNCTION(py_func_obj); 897a5d6765cSEnrico Granata PythonObject im_self = GetAttributeValue("im_self"); 898a5d6765cSEnrico Granata if (im_self.IsValid() && !im_self.IsNone()) 899a5d6765cSEnrico Granata result.is_bound_method = true; 900*b9c1b51eSKate Stone } else { 901a5d6765cSEnrico Granata // see if this is a callable object with an __call__ method 902*b9c1b51eSKate Stone if (!PyFunction_Check(py_func_obj)) { 903a5d6765cSEnrico Granata PythonObject __call__ = GetAttributeValue("__call__"); 904*b9c1b51eSKate Stone if (__call__.IsValid()) { 905a5d6765cSEnrico Granata auto __callable__ = __call__.AsType<PythonCallable>(); 906*b9c1b51eSKate Stone if (__callable__.IsValid()) { 907a5d6765cSEnrico Granata py_func_obj = PyMethod_GET_FUNCTION(__callable__.get()); 908a5d6765cSEnrico Granata PythonObject im_self = GetAttributeValue("im_self"); 909a5d6765cSEnrico Granata if (im_self.IsValid() && !im_self.IsNone()) 910a5d6765cSEnrico Granata result.is_bound_method = true; 911a5d6765cSEnrico Granata } 912a5d6765cSEnrico Granata } 913a5d6765cSEnrico Granata } 914a5d6765cSEnrico Granata } 915a1405147SZachary Turner 916a1405147SZachary Turner if (!py_func_obj) 917b58fb2f4SZachary Turner return result; 918a1405147SZachary Turner 919a1405147SZachary Turner PyCodeObject *code = (PyCodeObject *)PyFunction_GET_CODE(py_func_obj); 920a1405147SZachary Turner if (!code) 921b58fb2f4SZachary Turner return result; 922a1405147SZachary Turner 923b58fb2f4SZachary Turner result.count = code->co_argcount; 924b58fb2f4SZachary Turner result.has_varargs = !!(code->co_flags & CO_VARARGS); 925b58fb2f4SZachary Turner result.has_kwargs = !!(code->co_flags & CO_VARKEYWORDS); 926b58fb2f4SZachary Turner return result; 927b58fb2f4SZachary Turner } 928b58fb2f4SZachary Turner 929*b9c1b51eSKate Stone PythonObject PythonCallable::operator()() { 930*b9c1b51eSKate Stone return PythonObject(PyRefType::Owned, PyObject_CallObject(m_py_obj, nullptr)); 931a1405147SZachary Turner } 932a1405147SZachary Turner 933*b9c1b51eSKate Stone PythonObject PythonCallable:: 934*b9c1b51eSKate Stone operator()(std::initializer_list<PyObject *> args) { 935a1405147SZachary Turner PythonTuple arg_tuple(args); 936a1405147SZachary Turner return PythonObject(PyRefType::Owned, 937a1405147SZachary Turner PyObject_CallObject(m_py_obj, arg_tuple.get())); 938a1405147SZachary Turner } 939a1405147SZachary Turner 940*b9c1b51eSKate Stone PythonObject PythonCallable:: 941*b9c1b51eSKate Stone operator()(std::initializer_list<PythonObject> args) { 942a1405147SZachary Turner PythonTuple arg_tuple(args); 943a1405147SZachary Turner return PythonObject(PyRefType::Owned, 944a1405147SZachary Turner PyObject_CallObject(m_py_obj, arg_tuple.get())); 945a1405147SZachary Turner } 946a1405147SZachary Turner 947*b9c1b51eSKate Stone PythonFile::PythonFile() : PythonObject() {} 94832064024SZachary Turner 949*b9c1b51eSKate Stone PythonFile::PythonFile(File &file, const char *mode) { Reset(file, mode); } 9509c40264fSZachary Turner 951*b9c1b51eSKate Stone PythonFile::PythonFile(const char *path, const char *mode) { 952190fadcdSZachary Turner lldb_private::File file(path, GetOptionsFromMode(mode)); 953eda01c31SZachary Turner Reset(file, mode); 954eda01c31SZachary Turner } 955eda01c31SZachary Turner 956*b9c1b51eSKate Stone PythonFile::PythonFile(PyRefType type, PyObject *o) { Reset(type, o); } 9579c40264fSZachary Turner 958*b9c1b51eSKate Stone PythonFile::~PythonFile() {} 9599c40264fSZachary Turner 960*b9c1b51eSKate Stone bool PythonFile::Check(PyObject *py_obj) { 9619c40264fSZachary Turner #if PY_MAJOR_VERSION < 3 9629c40264fSZachary Turner return PyFile_Check(py_obj); 9639c40264fSZachary Turner #else 9649c40264fSZachary Turner // In Python 3, there is no `PyFile_Check`, and in fact PyFile is not even a 9659c40264fSZachary Turner // first-class object type anymore. `PyFile_FromFd` is just a thin wrapper 9669c40264fSZachary Turner // over `io.open()`, which returns some object derived from `io.IOBase`. 9679c40264fSZachary Turner // As a result, the only way to detect a file in Python 3 is to check whether 9689c40264fSZachary Turner // it inherits from `io.IOBase`. Since it is possible for non-files to also 9699c40264fSZachary Turner // inherit from `io.IOBase`, we additionally verify that it has the `fileno` 9709c40264fSZachary Turner // attribute, which should guarantee that it is backed by the file system. 9719c40264fSZachary Turner PythonObject io_module(PyRefType::Owned, PyImport_ImportModule("io")); 972*b9c1b51eSKate Stone PythonDictionary io_dict(PyRefType::Borrowed, 973*b9c1b51eSKate Stone PyModule_GetDict(io_module.get())); 9749c40264fSZachary Turner PythonObject io_base_class = io_dict.GetItemForKey(PythonString("IOBase")); 9759c40264fSZachary Turner 9769c40264fSZachary Turner PythonObject object_type(PyRefType::Owned, PyObject_Type(py_obj)); 9779c40264fSZachary Turner 9789c40264fSZachary Turner if (1 != PyObject_IsSubclass(object_type.get(), io_base_class.get())) 9799c40264fSZachary Turner return false; 9809c40264fSZachary Turner if (!object_type.HasAttribute("fileno")) 9819c40264fSZachary Turner return false; 9829c40264fSZachary Turner 9839c40264fSZachary Turner return true; 9849c40264fSZachary Turner #endif 9859c40264fSZachary Turner } 9869c40264fSZachary Turner 987*b9c1b51eSKate Stone void PythonFile::Reset(PyRefType type, PyObject *py_obj) { 9889c40264fSZachary Turner // Grab the desired reference type so that if we end up rejecting 9899c40264fSZachary Turner // `py_obj` it still gets decremented if necessary. 9909c40264fSZachary Turner PythonObject result(type, py_obj); 9919c40264fSZachary Turner 992*b9c1b51eSKate Stone if (!PythonFile::Check(py_obj)) { 9939c40264fSZachary Turner PythonObject::Reset(); 9949c40264fSZachary Turner return; 9959c40264fSZachary Turner } 9969c40264fSZachary Turner 9979c40264fSZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack 9989c40264fSZachary Turner // overflow since it calls back into the virtual implementation. 9999c40264fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 10009c40264fSZachary Turner } 10019c40264fSZachary Turner 1002*b9c1b51eSKate Stone void PythonFile::Reset(File &file, const char *mode) { 1003*b9c1b51eSKate Stone if (!file.IsValid()) { 100432ac147bSZachary Turner Reset(); 100532ac147bSZachary Turner return; 100632ac147bSZachary Turner } 100732ac147bSZachary Turner 10089c40264fSZachary Turner char *cmode = const_cast<char *>(mode); 10099c40264fSZachary Turner #if PY_MAJOR_VERSION >= 3 1010*b9c1b51eSKate Stone Reset(PyRefType::Owned, PyFile_FromFd(file.GetDescriptor(), nullptr, cmode, 1011*b9c1b51eSKate Stone -1, nullptr, "ignore", nullptr, 0)); 10129c40264fSZachary Turner #else 10139c40264fSZachary Turner // Read through the Python source, doesn't seem to modify these strings 10149c40264fSZachary Turner Reset(PyRefType::Owned, 1015*b9c1b51eSKate Stone PyFile_FromFile(file.GetStream(), const_cast<char *>(""), cmode, 1016*b9c1b51eSKate Stone nullptr)); 10179c40264fSZachary Turner #endif 10189c40264fSZachary Turner } 10199c40264fSZachary Turner 1020*b9c1b51eSKate Stone uint32_t PythonFile::GetOptionsFromMode(llvm::StringRef mode) { 1021744959b9SEnrico Granata if (mode.empty()) 1022744959b9SEnrico Granata return 0; 1023744959b9SEnrico Granata 1024744959b9SEnrico Granata return llvm::StringSwitch<uint32_t>(mode.str().c_str()) 1025744959b9SEnrico Granata .Case("r", File::eOpenOptionRead) 1026744959b9SEnrico Granata .Case("w", File::eOpenOptionWrite) 1027*b9c1b51eSKate Stone .Case("a", File::eOpenOptionWrite | File::eOpenOptionAppend | 1028*b9c1b51eSKate Stone File::eOpenOptionCanCreate) 1029744959b9SEnrico Granata .Case("r+", File::eOpenOptionRead | File::eOpenOptionWrite) 1030*b9c1b51eSKate Stone .Case("w+", File::eOpenOptionRead | File::eOpenOptionWrite | 1031*b9c1b51eSKate Stone File::eOpenOptionCanCreate | File::eOpenOptionTruncate) 1032*b9c1b51eSKate Stone .Case("a+", File::eOpenOptionRead | File::eOpenOptionWrite | 1033*b9c1b51eSKate Stone File::eOpenOptionAppend | File::eOpenOptionCanCreate) 1034744959b9SEnrico Granata .Default(0); 1035744959b9SEnrico Granata } 1036744959b9SEnrico Granata 1037*b9c1b51eSKate Stone bool PythonFile::GetUnderlyingFile(File &file) const { 1038eda01c31SZachary Turner if (!IsValid()) 1039eda01c31SZachary Turner return false; 1040eda01c31SZachary Turner 1041eda01c31SZachary Turner file.Close(); 1042eda01c31SZachary Turner // We don't own the file descriptor returned by this function, make sure the 1043eda01c31SZachary Turner // File object knows about that. 1044eda01c31SZachary Turner file.SetDescriptor(PyObject_AsFileDescriptor(m_py_obj), false); 1045744959b9SEnrico Granata PythonString py_mode = GetAttributeValue("mode").AsType<PythonString>(); 1046744959b9SEnrico Granata file.SetOptions(PythonFile::GetOptionsFromMode(py_mode.GetString())); 1047eda01c31SZachary Turner return file.IsValid(); 1048eda01c31SZachary Turner } 1049eda01c31SZachary Turner 10502c1f46dcSZachary Turner #endif 1051