12c1f46dcSZachary Turner //===-- PythonDataObjects.cpp ------------------------------------*- C++ -*-===//
22c1f46dcSZachary Turner //
32c1f46dcSZachary Turner //                     The LLVM Compiler Infrastructure
42c1f46dcSZachary Turner //
52c1f46dcSZachary Turner // This file is distributed under the University of Illinois Open Source
62c1f46dcSZachary Turner // License. See LICENSE.TXT for details.
72c1f46dcSZachary Turner //
82c1f46dcSZachary Turner //===----------------------------------------------------------------------===//
92c1f46dcSZachary Turner 
102c1f46dcSZachary Turner #ifdef LLDB_DISABLE_PYTHON
112c1f46dcSZachary Turner 
122c1f46dcSZachary Turner // Python is disabled in this build
132c1f46dcSZachary Turner 
142c1f46dcSZachary Turner #else
152c1f46dcSZachary Turner 
162c1f46dcSZachary Turner #include "lldb-python.h"
172c1f46dcSZachary Turner #include "PythonDataObjects.h"
182c1f46dcSZachary Turner #include "ScriptInterpreterPython.h"
192c1f46dcSZachary Turner 
202c1f46dcSZachary Turner #include "lldb/Core/Stream.h"
212c1f46dcSZachary Turner #include "lldb/Host/File.h"
222c1f46dcSZachary Turner #include "lldb/Interpreter/ScriptInterpreter.h"
232c1f46dcSZachary Turner 
242c1f46dcSZachary Turner #include <stdio.h>
252c1f46dcSZachary Turner 
262c1f46dcSZachary Turner using namespace lldb_private;
272c1f46dcSZachary Turner using namespace lldb;
282c1f46dcSZachary Turner 
292c1f46dcSZachary Turner void
302c1f46dcSZachary Turner StructuredPythonObject::Dump(Stream &s) const
312c1f46dcSZachary Turner {
322c1f46dcSZachary Turner     s << "Python Obj: 0x" << GetValue();
332c1f46dcSZachary Turner }
342c1f46dcSZachary Turner 
352c1f46dcSZachary Turner //----------------------------------------------------------------------
362c1f46dcSZachary Turner // PythonObject
372c1f46dcSZachary Turner //----------------------------------------------------------------------
382c1f46dcSZachary Turner 
392c1f46dcSZachary Turner void
402c1f46dcSZachary Turner PythonObject::Dump(Stream &strm) const
412c1f46dcSZachary Turner {
422c1f46dcSZachary Turner     if (m_py_obj)
432c1f46dcSZachary Turner     {
442c1f46dcSZachary Turner         FILE *file = ::tmpfile();
452c1f46dcSZachary Turner         if (file)
462c1f46dcSZachary Turner         {
472c1f46dcSZachary Turner             ::PyObject_Print (m_py_obj, file, 0);
482c1f46dcSZachary Turner             const long length = ftell (file);
492c1f46dcSZachary Turner             if (length)
502c1f46dcSZachary Turner             {
512c1f46dcSZachary Turner                 ::rewind(file);
522c1f46dcSZachary Turner                 std::vector<char> file_contents (length,'\0');
532c1f46dcSZachary Turner                 const size_t length_read = ::fread (file_contents.data(), 1, file_contents.size(), file);
542c1f46dcSZachary Turner                 if (length_read > 0)
552c1f46dcSZachary Turner                     strm.Write (file_contents.data(), length_read);
562c1f46dcSZachary Turner             }
572c1f46dcSZachary Turner             ::fclose (file);
582c1f46dcSZachary Turner         }
592c1f46dcSZachary Turner     }
602c1f46dcSZachary Turner     else
612c1f46dcSZachary Turner         strm.PutCString ("NULL");
622c1f46dcSZachary Turner }
632c1f46dcSZachary Turner 
642c1f46dcSZachary Turner PyObjectType
652c1f46dcSZachary Turner PythonObject::GetObjectType() const
662c1f46dcSZachary Turner {
67f8b22f8fSZachary Turner     if (!IsAllocated())
682c1f46dcSZachary Turner         return PyObjectType::None;
692c1f46dcSZachary Turner 
70*7841efbbSZachary Turner     if (PythonModule::Check(m_py_obj))
71*7841efbbSZachary Turner         return PyObjectType::Module;
7218426935SZachary Turner     if (PythonList::Check(m_py_obj))
732c1f46dcSZachary Turner         return PyObjectType::List;
7418426935SZachary Turner     if (PythonDictionary::Check(m_py_obj))
752c1f46dcSZachary Turner         return PyObjectType::Dictionary;
7618426935SZachary Turner     if (PythonString::Check(m_py_obj))
7722c8efcdSZachary Turner         return PyObjectType::String;
7818426935SZachary Turner     if (PythonInteger::Check(m_py_obj))
7922c8efcdSZachary Turner         return PyObjectType::Integer;
809c40264fSZachary Turner     if (PythonFile::Check(m_py_obj))
819c40264fSZachary Turner         return PyObjectType::File;
822c1f46dcSZachary Turner     return PyObjectType::Unknown;
832c1f46dcSZachary Turner }
842c1f46dcSZachary Turner 
852c1f46dcSZachary Turner PythonString
86*7841efbbSZachary Turner PythonObject::Repr() const
872c1f46dcSZachary Turner {
882c1f46dcSZachary Turner     if (!m_py_obj)
892c1f46dcSZachary Turner         return PythonString();
902c1f46dcSZachary Turner     PyObject *repr = PyObject_Repr(m_py_obj);
912c1f46dcSZachary Turner     if (!repr)
922c1f46dcSZachary Turner         return PythonString();
93f8b22f8fSZachary Turner     return PythonString(PyRefType::Owned, repr);
942c1f46dcSZachary Turner }
952c1f46dcSZachary Turner 
962c1f46dcSZachary Turner PythonString
97*7841efbbSZachary Turner PythonObject::Str() const
982c1f46dcSZachary Turner {
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 
107*7841efbbSZachary Turner PythonObject
108*7841efbbSZachary Turner PythonObject::ResolveNameGlobal(llvm::StringRef name)
109*7841efbbSZachary Turner {
110*7841efbbSZachary Turner     return PythonModule::MainModule().ResolveName(name);
111*7841efbbSZachary Turner }
112*7841efbbSZachary Turner 
113*7841efbbSZachary Turner PythonObject
114*7841efbbSZachary Turner PythonObject::ResolveName(llvm::StringRef name) const
115*7841efbbSZachary Turner {
116*7841efbbSZachary Turner     // Resolve the name in the context of the specified object.  If,
117*7841efbbSZachary Turner     // for example, `this` refers to a PyModule, then this will look for
118*7841efbbSZachary Turner     // `name` in this module.  If `this` refers to a PyType, then it will
119*7841efbbSZachary Turner     // resolve `name` as an attribute of that type.  If `this` refers to
120*7841efbbSZachary Turner     // an instance of an object, then it will resolve `name` as the value
121*7841efbbSZachary Turner     // of the specified field.
122*7841efbbSZachary Turner     //
123*7841efbbSZachary Turner     // This function handles dotted names so that, for example, if `m_py_obj`
124*7841efbbSZachary Turner     // refers to the `sys` module, and `name` == "path.append", then it
125*7841efbbSZachary Turner     // will find the function `sys.path.append`.
126*7841efbbSZachary Turner 
127*7841efbbSZachary Turner     size_t dot_pos = name.find_first_of('.');
128*7841efbbSZachary Turner     if (dot_pos == llvm::StringRef::npos)
129*7841efbbSZachary Turner     {
130*7841efbbSZachary Turner         // No dots in the name, we should be able to find the value immediately
131*7841efbbSZachary Turner         // as an attribute of `use_object`.
132*7841efbbSZachary Turner         return GetAttributeValue(name);
133*7841efbbSZachary Turner     }
134*7841efbbSZachary Turner 
135*7841efbbSZachary Turner     // Look up the first piece of the name, and resolve the rest as a child of that.
136*7841efbbSZachary Turner     PythonObject parent = ResolveName(name.substr(0, dot_pos));
137*7841efbbSZachary Turner     if (!parent.IsAllocated())
138*7841efbbSZachary Turner         return PythonObject();
139*7841efbbSZachary Turner 
140*7841efbbSZachary Turner     // Tail recursion.. should be optimized by the compiler
141*7841efbbSZachary Turner     return parent.ResolveName(name.substr(dot_pos + 1));
142*7841efbbSZachary Turner }
143*7841efbbSZachary Turner 
1442c1f46dcSZachary Turner bool
1459c40264fSZachary Turner PythonObject::HasAttribute(llvm::StringRef attr) const
1469c40264fSZachary Turner {
1479c40264fSZachary Turner     if (!IsValid())
1489c40264fSZachary Turner         return false;
1499c40264fSZachary Turner     PythonString py_attr(attr);
1509c40264fSZachary Turner     return !!PyObject_HasAttr(m_py_obj, py_attr.get());
1519c40264fSZachary Turner }
1529c40264fSZachary Turner 
1537d6d218eSZachary Turner PythonObject
1547d6d218eSZachary Turner PythonObject::GetAttributeValue(llvm::StringRef attr) const
1557d6d218eSZachary Turner {
1567d6d218eSZachary Turner     if (!IsValid())
1577d6d218eSZachary Turner         return PythonObject();
1587d6d218eSZachary Turner 
1597d6d218eSZachary Turner     PythonString py_attr(attr);
1607d6d218eSZachary Turner     if (!PyObject_HasAttr(m_py_obj, py_attr.get()))
1617d6d218eSZachary Turner         return PythonObject();
1627d6d218eSZachary Turner 
1637d6d218eSZachary Turner     return PythonObject(PyRefType::Owned,
1647d6d218eSZachary Turner         PyObject_GetAttr(m_py_obj, py_attr.get()));
1657d6d218eSZachary Turner }
1667d6d218eSZachary Turner 
1679c40264fSZachary Turner bool
168f8b22f8fSZachary Turner PythonObject::IsNone() const
1692c1f46dcSZachary Turner {
170f8b22f8fSZachary Turner     return m_py_obj == Py_None;
171f8b22f8fSZachary Turner }
172f8b22f8fSZachary Turner 
173f8b22f8fSZachary Turner bool
174f8b22f8fSZachary Turner PythonObject::IsValid() const
175f8b22f8fSZachary Turner {
176f8b22f8fSZachary Turner     return m_py_obj != nullptr;
177f8b22f8fSZachary Turner }
178f8b22f8fSZachary Turner 
179f8b22f8fSZachary Turner bool
180f8b22f8fSZachary Turner PythonObject::IsAllocated() const
181f8b22f8fSZachary Turner {
182f8b22f8fSZachary Turner     return IsValid() && !IsNone();
1832c1f46dcSZachary Turner }
1842c1f46dcSZachary Turner 
1852c1f46dcSZachary Turner StructuredData::ObjectSP
1862c1f46dcSZachary Turner PythonObject::CreateStructuredObject() const
1872c1f46dcSZachary Turner {
1882c1f46dcSZachary Turner     switch (GetObjectType())
1892c1f46dcSZachary Turner     {
1902c1f46dcSZachary Turner         case PyObjectType::Dictionary:
191f8b22f8fSZachary Turner             return PythonDictionary(PyRefType::Borrowed, m_py_obj).CreateStructuredDictionary();
1922c1f46dcSZachary Turner         case PyObjectType::Integer:
193f8b22f8fSZachary Turner             return PythonInteger(PyRefType::Borrowed, m_py_obj).CreateStructuredInteger();
1942c1f46dcSZachary Turner         case PyObjectType::List:
195f8b22f8fSZachary Turner             return PythonList(PyRefType::Borrowed, m_py_obj).CreateStructuredArray();
1962c1f46dcSZachary Turner         case PyObjectType::String:
197f8b22f8fSZachary Turner             return PythonString(PyRefType::Borrowed, m_py_obj).CreateStructuredString();
1982c1f46dcSZachary Turner         case PyObjectType::None:
1992c1f46dcSZachary Turner             return StructuredData::ObjectSP();
2002c1f46dcSZachary Turner         default:
2012c1f46dcSZachary Turner             return StructuredData::ObjectSP(new StructuredPythonObject(m_py_obj));
2022c1f46dcSZachary Turner     }
2032c1f46dcSZachary Turner }
2042c1f46dcSZachary Turner 
2052c1f46dcSZachary Turner //----------------------------------------------------------------------
2062c1f46dcSZachary Turner // PythonString
2072c1f46dcSZachary Turner //----------------------------------------------------------------------
2082c1f46dcSZachary Turner 
209f8b22f8fSZachary Turner PythonString::PythonString(PyRefType type, PyObject *py_obj)
210f8b22f8fSZachary Turner     : PythonObject()
2112c1f46dcSZachary Turner {
212f8b22f8fSZachary Turner     Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string
2132c1f46dcSZachary Turner }
2142c1f46dcSZachary Turner 
215f8b22f8fSZachary Turner PythonString::PythonString(const PythonString &object)
216f8b22f8fSZachary Turner     : PythonObject(object)
2172c1f46dcSZachary Turner {
2182c1f46dcSZachary Turner }
2192c1f46dcSZachary Turner 
22022c8efcdSZachary Turner PythonString::PythonString(llvm::StringRef string)
22122c8efcdSZachary Turner     : PythonObject()
2222c1f46dcSZachary Turner {
22322c8efcdSZachary Turner     SetString(string);
2242c1f46dcSZachary Turner }
2252c1f46dcSZachary Turner 
22622c8efcdSZachary Turner PythonString::PythonString(const char *string)
22722c8efcdSZachary Turner     : PythonObject()
2282c1f46dcSZachary Turner {
22922c8efcdSZachary Turner     SetString(llvm::StringRef(string));
2302c1f46dcSZachary Turner }
2312c1f46dcSZachary Turner 
232f8b22f8fSZachary Turner PythonString::PythonString()
233f8b22f8fSZachary Turner     : PythonObject()
2342c1f46dcSZachary Turner {
2352c1f46dcSZachary Turner }
2362c1f46dcSZachary Turner 
2372c1f46dcSZachary Turner PythonString::~PythonString ()
2382c1f46dcSZachary Turner {
2392c1f46dcSZachary Turner }
2402c1f46dcSZachary Turner 
2412c1f46dcSZachary Turner bool
24222c8efcdSZachary Turner PythonString::Check(PyObject *py_obj)
24322c8efcdSZachary Turner {
24422c8efcdSZachary Turner     if (!py_obj)
24522c8efcdSZachary Turner         return false;
24618426935SZachary Turner 
2477d6d218eSZachary Turner     if (PyUnicode_Check(py_obj))
2487d6d218eSZachary Turner         return true;
2497d6d218eSZachary Turner #if PY_MAJOR_VERSION < 3
2507d6d218eSZachary Turner     if (PyString_Check(py_obj))
2517d6d218eSZachary Turner         return true;
25222c8efcdSZachary Turner #endif
2537d6d218eSZachary Turner     return false;
25422c8efcdSZachary Turner }
25522c8efcdSZachary Turner 
256f8b22f8fSZachary Turner void
257f8b22f8fSZachary Turner PythonString::Reset(PyRefType type, PyObject *py_obj)
2582c1f46dcSZachary Turner {
259f8b22f8fSZachary Turner     // Grab the desired reference type so that if we end up rejecting
260f8b22f8fSZachary Turner     // `py_obj` it still gets decremented if necessary.
261f8b22f8fSZachary Turner     PythonObject result(type, py_obj);
262f8b22f8fSZachary Turner 
26322c8efcdSZachary Turner     if (!PythonString::Check(py_obj))
26422c8efcdSZachary Turner     {
265f8b22f8fSZachary Turner         PythonObject::Reset();
266f8b22f8fSZachary Turner         return;
26722c8efcdSZachary Turner     }
2687d6d218eSZachary Turner #if PY_MAJOR_VERSION < 3
2697d6d218eSZachary Turner     // In Python 2, Don't store PyUnicode objects directly, because we need
2707d6d218eSZachary Turner     // access to their underlying character buffers which Python 2 doesn't
2717d6d218eSZachary Turner     // provide.
2727d6d218eSZachary Turner     if (PyUnicode_Check(py_obj))
2737d6d218eSZachary Turner         result.Reset(PyRefType::Owned, PyUnicode_AsUTF8String(result.get()));
2747d6d218eSZachary Turner #endif
275f8b22f8fSZachary Turner     // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
276f8b22f8fSZachary Turner     // back into the virtual implementation.
277f8b22f8fSZachary Turner     PythonObject::Reset(PyRefType::Borrowed, result.get());
2782c1f46dcSZachary Turner }
2792c1f46dcSZachary Turner 
2802c1f46dcSZachary Turner llvm::StringRef
2812c1f46dcSZachary Turner PythonString::GetString() const
2822c1f46dcSZachary Turner {
28318426935SZachary Turner     if (!IsValid())
28418426935SZachary Turner         return llvm::StringRef();
28518426935SZachary Turner 
28622c8efcdSZachary Turner     Py_ssize_t size;
28722c8efcdSZachary Turner     char *c;
28818426935SZachary Turner 
28918426935SZachary Turner #if PY_MAJOR_VERSION >= 3
29018426935SZachary Turner     c = PyUnicode_AsUTF8AndSize(m_py_obj, &size);
29118426935SZachary Turner #else
29218426935SZachary Turner     PyString_AsStringAndSize(m_py_obj, &c, &size);
29318426935SZachary Turner #endif
29422c8efcdSZachary Turner     return llvm::StringRef(c, size);
29522c8efcdSZachary Turner }
2962c1f46dcSZachary Turner 
2972c1f46dcSZachary Turner size_t
2982c1f46dcSZachary Turner PythonString::GetSize() const
2992c1f46dcSZachary Turner {
300f8b22f8fSZachary Turner     if (IsValid())
30118426935SZachary Turner     {
30218426935SZachary Turner #if PY_MAJOR_VERSION >= 3
30318426935SZachary Turner         return PyUnicode_GetSize(m_py_obj);
30418426935SZachary Turner #else
30518426935SZachary Turner         return PyString_Size(m_py_obj);
30618426935SZachary Turner #endif
30718426935SZachary Turner     }
3082c1f46dcSZachary Turner     return 0;
3092c1f46dcSZachary Turner }
3102c1f46dcSZachary Turner 
3112c1f46dcSZachary Turner void
3122c1f46dcSZachary Turner PythonString::SetString (llvm::StringRef string)
3132c1f46dcSZachary Turner {
31422c8efcdSZachary Turner #if PY_MAJOR_VERSION >= 3
31522c8efcdSZachary Turner     PyObject *unicode = PyUnicode_FromStringAndSize(string.data(), string.size());
31618426935SZachary Turner     PythonObject::Reset(PyRefType::Owned, unicode);
31722c8efcdSZachary Turner #else
31818426935SZachary Turner     PyObject *str = PyString_FromStringAndSize(string.data(), string.size());
31918426935SZachary Turner     PythonObject::Reset(PyRefType::Owned, str);
32022c8efcdSZachary Turner #endif
3212c1f46dcSZachary Turner }
3222c1f46dcSZachary Turner 
3232c1f46dcSZachary Turner StructuredData::StringSP
3242c1f46dcSZachary Turner PythonString::CreateStructuredString() const
3252c1f46dcSZachary Turner {
3262c1f46dcSZachary Turner     StructuredData::StringSP result(new StructuredData::String);
3272c1f46dcSZachary Turner     result->SetValue(GetString());
3282c1f46dcSZachary Turner     return result;
3292c1f46dcSZachary Turner }
3302c1f46dcSZachary Turner 
3312c1f46dcSZachary Turner //----------------------------------------------------------------------
3322c1f46dcSZachary Turner // PythonInteger
3332c1f46dcSZachary Turner //----------------------------------------------------------------------
3342c1f46dcSZachary Turner 
3357d6d218eSZachary Turner PythonInteger::PythonInteger()
3367d6d218eSZachary Turner     : PythonObject()
3377d6d218eSZachary Turner {
3387d6d218eSZachary Turner 
3397d6d218eSZachary Turner }
3407d6d218eSZachary Turner 
341f8b22f8fSZachary Turner PythonInteger::PythonInteger(PyRefType type, PyObject *py_obj)
342f8b22f8fSZachary Turner     : PythonObject()
3432c1f46dcSZachary Turner {
344f8b22f8fSZachary Turner     Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a integer type
3452c1f46dcSZachary Turner }
3462c1f46dcSZachary Turner 
347f8b22f8fSZachary Turner PythonInteger::PythonInteger(const PythonInteger &object)
348f8b22f8fSZachary Turner     : PythonObject(object)
3492c1f46dcSZachary Turner {
3502c1f46dcSZachary Turner }
3512c1f46dcSZachary Turner 
352f8b22f8fSZachary Turner PythonInteger::PythonInteger(int64_t value)
353f8b22f8fSZachary Turner     : PythonObject()
3542c1f46dcSZachary Turner {
3552c1f46dcSZachary Turner     SetInteger(value);
3562c1f46dcSZachary Turner }
3572c1f46dcSZachary Turner 
3582c1f46dcSZachary Turner 
3592c1f46dcSZachary Turner PythonInteger::~PythonInteger ()
3602c1f46dcSZachary Turner {
3612c1f46dcSZachary Turner }
3622c1f46dcSZachary Turner 
3632c1f46dcSZachary Turner bool
36422c8efcdSZachary Turner PythonInteger::Check(PyObject *py_obj)
3652c1f46dcSZachary Turner {
36622c8efcdSZachary Turner     if (!py_obj)
36722c8efcdSZachary Turner         return false;
36822c8efcdSZachary Turner 
36922c8efcdSZachary Turner #if PY_MAJOR_VERSION >= 3
37022c8efcdSZachary Turner     // Python 3 does not have PyInt_Check.  There is only one type of
37122c8efcdSZachary Turner     // integral value, long.
37222c8efcdSZachary Turner     return PyLong_Check(py_obj);
37322c8efcdSZachary Turner #else
37422c8efcdSZachary Turner     return PyLong_Check(py_obj) || PyInt_Check(py_obj);
37522c8efcdSZachary Turner #endif
3762c1f46dcSZachary Turner }
3772c1f46dcSZachary Turner 
378f8b22f8fSZachary Turner void
379f8b22f8fSZachary Turner PythonInteger::Reset(PyRefType type, PyObject *py_obj)
38022c8efcdSZachary Turner {
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 
38522c8efcdSZachary Turner     if (!PythonInteger::Check(py_obj))
38622c8efcdSZachary Turner     {
387f8b22f8fSZachary Turner         PythonObject::Reset();
388f8b22f8fSZachary Turner         return;
38922c8efcdSZachary Turner     }
39022c8efcdSZachary Turner 
39122c8efcdSZachary Turner #if PY_MAJOR_VERSION < 3
39222c8efcdSZachary Turner     // Always store this as a PyLong, which makes interoperability between
39322c8efcdSZachary Turner     // Python 2.x and Python 3.x easier.  This is only necessary in 2.x,
39422c8efcdSZachary Turner     // since 3.x doesn't even have a PyInt.
39522c8efcdSZachary Turner     if (PyInt_Check(py_obj))
39622c8efcdSZachary Turner     {
397f8b22f8fSZachary Turner         // Since we converted the original object to a different type, the new
398f8b22f8fSZachary Turner         // object is an owned object regardless of the ownership semantics requested
399f8b22f8fSZachary Turner         // by the user.
400f8b22f8fSZachary Turner         result.Reset(PyRefType::Owned, PyLong_FromLongLong(PyInt_AsLong(py_obj)));
40122c8efcdSZachary Turner     }
40222c8efcdSZachary Turner #endif
40322c8efcdSZachary Turner 
404f8b22f8fSZachary Turner     assert(PyLong_Check(result.get()) && "Couldn't get a PyLong from this PyObject");
40522c8efcdSZachary Turner 
406f8b22f8fSZachary Turner     // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
407f8b22f8fSZachary Turner     // back into the virtual implementation.
408f8b22f8fSZachary Turner     PythonObject::Reset(PyRefType::Borrowed, result.get());
4092c1f46dcSZachary Turner }
4102c1f46dcSZachary Turner 
4112c1f46dcSZachary Turner int64_t
4122c1f46dcSZachary Turner PythonInteger::GetInteger() const
4132c1f46dcSZachary Turner {
4142c1f46dcSZachary Turner     if (m_py_obj)
4152c1f46dcSZachary Turner     {
41622c8efcdSZachary Turner         assert(PyLong_Check(m_py_obj) && "PythonInteger::GetInteger has a PyObject that isn't a PyLong");
41722c8efcdSZachary Turner 
4182c1f46dcSZachary Turner         return PyLong_AsLongLong(m_py_obj);
4192c1f46dcSZachary Turner     }
4202c1f46dcSZachary Turner     return UINT64_MAX;
4212c1f46dcSZachary Turner }
4222c1f46dcSZachary Turner 
4232c1f46dcSZachary Turner void
4242c1f46dcSZachary Turner PythonInteger::SetInteger(int64_t value)
4252c1f46dcSZachary Turner {
426f8b22f8fSZachary Turner     PythonObject::Reset(PyRefType::Owned, PyLong_FromLongLong(value));
4272c1f46dcSZachary Turner }
4282c1f46dcSZachary Turner 
4292c1f46dcSZachary Turner StructuredData::IntegerSP
4302c1f46dcSZachary Turner PythonInteger::CreateStructuredInteger() const
4312c1f46dcSZachary Turner {
4322c1f46dcSZachary Turner     StructuredData::IntegerSP result(new StructuredData::Integer);
4332c1f46dcSZachary Turner     result->SetValue(GetInteger());
4342c1f46dcSZachary Turner     return result;
4352c1f46dcSZachary Turner }
4362c1f46dcSZachary Turner 
4372c1f46dcSZachary Turner //----------------------------------------------------------------------
4382c1f46dcSZachary Turner // PythonList
4392c1f46dcSZachary Turner //----------------------------------------------------------------------
4402c1f46dcSZachary Turner 
441f8b22f8fSZachary Turner PythonList::PythonList(PyInitialValue value)
442f8b22f8fSZachary Turner     : PythonObject()
4432c1f46dcSZachary Turner {
444f8b22f8fSZachary Turner     if (value == PyInitialValue::Empty)
445f8b22f8fSZachary Turner         Reset(PyRefType::Owned, PyList_New(0));
4462c1f46dcSZachary Turner }
4472c1f46dcSZachary Turner 
44887f47729SZachary Turner PythonList::PythonList(int list_size)
44987f47729SZachary Turner     : PythonObject()
45087f47729SZachary Turner {
45187f47729SZachary Turner     Reset(PyRefType::Owned, PyList_New(list_size));
45287f47729SZachary Turner }
45387f47729SZachary Turner 
454f8b22f8fSZachary Turner PythonList::PythonList(PyRefType type, PyObject *py_obj)
455f8b22f8fSZachary Turner     : PythonObject()
4562c1f46dcSZachary Turner {
457f8b22f8fSZachary Turner     Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a list
4582c1f46dcSZachary Turner }
4592c1f46dcSZachary Turner 
460f8b22f8fSZachary Turner PythonList::PythonList(const PythonList &list)
461f8b22f8fSZachary Turner     : PythonObject(list)
4622c1f46dcSZachary Turner {
4632c1f46dcSZachary Turner }
4642c1f46dcSZachary Turner 
4652c1f46dcSZachary Turner PythonList::~PythonList ()
4662c1f46dcSZachary Turner {
4672c1f46dcSZachary Turner }
4682c1f46dcSZachary Turner 
4692c1f46dcSZachary Turner bool
47022c8efcdSZachary Turner PythonList::Check(PyObject *py_obj)
47122c8efcdSZachary Turner {
47222c8efcdSZachary Turner     if (!py_obj)
47322c8efcdSZachary Turner         return false;
47422c8efcdSZachary Turner     return PyList_Check(py_obj);
47522c8efcdSZachary Turner }
47622c8efcdSZachary Turner 
477f8b22f8fSZachary Turner void
478f8b22f8fSZachary Turner PythonList::Reset(PyRefType type, PyObject *py_obj)
4792c1f46dcSZachary Turner {
480f8b22f8fSZachary Turner     // Grab the desired reference type so that if we end up rejecting
481f8b22f8fSZachary Turner     // `py_obj` it still gets decremented if necessary.
482f8b22f8fSZachary Turner     PythonObject result(type, py_obj);
483f8b22f8fSZachary Turner 
48422c8efcdSZachary Turner     if (!PythonList::Check(py_obj))
48522c8efcdSZachary Turner     {
486f8b22f8fSZachary Turner         PythonObject::Reset();
487f8b22f8fSZachary Turner         return;
48822c8efcdSZachary Turner     }
48922c8efcdSZachary Turner 
490f8b22f8fSZachary Turner     // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
491f8b22f8fSZachary Turner     // back into the virtual implementation.
492f8b22f8fSZachary Turner     PythonObject::Reset(PyRefType::Borrowed, result.get());
4932c1f46dcSZachary Turner }
4942c1f46dcSZachary Turner 
4952c1f46dcSZachary Turner uint32_t
4962c1f46dcSZachary Turner PythonList::GetSize() const
4972c1f46dcSZachary Turner {
498f8b22f8fSZachary Turner     if (IsValid())
4992c1f46dcSZachary Turner         return PyList_GET_SIZE(m_py_obj);
5002c1f46dcSZachary Turner     return 0;
5012c1f46dcSZachary Turner }
5022c1f46dcSZachary Turner 
5032c1f46dcSZachary Turner PythonObject
5042c1f46dcSZachary Turner PythonList::GetItemAtIndex(uint32_t index) const
5052c1f46dcSZachary Turner {
506f8b22f8fSZachary Turner     if (IsValid())
507f8b22f8fSZachary Turner         return PythonObject(PyRefType::Borrowed, PyList_GetItem(m_py_obj, index));
5082c1f46dcSZachary Turner     return PythonObject();
5092c1f46dcSZachary Turner }
5102c1f46dcSZachary Turner 
5112c1f46dcSZachary Turner void
5122c1f46dcSZachary Turner PythonList::SetItemAtIndex(uint32_t index, const PythonObject &object)
5132c1f46dcSZachary Turner {
514f8b22f8fSZachary Turner     if (IsAllocated() && object.IsValid())
515f8b22f8fSZachary Turner     {
516f8b22f8fSZachary Turner         // PyList_SetItem is documented to "steal" a reference, so we need to
517f8b22f8fSZachary Turner         // convert it to an owned reference by incrementing it.
518f8b22f8fSZachary Turner         Py_INCREF(object.get());
5192c1f46dcSZachary Turner         PyList_SetItem(m_py_obj, index, object.get());
5202c1f46dcSZachary Turner     }
521f8b22f8fSZachary Turner }
5222c1f46dcSZachary Turner 
5232c1f46dcSZachary Turner void
5242c1f46dcSZachary Turner PythonList::AppendItem(const PythonObject &object)
5252c1f46dcSZachary Turner {
526f8b22f8fSZachary Turner     if (IsAllocated() && object.IsValid())
527f8b22f8fSZachary Turner     {
528f8b22f8fSZachary Turner         // `PyList_Append` does *not* steal a reference, so do not call `Py_INCREF`
529f8b22f8fSZachary Turner         // here like we do with `PyList_SetItem`.
5302c1f46dcSZachary Turner         PyList_Append(m_py_obj, object.get());
5312c1f46dcSZachary Turner     }
532f8b22f8fSZachary Turner }
5332c1f46dcSZachary Turner 
5342c1f46dcSZachary Turner StructuredData::ArraySP
5352c1f46dcSZachary Turner PythonList::CreateStructuredArray() const
5362c1f46dcSZachary Turner {
5372c1f46dcSZachary Turner     StructuredData::ArraySP result(new StructuredData::Array);
5382c1f46dcSZachary Turner     uint32_t count = GetSize();
5392c1f46dcSZachary Turner     for (uint32_t i = 0; i < count; ++i)
5402c1f46dcSZachary Turner     {
5412c1f46dcSZachary Turner         PythonObject obj = GetItemAtIndex(i);
5422c1f46dcSZachary Turner         result->AddItem(obj.CreateStructuredObject());
5432c1f46dcSZachary Turner     }
5442c1f46dcSZachary Turner     return result;
5452c1f46dcSZachary Turner }
5462c1f46dcSZachary Turner 
5472c1f46dcSZachary Turner //----------------------------------------------------------------------
5482c1f46dcSZachary Turner // PythonDictionary
5492c1f46dcSZachary Turner //----------------------------------------------------------------------
5502c1f46dcSZachary Turner 
551f8b22f8fSZachary Turner PythonDictionary::PythonDictionary(PyInitialValue value)
552f8b22f8fSZachary Turner     : PythonObject()
5532c1f46dcSZachary Turner {
554f8b22f8fSZachary Turner     if (value == PyInitialValue::Empty)
555f8b22f8fSZachary Turner         Reset(PyRefType::Owned, PyDict_New());
5562c1f46dcSZachary Turner }
5572c1f46dcSZachary Turner 
558f8b22f8fSZachary Turner PythonDictionary::PythonDictionary(PyRefType type, PyObject *py_obj)
559f8b22f8fSZachary Turner     : PythonObject()
5602c1f46dcSZachary Turner {
561f8b22f8fSZachary Turner     Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a dictionary
5622c1f46dcSZachary Turner }
5632c1f46dcSZachary Turner 
564f8b22f8fSZachary Turner PythonDictionary::PythonDictionary(const PythonDictionary &object)
565f8b22f8fSZachary Turner     : PythonObject(object)
5662c1f46dcSZachary Turner {
5672c1f46dcSZachary Turner }
5682c1f46dcSZachary Turner 
5692c1f46dcSZachary Turner PythonDictionary::~PythonDictionary ()
5702c1f46dcSZachary Turner {
5712c1f46dcSZachary Turner }
5722c1f46dcSZachary Turner 
5732c1f46dcSZachary Turner bool
57422c8efcdSZachary Turner PythonDictionary::Check(PyObject *py_obj)
57522c8efcdSZachary Turner {
57622c8efcdSZachary Turner     if (!py_obj)
57722c8efcdSZachary Turner         return false;
57822c8efcdSZachary Turner 
57922c8efcdSZachary Turner     return PyDict_Check(py_obj);
58022c8efcdSZachary Turner }
58122c8efcdSZachary Turner 
582f8b22f8fSZachary Turner void
583f8b22f8fSZachary Turner PythonDictionary::Reset(PyRefType type, PyObject *py_obj)
5842c1f46dcSZachary Turner {
585f8b22f8fSZachary Turner     // Grab the desired reference type so that if we end up rejecting
586f8b22f8fSZachary Turner     // `py_obj` it still gets decremented if necessary.
587f8b22f8fSZachary Turner     PythonObject result(type, py_obj);
588f8b22f8fSZachary Turner 
58922c8efcdSZachary Turner     if (!PythonDictionary::Check(py_obj))
59022c8efcdSZachary Turner     {
591f8b22f8fSZachary Turner         PythonObject::Reset();
592f8b22f8fSZachary Turner         return;
59322c8efcdSZachary Turner     }
59422c8efcdSZachary Turner 
595f8b22f8fSZachary Turner     // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
596f8b22f8fSZachary Turner     // back into the virtual implementation.
597f8b22f8fSZachary Turner     PythonObject::Reset(PyRefType::Borrowed, result.get());
5982c1f46dcSZachary Turner }
5992c1f46dcSZachary Turner 
6002c1f46dcSZachary Turner uint32_t
6012c1f46dcSZachary Turner PythonDictionary::GetSize() const
6022c1f46dcSZachary Turner {
603f8b22f8fSZachary Turner     if (IsValid())
6042c1f46dcSZachary Turner         return PyDict_Size(m_py_obj);
6052c1f46dcSZachary Turner     return 0;
6062c1f46dcSZachary Turner }
6072c1f46dcSZachary Turner 
6082c1f46dcSZachary Turner PythonList
6092c1f46dcSZachary Turner PythonDictionary::GetKeys() const
6102c1f46dcSZachary Turner {
611f8b22f8fSZachary Turner     if (IsValid())
612f8b22f8fSZachary Turner         return PythonList(PyRefType::Owned, PyDict_Keys(m_py_obj));
613f8b22f8fSZachary Turner     return PythonList(PyInitialValue::Invalid);
6142c1f46dcSZachary Turner }
6152c1f46dcSZachary Turner 
6162c1f46dcSZachary Turner PythonObject
617f8b22f8fSZachary Turner PythonDictionary::GetItemForKey(const PythonObject &key) const
6182c1f46dcSZachary Turner {
619f8b22f8fSZachary Turner     if (IsAllocated() && key.IsValid())
620f8b22f8fSZachary Turner         return PythonObject(PyRefType::Borrowed, PyDict_GetItem(m_py_obj, key.get()));
6212c1f46dcSZachary Turner     return PythonObject();
6222c1f46dcSZachary Turner }
6232c1f46dcSZachary Turner 
6242c1f46dcSZachary Turner void
625f8b22f8fSZachary Turner PythonDictionary::SetItemForKey(const PythonObject &key, const PythonObject &value)
6262c1f46dcSZachary Turner {
627f8b22f8fSZachary Turner     if (IsAllocated() && key.IsValid() && value.IsValid())
6282c1f46dcSZachary Turner         PyDict_SetItem(m_py_obj, key.get(), value.get());
6292c1f46dcSZachary Turner }
6302c1f46dcSZachary Turner 
6312c1f46dcSZachary Turner StructuredData::DictionarySP
6322c1f46dcSZachary Turner PythonDictionary::CreateStructuredDictionary() const
6332c1f46dcSZachary Turner {
6342c1f46dcSZachary Turner     StructuredData::DictionarySP result(new StructuredData::Dictionary);
6352c1f46dcSZachary Turner     PythonList keys(GetKeys());
6362c1f46dcSZachary Turner     uint32_t num_keys = keys.GetSize();
6372c1f46dcSZachary Turner     for (uint32_t i = 0; i < num_keys; ++i)
6382c1f46dcSZachary Turner     {
6392c1f46dcSZachary Turner         PythonObject key = keys.GetItemAtIndex(i);
6402c1f46dcSZachary Turner         PythonObject value = GetItemForKey(key);
6412c1f46dcSZachary Turner         StructuredData::ObjectSP structured_value = value.CreateStructuredObject();
642f8b22f8fSZachary Turner         result->AddItem(key.Str().GetString(), structured_value);
6432c1f46dcSZachary Turner     }
6442c1f46dcSZachary Turner     return result;
6452c1f46dcSZachary Turner }
6462c1f46dcSZachary Turner 
647*7841efbbSZachary Turner PythonModule::PythonModule() : PythonObject()
648*7841efbbSZachary Turner {
649*7841efbbSZachary Turner }
650*7841efbbSZachary Turner 
651*7841efbbSZachary Turner PythonModule::PythonModule(PyRefType type, PyObject *py_obj)
652*7841efbbSZachary Turner {
653*7841efbbSZachary Turner     Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a module
654*7841efbbSZachary Turner }
655*7841efbbSZachary Turner 
656*7841efbbSZachary Turner PythonModule::PythonModule(const PythonModule &dict) : PythonObject(dict)
657*7841efbbSZachary Turner {
658*7841efbbSZachary Turner }
659*7841efbbSZachary Turner 
660*7841efbbSZachary Turner PythonModule::~PythonModule()
661*7841efbbSZachary Turner {
662*7841efbbSZachary Turner }
663*7841efbbSZachary Turner 
664*7841efbbSZachary Turner PythonModule
665*7841efbbSZachary Turner PythonModule::MainModule()
666*7841efbbSZachary Turner {
667*7841efbbSZachary Turner     return PythonModule(PyRefType::Borrowed, PyImport_AddModule("__main__"));
668*7841efbbSZachary Turner }
669*7841efbbSZachary Turner 
670*7841efbbSZachary Turner bool
671*7841efbbSZachary Turner PythonModule::Check(PyObject *py_obj)
672*7841efbbSZachary Turner {
673*7841efbbSZachary Turner     if (!py_obj)
674*7841efbbSZachary Turner         return false;
675*7841efbbSZachary Turner 
676*7841efbbSZachary Turner     return PyModule_Check(py_obj);
677*7841efbbSZachary Turner }
678*7841efbbSZachary Turner 
679*7841efbbSZachary Turner void
680*7841efbbSZachary Turner PythonModule::Reset(PyRefType type, PyObject *py_obj)
681*7841efbbSZachary Turner {
682*7841efbbSZachary Turner     // Grab the desired reference type so that if we end up rejecting
683*7841efbbSZachary Turner     // `py_obj` it still gets decremented if necessary.
684*7841efbbSZachary Turner     PythonObject result(type, py_obj);
685*7841efbbSZachary Turner 
686*7841efbbSZachary Turner     if (!PythonModule::Check(py_obj))
687*7841efbbSZachary Turner     {
688*7841efbbSZachary Turner         PythonObject::Reset();
689*7841efbbSZachary Turner         return;
690*7841efbbSZachary Turner     }
691*7841efbbSZachary Turner 
692*7841efbbSZachary Turner     // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
693*7841efbbSZachary Turner     // back into the virtual implementation.
694*7841efbbSZachary Turner     PythonObject::Reset(PyRefType::Borrowed, result.get());
695*7841efbbSZachary Turner }
696*7841efbbSZachary Turner 
697*7841efbbSZachary Turner PythonDictionary
698*7841efbbSZachary Turner PythonModule::GetDictionary() const
699*7841efbbSZachary Turner {
700*7841efbbSZachary Turner     return PythonDictionary(PyRefType::Borrowed, PyModule_GetDict(m_py_obj));
701*7841efbbSZachary Turner }
702*7841efbbSZachary Turner 
70332064024SZachary Turner PythonFile::PythonFile()
70432064024SZachary Turner     : PythonObject()
70532064024SZachary Turner {
70632064024SZachary Turner }
70732064024SZachary Turner 
7089c40264fSZachary Turner PythonFile::PythonFile(File &file, const char *mode)
7099c40264fSZachary Turner {
7109c40264fSZachary Turner     Reset(file, mode);
7119c40264fSZachary Turner }
7129c40264fSZachary Turner 
713eda01c31SZachary Turner PythonFile::PythonFile(const char *path, const char *mode)
714eda01c31SZachary Turner {
715eda01c31SZachary Turner     FILE *fp = nullptr;
716eda01c31SZachary Turner     fp = fopen(path, mode);
717eda01c31SZachary Turner     lldb_private::File file(fp, true);
718eda01c31SZachary Turner     Reset(file, mode);
719eda01c31SZachary Turner }
720eda01c31SZachary Turner 
7219c40264fSZachary Turner PythonFile::PythonFile(PyRefType type, PyObject *o)
7229c40264fSZachary Turner {
7239c40264fSZachary Turner     Reset(type, o);
7249c40264fSZachary Turner }
7259c40264fSZachary Turner 
7269c40264fSZachary Turner PythonFile::~PythonFile()
7279c40264fSZachary Turner {
7289c40264fSZachary Turner }
7299c40264fSZachary Turner 
7309c40264fSZachary Turner bool
7319c40264fSZachary Turner PythonFile::Check(PyObject *py_obj)
7329c40264fSZachary Turner {
7339c40264fSZachary Turner #if PY_MAJOR_VERSION < 3
7349c40264fSZachary Turner     return PyFile_Check(py_obj);
7359c40264fSZachary Turner #else
7369c40264fSZachary Turner     // In Python 3, there is no `PyFile_Check`, and in fact PyFile is not even a
7379c40264fSZachary Turner     // first-class object type anymore.  `PyFile_FromFd` is just a thin wrapper
7389c40264fSZachary Turner     // over `io.open()`, which returns some object derived from `io.IOBase`.
7399c40264fSZachary Turner     // As a result, the only way to detect a file in Python 3 is to check whether
7409c40264fSZachary Turner     // it inherits from `io.IOBase`.  Since it is possible for non-files to also
7419c40264fSZachary Turner     // inherit from `io.IOBase`, we additionally verify that it has the `fileno`
7429c40264fSZachary Turner     // attribute, which should guarantee that it is backed by the file system.
7439c40264fSZachary Turner     PythonObject io_module(PyRefType::Owned, PyImport_ImportModule("io"));
7449c40264fSZachary Turner     PythonDictionary io_dict(PyRefType::Borrowed, PyModule_GetDict(io_module.get()));
7459c40264fSZachary Turner     PythonObject io_base_class = io_dict.GetItemForKey(PythonString("IOBase"));
7469c40264fSZachary Turner 
7479c40264fSZachary Turner     PythonObject object_type(PyRefType::Owned, PyObject_Type(py_obj));
7489c40264fSZachary Turner 
7499c40264fSZachary Turner     if (1 != PyObject_IsSubclass(object_type.get(), io_base_class.get()))
7509c40264fSZachary Turner         return false;
7519c40264fSZachary Turner     if (!object_type.HasAttribute("fileno"))
7529c40264fSZachary Turner         return false;
7539c40264fSZachary Turner 
7549c40264fSZachary Turner     return true;
7559c40264fSZachary Turner #endif
7569c40264fSZachary Turner }
7579c40264fSZachary Turner 
7589c40264fSZachary Turner void
7599c40264fSZachary Turner PythonFile::Reset(PyRefType type, PyObject *py_obj)
7609c40264fSZachary Turner {
7619c40264fSZachary Turner     // Grab the desired reference type so that if we end up rejecting
7629c40264fSZachary Turner     // `py_obj` it still gets decremented if necessary.
7639c40264fSZachary Turner     PythonObject result(type, py_obj);
7649c40264fSZachary Turner 
7659c40264fSZachary Turner     if (!PythonFile::Check(py_obj))
7669c40264fSZachary Turner     {
7679c40264fSZachary Turner         PythonObject::Reset();
7689c40264fSZachary Turner         return;
7699c40264fSZachary Turner     }
7709c40264fSZachary Turner 
7719c40264fSZachary Turner     // Calling PythonObject::Reset(const PythonObject&) will lead to stack
7729c40264fSZachary Turner     // overflow since it calls back into the virtual implementation.
7739c40264fSZachary Turner     PythonObject::Reset(PyRefType::Borrowed, result.get());
7749c40264fSZachary Turner }
7759c40264fSZachary Turner 
7769c40264fSZachary Turner void
7779c40264fSZachary Turner PythonFile::Reset(File &file, const char *mode)
7789c40264fSZachary Turner {
7799c40264fSZachary Turner     char *cmode = const_cast<char *>(mode);
7809c40264fSZachary Turner #if PY_MAJOR_VERSION >= 3
7819c40264fSZachary Turner     Reset(PyRefType::Owned,
7829c40264fSZachary Turner         PyFile_FromFd(file.GetDescriptor(), nullptr, cmode, -1, nullptr, "ignore", nullptr, 0));
7839c40264fSZachary Turner #else
7849c40264fSZachary Turner     // Read through the Python source, doesn't seem to modify these strings
7859c40264fSZachary Turner     Reset(PyRefType::Owned,
7869c40264fSZachary Turner         PyFile_FromFile(file.GetStream(), const_cast<char *>(""), cmode, nullptr));
7879c40264fSZachary Turner #endif
7889c40264fSZachary Turner }
7899c40264fSZachary Turner 
790eda01c31SZachary Turner bool
791eda01c31SZachary Turner PythonFile::GetUnderlyingFile(File &file) const
792eda01c31SZachary Turner {
793eda01c31SZachary Turner     if (!IsValid())
794eda01c31SZachary Turner         return false;
795eda01c31SZachary Turner 
796eda01c31SZachary Turner     file.Close();
797eda01c31SZachary Turner     // We don't own the file descriptor returned by this function, make sure the
798eda01c31SZachary Turner     // File object knows about that.
799eda01c31SZachary Turner     file.SetDescriptor(PyObject_AsFileDescriptor(m_py_obj), false);
800eda01c31SZachary Turner     return file.IsValid();
801eda01c31SZachary Turner }
802eda01c31SZachary Turner 
803eda01c31SZachary Turner 
8042c1f46dcSZachary Turner #endif
805