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 
707841efbbSZachary Turner     if (PythonModule::Check(m_py_obj))
717841efbbSZachary Turner         return PyObjectType::Module;
7218426935SZachary Turner     if (PythonList::Check(m_py_obj))
732c1f46dcSZachary Turner         return PyObjectType::List;
74*a1405147SZachary Turner     if (PythonTuple::Check(m_py_obj))
75*a1405147SZachary Turner         return PyObjectType::Tuple;
7618426935SZachary Turner     if (PythonDictionary::Check(m_py_obj))
772c1f46dcSZachary Turner         return PyObjectType::Dictionary;
7818426935SZachary Turner     if (PythonString::Check(m_py_obj))
7922c8efcdSZachary Turner         return PyObjectType::String;
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;
84*a1405147SZachary Turner     if (PythonCallable::Check(m_py_obj))
85*a1405147SZachary Turner         return PyObjectType::Callable;
862c1f46dcSZachary Turner     return PyObjectType::Unknown;
872c1f46dcSZachary Turner }
882c1f46dcSZachary Turner 
892c1f46dcSZachary Turner PythonString
907841efbbSZachary Turner PythonObject::Repr() const
912c1f46dcSZachary Turner {
922c1f46dcSZachary Turner     if (!m_py_obj)
932c1f46dcSZachary Turner         return PythonString();
942c1f46dcSZachary Turner     PyObject *repr = PyObject_Repr(m_py_obj);
952c1f46dcSZachary Turner     if (!repr)
962c1f46dcSZachary Turner         return PythonString();
97f8b22f8fSZachary Turner     return PythonString(PyRefType::Owned, repr);
982c1f46dcSZachary Turner }
992c1f46dcSZachary Turner 
1002c1f46dcSZachary Turner PythonString
1017841efbbSZachary Turner PythonObject::Str() const
1022c1f46dcSZachary Turner {
1032c1f46dcSZachary Turner     if (!m_py_obj)
1042c1f46dcSZachary Turner         return PythonString();
1052c1f46dcSZachary Turner     PyObject *str = PyObject_Str(m_py_obj);
1062c1f46dcSZachary Turner     if (!str)
1072c1f46dcSZachary Turner         return PythonString();
108f8b22f8fSZachary Turner     return PythonString(PyRefType::Owned, str);
1092c1f46dcSZachary Turner }
1102c1f46dcSZachary Turner 
1117841efbbSZachary Turner PythonObject
112*a1405147SZachary Turner PythonObject::ResolveNameWithDictionary(llvm::StringRef name, PythonDictionary dict)
1137841efbbSZachary Turner {
114*a1405147SZachary Turner     size_t dot_pos = name.find_first_of('.');
115*a1405147SZachary Turner     llvm::StringRef piece = name.substr(0, dot_pos);
116*a1405147SZachary Turner     PythonObject result = dict.GetItemForKey(PythonString(piece));
117*a1405147SZachary Turner     if (dot_pos == llvm::StringRef::npos)
118*a1405147SZachary Turner     {
119*a1405147SZachary Turner         // There was no dot, we're done.
120*a1405147SZachary Turner         return result;
121*a1405147SZachary Turner     }
122*a1405147SZachary Turner 
123*a1405147SZachary Turner     // There was a dot.  The remaining portion of the name should be looked up in
124*a1405147SZachary Turner     // the context of the object that was found in the dictionary.
125*a1405147SZachary Turner     return result.ResolveName(name.substr(dot_pos + 1));
1267841efbbSZachary Turner }
1277841efbbSZachary Turner 
1287841efbbSZachary Turner PythonObject
1297841efbbSZachary Turner PythonObject::ResolveName(llvm::StringRef name) const
1307841efbbSZachary Turner {
1317841efbbSZachary Turner     // Resolve the name in the context of the specified object.  If,
1327841efbbSZachary Turner     // for example, `this` refers to a PyModule, then this will look for
1337841efbbSZachary Turner     // `name` in this module.  If `this` refers to a PyType, then it will
1347841efbbSZachary Turner     // resolve `name` as an attribute of that type.  If `this` refers to
1357841efbbSZachary Turner     // an instance of an object, then it will resolve `name` as the value
1367841efbbSZachary Turner     // of the specified field.
1377841efbbSZachary Turner     //
1387841efbbSZachary Turner     // This function handles dotted names so that, for example, if `m_py_obj`
1397841efbbSZachary Turner     // refers to the `sys` module, and `name` == "path.append", then it
1407841efbbSZachary Turner     // will find the function `sys.path.append`.
1417841efbbSZachary Turner 
1427841efbbSZachary Turner     size_t dot_pos = name.find_first_of('.');
1437841efbbSZachary Turner     if (dot_pos == llvm::StringRef::npos)
1447841efbbSZachary Turner     {
1457841efbbSZachary Turner         // No dots in the name, we should be able to find the value immediately
146*a1405147SZachary Turner         // as an attribute of `m_py_obj`.
1477841efbbSZachary Turner         return GetAttributeValue(name);
1487841efbbSZachary Turner     }
1497841efbbSZachary Turner 
1507841efbbSZachary Turner     // Look up the first piece of the name, and resolve the rest as a child of that.
1517841efbbSZachary Turner     PythonObject parent = ResolveName(name.substr(0, dot_pos));
1527841efbbSZachary Turner     if (!parent.IsAllocated())
1537841efbbSZachary Turner         return PythonObject();
1547841efbbSZachary Turner 
1557841efbbSZachary Turner     // Tail recursion.. should be optimized by the compiler
1567841efbbSZachary Turner     return parent.ResolveName(name.substr(dot_pos + 1));
1577841efbbSZachary Turner }
1587841efbbSZachary Turner 
1592c1f46dcSZachary Turner bool
1609c40264fSZachary Turner PythonObject::HasAttribute(llvm::StringRef attr) const
1619c40264fSZachary Turner {
1629c40264fSZachary Turner     if (!IsValid())
1639c40264fSZachary Turner         return false;
1649c40264fSZachary Turner     PythonString py_attr(attr);
1659c40264fSZachary Turner     return !!PyObject_HasAttr(m_py_obj, py_attr.get());
1669c40264fSZachary Turner }
1679c40264fSZachary Turner 
1687d6d218eSZachary Turner PythonObject
1697d6d218eSZachary Turner PythonObject::GetAttributeValue(llvm::StringRef attr) const
1707d6d218eSZachary Turner {
1717d6d218eSZachary Turner     if (!IsValid())
1727d6d218eSZachary Turner         return PythonObject();
1737d6d218eSZachary Turner 
1747d6d218eSZachary Turner     PythonString py_attr(attr);
1757d6d218eSZachary Turner     if (!PyObject_HasAttr(m_py_obj, py_attr.get()))
1767d6d218eSZachary Turner         return PythonObject();
1777d6d218eSZachary Turner 
1787d6d218eSZachary Turner     return PythonObject(PyRefType::Owned,
1797d6d218eSZachary Turner         PyObject_GetAttr(m_py_obj, py_attr.get()));
1807d6d218eSZachary Turner }
1817d6d218eSZachary Turner 
1829c40264fSZachary Turner bool
183f8b22f8fSZachary Turner PythonObject::IsNone() const
1842c1f46dcSZachary Turner {
185f8b22f8fSZachary Turner     return m_py_obj == Py_None;
186f8b22f8fSZachary Turner }
187f8b22f8fSZachary Turner 
188f8b22f8fSZachary Turner bool
189f8b22f8fSZachary Turner PythonObject::IsValid() const
190f8b22f8fSZachary Turner {
191f8b22f8fSZachary Turner     return m_py_obj != nullptr;
192f8b22f8fSZachary Turner }
193f8b22f8fSZachary Turner 
194f8b22f8fSZachary Turner bool
195f8b22f8fSZachary Turner PythonObject::IsAllocated() const
196f8b22f8fSZachary Turner {
197f8b22f8fSZachary Turner     return IsValid() && !IsNone();
1982c1f46dcSZachary Turner }
1992c1f46dcSZachary Turner 
2002c1f46dcSZachary Turner StructuredData::ObjectSP
2012c1f46dcSZachary Turner PythonObject::CreateStructuredObject() const
2022c1f46dcSZachary Turner {
2032c1f46dcSZachary Turner     switch (GetObjectType())
2042c1f46dcSZachary Turner     {
2052c1f46dcSZachary Turner         case PyObjectType::Dictionary:
206f8b22f8fSZachary Turner             return PythonDictionary(PyRefType::Borrowed, m_py_obj).CreateStructuredDictionary();
2072c1f46dcSZachary Turner         case PyObjectType::Integer:
208f8b22f8fSZachary Turner             return PythonInteger(PyRefType::Borrowed, m_py_obj).CreateStructuredInteger();
2092c1f46dcSZachary Turner         case PyObjectType::List:
210f8b22f8fSZachary Turner             return PythonList(PyRefType::Borrowed, m_py_obj).CreateStructuredArray();
2112c1f46dcSZachary Turner         case PyObjectType::String:
212f8b22f8fSZachary Turner             return PythonString(PyRefType::Borrowed, m_py_obj).CreateStructuredString();
2132c1f46dcSZachary Turner         case PyObjectType::None:
2142c1f46dcSZachary Turner             return StructuredData::ObjectSP();
2152c1f46dcSZachary Turner         default:
2162c1f46dcSZachary Turner             return StructuredData::ObjectSP(new StructuredPythonObject(m_py_obj));
2172c1f46dcSZachary Turner     }
2182c1f46dcSZachary Turner }
2192c1f46dcSZachary Turner 
2202c1f46dcSZachary Turner //----------------------------------------------------------------------
2212c1f46dcSZachary Turner // PythonString
2222c1f46dcSZachary Turner //----------------------------------------------------------------------
2232c1f46dcSZachary Turner 
224f8b22f8fSZachary Turner PythonString::PythonString(PyRefType type, PyObject *py_obj)
225f8b22f8fSZachary Turner     : PythonObject()
2262c1f46dcSZachary Turner {
227f8b22f8fSZachary Turner     Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string
2282c1f46dcSZachary Turner }
2292c1f46dcSZachary Turner 
230f8b22f8fSZachary Turner PythonString::PythonString(const PythonString &object)
231f8b22f8fSZachary Turner     : PythonObject(object)
2322c1f46dcSZachary Turner {
2332c1f46dcSZachary Turner }
2342c1f46dcSZachary Turner 
23522c8efcdSZachary Turner PythonString::PythonString(llvm::StringRef string)
23622c8efcdSZachary Turner     : PythonObject()
2372c1f46dcSZachary Turner {
23822c8efcdSZachary Turner     SetString(string);
2392c1f46dcSZachary Turner }
2402c1f46dcSZachary Turner 
24122c8efcdSZachary Turner PythonString::PythonString(const char *string)
24222c8efcdSZachary Turner     : PythonObject()
2432c1f46dcSZachary Turner {
24422c8efcdSZachary Turner     SetString(llvm::StringRef(string));
2452c1f46dcSZachary Turner }
2462c1f46dcSZachary Turner 
247f8b22f8fSZachary Turner PythonString::PythonString()
248f8b22f8fSZachary Turner     : PythonObject()
2492c1f46dcSZachary Turner {
2502c1f46dcSZachary Turner }
2512c1f46dcSZachary Turner 
2522c1f46dcSZachary Turner PythonString::~PythonString ()
2532c1f46dcSZachary Turner {
2542c1f46dcSZachary Turner }
2552c1f46dcSZachary Turner 
2562c1f46dcSZachary Turner bool
25722c8efcdSZachary Turner PythonString::Check(PyObject *py_obj)
25822c8efcdSZachary Turner {
25922c8efcdSZachary Turner     if (!py_obj)
26022c8efcdSZachary Turner         return false;
26118426935SZachary Turner 
2627d6d218eSZachary Turner     if (PyUnicode_Check(py_obj))
2637d6d218eSZachary Turner         return true;
2647d6d218eSZachary Turner #if PY_MAJOR_VERSION < 3
2657d6d218eSZachary Turner     if (PyString_Check(py_obj))
2667d6d218eSZachary Turner         return true;
26722c8efcdSZachary Turner #endif
2687d6d218eSZachary Turner     return false;
26922c8efcdSZachary Turner }
27022c8efcdSZachary Turner 
271f8b22f8fSZachary Turner void
272f8b22f8fSZachary Turner PythonString::Reset(PyRefType type, PyObject *py_obj)
2732c1f46dcSZachary Turner {
274f8b22f8fSZachary Turner     // Grab the desired reference type so that if we end up rejecting
275f8b22f8fSZachary Turner     // `py_obj` it still gets decremented if necessary.
276f8b22f8fSZachary Turner     PythonObject result(type, py_obj);
277f8b22f8fSZachary Turner 
27822c8efcdSZachary Turner     if (!PythonString::Check(py_obj))
27922c8efcdSZachary Turner     {
280f8b22f8fSZachary Turner         PythonObject::Reset();
281f8b22f8fSZachary Turner         return;
28222c8efcdSZachary Turner     }
2837d6d218eSZachary Turner #if PY_MAJOR_VERSION < 3
2847d6d218eSZachary Turner     // In Python 2, Don't store PyUnicode objects directly, because we need
2857d6d218eSZachary Turner     // access to their underlying character buffers which Python 2 doesn't
2867d6d218eSZachary Turner     // provide.
2877d6d218eSZachary Turner     if (PyUnicode_Check(py_obj))
2887d6d218eSZachary Turner         result.Reset(PyRefType::Owned, PyUnicode_AsUTF8String(result.get()));
2897d6d218eSZachary Turner #endif
290f8b22f8fSZachary Turner     // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
291f8b22f8fSZachary Turner     // back into the virtual implementation.
292f8b22f8fSZachary Turner     PythonObject::Reset(PyRefType::Borrowed, result.get());
2932c1f46dcSZachary Turner }
2942c1f46dcSZachary Turner 
2952c1f46dcSZachary Turner llvm::StringRef
2962c1f46dcSZachary Turner PythonString::GetString() const
2972c1f46dcSZachary Turner {
29818426935SZachary Turner     if (!IsValid())
29918426935SZachary Turner         return llvm::StringRef();
30018426935SZachary Turner 
30122c8efcdSZachary Turner     Py_ssize_t size;
30222c8efcdSZachary Turner     char *c;
30318426935SZachary Turner 
30418426935SZachary Turner #if PY_MAJOR_VERSION >= 3
30518426935SZachary Turner     c = PyUnicode_AsUTF8AndSize(m_py_obj, &size);
30618426935SZachary Turner #else
30718426935SZachary Turner     PyString_AsStringAndSize(m_py_obj, &c, &size);
30818426935SZachary Turner #endif
30922c8efcdSZachary Turner     return llvm::StringRef(c, size);
31022c8efcdSZachary Turner }
3112c1f46dcSZachary Turner 
3122c1f46dcSZachary Turner size_t
3132c1f46dcSZachary Turner PythonString::GetSize() const
3142c1f46dcSZachary Turner {
315f8b22f8fSZachary Turner     if (IsValid())
31618426935SZachary Turner     {
31718426935SZachary Turner #if PY_MAJOR_VERSION >= 3
31818426935SZachary Turner         return PyUnicode_GetSize(m_py_obj);
31918426935SZachary Turner #else
32018426935SZachary Turner         return PyString_Size(m_py_obj);
32118426935SZachary Turner #endif
32218426935SZachary Turner     }
3232c1f46dcSZachary Turner     return 0;
3242c1f46dcSZachary Turner }
3252c1f46dcSZachary Turner 
3262c1f46dcSZachary Turner void
3272c1f46dcSZachary Turner PythonString::SetString (llvm::StringRef string)
3282c1f46dcSZachary Turner {
32922c8efcdSZachary Turner #if PY_MAJOR_VERSION >= 3
33022c8efcdSZachary Turner     PyObject *unicode = PyUnicode_FromStringAndSize(string.data(), string.size());
33118426935SZachary Turner     PythonObject::Reset(PyRefType::Owned, unicode);
33222c8efcdSZachary Turner #else
33318426935SZachary Turner     PyObject *str = PyString_FromStringAndSize(string.data(), string.size());
33418426935SZachary Turner     PythonObject::Reset(PyRefType::Owned, str);
33522c8efcdSZachary Turner #endif
3362c1f46dcSZachary Turner }
3372c1f46dcSZachary Turner 
3382c1f46dcSZachary Turner StructuredData::StringSP
3392c1f46dcSZachary Turner PythonString::CreateStructuredString() const
3402c1f46dcSZachary Turner {
3412c1f46dcSZachary Turner     StructuredData::StringSP result(new StructuredData::String);
3422c1f46dcSZachary Turner     result->SetValue(GetString());
3432c1f46dcSZachary Turner     return result;
3442c1f46dcSZachary Turner }
3452c1f46dcSZachary Turner 
3462c1f46dcSZachary Turner //----------------------------------------------------------------------
3472c1f46dcSZachary Turner // PythonInteger
3482c1f46dcSZachary Turner //----------------------------------------------------------------------
3492c1f46dcSZachary Turner 
3507d6d218eSZachary Turner PythonInteger::PythonInteger()
3517d6d218eSZachary Turner     : PythonObject()
3527d6d218eSZachary Turner {
3537d6d218eSZachary Turner 
3547d6d218eSZachary Turner }
3557d6d218eSZachary Turner 
356f8b22f8fSZachary Turner PythonInteger::PythonInteger(PyRefType type, PyObject *py_obj)
357f8b22f8fSZachary Turner     : PythonObject()
3582c1f46dcSZachary Turner {
359f8b22f8fSZachary Turner     Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a integer type
3602c1f46dcSZachary Turner }
3612c1f46dcSZachary Turner 
362f8b22f8fSZachary Turner PythonInteger::PythonInteger(const PythonInteger &object)
363f8b22f8fSZachary Turner     : PythonObject(object)
3642c1f46dcSZachary Turner {
3652c1f46dcSZachary Turner }
3662c1f46dcSZachary Turner 
367f8b22f8fSZachary Turner PythonInteger::PythonInteger(int64_t value)
368f8b22f8fSZachary Turner     : PythonObject()
3692c1f46dcSZachary Turner {
3702c1f46dcSZachary Turner     SetInteger(value);
3712c1f46dcSZachary Turner }
3722c1f46dcSZachary Turner 
3732c1f46dcSZachary Turner 
3742c1f46dcSZachary Turner PythonInteger::~PythonInteger ()
3752c1f46dcSZachary Turner {
3762c1f46dcSZachary Turner }
3772c1f46dcSZachary Turner 
3782c1f46dcSZachary Turner bool
37922c8efcdSZachary Turner PythonInteger::Check(PyObject *py_obj)
3802c1f46dcSZachary Turner {
38122c8efcdSZachary Turner     if (!py_obj)
38222c8efcdSZachary Turner         return false;
38322c8efcdSZachary Turner 
38422c8efcdSZachary Turner #if PY_MAJOR_VERSION >= 3
38522c8efcdSZachary Turner     // Python 3 does not have PyInt_Check.  There is only one type of
38622c8efcdSZachary Turner     // integral value, long.
38722c8efcdSZachary Turner     return PyLong_Check(py_obj);
38822c8efcdSZachary Turner #else
38922c8efcdSZachary Turner     return PyLong_Check(py_obj) || PyInt_Check(py_obj);
39022c8efcdSZachary Turner #endif
3912c1f46dcSZachary Turner }
3922c1f46dcSZachary Turner 
393f8b22f8fSZachary Turner void
394f8b22f8fSZachary Turner PythonInteger::Reset(PyRefType type, PyObject *py_obj)
39522c8efcdSZachary Turner {
396f8b22f8fSZachary Turner     // Grab the desired reference type so that if we end up rejecting
397f8b22f8fSZachary Turner     // `py_obj` it still gets decremented if necessary.
398f8b22f8fSZachary Turner     PythonObject result(type, py_obj);
399f8b22f8fSZachary Turner 
40022c8efcdSZachary Turner     if (!PythonInteger::Check(py_obj))
40122c8efcdSZachary Turner     {
402f8b22f8fSZachary Turner         PythonObject::Reset();
403f8b22f8fSZachary Turner         return;
40422c8efcdSZachary Turner     }
40522c8efcdSZachary Turner 
40622c8efcdSZachary Turner #if PY_MAJOR_VERSION < 3
40722c8efcdSZachary Turner     // Always store this as a PyLong, which makes interoperability between
40822c8efcdSZachary Turner     // Python 2.x and Python 3.x easier.  This is only necessary in 2.x,
40922c8efcdSZachary Turner     // since 3.x doesn't even have a PyInt.
41022c8efcdSZachary Turner     if (PyInt_Check(py_obj))
41122c8efcdSZachary Turner     {
412f8b22f8fSZachary Turner         // Since we converted the original object to a different type, the new
413f8b22f8fSZachary Turner         // object is an owned object regardless of the ownership semantics requested
414f8b22f8fSZachary Turner         // by the user.
415f8b22f8fSZachary Turner         result.Reset(PyRefType::Owned, PyLong_FromLongLong(PyInt_AsLong(py_obj)));
41622c8efcdSZachary Turner     }
41722c8efcdSZachary Turner #endif
41822c8efcdSZachary Turner 
419f8b22f8fSZachary Turner     assert(PyLong_Check(result.get()) && "Couldn't get a PyLong from this PyObject");
42022c8efcdSZachary Turner 
421f8b22f8fSZachary Turner     // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
422f8b22f8fSZachary Turner     // back into the virtual implementation.
423f8b22f8fSZachary Turner     PythonObject::Reset(PyRefType::Borrowed, result.get());
4242c1f46dcSZachary Turner }
4252c1f46dcSZachary Turner 
4262c1f46dcSZachary Turner int64_t
4272c1f46dcSZachary Turner PythonInteger::GetInteger() const
4282c1f46dcSZachary Turner {
4292c1f46dcSZachary Turner     if (m_py_obj)
4302c1f46dcSZachary Turner     {
43122c8efcdSZachary Turner         assert(PyLong_Check(m_py_obj) && "PythonInteger::GetInteger has a PyObject that isn't a PyLong");
43222c8efcdSZachary Turner 
4332c1f46dcSZachary Turner         return PyLong_AsLongLong(m_py_obj);
4342c1f46dcSZachary Turner     }
4352c1f46dcSZachary Turner     return UINT64_MAX;
4362c1f46dcSZachary Turner }
4372c1f46dcSZachary Turner 
4382c1f46dcSZachary Turner void
4392c1f46dcSZachary Turner PythonInteger::SetInteger(int64_t value)
4402c1f46dcSZachary Turner {
441f8b22f8fSZachary Turner     PythonObject::Reset(PyRefType::Owned, PyLong_FromLongLong(value));
4422c1f46dcSZachary Turner }
4432c1f46dcSZachary Turner 
4442c1f46dcSZachary Turner StructuredData::IntegerSP
4452c1f46dcSZachary Turner PythonInteger::CreateStructuredInteger() const
4462c1f46dcSZachary Turner {
4472c1f46dcSZachary Turner     StructuredData::IntegerSP result(new StructuredData::Integer);
4482c1f46dcSZachary Turner     result->SetValue(GetInteger());
4492c1f46dcSZachary Turner     return result;
4502c1f46dcSZachary Turner }
4512c1f46dcSZachary Turner 
4522c1f46dcSZachary Turner //----------------------------------------------------------------------
4532c1f46dcSZachary Turner // PythonList
4542c1f46dcSZachary Turner //----------------------------------------------------------------------
4552c1f46dcSZachary Turner 
456f8b22f8fSZachary Turner PythonList::PythonList(PyInitialValue value)
457f8b22f8fSZachary Turner     : PythonObject()
4582c1f46dcSZachary Turner {
459f8b22f8fSZachary Turner     if (value == PyInitialValue::Empty)
460f8b22f8fSZachary Turner         Reset(PyRefType::Owned, PyList_New(0));
4612c1f46dcSZachary Turner }
4622c1f46dcSZachary Turner 
46387f47729SZachary Turner PythonList::PythonList(int list_size)
46487f47729SZachary Turner     : PythonObject()
46587f47729SZachary Turner {
46687f47729SZachary Turner     Reset(PyRefType::Owned, PyList_New(list_size));
46787f47729SZachary Turner }
46887f47729SZachary Turner 
469f8b22f8fSZachary Turner PythonList::PythonList(PyRefType type, PyObject *py_obj)
470f8b22f8fSZachary Turner     : PythonObject()
4712c1f46dcSZachary Turner {
472f8b22f8fSZachary Turner     Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a list
4732c1f46dcSZachary Turner }
4742c1f46dcSZachary Turner 
475f8b22f8fSZachary Turner PythonList::PythonList(const PythonList &list)
476f8b22f8fSZachary Turner     : PythonObject(list)
4772c1f46dcSZachary Turner {
4782c1f46dcSZachary Turner }
4792c1f46dcSZachary Turner 
4802c1f46dcSZachary Turner PythonList::~PythonList ()
4812c1f46dcSZachary Turner {
4822c1f46dcSZachary Turner }
4832c1f46dcSZachary Turner 
4842c1f46dcSZachary Turner bool
48522c8efcdSZachary Turner PythonList::Check(PyObject *py_obj)
48622c8efcdSZachary Turner {
48722c8efcdSZachary Turner     if (!py_obj)
48822c8efcdSZachary Turner         return false;
48922c8efcdSZachary Turner     return PyList_Check(py_obj);
49022c8efcdSZachary Turner }
49122c8efcdSZachary Turner 
492f8b22f8fSZachary Turner void
493f8b22f8fSZachary Turner PythonList::Reset(PyRefType type, PyObject *py_obj)
4942c1f46dcSZachary Turner {
495f8b22f8fSZachary Turner     // Grab the desired reference type so that if we end up rejecting
496f8b22f8fSZachary Turner     // `py_obj` it still gets decremented if necessary.
497f8b22f8fSZachary Turner     PythonObject result(type, py_obj);
498f8b22f8fSZachary Turner 
49922c8efcdSZachary Turner     if (!PythonList::Check(py_obj))
50022c8efcdSZachary Turner     {
501f8b22f8fSZachary Turner         PythonObject::Reset();
502f8b22f8fSZachary Turner         return;
50322c8efcdSZachary Turner     }
50422c8efcdSZachary Turner 
505f8b22f8fSZachary Turner     // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
506f8b22f8fSZachary Turner     // back into the virtual implementation.
507f8b22f8fSZachary Turner     PythonObject::Reset(PyRefType::Borrowed, result.get());
5082c1f46dcSZachary Turner }
5092c1f46dcSZachary Turner 
5102c1f46dcSZachary Turner uint32_t
5112c1f46dcSZachary Turner PythonList::GetSize() const
5122c1f46dcSZachary Turner {
513f8b22f8fSZachary Turner     if (IsValid())
5142c1f46dcSZachary Turner         return PyList_GET_SIZE(m_py_obj);
5152c1f46dcSZachary Turner     return 0;
5162c1f46dcSZachary Turner }
5172c1f46dcSZachary Turner 
5182c1f46dcSZachary Turner PythonObject
5192c1f46dcSZachary Turner PythonList::GetItemAtIndex(uint32_t index) const
5202c1f46dcSZachary Turner {
521f8b22f8fSZachary Turner     if (IsValid())
522f8b22f8fSZachary Turner         return PythonObject(PyRefType::Borrowed, PyList_GetItem(m_py_obj, index));
5232c1f46dcSZachary Turner     return PythonObject();
5242c1f46dcSZachary Turner }
5252c1f46dcSZachary Turner 
5262c1f46dcSZachary Turner void
5272c1f46dcSZachary Turner PythonList::SetItemAtIndex(uint32_t index, const PythonObject &object)
5282c1f46dcSZachary Turner {
529f8b22f8fSZachary Turner     if (IsAllocated() && object.IsValid())
530f8b22f8fSZachary Turner     {
531f8b22f8fSZachary Turner         // PyList_SetItem is documented to "steal" a reference, so we need to
532f8b22f8fSZachary Turner         // convert it to an owned reference by incrementing it.
533f8b22f8fSZachary Turner         Py_INCREF(object.get());
5342c1f46dcSZachary Turner         PyList_SetItem(m_py_obj, index, object.get());
5352c1f46dcSZachary Turner     }
536f8b22f8fSZachary Turner }
5372c1f46dcSZachary Turner 
5382c1f46dcSZachary Turner void
5392c1f46dcSZachary Turner PythonList::AppendItem(const PythonObject &object)
5402c1f46dcSZachary Turner {
541f8b22f8fSZachary Turner     if (IsAllocated() && object.IsValid())
542f8b22f8fSZachary Turner     {
543f8b22f8fSZachary Turner         // `PyList_Append` does *not* steal a reference, so do not call `Py_INCREF`
544f8b22f8fSZachary Turner         // here like we do with `PyList_SetItem`.
5452c1f46dcSZachary Turner         PyList_Append(m_py_obj, object.get());
5462c1f46dcSZachary Turner     }
547f8b22f8fSZachary Turner }
5482c1f46dcSZachary Turner 
5492c1f46dcSZachary Turner StructuredData::ArraySP
5502c1f46dcSZachary Turner PythonList::CreateStructuredArray() const
5512c1f46dcSZachary Turner {
5522c1f46dcSZachary Turner     StructuredData::ArraySP result(new StructuredData::Array);
5532c1f46dcSZachary Turner     uint32_t count = GetSize();
5542c1f46dcSZachary Turner     for (uint32_t i = 0; i < count; ++i)
5552c1f46dcSZachary Turner     {
5562c1f46dcSZachary Turner         PythonObject obj = GetItemAtIndex(i);
5572c1f46dcSZachary Turner         result->AddItem(obj.CreateStructuredObject());
5582c1f46dcSZachary Turner     }
5592c1f46dcSZachary Turner     return result;
5602c1f46dcSZachary Turner }
5612c1f46dcSZachary Turner 
5622c1f46dcSZachary Turner //----------------------------------------------------------------------
563*a1405147SZachary Turner // PythonTuple
564*a1405147SZachary Turner //----------------------------------------------------------------------
565*a1405147SZachary Turner 
566*a1405147SZachary Turner PythonTuple::PythonTuple(PyInitialValue value)
567*a1405147SZachary Turner     : PythonObject()
568*a1405147SZachary Turner {
569*a1405147SZachary Turner     if (value == PyInitialValue::Empty)
570*a1405147SZachary Turner         Reset(PyRefType::Owned, PyTuple_New(0));
571*a1405147SZachary Turner }
572*a1405147SZachary Turner 
573*a1405147SZachary Turner PythonTuple::PythonTuple(int tuple_size)
574*a1405147SZachary Turner     : PythonObject()
575*a1405147SZachary Turner {
576*a1405147SZachary Turner     Reset(PyRefType::Owned, PyTuple_New(tuple_size));
577*a1405147SZachary Turner }
578*a1405147SZachary Turner 
579*a1405147SZachary Turner PythonTuple::PythonTuple(PyRefType type, PyObject *py_obj)
580*a1405147SZachary Turner     : PythonObject()
581*a1405147SZachary Turner {
582*a1405147SZachary Turner     Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a tuple
583*a1405147SZachary Turner }
584*a1405147SZachary Turner 
585*a1405147SZachary Turner PythonTuple::PythonTuple(const PythonTuple &tuple)
586*a1405147SZachary Turner     : PythonObject(tuple)
587*a1405147SZachary Turner {
588*a1405147SZachary Turner }
589*a1405147SZachary Turner 
590*a1405147SZachary Turner PythonTuple::PythonTuple(std::initializer_list<PythonObject> objects)
591*a1405147SZachary Turner {
592*a1405147SZachary Turner     m_py_obj = PyTuple_New(objects.size());
593*a1405147SZachary Turner 
594*a1405147SZachary Turner     uint32_t idx = 0;
595*a1405147SZachary Turner     for (auto object : objects)
596*a1405147SZachary Turner     {
597*a1405147SZachary Turner         if (object.IsValid())
598*a1405147SZachary Turner             SetItemAtIndex(idx, object);
599*a1405147SZachary Turner         idx++;
600*a1405147SZachary Turner     }
601*a1405147SZachary Turner }
602*a1405147SZachary Turner 
603*a1405147SZachary Turner PythonTuple::PythonTuple(std::initializer_list<PyObject*> objects)
604*a1405147SZachary Turner {
605*a1405147SZachary Turner     m_py_obj = PyTuple_New(objects.size());
606*a1405147SZachary Turner 
607*a1405147SZachary Turner     uint32_t idx = 0;
608*a1405147SZachary Turner     for (auto py_object : objects)
609*a1405147SZachary Turner     {
610*a1405147SZachary Turner         PythonObject object(PyRefType::Borrowed, py_object);
611*a1405147SZachary Turner         if (object.IsValid())
612*a1405147SZachary Turner             SetItemAtIndex(idx, object);
613*a1405147SZachary Turner         idx++;
614*a1405147SZachary Turner     }
615*a1405147SZachary Turner }
616*a1405147SZachary Turner 
617*a1405147SZachary Turner PythonTuple::~PythonTuple()
618*a1405147SZachary Turner {
619*a1405147SZachary Turner }
620*a1405147SZachary Turner 
621*a1405147SZachary Turner bool
622*a1405147SZachary Turner PythonTuple::Check(PyObject *py_obj)
623*a1405147SZachary Turner {
624*a1405147SZachary Turner     if (!py_obj)
625*a1405147SZachary Turner         return false;
626*a1405147SZachary Turner     return PyTuple_Check(py_obj);
627*a1405147SZachary Turner }
628*a1405147SZachary Turner 
629*a1405147SZachary Turner void
630*a1405147SZachary Turner PythonTuple::Reset(PyRefType type, PyObject *py_obj)
631*a1405147SZachary Turner {
632*a1405147SZachary Turner     // Grab the desired reference type so that if we end up rejecting
633*a1405147SZachary Turner     // `py_obj` it still gets decremented if necessary.
634*a1405147SZachary Turner     PythonObject result(type, py_obj);
635*a1405147SZachary Turner 
636*a1405147SZachary Turner     if (!PythonTuple::Check(py_obj))
637*a1405147SZachary Turner     {
638*a1405147SZachary Turner         PythonObject::Reset();
639*a1405147SZachary Turner         return;
640*a1405147SZachary Turner     }
641*a1405147SZachary Turner 
642*a1405147SZachary Turner     // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
643*a1405147SZachary Turner     // back into the virtual implementation.
644*a1405147SZachary Turner     PythonObject::Reset(PyRefType::Borrowed, result.get());
645*a1405147SZachary Turner }
646*a1405147SZachary Turner 
647*a1405147SZachary Turner uint32_t
648*a1405147SZachary Turner PythonTuple::GetSize() const
649*a1405147SZachary Turner {
650*a1405147SZachary Turner     if (IsValid())
651*a1405147SZachary Turner         return PyTuple_GET_SIZE(m_py_obj);
652*a1405147SZachary Turner     return 0;
653*a1405147SZachary Turner }
654*a1405147SZachary Turner 
655*a1405147SZachary Turner PythonObject
656*a1405147SZachary Turner PythonTuple::GetItemAtIndex(uint32_t index) const
657*a1405147SZachary Turner {
658*a1405147SZachary Turner     if (IsValid())
659*a1405147SZachary Turner         return PythonObject(PyRefType::Borrowed, PyTuple_GetItem(m_py_obj, index));
660*a1405147SZachary Turner     return PythonObject();
661*a1405147SZachary Turner }
662*a1405147SZachary Turner 
663*a1405147SZachary Turner void
664*a1405147SZachary Turner PythonTuple::SetItemAtIndex(uint32_t index, const PythonObject &object)
665*a1405147SZachary Turner {
666*a1405147SZachary Turner     if (IsAllocated() && object.IsValid())
667*a1405147SZachary Turner     {
668*a1405147SZachary Turner         // PyTuple_SetItem is documented to "steal" a reference, so we need to
669*a1405147SZachary Turner         // convert it to an owned reference by incrementing it.
670*a1405147SZachary Turner         Py_INCREF(object.get());
671*a1405147SZachary Turner         PyTuple_SetItem(m_py_obj, index, object.get());
672*a1405147SZachary Turner     }
673*a1405147SZachary Turner }
674*a1405147SZachary Turner 
675*a1405147SZachary Turner StructuredData::ArraySP
676*a1405147SZachary Turner PythonTuple::CreateStructuredArray() const
677*a1405147SZachary Turner {
678*a1405147SZachary Turner     StructuredData::ArraySP result(new StructuredData::Array);
679*a1405147SZachary Turner     uint32_t count = GetSize();
680*a1405147SZachary Turner     for (uint32_t i = 0; i < count; ++i)
681*a1405147SZachary Turner     {
682*a1405147SZachary Turner         PythonObject obj = GetItemAtIndex(i);
683*a1405147SZachary Turner         result->AddItem(obj.CreateStructuredObject());
684*a1405147SZachary Turner     }
685*a1405147SZachary Turner     return result;
686*a1405147SZachary Turner }
687*a1405147SZachary Turner 
688*a1405147SZachary Turner //----------------------------------------------------------------------
6892c1f46dcSZachary Turner // PythonDictionary
6902c1f46dcSZachary Turner //----------------------------------------------------------------------
6912c1f46dcSZachary Turner 
692f8b22f8fSZachary Turner PythonDictionary::PythonDictionary(PyInitialValue value)
693f8b22f8fSZachary Turner     : PythonObject()
6942c1f46dcSZachary Turner {
695f8b22f8fSZachary Turner     if (value == PyInitialValue::Empty)
696f8b22f8fSZachary Turner         Reset(PyRefType::Owned, PyDict_New());
6972c1f46dcSZachary Turner }
6982c1f46dcSZachary Turner 
699f8b22f8fSZachary Turner PythonDictionary::PythonDictionary(PyRefType type, PyObject *py_obj)
700f8b22f8fSZachary Turner     : PythonObject()
7012c1f46dcSZachary Turner {
702f8b22f8fSZachary Turner     Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a dictionary
7032c1f46dcSZachary Turner }
7042c1f46dcSZachary Turner 
705f8b22f8fSZachary Turner PythonDictionary::PythonDictionary(const PythonDictionary &object)
706f8b22f8fSZachary Turner     : PythonObject(object)
7072c1f46dcSZachary Turner {
7082c1f46dcSZachary Turner }
7092c1f46dcSZachary Turner 
7102c1f46dcSZachary Turner PythonDictionary::~PythonDictionary ()
7112c1f46dcSZachary Turner {
7122c1f46dcSZachary Turner }
7132c1f46dcSZachary Turner 
7142c1f46dcSZachary Turner bool
71522c8efcdSZachary Turner PythonDictionary::Check(PyObject *py_obj)
71622c8efcdSZachary Turner {
71722c8efcdSZachary Turner     if (!py_obj)
71822c8efcdSZachary Turner         return false;
71922c8efcdSZachary Turner 
72022c8efcdSZachary Turner     return PyDict_Check(py_obj);
72122c8efcdSZachary Turner }
72222c8efcdSZachary Turner 
723f8b22f8fSZachary Turner void
724f8b22f8fSZachary Turner PythonDictionary::Reset(PyRefType type, PyObject *py_obj)
7252c1f46dcSZachary Turner {
726f8b22f8fSZachary Turner     // Grab the desired reference type so that if we end up rejecting
727f8b22f8fSZachary Turner     // `py_obj` it still gets decremented if necessary.
728f8b22f8fSZachary Turner     PythonObject result(type, py_obj);
729f8b22f8fSZachary Turner 
73022c8efcdSZachary Turner     if (!PythonDictionary::Check(py_obj))
73122c8efcdSZachary Turner     {
732f8b22f8fSZachary Turner         PythonObject::Reset();
733f8b22f8fSZachary Turner         return;
73422c8efcdSZachary Turner     }
73522c8efcdSZachary Turner 
736f8b22f8fSZachary Turner     // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
737f8b22f8fSZachary Turner     // back into the virtual implementation.
738f8b22f8fSZachary Turner     PythonObject::Reset(PyRefType::Borrowed, result.get());
7392c1f46dcSZachary Turner }
7402c1f46dcSZachary Turner 
7412c1f46dcSZachary Turner uint32_t
7422c1f46dcSZachary Turner PythonDictionary::GetSize() const
7432c1f46dcSZachary Turner {
744f8b22f8fSZachary Turner     if (IsValid())
7452c1f46dcSZachary Turner         return PyDict_Size(m_py_obj);
7462c1f46dcSZachary Turner     return 0;
7472c1f46dcSZachary Turner }
7482c1f46dcSZachary Turner 
7492c1f46dcSZachary Turner PythonList
7502c1f46dcSZachary Turner PythonDictionary::GetKeys() const
7512c1f46dcSZachary Turner {
752f8b22f8fSZachary Turner     if (IsValid())
753f8b22f8fSZachary Turner         return PythonList(PyRefType::Owned, PyDict_Keys(m_py_obj));
754f8b22f8fSZachary Turner     return PythonList(PyInitialValue::Invalid);
7552c1f46dcSZachary Turner }
7562c1f46dcSZachary Turner 
7572c1f46dcSZachary Turner PythonObject
758f8b22f8fSZachary Turner PythonDictionary::GetItemForKey(const PythonObject &key) const
7592c1f46dcSZachary Turner {
760f8b22f8fSZachary Turner     if (IsAllocated() && key.IsValid())
761f8b22f8fSZachary Turner         return PythonObject(PyRefType::Borrowed, PyDict_GetItem(m_py_obj, key.get()));
7622c1f46dcSZachary Turner     return PythonObject();
7632c1f46dcSZachary Turner }
7642c1f46dcSZachary Turner 
7652c1f46dcSZachary Turner void
766f8b22f8fSZachary Turner PythonDictionary::SetItemForKey(const PythonObject &key, const PythonObject &value)
7672c1f46dcSZachary Turner {
768f8b22f8fSZachary Turner     if (IsAllocated() && key.IsValid() && value.IsValid())
7692c1f46dcSZachary Turner         PyDict_SetItem(m_py_obj, key.get(), value.get());
7702c1f46dcSZachary Turner }
7712c1f46dcSZachary Turner 
7722c1f46dcSZachary Turner StructuredData::DictionarySP
7732c1f46dcSZachary Turner PythonDictionary::CreateStructuredDictionary() const
7742c1f46dcSZachary Turner {
7752c1f46dcSZachary Turner     StructuredData::DictionarySP result(new StructuredData::Dictionary);
7762c1f46dcSZachary Turner     PythonList keys(GetKeys());
7772c1f46dcSZachary Turner     uint32_t num_keys = keys.GetSize();
7782c1f46dcSZachary Turner     for (uint32_t i = 0; i < num_keys; ++i)
7792c1f46dcSZachary Turner     {
7802c1f46dcSZachary Turner         PythonObject key = keys.GetItemAtIndex(i);
7812c1f46dcSZachary Turner         PythonObject value = GetItemForKey(key);
7822c1f46dcSZachary Turner         StructuredData::ObjectSP structured_value = value.CreateStructuredObject();
783f8b22f8fSZachary Turner         result->AddItem(key.Str().GetString(), structured_value);
7842c1f46dcSZachary Turner     }
7852c1f46dcSZachary Turner     return result;
7862c1f46dcSZachary Turner }
7872c1f46dcSZachary Turner 
7887841efbbSZachary Turner PythonModule::PythonModule() : PythonObject()
7897841efbbSZachary Turner {
7907841efbbSZachary Turner }
7917841efbbSZachary Turner 
7927841efbbSZachary Turner PythonModule::PythonModule(PyRefType type, PyObject *py_obj)
7937841efbbSZachary Turner {
7947841efbbSZachary Turner     Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a module
7957841efbbSZachary Turner }
7967841efbbSZachary Turner 
7977841efbbSZachary Turner PythonModule::PythonModule(const PythonModule &dict) : PythonObject(dict)
7987841efbbSZachary Turner {
7997841efbbSZachary Turner }
8007841efbbSZachary Turner 
8017841efbbSZachary Turner PythonModule::~PythonModule()
8027841efbbSZachary Turner {
8037841efbbSZachary Turner }
8047841efbbSZachary Turner 
8057841efbbSZachary Turner PythonModule
806*a1405147SZachary Turner PythonModule::BuiltinsModule()
807*a1405147SZachary Turner {
808*a1405147SZachary Turner #if PY_MAJOR_VERSION >= 3
809*a1405147SZachary Turner     return AddModule("builtins");
810*a1405147SZachary Turner #else
811*a1405147SZachary Turner     return AddModule("__builtin__");
812*a1405147SZachary Turner #endif
813*a1405147SZachary Turner }
814*a1405147SZachary Turner 
815*a1405147SZachary Turner PythonModule
8167841efbbSZachary Turner PythonModule::MainModule()
8177841efbbSZachary Turner {
818*a1405147SZachary Turner     return AddModule("__main__");
819*a1405147SZachary Turner }
820*a1405147SZachary Turner 
821*a1405147SZachary Turner PythonModule
822*a1405147SZachary Turner PythonModule::AddModule(llvm::StringRef module)
823*a1405147SZachary Turner {
824*a1405147SZachary Turner     std::string str = module.str();
825*a1405147SZachary Turner     return PythonModule(PyRefType::Borrowed, PyImport_AddModule(str.c_str()));
8267841efbbSZachary Turner }
8277841efbbSZachary Turner 
8287841efbbSZachary Turner bool
8297841efbbSZachary Turner PythonModule::Check(PyObject *py_obj)
8307841efbbSZachary Turner {
8317841efbbSZachary Turner     if (!py_obj)
8327841efbbSZachary Turner         return false;
8337841efbbSZachary Turner 
8347841efbbSZachary Turner     return PyModule_Check(py_obj);
8357841efbbSZachary Turner }
8367841efbbSZachary Turner 
8377841efbbSZachary Turner void
8387841efbbSZachary Turner PythonModule::Reset(PyRefType type, PyObject *py_obj)
8397841efbbSZachary Turner {
8407841efbbSZachary Turner     // Grab the desired reference type so that if we end up rejecting
8417841efbbSZachary Turner     // `py_obj` it still gets decremented if necessary.
8427841efbbSZachary Turner     PythonObject result(type, py_obj);
8437841efbbSZachary Turner 
8447841efbbSZachary Turner     if (!PythonModule::Check(py_obj))
8457841efbbSZachary Turner     {
8467841efbbSZachary Turner         PythonObject::Reset();
8477841efbbSZachary Turner         return;
8487841efbbSZachary Turner     }
8497841efbbSZachary Turner 
8507841efbbSZachary Turner     // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
8517841efbbSZachary Turner     // back into the virtual implementation.
8527841efbbSZachary Turner     PythonObject::Reset(PyRefType::Borrowed, result.get());
8537841efbbSZachary Turner }
8547841efbbSZachary Turner 
8557841efbbSZachary Turner PythonDictionary
8567841efbbSZachary Turner PythonModule::GetDictionary() const
8577841efbbSZachary Turner {
8587841efbbSZachary Turner     return PythonDictionary(PyRefType::Borrowed, PyModule_GetDict(m_py_obj));
8597841efbbSZachary Turner }
8607841efbbSZachary Turner 
861*a1405147SZachary Turner PythonCallable::PythonCallable() : PythonObject()
862*a1405147SZachary Turner {
863*a1405147SZachary Turner }
864*a1405147SZachary Turner 
865*a1405147SZachary Turner PythonCallable::PythonCallable(PyRefType type, PyObject *py_obj)
866*a1405147SZachary Turner {
867*a1405147SZachary Turner     Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a callable
868*a1405147SZachary Turner }
869*a1405147SZachary Turner 
870*a1405147SZachary Turner PythonCallable::PythonCallable(const PythonCallable &callable)
871*a1405147SZachary Turner     : PythonObject(callable)
872*a1405147SZachary Turner {
873*a1405147SZachary Turner }
874*a1405147SZachary Turner 
875*a1405147SZachary Turner PythonCallable::~PythonCallable()
876*a1405147SZachary Turner {
877*a1405147SZachary Turner }
878*a1405147SZachary Turner 
879*a1405147SZachary Turner bool
880*a1405147SZachary Turner PythonCallable::Check(PyObject *py_obj)
881*a1405147SZachary Turner {
882*a1405147SZachary Turner     if (!py_obj)
883*a1405147SZachary Turner         return false;
884*a1405147SZachary Turner 
885*a1405147SZachary Turner     return PyCallable_Check(py_obj);
886*a1405147SZachary Turner }
887*a1405147SZachary Turner 
888*a1405147SZachary Turner void
889*a1405147SZachary Turner PythonCallable::Reset(PyRefType type, PyObject *py_obj)
890*a1405147SZachary Turner {
891*a1405147SZachary Turner     // Grab the desired reference type so that if we end up rejecting
892*a1405147SZachary Turner     // `py_obj` it still gets decremented if necessary.
893*a1405147SZachary Turner     PythonObject result(type, py_obj);
894*a1405147SZachary Turner 
895*a1405147SZachary Turner     if (!PythonCallable::Check(py_obj))
896*a1405147SZachary Turner     {
897*a1405147SZachary Turner         PythonObject::Reset();
898*a1405147SZachary Turner         return;
899*a1405147SZachary Turner     }
900*a1405147SZachary Turner 
901*a1405147SZachary Turner     // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
902*a1405147SZachary Turner     // back into the virtual implementation.
903*a1405147SZachary Turner     PythonObject::Reset(PyRefType::Borrowed, result.get());
904*a1405147SZachary Turner }
905*a1405147SZachary Turner 
906*a1405147SZachary Turner 
907*a1405147SZachary Turner void
908*a1405147SZachary Turner PythonCallable::GetNumArguments(size_t &num_args, bool &has_varargs, bool &has_kwargs) const
909*a1405147SZachary Turner {
910*a1405147SZachary Turner     num_args = 0;
911*a1405147SZachary Turner     has_varargs = false;
912*a1405147SZachary Turner     has_kwargs = false;
913*a1405147SZachary Turner     if (!IsValid())
914*a1405147SZachary Turner         return;
915*a1405147SZachary Turner 
916*a1405147SZachary Turner     PyObject *py_func_obj = m_py_obj;
917*a1405147SZachary Turner     if (PyMethod_Check(py_func_obj))
918*a1405147SZachary Turner         py_func_obj = PyMethod_GET_FUNCTION(py_func_obj);
919*a1405147SZachary Turner 
920*a1405147SZachary Turner     if (!py_func_obj)
921*a1405147SZachary Turner         return;
922*a1405147SZachary Turner 
923*a1405147SZachary Turner     PyCodeObject* code = (PyCodeObject*)PyFunction_GET_CODE(py_func_obj);
924*a1405147SZachary Turner     if (!code)
925*a1405147SZachary Turner         return;
926*a1405147SZachary Turner 
927*a1405147SZachary Turner     num_args = code->co_argcount;
928*a1405147SZachary Turner     if (code->co_flags & CO_VARARGS)
929*a1405147SZachary Turner         has_varargs = true;
930*a1405147SZachary Turner     if (code->co_flags & CO_VARKEYWORDS)
931*a1405147SZachary Turner         has_kwargs = true;
932*a1405147SZachary Turner }
933*a1405147SZachary Turner 
934*a1405147SZachary Turner PythonObject
935*a1405147SZachary Turner PythonCallable::operator ()(std::initializer_list<PyObject*> args)
936*a1405147SZachary Turner {
937*a1405147SZachary Turner     PythonTuple arg_tuple(args);
938*a1405147SZachary Turner     return PythonObject(PyRefType::Owned,
939*a1405147SZachary Turner         PyObject_CallObject(m_py_obj, arg_tuple.get()));
940*a1405147SZachary Turner }
941*a1405147SZachary Turner 
942*a1405147SZachary Turner PythonObject
943*a1405147SZachary Turner PythonCallable::operator ()(std::initializer_list<PythonObject> args)
944*a1405147SZachary Turner {
945*a1405147SZachary Turner     PythonTuple arg_tuple(args);
946*a1405147SZachary Turner     return PythonObject(PyRefType::Owned,
947*a1405147SZachary Turner         PyObject_CallObject(m_py_obj, arg_tuple.get()));
948*a1405147SZachary Turner }
949*a1405147SZachary Turner 
95032064024SZachary Turner PythonFile::PythonFile()
95132064024SZachary Turner     : PythonObject()
95232064024SZachary Turner {
95332064024SZachary Turner }
95432064024SZachary Turner 
9559c40264fSZachary Turner PythonFile::PythonFile(File &file, const char *mode)
9569c40264fSZachary Turner {
9579c40264fSZachary Turner     Reset(file, mode);
9589c40264fSZachary Turner }
9599c40264fSZachary Turner 
960eda01c31SZachary Turner PythonFile::PythonFile(const char *path, const char *mode)
961eda01c31SZachary Turner {
962eda01c31SZachary Turner     FILE *fp = nullptr;
963eda01c31SZachary Turner     fp = fopen(path, mode);
964eda01c31SZachary Turner     lldb_private::File file(fp, true);
965eda01c31SZachary Turner     Reset(file, mode);
966eda01c31SZachary Turner }
967eda01c31SZachary Turner 
9689c40264fSZachary Turner PythonFile::PythonFile(PyRefType type, PyObject *o)
9699c40264fSZachary Turner {
9709c40264fSZachary Turner     Reset(type, o);
9719c40264fSZachary Turner }
9729c40264fSZachary Turner 
9739c40264fSZachary Turner PythonFile::~PythonFile()
9749c40264fSZachary Turner {
9759c40264fSZachary Turner }
9769c40264fSZachary Turner 
9779c40264fSZachary Turner bool
9789c40264fSZachary Turner PythonFile::Check(PyObject *py_obj)
9799c40264fSZachary Turner {
9809c40264fSZachary Turner #if PY_MAJOR_VERSION < 3
9819c40264fSZachary Turner     return PyFile_Check(py_obj);
9829c40264fSZachary Turner #else
9839c40264fSZachary Turner     // In Python 3, there is no `PyFile_Check`, and in fact PyFile is not even a
9849c40264fSZachary Turner     // first-class object type anymore.  `PyFile_FromFd` is just a thin wrapper
9859c40264fSZachary Turner     // over `io.open()`, which returns some object derived from `io.IOBase`.
9869c40264fSZachary Turner     // As a result, the only way to detect a file in Python 3 is to check whether
9879c40264fSZachary Turner     // it inherits from `io.IOBase`.  Since it is possible for non-files to also
9889c40264fSZachary Turner     // inherit from `io.IOBase`, we additionally verify that it has the `fileno`
9899c40264fSZachary Turner     // attribute, which should guarantee that it is backed by the file system.
9909c40264fSZachary Turner     PythonObject io_module(PyRefType::Owned, PyImport_ImportModule("io"));
9919c40264fSZachary Turner     PythonDictionary io_dict(PyRefType::Borrowed, PyModule_GetDict(io_module.get()));
9929c40264fSZachary Turner     PythonObject io_base_class = io_dict.GetItemForKey(PythonString("IOBase"));
9939c40264fSZachary Turner 
9949c40264fSZachary Turner     PythonObject object_type(PyRefType::Owned, PyObject_Type(py_obj));
9959c40264fSZachary Turner 
9969c40264fSZachary Turner     if (1 != PyObject_IsSubclass(object_type.get(), io_base_class.get()))
9979c40264fSZachary Turner         return false;
9989c40264fSZachary Turner     if (!object_type.HasAttribute("fileno"))
9999c40264fSZachary Turner         return false;
10009c40264fSZachary Turner 
10019c40264fSZachary Turner     return true;
10029c40264fSZachary Turner #endif
10039c40264fSZachary Turner }
10049c40264fSZachary Turner 
10059c40264fSZachary Turner void
10069c40264fSZachary Turner PythonFile::Reset(PyRefType type, PyObject *py_obj)
10079c40264fSZachary Turner {
10089c40264fSZachary Turner     // Grab the desired reference type so that if we end up rejecting
10099c40264fSZachary Turner     // `py_obj` it still gets decremented if necessary.
10109c40264fSZachary Turner     PythonObject result(type, py_obj);
10119c40264fSZachary Turner 
10129c40264fSZachary Turner     if (!PythonFile::Check(py_obj))
10139c40264fSZachary Turner     {
10149c40264fSZachary Turner         PythonObject::Reset();
10159c40264fSZachary Turner         return;
10169c40264fSZachary Turner     }
10179c40264fSZachary Turner 
10189c40264fSZachary Turner     // Calling PythonObject::Reset(const PythonObject&) will lead to stack
10199c40264fSZachary Turner     // overflow since it calls back into the virtual implementation.
10209c40264fSZachary Turner     PythonObject::Reset(PyRefType::Borrowed, result.get());
10219c40264fSZachary Turner }
10229c40264fSZachary Turner 
10239c40264fSZachary Turner void
10249c40264fSZachary Turner PythonFile::Reset(File &file, const char *mode)
10259c40264fSZachary Turner {
10269c40264fSZachary Turner     char *cmode = const_cast<char *>(mode);
10279c40264fSZachary Turner #if PY_MAJOR_VERSION >= 3
10289c40264fSZachary Turner     Reset(PyRefType::Owned,
10299c40264fSZachary Turner         PyFile_FromFd(file.GetDescriptor(), nullptr, cmode, -1, nullptr, "ignore", nullptr, 0));
10309c40264fSZachary Turner #else
10319c40264fSZachary Turner     // Read through the Python source, doesn't seem to modify these strings
10329c40264fSZachary Turner     Reset(PyRefType::Owned,
10339c40264fSZachary Turner         PyFile_FromFile(file.GetStream(), const_cast<char *>(""), cmode, nullptr));
10349c40264fSZachary Turner #endif
10359c40264fSZachary Turner }
10369c40264fSZachary Turner 
1037eda01c31SZachary Turner bool
1038eda01c31SZachary Turner PythonFile::GetUnderlyingFile(File &file) const
1039eda01c31SZachary Turner {
1040eda01c31SZachary Turner     if (!IsValid())
1041eda01c31SZachary Turner         return false;
1042eda01c31SZachary Turner 
1043eda01c31SZachary Turner     file.Close();
1044eda01c31SZachary Turner     // We don't own the file descriptor returned by this function, make sure the
1045eda01c31SZachary Turner     // File object knows about that.
1046eda01c31SZachary Turner     file.SetDescriptor(PyObject_AsFileDescriptor(m_py_obj), false);
1047eda01c31SZachary Turner     return file.IsValid();
1048eda01c31SZachary Turner }
1049eda01c31SZachary Turner 
1050eda01c31SZachary Turner 
10512c1f46dcSZachary Turner #endif
1052