1bcadb5a3SPavel Labath //===-- PythonDataObjects.cpp -----------------------------------*- C++ -*-===// 22c1f46dcSZachary Turner // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 62c1f46dcSZachary Turner // 72c1f46dcSZachary Turner //===----------------------------------------------------------------------===// 82c1f46dcSZachary Turner 9d68983e3SPavel Labath #ifdef LLDB_DISABLE_PYTHON 10d68983e3SPavel Labath 11d68983e3SPavel Labath // Python is disabled in this build 12d68983e3SPavel Labath 13d68983e3SPavel Labath #else 14d68983e3SPavel Labath 152c1f46dcSZachary Turner #include "PythonDataObjects.h" 162c1f46dcSZachary Turner #include "ScriptInterpreterPython.h" 172c1f46dcSZachary Turner 182c1f46dcSZachary Turner #include "lldb/Host/File.h" 19190fadcdSZachary Turner #include "lldb/Host/FileSystem.h" 202c1f46dcSZachary Turner #include "lldb/Interpreter/ScriptInterpreter.h" 21bf9a7730SZachary Turner #include "lldb/Utility/Stream.h" 222c1f46dcSZachary Turner 239a6c7572SJonas Devlieghere #include "llvm/ADT/StringSwitch.h" 24190fadcdSZachary Turner #include "llvm/Support/ConvertUTF.h" 252819136fSMichal Gorny #include "llvm/Support/Errno.h" 26190fadcdSZachary Turner 272c1f46dcSZachary Turner #include <stdio.h> 282c1f46dcSZachary Turner 292c1f46dcSZachary Turner using namespace lldb_private; 302c1f46dcSZachary Turner using namespace lldb; 312c1f46dcSZachary Turner 322783d817SJonas Devlieghere void StructuredPythonObject::Serialize(llvm::json::OStream &s) const { 332783d817SJonas Devlieghere s.value(llvm::formatv("Python Obj: {0:X}", GetValue()).str()); 342c1f46dcSZachary Turner } 352c1f46dcSZachary Turner 362c1f46dcSZachary Turner // PythonObject 372c1f46dcSZachary Turner 38b9c1b51eSKate Stone void PythonObject::Dump(Stream &strm) const { 39b9c1b51eSKate Stone if (m_py_obj) { 402819136fSMichal Gorny FILE *file = llvm::sys::RetryAfterSignal(nullptr, ::tmpfile); 41b9c1b51eSKate Stone if (file) { 422c1f46dcSZachary Turner ::PyObject_Print(m_py_obj, file, 0); 432c1f46dcSZachary Turner const long length = ftell(file); 44b9c1b51eSKate Stone if (length) { 452c1f46dcSZachary Turner ::rewind(file); 462c1f46dcSZachary Turner std::vector<char> file_contents(length, '\0'); 47b9c1b51eSKate Stone const size_t length_read = 48b9c1b51eSKate Stone ::fread(file_contents.data(), 1, file_contents.size(), file); 492c1f46dcSZachary Turner if (length_read > 0) 502c1f46dcSZachary Turner strm.Write(file_contents.data(), length_read); 512c1f46dcSZachary Turner } 522c1f46dcSZachary Turner ::fclose(file); 532c1f46dcSZachary Turner } 54b9c1b51eSKate Stone } else 552c1f46dcSZachary Turner strm.PutCString("NULL"); 562c1f46dcSZachary Turner } 572c1f46dcSZachary Turner 58b9c1b51eSKate Stone PyObjectType PythonObject::GetObjectType() const { 59f8b22f8fSZachary Turner if (!IsAllocated()) 602c1f46dcSZachary Turner return PyObjectType::None; 612c1f46dcSZachary Turner 627841efbbSZachary Turner if (PythonModule::Check(m_py_obj)) 637841efbbSZachary Turner return PyObjectType::Module; 6418426935SZachary Turner if (PythonList::Check(m_py_obj)) 652c1f46dcSZachary Turner return PyObjectType::List; 66a1405147SZachary Turner if (PythonTuple::Check(m_py_obj)) 67a1405147SZachary Turner return PyObjectType::Tuple; 6818426935SZachary Turner if (PythonDictionary::Check(m_py_obj)) 692c1f46dcSZachary Turner return PyObjectType::Dictionary; 7018426935SZachary Turner if (PythonString::Check(m_py_obj)) 7122c8efcdSZachary Turner return PyObjectType::String; 725a72c02bSZachary Turner #if PY_MAJOR_VERSION >= 3 735a72c02bSZachary Turner if (PythonBytes::Check(m_py_obj)) 745a72c02bSZachary Turner return PyObjectType::Bytes; 755a72c02bSZachary Turner #endif 76f9d6d204SZachary Turner if (PythonByteArray::Check(m_py_obj)) 77f9d6d204SZachary Turner return PyObjectType::ByteArray; 78b81d715cSTatyana Krasnukha if (PythonBoolean::Check(m_py_obj)) 79b81d715cSTatyana Krasnukha return PyObjectType::Boolean; 8018426935SZachary Turner if (PythonInteger::Check(m_py_obj)) 8122c8efcdSZachary Turner return PyObjectType::Integer; 829c40264fSZachary Turner if (PythonFile::Check(m_py_obj)) 839c40264fSZachary Turner return PyObjectType::File; 84a1405147SZachary Turner if (PythonCallable::Check(m_py_obj)) 85a1405147SZachary Turner return PyObjectType::Callable; 862c1f46dcSZachary Turner return PyObjectType::Unknown; 872c1f46dcSZachary Turner } 882c1f46dcSZachary Turner 89b9c1b51eSKate Stone PythonString PythonObject::Repr() const { 902c1f46dcSZachary Turner if (!m_py_obj) 912c1f46dcSZachary Turner return PythonString(); 922c1f46dcSZachary Turner PyObject *repr = PyObject_Repr(m_py_obj); 932c1f46dcSZachary Turner if (!repr) 942c1f46dcSZachary Turner return PythonString(); 95f8b22f8fSZachary Turner return PythonString(PyRefType::Owned, repr); 962c1f46dcSZachary Turner } 972c1f46dcSZachary Turner 98b9c1b51eSKate Stone PythonString PythonObject::Str() const { 992c1f46dcSZachary Turner if (!m_py_obj) 1002c1f46dcSZachary Turner return PythonString(); 1012c1f46dcSZachary Turner PyObject *str = PyObject_Str(m_py_obj); 1022c1f46dcSZachary Turner if (!str) 1032c1f46dcSZachary Turner return PythonString(); 104f8b22f8fSZachary Turner return PythonString(PyRefType::Owned, str); 1052c1f46dcSZachary Turner } 1062c1f46dcSZachary Turner 1077841efbbSZachary Turner PythonObject 108b9c1b51eSKate Stone PythonObject::ResolveNameWithDictionary(llvm::StringRef name, 109b9c1b51eSKate Stone const PythonDictionary &dict) { 110c712bac7SJonas Devlieghere size_t dot_pos = name.find('.'); 111a1405147SZachary Turner llvm::StringRef piece = name.substr(0, dot_pos); 112a1405147SZachary Turner PythonObject result = dict.GetItemForKey(PythonString(piece)); 113b9c1b51eSKate Stone if (dot_pos == llvm::StringRef::npos) { 114a1405147SZachary Turner // There was no dot, we're done. 115a1405147SZachary Turner return result; 116a1405147SZachary Turner } 117a1405147SZachary Turner 118a1405147SZachary Turner // There was a dot. The remaining portion of the name should be looked up in 119a1405147SZachary Turner // the context of the object that was found in the dictionary. 120a1405147SZachary Turner return result.ResolveName(name.substr(dot_pos + 1)); 1217841efbbSZachary Turner } 1227841efbbSZachary Turner 123b9c1b51eSKate Stone PythonObject PythonObject::ResolveName(llvm::StringRef name) const { 12405097246SAdrian Prantl // Resolve the name in the context of the specified object. If, for example, 12505097246SAdrian Prantl // `this` refers to a PyModule, then this will look for `name` in this 12605097246SAdrian Prantl // module. If `this` refers to a PyType, then it will resolve `name` as an 12705097246SAdrian Prantl // attribute of that type. If `this` refers to an instance of an object, 12805097246SAdrian Prantl // then it will resolve `name` as the value of the specified field. 1297841efbbSZachary Turner // 1307841efbbSZachary Turner // This function handles dotted names so that, for example, if `m_py_obj` 13105097246SAdrian Prantl // refers to the `sys` module, and `name` == "path.append", then it will find 13205097246SAdrian Prantl // the function `sys.path.append`. 1337841efbbSZachary Turner 134c712bac7SJonas Devlieghere size_t dot_pos = name.find('.'); 135b9c1b51eSKate Stone if (dot_pos == llvm::StringRef::npos) { 13605097246SAdrian Prantl // No dots in the name, we should be able to find the value immediately as 13705097246SAdrian Prantl // an attribute of `m_py_obj`. 1387841efbbSZachary Turner return GetAttributeValue(name); 1397841efbbSZachary Turner } 1407841efbbSZachary Turner 141b9c1b51eSKate Stone // Look up the first piece of the name, and resolve the rest as a child of 142b9c1b51eSKate Stone // that. 1437841efbbSZachary Turner PythonObject parent = ResolveName(name.substr(0, dot_pos)); 1447841efbbSZachary Turner if (!parent.IsAllocated()) 1457841efbbSZachary Turner return PythonObject(); 1467841efbbSZachary Turner 1477841efbbSZachary Turner // Tail recursion.. should be optimized by the compiler 1487841efbbSZachary Turner return parent.ResolveName(name.substr(dot_pos + 1)); 1497841efbbSZachary Turner } 1507841efbbSZachary Turner 151b9c1b51eSKate Stone bool PythonObject::HasAttribute(llvm::StringRef attr) const { 1529c40264fSZachary Turner if (!IsValid()) 1539c40264fSZachary Turner return false; 1549c40264fSZachary Turner PythonString py_attr(attr); 1559c40264fSZachary Turner return !!PyObject_HasAttr(m_py_obj, py_attr.get()); 1569c40264fSZachary Turner } 1579c40264fSZachary Turner 158b9c1b51eSKate Stone PythonObject PythonObject::GetAttributeValue(llvm::StringRef attr) const { 1597d6d218eSZachary Turner if (!IsValid()) 1607d6d218eSZachary Turner return PythonObject(); 1617d6d218eSZachary Turner 1627d6d218eSZachary Turner PythonString py_attr(attr); 1637d6d218eSZachary Turner if (!PyObject_HasAttr(m_py_obj, py_attr.get())) 1647d6d218eSZachary Turner return PythonObject(); 1657d6d218eSZachary Turner 1667d6d218eSZachary Turner return PythonObject(PyRefType::Owned, 1677d6d218eSZachary Turner PyObject_GetAttr(m_py_obj, py_attr.get())); 1687d6d218eSZachary Turner } 1697d6d218eSZachary Turner 170b9c1b51eSKate Stone bool PythonObject::IsNone() const { return m_py_obj == Py_None; } 171f8b22f8fSZachary Turner 172b9c1b51eSKate Stone bool PythonObject::IsValid() const { return m_py_obj != nullptr; } 173f8b22f8fSZachary Turner 174b9c1b51eSKate Stone bool PythonObject::IsAllocated() const { return IsValid() && !IsNone(); } 1752c1f46dcSZachary Turner 176b9c1b51eSKate Stone StructuredData::ObjectSP PythonObject::CreateStructuredObject() const { 177b9c1b51eSKate Stone switch (GetObjectType()) { 1782c1f46dcSZachary Turner case PyObjectType::Dictionary: 179b9c1b51eSKate Stone return PythonDictionary(PyRefType::Borrowed, m_py_obj) 180b9c1b51eSKate Stone .CreateStructuredDictionary(); 181b81d715cSTatyana Krasnukha case PyObjectType::Boolean: 182b81d715cSTatyana Krasnukha return PythonBoolean(PyRefType::Borrowed, m_py_obj) 183b81d715cSTatyana Krasnukha .CreateStructuredBoolean(); 1842c1f46dcSZachary Turner case PyObjectType::Integer: 185b9c1b51eSKate Stone return PythonInteger(PyRefType::Borrowed, m_py_obj) 186b9c1b51eSKate 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: 194b9c1b51eSKate Stone return PythonByteArray(PyRefType::Borrowed, m_py_obj) 195b9c1b51eSKate 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 // PythonString 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() {} 2195a72c02bSZachary Turner 220b9c1b51eSKate Stone bool PythonBytes::Check(PyObject *py_obj) { 2215a72c02bSZachary Turner if (!py_obj) 2225a72c02bSZachary Turner return false; 223a6682a41SJonas Devlieghere return PyBytes_Check(py_obj); 2245a72c02bSZachary Turner } 2255a72c02bSZachary Turner 226b9c1b51eSKate Stone void PythonBytes::Reset(PyRefType type, PyObject *py_obj) { 22705097246SAdrian Prantl // Grab the desired reference type so that if we end up rejecting `py_obj` it 22805097246SAdrian Prantl // still gets decremented if necessary. 2295a72c02bSZachary Turner PythonObject result(type, py_obj); 2305a72c02bSZachary Turner 231b9c1b51eSKate Stone if (!PythonBytes::Check(py_obj)) { 2325a72c02bSZachary Turner PythonObject::Reset(); 2335a72c02bSZachary Turner return; 2345a72c02bSZachary Turner } 2355a72c02bSZachary Turner 236b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 23705097246SAdrian Prantl // overflow since it calls back into the virtual implementation. 2385a72c02bSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 2395a72c02bSZachary Turner } 2405a72c02bSZachary Turner 241b9c1b51eSKate Stone llvm::ArrayRef<uint8_t> PythonBytes::GetBytes() const { 2425a72c02bSZachary Turner if (!IsValid()) 2435a72c02bSZachary Turner return llvm::ArrayRef<uint8_t>(); 2445a72c02bSZachary Turner 2455a72c02bSZachary Turner Py_ssize_t size; 2465a72c02bSZachary Turner char *c; 2475a72c02bSZachary Turner 2485a72c02bSZachary Turner PyBytes_AsStringAndSize(m_py_obj, &c, &size); 2495a72c02bSZachary Turner return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size); 2505a72c02bSZachary Turner } 2515a72c02bSZachary Turner 252b9c1b51eSKate Stone size_t PythonBytes::GetSize() const { 2535a72c02bSZachary Turner if (!IsValid()) 2545a72c02bSZachary Turner return 0; 2555a72c02bSZachary Turner return PyBytes_Size(m_py_obj); 2565a72c02bSZachary Turner } 2575a72c02bSZachary Turner 258b9c1b51eSKate Stone void PythonBytes::SetBytes(llvm::ArrayRef<uint8_t> bytes) { 2595a72c02bSZachary Turner const char *data = reinterpret_cast<const char *>(bytes.data()); 2605a72c02bSZachary Turner PyObject *py_bytes = PyBytes_FromStringAndSize(data, bytes.size()); 2615a72c02bSZachary Turner PythonObject::Reset(PyRefType::Owned, py_bytes); 2625a72c02bSZachary Turner } 2635a72c02bSZachary Turner 264b9c1b51eSKate Stone StructuredData::StringSP PythonBytes::CreateStructuredString() const { 2655a72c02bSZachary Turner StructuredData::StringSP result(new StructuredData::String); 2665a72c02bSZachary Turner Py_ssize_t size; 2675a72c02bSZachary Turner char *c; 2685a72c02bSZachary Turner PyBytes_AsStringAndSize(m_py_obj, &c, &size); 2695a72c02bSZachary Turner result->SetValue(std::string(c, size)); 2705a72c02bSZachary Turner return result; 2715a72c02bSZachary Turner } 2725a72c02bSZachary Turner 273b9c1b51eSKate Stone PythonByteArray::PythonByteArray(llvm::ArrayRef<uint8_t> bytes) 274b9c1b51eSKate Stone : PythonByteArray(bytes.data(), bytes.size()) {} 275f9d6d204SZachary Turner 276b9c1b51eSKate Stone PythonByteArray::PythonByteArray(const uint8_t *bytes, size_t length) { 277f9d6d204SZachary Turner const char *str = reinterpret_cast<const char *>(bytes); 278f9d6d204SZachary Turner Reset(PyRefType::Owned, PyByteArray_FromStringAndSize(str, length)); 279f9d6d204SZachary Turner } 280f9d6d204SZachary Turner 281b9c1b51eSKate Stone PythonByteArray::PythonByteArray(PyRefType type, PyObject *o) { 282f9d6d204SZachary Turner Reset(type, o); 283f9d6d204SZachary Turner } 284f9d6d204SZachary Turner 285b9c1b51eSKate Stone PythonByteArray::PythonByteArray(const PythonBytes &object) 286b9c1b51eSKate Stone : PythonObject(object) {} 287f9d6d204SZachary Turner 288b9c1b51eSKate Stone PythonByteArray::~PythonByteArray() {} 289f9d6d204SZachary Turner 290b9c1b51eSKate Stone bool PythonByteArray::Check(PyObject *py_obj) { 291f9d6d204SZachary Turner if (!py_obj) 292f9d6d204SZachary Turner return false; 293a6682a41SJonas Devlieghere return PyByteArray_Check(py_obj); 294f9d6d204SZachary Turner } 295f9d6d204SZachary Turner 296b9c1b51eSKate Stone void PythonByteArray::Reset(PyRefType type, PyObject *py_obj) { 29705097246SAdrian Prantl // Grab the desired reference type so that if we end up rejecting `py_obj` it 29805097246SAdrian Prantl // still gets decremented if necessary. 299f9d6d204SZachary Turner PythonObject result(type, py_obj); 300f9d6d204SZachary Turner 301b9c1b51eSKate Stone if (!PythonByteArray::Check(py_obj)) { 302f9d6d204SZachary Turner PythonObject::Reset(); 303f9d6d204SZachary Turner return; 304f9d6d204SZachary Turner } 305f9d6d204SZachary Turner 306b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 30705097246SAdrian Prantl // overflow since it calls back into the virtual implementation. 308f9d6d204SZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 309f9d6d204SZachary Turner } 310f9d6d204SZachary Turner 311b9c1b51eSKate Stone llvm::ArrayRef<uint8_t> PythonByteArray::GetBytes() const { 312f9d6d204SZachary Turner if (!IsValid()) 313f9d6d204SZachary Turner return llvm::ArrayRef<uint8_t>(); 314f9d6d204SZachary Turner 315f9d6d204SZachary Turner char *c = PyByteArray_AsString(m_py_obj); 316f9d6d204SZachary Turner size_t size = GetSize(); 317f9d6d204SZachary Turner return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size); 318f9d6d204SZachary Turner } 319f9d6d204SZachary Turner 320b9c1b51eSKate Stone size_t PythonByteArray::GetSize() const { 321f9d6d204SZachary Turner if (!IsValid()) 322f9d6d204SZachary Turner return 0; 323f9d6d204SZachary Turner 324f9d6d204SZachary Turner return PyByteArray_Size(m_py_obj); 325f9d6d204SZachary Turner } 326f9d6d204SZachary Turner 327b9c1b51eSKate Stone StructuredData::StringSP PythonByteArray::CreateStructuredString() const { 328f9d6d204SZachary Turner StructuredData::StringSP result(new StructuredData::String); 329f9d6d204SZachary Turner llvm::ArrayRef<uint8_t> bytes = GetBytes(); 330f9d6d204SZachary Turner const char *str = reinterpret_cast<const char *>(bytes.data()); 331f9d6d204SZachary Turner result->SetValue(std::string(str, bytes.size())); 332f9d6d204SZachary Turner return result; 333f9d6d204SZachary Turner } 334f9d6d204SZachary Turner 3355a72c02bSZachary Turner // PythonString 3362c1f46dcSZachary Turner 337b9c1b51eSKate Stone PythonString::PythonString(PyRefType type, PyObject *py_obj) : PythonObject() { 338f8b22f8fSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string 3392c1f46dcSZachary Turner } 3402c1f46dcSZachary Turner 341b9c1b51eSKate Stone PythonString::PythonString(llvm::StringRef string) : PythonObject() { 34222c8efcdSZachary Turner SetString(string); 3432c1f46dcSZachary Turner } 3442c1f46dcSZachary Turner 345b9c1b51eSKate Stone PythonString::PythonString(const char *string) : PythonObject() { 34622c8efcdSZachary Turner SetString(llvm::StringRef(string)); 3472c1f46dcSZachary Turner } 3482c1f46dcSZachary Turner 349b9c1b51eSKate Stone PythonString::PythonString() : PythonObject() {} 3502c1f46dcSZachary Turner 351b9c1b51eSKate Stone PythonString::~PythonString() {} 3522c1f46dcSZachary Turner 353b9c1b51eSKate Stone bool PythonString::Check(PyObject *py_obj) { 35422c8efcdSZachary Turner if (!py_obj) 35522c8efcdSZachary Turner return false; 35618426935SZachary Turner 3577d6d218eSZachary Turner if (PyUnicode_Check(py_obj)) 3587d6d218eSZachary Turner return true; 3597d6d218eSZachary Turner #if PY_MAJOR_VERSION < 3 3607d6d218eSZachary Turner if (PyString_Check(py_obj)) 3617d6d218eSZachary Turner return true; 36222c8efcdSZachary Turner #endif 3637d6d218eSZachary Turner return false; 36422c8efcdSZachary Turner } 36522c8efcdSZachary Turner 366b9c1b51eSKate Stone void PythonString::Reset(PyRefType type, PyObject *py_obj) { 36705097246SAdrian Prantl // Grab the desired reference type so that if we end up rejecting `py_obj` it 36805097246SAdrian Prantl // still gets decremented if necessary. 369f8b22f8fSZachary Turner PythonObject result(type, py_obj); 370f8b22f8fSZachary Turner 371b9c1b51eSKate Stone if (!PythonString::Check(py_obj)) { 372f8b22f8fSZachary Turner PythonObject::Reset(); 373f8b22f8fSZachary Turner return; 37422c8efcdSZachary Turner } 3757d6d218eSZachary Turner #if PY_MAJOR_VERSION < 3 3767d6d218eSZachary Turner // In Python 2, Don't store PyUnicode objects directly, because we need 3777d6d218eSZachary Turner // access to their underlying character buffers which Python 2 doesn't 3787d6d218eSZachary Turner // provide. 3797d6d218eSZachary Turner if (PyUnicode_Check(py_obj)) 3807d6d218eSZachary Turner result.Reset(PyRefType::Owned, PyUnicode_AsUTF8String(result.get())); 3817d6d218eSZachary Turner #endif 382b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 38305097246SAdrian Prantl // overflow since it calls back into the virtual implementation. 384f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 3852c1f46dcSZachary Turner } 3862c1f46dcSZachary Turner 387b9c1b51eSKate Stone llvm::StringRef PythonString::GetString() const { 38818426935SZachary Turner if (!IsValid()) 38918426935SZachary Turner return llvm::StringRef(); 39018426935SZachary Turner 39122c8efcdSZachary Turner Py_ssize_t size; 3925457b426SPavel Labath const char *data; 39318426935SZachary Turner 39418426935SZachary Turner #if PY_MAJOR_VERSION >= 3 3955457b426SPavel Labath data = PyUnicode_AsUTF8AndSize(m_py_obj, &size); 39618426935SZachary Turner #else 3975457b426SPavel Labath char *c; 39818426935SZachary Turner PyString_AsStringAndSize(m_py_obj, &c, &size); 3995457b426SPavel Labath data = c; 40018426935SZachary Turner #endif 4015457b426SPavel Labath return llvm::StringRef(data, size); 40222c8efcdSZachary Turner } 4032c1f46dcSZachary Turner 404b9c1b51eSKate Stone size_t PythonString::GetSize() const { 405b9c1b51eSKate Stone if (IsValid()) { 40618426935SZachary Turner #if PY_MAJOR_VERSION >= 3 40718426935SZachary Turner return PyUnicode_GetSize(m_py_obj); 40818426935SZachary Turner #else 40918426935SZachary Turner return PyString_Size(m_py_obj); 41018426935SZachary Turner #endif 41118426935SZachary Turner } 4122c1f46dcSZachary Turner return 0; 4132c1f46dcSZachary Turner } 4142c1f46dcSZachary Turner 415b9c1b51eSKate Stone void PythonString::SetString(llvm::StringRef string) { 41622c8efcdSZachary Turner #if PY_MAJOR_VERSION >= 3 41722c8efcdSZachary Turner PyObject *unicode = PyUnicode_FromStringAndSize(string.data(), string.size()); 41818426935SZachary Turner PythonObject::Reset(PyRefType::Owned, unicode); 41922c8efcdSZachary Turner #else 42018426935SZachary Turner PyObject *str = PyString_FromStringAndSize(string.data(), string.size()); 42118426935SZachary Turner PythonObject::Reset(PyRefType::Owned, str); 42222c8efcdSZachary Turner #endif 4232c1f46dcSZachary Turner } 4242c1f46dcSZachary Turner 425b9c1b51eSKate Stone StructuredData::StringSP PythonString::CreateStructuredString() const { 4262c1f46dcSZachary Turner StructuredData::StringSP result(new StructuredData::String); 4272c1f46dcSZachary Turner result->SetValue(GetString()); 4282c1f46dcSZachary Turner return result; 4292c1f46dcSZachary Turner } 4302c1f46dcSZachary Turner 4312c1f46dcSZachary Turner // PythonInteger 4322c1f46dcSZachary Turner 433b9c1b51eSKate Stone PythonInteger::PythonInteger() : PythonObject() {} 4347d6d218eSZachary Turner 435f8b22f8fSZachary Turner PythonInteger::PythonInteger(PyRefType type, PyObject *py_obj) 436b9c1b51eSKate Stone : PythonObject() { 437f8b22f8fSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a integer type 4382c1f46dcSZachary Turner } 4392c1f46dcSZachary Turner 440b9c1b51eSKate Stone PythonInteger::PythonInteger(int64_t value) : PythonObject() { 4412c1f46dcSZachary Turner SetInteger(value); 4422c1f46dcSZachary Turner } 4432c1f46dcSZachary Turner 444b9c1b51eSKate Stone PythonInteger::~PythonInteger() {} 4452c1f46dcSZachary Turner 446b9c1b51eSKate Stone bool PythonInteger::Check(PyObject *py_obj) { 44722c8efcdSZachary Turner if (!py_obj) 44822c8efcdSZachary Turner return false; 44922c8efcdSZachary Turner 45022c8efcdSZachary Turner #if PY_MAJOR_VERSION >= 3 45105097246SAdrian Prantl // Python 3 does not have PyInt_Check. There is only one type of integral 45205097246SAdrian Prantl // value, long. 45322c8efcdSZachary Turner return PyLong_Check(py_obj); 45422c8efcdSZachary Turner #else 45522c8efcdSZachary Turner return PyLong_Check(py_obj) || PyInt_Check(py_obj); 45622c8efcdSZachary Turner #endif 4572c1f46dcSZachary Turner } 4582c1f46dcSZachary Turner 459b9c1b51eSKate Stone void PythonInteger::Reset(PyRefType type, PyObject *py_obj) { 46005097246SAdrian Prantl // Grab the desired reference type so that if we end up rejecting `py_obj` it 46105097246SAdrian Prantl // still gets decremented if necessary. 462f8b22f8fSZachary Turner PythonObject result(type, py_obj); 463f8b22f8fSZachary Turner 464b9c1b51eSKate Stone if (!PythonInteger::Check(py_obj)) { 465f8b22f8fSZachary Turner PythonObject::Reset(); 466f8b22f8fSZachary Turner return; 46722c8efcdSZachary Turner } 46822c8efcdSZachary Turner 46922c8efcdSZachary Turner #if PY_MAJOR_VERSION < 3 47005097246SAdrian Prantl // Always store this as a PyLong, which makes interoperability between Python 47105097246SAdrian Prantl // 2.x and Python 3.x easier. This is only necessary in 2.x, since 3.x 47205097246SAdrian Prantl // doesn't even have a PyInt. 473b9c1b51eSKate Stone if (PyInt_Check(py_obj)) { 474f8b22f8fSZachary Turner // Since we converted the original object to a different type, the new 47505097246SAdrian Prantl // object is an owned object regardless of the ownership semantics 47605097246SAdrian Prantl // requested by the user. 477f8b22f8fSZachary Turner result.Reset(PyRefType::Owned, PyLong_FromLongLong(PyInt_AsLong(py_obj))); 47822c8efcdSZachary Turner } 47922c8efcdSZachary Turner #endif 48022c8efcdSZachary Turner 481b9c1b51eSKate Stone assert(PyLong_Check(result.get()) && 482b9c1b51eSKate Stone "Couldn't get a PyLong from this PyObject"); 48322c8efcdSZachary Turner 484b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 48505097246SAdrian Prantl // overflow since it calls back into the virtual implementation. 486f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 4872c1f46dcSZachary Turner } 4882c1f46dcSZachary Turner 489b9c1b51eSKate Stone int64_t PythonInteger::GetInteger() const { 490b9c1b51eSKate Stone if (m_py_obj) { 491b9c1b51eSKate Stone assert(PyLong_Check(m_py_obj) && 492b9c1b51eSKate Stone "PythonInteger::GetInteger has a PyObject that isn't a PyLong"); 49322c8efcdSZachary Turner 494008ec446SGreg Clayton int overflow = 0; 495008ec446SGreg Clayton int64_t result = PyLong_AsLongLongAndOverflow(m_py_obj, &overflow); 496b9c1b51eSKate Stone if (overflow != 0) { 49705097246SAdrian Prantl // We got an integer that overflows, like 18446744072853913392L we can't 49805097246SAdrian Prantl // use PyLong_AsLongLong() as it will return 0xffffffffffffffff. If we 49905097246SAdrian Prantl // use the unsigned long long it will work as expected. 500008ec446SGreg Clayton const uint64_t uval = PyLong_AsUnsignedLongLong(m_py_obj); 5014f730dc7SIlia K result = static_cast<int64_t>(uval); 502008ec446SGreg Clayton } 503008ec446SGreg Clayton return result; 5042c1f46dcSZachary Turner } 5052c1f46dcSZachary Turner return UINT64_MAX; 5062c1f46dcSZachary Turner } 5072c1f46dcSZachary Turner 508b9c1b51eSKate Stone void PythonInteger::SetInteger(int64_t value) { 509f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Owned, PyLong_FromLongLong(value)); 5102c1f46dcSZachary Turner } 5112c1f46dcSZachary Turner 512b9c1b51eSKate Stone StructuredData::IntegerSP PythonInteger::CreateStructuredInteger() const { 5132c1f46dcSZachary Turner StructuredData::IntegerSP result(new StructuredData::Integer); 5142c1f46dcSZachary Turner result->SetValue(GetInteger()); 5152c1f46dcSZachary Turner return result; 5162c1f46dcSZachary Turner } 5172c1f46dcSZachary Turner 518b81d715cSTatyana Krasnukha // PythonBoolean 519b81d715cSTatyana Krasnukha 520b81d715cSTatyana Krasnukha PythonBoolean::PythonBoolean(PyRefType type, PyObject *py_obj) 521b81d715cSTatyana Krasnukha : PythonObject() { 522b81d715cSTatyana Krasnukha Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a boolean type 523b81d715cSTatyana Krasnukha } 524b81d715cSTatyana Krasnukha 525b81d715cSTatyana Krasnukha PythonBoolean::PythonBoolean(bool value) { 526b81d715cSTatyana Krasnukha SetValue(value); 527b81d715cSTatyana Krasnukha } 528b81d715cSTatyana Krasnukha 529b81d715cSTatyana Krasnukha bool PythonBoolean::Check(PyObject *py_obj) { 530b81d715cSTatyana Krasnukha return py_obj ? PyBool_Check(py_obj) : false; 531b81d715cSTatyana Krasnukha } 532b81d715cSTatyana Krasnukha 533b81d715cSTatyana Krasnukha void PythonBoolean::Reset(PyRefType type, PyObject *py_obj) { 534b81d715cSTatyana Krasnukha // Grab the desired reference type so that if we end up rejecting `py_obj` it 535b81d715cSTatyana Krasnukha // still gets decremented if necessary. 536b81d715cSTatyana Krasnukha PythonObject result(type, py_obj); 537b81d715cSTatyana Krasnukha 538b81d715cSTatyana Krasnukha if (!PythonBoolean::Check(py_obj)) { 539b81d715cSTatyana Krasnukha PythonObject::Reset(); 540b81d715cSTatyana Krasnukha return; 541b81d715cSTatyana Krasnukha } 542b81d715cSTatyana Krasnukha 543b81d715cSTatyana Krasnukha // Calling PythonObject::Reset(const PythonObject&) will lead to stack 544b81d715cSTatyana Krasnukha // overflow since it calls back into the virtual implementation. 545b81d715cSTatyana Krasnukha PythonObject::Reset(PyRefType::Borrowed, result.get()); 546b81d715cSTatyana Krasnukha } 547b81d715cSTatyana Krasnukha 548b81d715cSTatyana Krasnukha bool PythonBoolean::GetValue() const { 549b81d715cSTatyana Krasnukha return m_py_obj ? PyObject_IsTrue(m_py_obj) : false; 550b81d715cSTatyana Krasnukha } 551b81d715cSTatyana Krasnukha 552b81d715cSTatyana Krasnukha void PythonBoolean::SetValue(bool value) { 553b81d715cSTatyana Krasnukha PythonObject::Reset(PyRefType::Owned, PyBool_FromLong(value)); 554b81d715cSTatyana Krasnukha } 555b81d715cSTatyana Krasnukha 556b81d715cSTatyana Krasnukha StructuredData::BooleanSP PythonBoolean::CreateStructuredBoolean() const { 557b81d715cSTatyana Krasnukha StructuredData::BooleanSP result(new StructuredData::Boolean); 558b81d715cSTatyana Krasnukha result->SetValue(GetValue()); 559b81d715cSTatyana Krasnukha return result; 560b81d715cSTatyana Krasnukha } 561b81d715cSTatyana Krasnukha 5622c1f46dcSZachary Turner // PythonList 5632c1f46dcSZachary Turner 564b9c1b51eSKate Stone PythonList::PythonList(PyInitialValue value) : PythonObject() { 565f8b22f8fSZachary Turner if (value == PyInitialValue::Empty) 566f8b22f8fSZachary Turner Reset(PyRefType::Owned, PyList_New(0)); 5672c1f46dcSZachary Turner } 5682c1f46dcSZachary Turner 569b9c1b51eSKate Stone PythonList::PythonList(int list_size) : PythonObject() { 57087f47729SZachary Turner Reset(PyRefType::Owned, PyList_New(list_size)); 57187f47729SZachary Turner } 57287f47729SZachary Turner 573b9c1b51eSKate Stone PythonList::PythonList(PyRefType type, PyObject *py_obj) : PythonObject() { 574f8b22f8fSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a list 5752c1f46dcSZachary Turner } 5762c1f46dcSZachary Turner 577b9c1b51eSKate Stone PythonList::~PythonList() {} 5782c1f46dcSZachary Turner 579b9c1b51eSKate Stone bool PythonList::Check(PyObject *py_obj) { 58022c8efcdSZachary Turner if (!py_obj) 58122c8efcdSZachary Turner return false; 58222c8efcdSZachary Turner return PyList_Check(py_obj); 58322c8efcdSZachary Turner } 58422c8efcdSZachary Turner 585b9c1b51eSKate Stone void PythonList::Reset(PyRefType type, PyObject *py_obj) { 58605097246SAdrian Prantl // Grab the desired reference type so that if we end up rejecting `py_obj` it 58705097246SAdrian Prantl // still gets decremented if necessary. 588f8b22f8fSZachary Turner PythonObject result(type, py_obj); 589f8b22f8fSZachary Turner 590b9c1b51eSKate Stone if (!PythonList::Check(py_obj)) { 591f8b22f8fSZachary Turner PythonObject::Reset(); 592f8b22f8fSZachary Turner return; 59322c8efcdSZachary Turner } 59422c8efcdSZachary Turner 595b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 59605097246SAdrian Prantl // overflow since it calls back into the virtual implementation. 597f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 5982c1f46dcSZachary Turner } 5992c1f46dcSZachary Turner 600b9c1b51eSKate Stone uint32_t PythonList::GetSize() const { 601f8b22f8fSZachary Turner if (IsValid()) 6022c1f46dcSZachary Turner return PyList_GET_SIZE(m_py_obj); 6032c1f46dcSZachary Turner return 0; 6042c1f46dcSZachary Turner } 6052c1f46dcSZachary Turner 606b9c1b51eSKate Stone PythonObject PythonList::GetItemAtIndex(uint32_t index) const { 607f8b22f8fSZachary Turner if (IsValid()) 608f8b22f8fSZachary Turner return PythonObject(PyRefType::Borrowed, PyList_GetItem(m_py_obj, index)); 6092c1f46dcSZachary Turner return PythonObject(); 6102c1f46dcSZachary Turner } 6112c1f46dcSZachary Turner 612b9c1b51eSKate Stone void PythonList::SetItemAtIndex(uint32_t index, const PythonObject &object) { 613b9c1b51eSKate Stone if (IsAllocated() && object.IsValid()) { 614f8b22f8fSZachary Turner // PyList_SetItem is documented to "steal" a reference, so we need to 615f8b22f8fSZachary Turner // convert it to an owned reference by incrementing it. 616f8b22f8fSZachary Turner Py_INCREF(object.get()); 6172c1f46dcSZachary Turner PyList_SetItem(m_py_obj, index, object.get()); 6182c1f46dcSZachary Turner } 619f8b22f8fSZachary Turner } 6202c1f46dcSZachary Turner 621b9c1b51eSKate Stone void PythonList::AppendItem(const PythonObject &object) { 622b9c1b51eSKate Stone if (IsAllocated() && object.IsValid()) { 623f8b22f8fSZachary Turner // `PyList_Append` does *not* steal a reference, so do not call `Py_INCREF` 624f8b22f8fSZachary Turner // here like we do with `PyList_SetItem`. 6252c1f46dcSZachary Turner PyList_Append(m_py_obj, object.get()); 6262c1f46dcSZachary Turner } 627f8b22f8fSZachary Turner } 6282c1f46dcSZachary Turner 629b9c1b51eSKate Stone StructuredData::ArraySP PythonList::CreateStructuredArray() const { 6302c1f46dcSZachary Turner StructuredData::ArraySP result(new StructuredData::Array); 6312c1f46dcSZachary Turner uint32_t count = GetSize(); 632b9c1b51eSKate Stone for (uint32_t i = 0; i < count; ++i) { 6332c1f46dcSZachary Turner PythonObject obj = GetItemAtIndex(i); 6342c1f46dcSZachary Turner result->AddItem(obj.CreateStructuredObject()); 6352c1f46dcSZachary Turner } 6362c1f46dcSZachary Turner return result; 6372c1f46dcSZachary Turner } 6382c1f46dcSZachary Turner 639a1405147SZachary Turner // PythonTuple 640a1405147SZachary Turner 641b9c1b51eSKate Stone PythonTuple::PythonTuple(PyInitialValue value) : PythonObject() { 642a1405147SZachary Turner if (value == PyInitialValue::Empty) 643a1405147SZachary Turner Reset(PyRefType::Owned, PyTuple_New(0)); 644a1405147SZachary Turner } 645a1405147SZachary Turner 646b9c1b51eSKate Stone PythonTuple::PythonTuple(int tuple_size) : PythonObject() { 647a1405147SZachary Turner Reset(PyRefType::Owned, PyTuple_New(tuple_size)); 648a1405147SZachary Turner } 649a1405147SZachary Turner 650b9c1b51eSKate Stone PythonTuple::PythonTuple(PyRefType type, PyObject *py_obj) : PythonObject() { 651a1405147SZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a tuple 652a1405147SZachary Turner } 653a1405147SZachary Turner 654b9c1b51eSKate Stone PythonTuple::PythonTuple(std::initializer_list<PythonObject> objects) { 655a1405147SZachary Turner m_py_obj = PyTuple_New(objects.size()); 656a1405147SZachary Turner 657a1405147SZachary Turner uint32_t idx = 0; 658b9c1b51eSKate Stone for (auto object : objects) { 659a1405147SZachary Turner if (object.IsValid()) 660a1405147SZachary Turner SetItemAtIndex(idx, object); 661a1405147SZachary Turner idx++; 662a1405147SZachary Turner } 663a1405147SZachary Turner } 664a1405147SZachary Turner 665b9c1b51eSKate Stone PythonTuple::PythonTuple(std::initializer_list<PyObject *> objects) { 666a1405147SZachary Turner m_py_obj = PyTuple_New(objects.size()); 667a1405147SZachary Turner 668a1405147SZachary Turner uint32_t idx = 0; 669b9c1b51eSKate Stone for (auto py_object : objects) { 670a1405147SZachary Turner PythonObject object(PyRefType::Borrowed, py_object); 671a1405147SZachary Turner if (object.IsValid()) 672a1405147SZachary Turner SetItemAtIndex(idx, object); 673a1405147SZachary Turner idx++; 674a1405147SZachary Turner } 675a1405147SZachary Turner } 676a1405147SZachary Turner 677b9c1b51eSKate Stone PythonTuple::~PythonTuple() {} 678a1405147SZachary Turner 679b9c1b51eSKate Stone bool PythonTuple::Check(PyObject *py_obj) { 680a1405147SZachary Turner if (!py_obj) 681a1405147SZachary Turner return false; 682a1405147SZachary Turner return PyTuple_Check(py_obj); 683a1405147SZachary Turner } 684a1405147SZachary Turner 685b9c1b51eSKate Stone void PythonTuple::Reset(PyRefType type, PyObject *py_obj) { 68605097246SAdrian Prantl // Grab the desired reference type so that if we end up rejecting `py_obj` it 68705097246SAdrian Prantl // still gets decremented if necessary. 688a1405147SZachary Turner PythonObject result(type, py_obj); 689a1405147SZachary Turner 690b9c1b51eSKate Stone if (!PythonTuple::Check(py_obj)) { 691a1405147SZachary Turner PythonObject::Reset(); 692a1405147SZachary Turner return; 693a1405147SZachary Turner } 694a1405147SZachary Turner 695b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 69605097246SAdrian Prantl // overflow since it calls back into the virtual implementation. 697a1405147SZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 698a1405147SZachary Turner } 699a1405147SZachary Turner 700b9c1b51eSKate Stone uint32_t PythonTuple::GetSize() const { 701a1405147SZachary Turner if (IsValid()) 702a1405147SZachary Turner return PyTuple_GET_SIZE(m_py_obj); 703a1405147SZachary Turner return 0; 704a1405147SZachary Turner } 705a1405147SZachary Turner 706b9c1b51eSKate Stone PythonObject PythonTuple::GetItemAtIndex(uint32_t index) const { 707a1405147SZachary Turner if (IsValid()) 708a1405147SZachary Turner return PythonObject(PyRefType::Borrowed, PyTuple_GetItem(m_py_obj, index)); 709a1405147SZachary Turner return PythonObject(); 710a1405147SZachary Turner } 711a1405147SZachary Turner 712b9c1b51eSKate Stone void PythonTuple::SetItemAtIndex(uint32_t index, const PythonObject &object) { 713b9c1b51eSKate Stone if (IsAllocated() && object.IsValid()) { 714a1405147SZachary Turner // PyTuple_SetItem is documented to "steal" a reference, so we need to 715a1405147SZachary Turner // convert it to an owned reference by incrementing it. 716a1405147SZachary Turner Py_INCREF(object.get()); 717a1405147SZachary Turner PyTuple_SetItem(m_py_obj, index, object.get()); 718a1405147SZachary Turner } 719a1405147SZachary Turner } 720a1405147SZachary Turner 721b9c1b51eSKate Stone StructuredData::ArraySP PythonTuple::CreateStructuredArray() const { 722a1405147SZachary Turner StructuredData::ArraySP result(new StructuredData::Array); 723a1405147SZachary Turner uint32_t count = GetSize(); 724b9c1b51eSKate Stone for (uint32_t i = 0; i < count; ++i) { 725a1405147SZachary Turner PythonObject obj = GetItemAtIndex(i); 726a1405147SZachary Turner result->AddItem(obj.CreateStructuredObject()); 727a1405147SZachary Turner } 728a1405147SZachary Turner return result; 729a1405147SZachary Turner } 730a1405147SZachary Turner 7312c1f46dcSZachary Turner // PythonDictionary 7322c1f46dcSZachary Turner 733b9c1b51eSKate Stone PythonDictionary::PythonDictionary(PyInitialValue value) : PythonObject() { 734f8b22f8fSZachary Turner if (value == PyInitialValue::Empty) 735f8b22f8fSZachary Turner Reset(PyRefType::Owned, PyDict_New()); 7362c1f46dcSZachary Turner } 7372c1f46dcSZachary Turner 738f8b22f8fSZachary Turner PythonDictionary::PythonDictionary(PyRefType type, PyObject *py_obj) 739b9c1b51eSKate Stone : PythonObject() { 740f8b22f8fSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a dictionary 7412c1f46dcSZachary Turner } 7422c1f46dcSZachary Turner 743b9c1b51eSKate Stone PythonDictionary::~PythonDictionary() {} 7442c1f46dcSZachary Turner 745b9c1b51eSKate Stone bool PythonDictionary::Check(PyObject *py_obj) { 74622c8efcdSZachary Turner if (!py_obj) 74722c8efcdSZachary Turner return false; 74822c8efcdSZachary Turner 74922c8efcdSZachary Turner return PyDict_Check(py_obj); 75022c8efcdSZachary Turner } 75122c8efcdSZachary Turner 752b9c1b51eSKate Stone void PythonDictionary::Reset(PyRefType type, PyObject *py_obj) { 75305097246SAdrian Prantl // Grab the desired reference type so that if we end up rejecting `py_obj` it 75405097246SAdrian Prantl // still gets decremented if necessary. 755f8b22f8fSZachary Turner PythonObject result(type, py_obj); 756f8b22f8fSZachary Turner 757b9c1b51eSKate Stone if (!PythonDictionary::Check(py_obj)) { 758f8b22f8fSZachary Turner PythonObject::Reset(); 759f8b22f8fSZachary Turner return; 76022c8efcdSZachary Turner } 76122c8efcdSZachary Turner 762b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 76305097246SAdrian Prantl // overflow since it calls back into the virtual implementation. 764f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 7652c1f46dcSZachary Turner } 7662c1f46dcSZachary Turner 767b9c1b51eSKate Stone uint32_t PythonDictionary::GetSize() const { 768f8b22f8fSZachary Turner if (IsValid()) 7692c1f46dcSZachary Turner return PyDict_Size(m_py_obj); 7702c1f46dcSZachary Turner return 0; 7712c1f46dcSZachary Turner } 7722c1f46dcSZachary Turner 773b9c1b51eSKate Stone PythonList PythonDictionary::GetKeys() const { 774f8b22f8fSZachary Turner if (IsValid()) 775f8b22f8fSZachary Turner return PythonList(PyRefType::Owned, PyDict_Keys(m_py_obj)); 776f8b22f8fSZachary Turner return PythonList(PyInitialValue::Invalid); 7772c1f46dcSZachary Turner } 7782c1f46dcSZachary Turner 779b9c1b51eSKate Stone PythonObject PythonDictionary::GetItemForKey(const PythonObject &key) const { 780f8b22f8fSZachary Turner if (IsAllocated() && key.IsValid()) 781b9c1b51eSKate Stone return PythonObject(PyRefType::Borrowed, 782b9c1b51eSKate Stone PyDict_GetItem(m_py_obj, key.get())); 7832c1f46dcSZachary Turner return PythonObject(); 7842c1f46dcSZachary Turner } 7852c1f46dcSZachary Turner 786b9c1b51eSKate Stone void PythonDictionary::SetItemForKey(const PythonObject &key, 787b9c1b51eSKate Stone const PythonObject &value) { 788f8b22f8fSZachary Turner if (IsAllocated() && key.IsValid() && value.IsValid()) 7892c1f46dcSZachary Turner PyDict_SetItem(m_py_obj, key.get(), value.get()); 7902c1f46dcSZachary Turner } 7912c1f46dcSZachary Turner 7922c1f46dcSZachary Turner StructuredData::DictionarySP 793b9c1b51eSKate Stone PythonDictionary::CreateStructuredDictionary() const { 7942c1f46dcSZachary Turner StructuredData::DictionarySP result(new StructuredData::Dictionary); 7952c1f46dcSZachary Turner PythonList keys(GetKeys()); 7962c1f46dcSZachary Turner uint32_t num_keys = keys.GetSize(); 797b9c1b51eSKate Stone for (uint32_t i = 0; i < num_keys; ++i) { 7982c1f46dcSZachary Turner PythonObject key = keys.GetItemAtIndex(i); 7992c1f46dcSZachary Turner PythonObject value = GetItemForKey(key); 8002c1f46dcSZachary Turner StructuredData::ObjectSP structured_value = value.CreateStructuredObject(); 801f8b22f8fSZachary Turner result->AddItem(key.Str().GetString(), structured_value); 8022c1f46dcSZachary Turner } 8032c1f46dcSZachary Turner return result; 8042c1f46dcSZachary Turner } 8052c1f46dcSZachary Turner 806b9c1b51eSKate Stone PythonModule::PythonModule() : PythonObject() {} 8077841efbbSZachary Turner 808b9c1b51eSKate Stone PythonModule::PythonModule(PyRefType type, PyObject *py_obj) { 8097841efbbSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a module 8107841efbbSZachary Turner } 8117841efbbSZachary Turner 812b9c1b51eSKate Stone PythonModule::~PythonModule() {} 8137841efbbSZachary Turner 814b9c1b51eSKate Stone PythonModule PythonModule::BuiltinsModule() { 815a1405147SZachary Turner #if PY_MAJOR_VERSION >= 3 816a1405147SZachary Turner return AddModule("builtins"); 817a1405147SZachary Turner #else 818a1405147SZachary Turner return AddModule("__builtin__"); 819a1405147SZachary Turner #endif 820a1405147SZachary Turner } 821a1405147SZachary Turner 822b9c1b51eSKate Stone PythonModule PythonModule::MainModule() { return AddModule("__main__"); } 823a1405147SZachary Turner 824b9c1b51eSKate Stone PythonModule PythonModule::AddModule(llvm::StringRef module) { 825a1405147SZachary Turner std::string str = module.str(); 826a1405147SZachary Turner return PythonModule(PyRefType::Borrowed, PyImport_AddModule(str.c_str())); 8277841efbbSZachary Turner } 8287841efbbSZachary Turner 829b9c1b51eSKate Stone PythonModule PythonModule::ImportModule(llvm::StringRef module) { 8302419f1d5SZachary Turner std::string str = module.str(); 8312419f1d5SZachary Turner return PythonModule(PyRefType::Owned, PyImport_ImportModule(str.c_str())); 8322419f1d5SZachary Turner } 8332419f1d5SZachary Turner 834b9c1b51eSKate Stone bool PythonModule::Check(PyObject *py_obj) { 8357841efbbSZachary Turner if (!py_obj) 8367841efbbSZachary Turner return false; 8377841efbbSZachary Turner 8387841efbbSZachary Turner return PyModule_Check(py_obj); 8397841efbbSZachary Turner } 8407841efbbSZachary Turner 841b9c1b51eSKate Stone void PythonModule::Reset(PyRefType type, PyObject *py_obj) { 84205097246SAdrian Prantl // Grab the desired reference type so that if we end up rejecting `py_obj` it 84305097246SAdrian Prantl // still gets decremented if necessary. 8447841efbbSZachary Turner PythonObject result(type, py_obj); 8457841efbbSZachary Turner 846b9c1b51eSKate Stone if (!PythonModule::Check(py_obj)) { 8477841efbbSZachary Turner PythonObject::Reset(); 8487841efbbSZachary Turner return; 8497841efbbSZachary Turner } 8507841efbbSZachary Turner 851b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 85205097246SAdrian Prantl // overflow since it calls back into the virtual implementation. 8537841efbbSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 8547841efbbSZachary Turner } 8557841efbbSZachary Turner 856b9c1b51eSKate Stone PythonDictionary PythonModule::GetDictionary() const { 8577841efbbSZachary Turner return PythonDictionary(PyRefType::Borrowed, PyModule_GetDict(m_py_obj)); 8587841efbbSZachary Turner } 8597841efbbSZachary Turner 860b9c1b51eSKate Stone PythonCallable::PythonCallable() : PythonObject() {} 861a1405147SZachary Turner 862b9c1b51eSKate Stone PythonCallable::PythonCallable(PyRefType type, PyObject *py_obj) { 863a1405147SZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a callable 864a1405147SZachary Turner } 865a1405147SZachary Turner 866b9c1b51eSKate Stone PythonCallable::~PythonCallable() {} 867a1405147SZachary Turner 868b9c1b51eSKate Stone bool PythonCallable::Check(PyObject *py_obj) { 869a1405147SZachary Turner if (!py_obj) 870a1405147SZachary Turner return false; 871a1405147SZachary Turner 872a1405147SZachary Turner return PyCallable_Check(py_obj); 873a1405147SZachary Turner } 874a1405147SZachary Turner 875b9c1b51eSKate Stone void PythonCallable::Reset(PyRefType type, PyObject *py_obj) { 87605097246SAdrian Prantl // Grab the desired reference type so that if we end up rejecting `py_obj` it 87705097246SAdrian Prantl // still gets decremented if necessary. 878a1405147SZachary Turner PythonObject result(type, py_obj); 879a1405147SZachary Turner 880b9c1b51eSKate Stone if (!PythonCallable::Check(py_obj)) { 881a1405147SZachary Turner PythonObject::Reset(); 882a1405147SZachary Turner return; 883a1405147SZachary Turner } 884a1405147SZachary Turner 885b9c1b51eSKate Stone // Calling PythonObject::Reset(const PythonObject&) will lead to stack 88605097246SAdrian Prantl // overflow since it calls back into the virtual implementation. 887a1405147SZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 888a1405147SZachary Turner } 889a1405147SZachary Turner 890*27a14f19SJim Ingham PythonCallable::ArgInfo PythonCallable::GetNumInitArguments() const { 891*27a14f19SJim Ingham ArgInfo result = {0, false, false, false}; 892*27a14f19SJim Ingham if (!IsValid()) 893*27a14f19SJim Ingham return result; 894*27a14f19SJim Ingham PyObject *py_func_obj = m_py_obj; 895*27a14f19SJim Ingham if (!PyClass_Check(m_py_obj)) 896*27a14f19SJim Ingham return result; 897*27a14f19SJim Ingham 898*27a14f19SJim Ingham PythonObject __init__ = GetAttributeValue("__init__"); 899*27a14f19SJim Ingham if (__init__.IsValid() ) { 900*27a14f19SJim Ingham auto __init_callable__ = __init__.AsType<PythonCallable>(); 901*27a14f19SJim Ingham if (__init_callable__.IsValid()) 902*27a14f19SJim Ingham return __init_callable__.GetNumArguments(); 903*27a14f19SJim Ingham } 904*27a14f19SJim Ingham return result; 905*27a14f19SJim Ingham } 906*27a14f19SJim Ingham 907b9c1b51eSKate Stone PythonCallable::ArgInfo PythonCallable::GetNumArguments() const { 908a5d6765cSEnrico Granata ArgInfo result = {0, false, false, false}; 909a1405147SZachary Turner if (!IsValid()) 910b58fb2f4SZachary Turner return result; 911a1405147SZachary Turner 912a1405147SZachary Turner PyObject *py_func_obj = m_py_obj; 913b9c1b51eSKate Stone if (PyMethod_Check(py_func_obj)) { 914a1405147SZachary Turner py_func_obj = PyMethod_GET_FUNCTION(py_func_obj); 915a5d6765cSEnrico Granata PythonObject im_self = GetAttributeValue("im_self"); 916a5d6765cSEnrico Granata if (im_self.IsValid() && !im_self.IsNone()) 917a5d6765cSEnrico Granata result.is_bound_method = true; 918b9c1b51eSKate Stone } else { 919a5d6765cSEnrico Granata // see if this is a callable object with an __call__ method 920b9c1b51eSKate Stone if (!PyFunction_Check(py_func_obj)) { 921a5d6765cSEnrico Granata PythonObject __call__ = GetAttributeValue("__call__"); 922b9c1b51eSKate Stone if (__call__.IsValid()) { 923a5d6765cSEnrico Granata auto __callable__ = __call__.AsType<PythonCallable>(); 924b9c1b51eSKate Stone if (__callable__.IsValid()) { 925a5d6765cSEnrico Granata py_func_obj = PyMethod_GET_FUNCTION(__callable__.get()); 926a5d6765cSEnrico Granata PythonObject im_self = GetAttributeValue("im_self"); 927a5d6765cSEnrico Granata if (im_self.IsValid() && !im_self.IsNone()) 928a5d6765cSEnrico Granata result.is_bound_method = true; 929a5d6765cSEnrico Granata } 930a5d6765cSEnrico Granata } 931a5d6765cSEnrico Granata } 932a5d6765cSEnrico Granata } 933a1405147SZachary Turner 934a1405147SZachary Turner if (!py_func_obj) 935b58fb2f4SZachary Turner return result; 936a1405147SZachary Turner 937a1405147SZachary Turner PyCodeObject *code = (PyCodeObject *)PyFunction_GET_CODE(py_func_obj); 938a1405147SZachary Turner if (!code) 939b58fb2f4SZachary Turner return result; 940a1405147SZachary Turner 941b58fb2f4SZachary Turner result.count = code->co_argcount; 942b58fb2f4SZachary Turner result.has_varargs = !!(code->co_flags & CO_VARARGS); 943b58fb2f4SZachary Turner result.has_kwargs = !!(code->co_flags & CO_VARKEYWORDS); 944b58fb2f4SZachary Turner return result; 945b58fb2f4SZachary Turner } 946b58fb2f4SZachary Turner 947b9c1b51eSKate Stone PythonObject PythonCallable::operator()() { 948b9c1b51eSKate Stone return PythonObject(PyRefType::Owned, PyObject_CallObject(m_py_obj, nullptr)); 949a1405147SZachary Turner } 950a1405147SZachary Turner 951b9c1b51eSKate Stone PythonObject PythonCallable:: 952b9c1b51eSKate Stone operator()(std::initializer_list<PyObject *> args) { 953a1405147SZachary Turner PythonTuple arg_tuple(args); 954a1405147SZachary Turner return PythonObject(PyRefType::Owned, 955a1405147SZachary Turner PyObject_CallObject(m_py_obj, arg_tuple.get())); 956a1405147SZachary Turner } 957a1405147SZachary Turner 958b9c1b51eSKate Stone PythonObject PythonCallable:: 959b9c1b51eSKate Stone operator()(std::initializer_list<PythonObject> args) { 960a1405147SZachary Turner PythonTuple arg_tuple(args); 961a1405147SZachary Turner return PythonObject(PyRefType::Owned, 962a1405147SZachary Turner PyObject_CallObject(m_py_obj, arg_tuple.get())); 963a1405147SZachary Turner } 964a1405147SZachary Turner 965b9c1b51eSKate Stone PythonFile::PythonFile() : PythonObject() {} 96632064024SZachary Turner 967b9c1b51eSKate Stone PythonFile::PythonFile(File &file, const char *mode) { Reset(file, mode); } 9689c40264fSZachary Turner 969b9c1b51eSKate Stone PythonFile::PythonFile(PyRefType type, PyObject *o) { Reset(type, o); } 9709c40264fSZachary Turner 971b9c1b51eSKate Stone PythonFile::~PythonFile() {} 9729c40264fSZachary Turner 973b9c1b51eSKate Stone bool PythonFile::Check(PyObject *py_obj) { 97496898eb6SLawrence D'Anna if (!py_obj) 97596898eb6SLawrence D'Anna return false; 9769c40264fSZachary Turner #if PY_MAJOR_VERSION < 3 97723502721SJason Molenda return PyFile_Check(py_obj); 97823502721SJason Molenda #else 9799c40264fSZachary Turner // In Python 3, there is no `PyFile_Check`, and in fact PyFile is not even a 9809c40264fSZachary Turner // first-class object type anymore. `PyFile_FromFd` is just a thin wrapper 98105097246SAdrian Prantl // over `io.open()`, which returns some object derived from `io.IOBase`. As a 98205097246SAdrian Prantl // result, the only way to detect a file in Python 3 is to check whether it 98305097246SAdrian Prantl // inherits from `io.IOBase`. Since it is possible for non-files to also 9849c40264fSZachary Turner // inherit from `io.IOBase`, we additionally verify that it has the `fileno` 9859c40264fSZachary Turner // attribute, which should guarantee that it is backed by the file system. 9869c40264fSZachary Turner PythonObject io_module(PyRefType::Owned, PyImport_ImportModule("io")); 987b9c1b51eSKate Stone PythonDictionary io_dict(PyRefType::Borrowed, 988b9c1b51eSKate Stone PyModule_GetDict(io_module.get())); 9899c40264fSZachary Turner PythonObject io_base_class = io_dict.GetItemForKey(PythonString("IOBase")); 9909c40264fSZachary Turner 9919c40264fSZachary Turner PythonObject object_type(PyRefType::Owned, PyObject_Type(py_obj)); 9929c40264fSZachary Turner 9939c40264fSZachary Turner if (1 != PyObject_IsSubclass(object_type.get(), io_base_class.get())) 9949c40264fSZachary Turner return false; 9959c40264fSZachary Turner if (!object_type.HasAttribute("fileno")) 9969c40264fSZachary Turner return false; 9979c40264fSZachary Turner 9989c40264fSZachary Turner return true; 99923502721SJason Molenda #endif 10009c40264fSZachary Turner } 10019c40264fSZachary Turner 1002b9c1b51eSKate Stone void PythonFile::Reset(PyRefType type, PyObject *py_obj) { 100305097246SAdrian Prantl // Grab the desired reference type so that if we end up rejecting `py_obj` it 100405097246SAdrian Prantl // still gets decremented if necessary. 10059c40264fSZachary Turner PythonObject result(type, py_obj); 10069c40264fSZachary Turner 100723502721SJason Molenda if (!PythonFile::Check(py_obj)) { 10089c40264fSZachary Turner PythonObject::Reset(); 10099c40264fSZachary Turner return; 10109c40264fSZachary Turner } 10119c40264fSZachary Turner 10129c40264fSZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack 10139c40264fSZachary Turner // overflow since it calls back into the virtual implementation. 10149c40264fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 10159c40264fSZachary Turner } 10169c40264fSZachary Turner 1017b9c1b51eSKate Stone void PythonFile::Reset(File &file, const char *mode) { 1018b9c1b51eSKate Stone if (!file.IsValid()) { 101932ac147bSZachary Turner Reset(); 102032ac147bSZachary Turner return; 102132ac147bSZachary Turner } 102232ac147bSZachary Turner 10239c40264fSZachary Turner char *cmode = const_cast<char *>(mode); 10249c40264fSZachary Turner #if PY_MAJOR_VERSION >= 3 1025b9c1b51eSKate Stone Reset(PyRefType::Owned, PyFile_FromFd(file.GetDescriptor(), nullptr, cmode, 1026b9c1b51eSKate Stone -1, nullptr, "ignore", nullptr, 0)); 10279c40264fSZachary Turner #else 10289c40264fSZachary Turner // Read through the Python source, doesn't seem to modify these strings 10299c40264fSZachary Turner Reset(PyRefType::Owned, 1030b9c1b51eSKate Stone PyFile_FromFile(file.GetStream(), const_cast<char *>(""), cmode, 1031b9c1b51eSKate Stone nullptr)); 10329c40264fSZachary Turner #endif 10339c40264fSZachary Turner } 10349c40264fSZachary Turner 1035744959b9SEnrico Granata 10362fce1137SLawrence D'Anna FileUP PythonFile::GetUnderlyingFile() const { 1037eda01c31SZachary Turner if (!IsValid()) 10382fce1137SLawrence D'Anna return nullptr; 1039eda01c31SZachary Turner 1040eda01c31SZachary Turner // We don't own the file descriptor returned by this function, make sure the 1041eda01c31SZachary Turner // File object knows about that. 1042744959b9SEnrico Granata PythonString py_mode = GetAttributeValue("mode").AsType<PythonString>(); 104357504530SLawrence D'Anna auto options = File::GetOptionsFromMode(py_mode.GetString()); 1044f913fd6eSLawrence D'Anna auto file = std::unique_ptr<File>( 1045f913fd6eSLawrence D'Anna new NativeFile(PyObject_AsFileDescriptor(m_py_obj), options, false)); 10462fce1137SLawrence D'Anna if (!file->IsValid()) 10472fce1137SLawrence D'Anna return nullptr; 10482fce1137SLawrence D'Anna return file; 1049eda01c31SZachary Turner } 1050d68983e3SPavel Labath 1051d68983e3SPavel Labath #endif 1052