14ba319b5SDimitry Andric //===-- PythonDataObjects.cpp -----------------------------------*- C++ -*-===//
29f2f44ceSEd Maste //
39f2f44ceSEd Maste //                     The LLVM Compiler Infrastructure
49f2f44ceSEd Maste //
59f2f44ceSEd Maste // This file is distributed under the University of Illinois Open Source
69f2f44ceSEd Maste // License. See LICENSE.TXT for details.
79f2f44ceSEd Maste //
89f2f44ceSEd Maste //===----------------------------------------------------------------------===//
99f2f44ceSEd Maste 
109f2f44ceSEd Maste #ifdef LLDB_DISABLE_PYTHON
119f2f44ceSEd Maste 
129f2f44ceSEd Maste // Python is disabled in this build
139f2f44ceSEd Maste 
149f2f44ceSEd Maste #else
159f2f44ceSEd Maste 
169f2f44ceSEd Maste #include "PythonDataObjects.h"
179f2f44ceSEd Maste #include "ScriptInterpreterPython.h"
189f2f44ceSEd Maste 
199f2f44ceSEd Maste #include "lldb/Host/File.h"
204bb0738eSEd Maste #include "lldb/Host/FileSystem.h"
219f2f44ceSEd Maste #include "lldb/Interpreter/ScriptInterpreter.h"
22f678e45dSDimitry Andric #include "lldb/Utility/Stream.h"
239f2f44ceSEd Maste 
244bb0738eSEd Maste #include "llvm/Support/ConvertUTF.h"
254bb0738eSEd Maste 
269f2f44ceSEd Maste #include <stdio.h>
279f2f44ceSEd Maste 
284bb0738eSEd Maste #include "llvm/ADT/StringSwitch.h"
294bb0738eSEd Maste 
309f2f44ceSEd Maste using namespace lldb_private;
319f2f44ceSEd Maste using namespace lldb;
329f2f44ceSEd Maste 
Dump(Stream & s,bool pretty_print) const33435933ddSDimitry Andric void StructuredPythonObject::Dump(Stream &s, bool pretty_print) const {
349f2f44ceSEd Maste   s << "Python Obj: 0x" << GetValue();
359f2f44ceSEd Maste }
369f2f44ceSEd Maste 
379f2f44ceSEd Maste //----------------------------------------------------------------------
389f2f44ceSEd Maste // PythonObject
399f2f44ceSEd Maste //----------------------------------------------------------------------
409f2f44ceSEd Maste 
Dump(Stream & strm) const41435933ddSDimitry Andric void PythonObject::Dump(Stream &strm) const {
42435933ddSDimitry Andric   if (m_py_obj) {
439f2f44ceSEd Maste     FILE *file = ::tmpfile();
44435933ddSDimitry Andric     if (file) {
459f2f44ceSEd Maste       ::PyObject_Print(m_py_obj, file, 0);
469f2f44ceSEd Maste       const long length = ftell(file);
47435933ddSDimitry Andric       if (length) {
489f2f44ceSEd Maste         ::rewind(file);
499f2f44ceSEd Maste         std::vector<char> file_contents(length, '\0');
50435933ddSDimitry Andric         const size_t length_read =
51435933ddSDimitry Andric             ::fread(file_contents.data(), 1, file_contents.size(), file);
529f2f44ceSEd Maste         if (length_read > 0)
539f2f44ceSEd Maste           strm.Write(file_contents.data(), length_read);
549f2f44ceSEd Maste       }
559f2f44ceSEd Maste       ::fclose(file);
569f2f44ceSEd Maste     }
57435933ddSDimitry Andric   } else
589f2f44ceSEd Maste     strm.PutCString("NULL");
599f2f44ceSEd Maste }
609f2f44ceSEd Maste 
GetObjectType() const61435933ddSDimitry Andric PyObjectType PythonObject::GetObjectType() const {
629f2f44ceSEd Maste   if (!IsAllocated())
639f2f44ceSEd Maste     return PyObjectType::None;
649f2f44ceSEd Maste 
659f2f44ceSEd Maste   if (PythonModule::Check(m_py_obj))
669f2f44ceSEd Maste     return PyObjectType::Module;
679f2f44ceSEd Maste   if (PythonList::Check(m_py_obj))
689f2f44ceSEd Maste     return PyObjectType::List;
699f2f44ceSEd Maste   if (PythonTuple::Check(m_py_obj))
709f2f44ceSEd Maste     return PyObjectType::Tuple;
719f2f44ceSEd Maste   if (PythonDictionary::Check(m_py_obj))
729f2f44ceSEd Maste     return PyObjectType::Dictionary;
739f2f44ceSEd Maste   if (PythonString::Check(m_py_obj))
749f2f44ceSEd Maste     return PyObjectType::String;
75444ed5c5SDimitry Andric #if PY_MAJOR_VERSION >= 3
76444ed5c5SDimitry Andric   if (PythonBytes::Check(m_py_obj))
77444ed5c5SDimitry Andric     return PyObjectType::Bytes;
78444ed5c5SDimitry Andric #endif
794bb0738eSEd Maste   if (PythonByteArray::Check(m_py_obj))
804bb0738eSEd Maste     return PyObjectType::ByteArray;
819f2f44ceSEd Maste   if (PythonInteger::Check(m_py_obj))
829f2f44ceSEd Maste     return PyObjectType::Integer;
839f2f44ceSEd Maste   if (PythonFile::Check(m_py_obj))
849f2f44ceSEd Maste     return PyObjectType::File;
859f2f44ceSEd Maste   if (PythonCallable::Check(m_py_obj))
869f2f44ceSEd Maste     return PyObjectType::Callable;
879f2f44ceSEd Maste   return PyObjectType::Unknown;
889f2f44ceSEd Maste }
899f2f44ceSEd Maste 
Repr() const90435933ddSDimitry Andric PythonString PythonObject::Repr() const {
919f2f44ceSEd Maste   if (!m_py_obj)
929f2f44ceSEd Maste     return PythonString();
939f2f44ceSEd Maste   PyObject *repr = PyObject_Repr(m_py_obj);
949f2f44ceSEd Maste   if (!repr)
959f2f44ceSEd Maste     return PythonString();
969f2f44ceSEd Maste   return PythonString(PyRefType::Owned, repr);
979f2f44ceSEd Maste }
989f2f44ceSEd Maste 
Str() const99435933ddSDimitry Andric PythonString PythonObject::Str() const {
1009f2f44ceSEd Maste   if (!m_py_obj)
1019f2f44ceSEd Maste     return PythonString();
1029f2f44ceSEd Maste   PyObject *str = PyObject_Str(m_py_obj);
1039f2f44ceSEd Maste   if (!str)
1049f2f44ceSEd Maste     return PythonString();
1059f2f44ceSEd Maste   return PythonString(PyRefType::Owned, str);
1069f2f44ceSEd Maste }
1079f2f44ceSEd Maste 
1089f2f44ceSEd Maste PythonObject
ResolveNameWithDictionary(llvm::StringRef name,const PythonDictionary & dict)109435933ddSDimitry Andric PythonObject::ResolveNameWithDictionary(llvm::StringRef name,
110435933ddSDimitry Andric                                         const PythonDictionary &dict) {
1119f2f44ceSEd Maste   size_t dot_pos = name.find_first_of('.');
1129f2f44ceSEd Maste   llvm::StringRef piece = name.substr(0, dot_pos);
1139f2f44ceSEd Maste   PythonObject result = dict.GetItemForKey(PythonString(piece));
114435933ddSDimitry Andric   if (dot_pos == llvm::StringRef::npos) {
1159f2f44ceSEd Maste     // There was no dot, we're done.
1169f2f44ceSEd Maste     return result;
1179f2f44ceSEd Maste   }
1189f2f44ceSEd Maste 
1199f2f44ceSEd Maste   // There was a dot.  The remaining portion of the name should be looked up in
1209f2f44ceSEd Maste   // the context of the object that was found in the dictionary.
1219f2f44ceSEd Maste   return result.ResolveName(name.substr(dot_pos + 1));
1229f2f44ceSEd Maste }
1239f2f44ceSEd Maste 
ResolveName(llvm::StringRef name) const124435933ddSDimitry Andric PythonObject PythonObject::ResolveName(llvm::StringRef name) const {
1254ba319b5SDimitry Andric   // Resolve the name in the context of the specified object.  If, for example,
1264ba319b5SDimitry Andric   // `this` refers to a PyModule, then this will look for `name` in this
1274ba319b5SDimitry Andric   // module.  If `this` refers to a PyType, then it will resolve `name` as an
1284ba319b5SDimitry Andric   // attribute of that type.  If `this` refers to an instance of an object,
1294ba319b5SDimitry Andric   // then it will resolve `name` as the value of the specified field.
1309f2f44ceSEd Maste   //
1319f2f44ceSEd Maste   // This function handles dotted names so that, for example, if `m_py_obj`
1324ba319b5SDimitry Andric   // refers to the `sys` module, and `name` == "path.append", then it will find
1334ba319b5SDimitry Andric   // the function `sys.path.append`.
1349f2f44ceSEd Maste 
1359f2f44ceSEd Maste   size_t dot_pos = name.find_first_of('.');
136435933ddSDimitry Andric   if (dot_pos == llvm::StringRef::npos) {
1374ba319b5SDimitry Andric     // No dots in the name, we should be able to find the value immediately as
1384ba319b5SDimitry Andric     // an attribute of `m_py_obj`.
1399f2f44ceSEd Maste     return GetAttributeValue(name);
1409f2f44ceSEd Maste   }
1419f2f44ceSEd Maste 
142435933ddSDimitry Andric   // Look up the first piece of the name, and resolve the rest as a child of
143435933ddSDimitry Andric   // that.
1449f2f44ceSEd Maste   PythonObject parent = ResolveName(name.substr(0, dot_pos));
1459f2f44ceSEd Maste   if (!parent.IsAllocated())
1469f2f44ceSEd Maste     return PythonObject();
1479f2f44ceSEd Maste 
1489f2f44ceSEd Maste   // Tail recursion.. should be optimized by the compiler
1499f2f44ceSEd Maste   return parent.ResolveName(name.substr(dot_pos + 1));
1509f2f44ceSEd Maste }
1519f2f44ceSEd Maste 
HasAttribute(llvm::StringRef attr) const152435933ddSDimitry Andric bool PythonObject::HasAttribute(llvm::StringRef attr) const {
1539f2f44ceSEd Maste   if (!IsValid())
1549f2f44ceSEd Maste     return false;
1559f2f44ceSEd Maste   PythonString py_attr(attr);
1569f2f44ceSEd Maste   return !!PyObject_HasAttr(m_py_obj, py_attr.get());
1579f2f44ceSEd Maste }
1589f2f44ceSEd Maste 
GetAttributeValue(llvm::StringRef attr) const159435933ddSDimitry Andric PythonObject PythonObject::GetAttributeValue(llvm::StringRef attr) const {
1609f2f44ceSEd Maste   if (!IsValid())
1619f2f44ceSEd Maste     return PythonObject();
1629f2f44ceSEd Maste 
1639f2f44ceSEd Maste   PythonString py_attr(attr);
1649f2f44ceSEd Maste   if (!PyObject_HasAttr(m_py_obj, py_attr.get()))
1659f2f44ceSEd Maste     return PythonObject();
1669f2f44ceSEd Maste 
1679f2f44ceSEd Maste   return PythonObject(PyRefType::Owned,
1689f2f44ceSEd Maste                       PyObject_GetAttr(m_py_obj, py_attr.get()));
1699f2f44ceSEd Maste }
1709f2f44ceSEd Maste 
IsNone() const171435933ddSDimitry Andric bool PythonObject::IsNone() const { return m_py_obj == Py_None; }
1729f2f44ceSEd Maste 
IsValid() const173435933ddSDimitry Andric bool PythonObject::IsValid() const { return m_py_obj != nullptr; }
1749f2f44ceSEd Maste 
IsAllocated() const175435933ddSDimitry Andric bool PythonObject::IsAllocated() const { return IsValid() && !IsNone(); }
1769f2f44ceSEd Maste 
CreateStructuredObject() const177435933ddSDimitry Andric StructuredData::ObjectSP PythonObject::CreateStructuredObject() const {
178435933ddSDimitry Andric   switch (GetObjectType()) {
1799f2f44ceSEd Maste   case PyObjectType::Dictionary:
180435933ddSDimitry Andric     return PythonDictionary(PyRefType::Borrowed, m_py_obj)
181435933ddSDimitry Andric         .CreateStructuredDictionary();
1829f2f44ceSEd Maste   case PyObjectType::Integer:
183435933ddSDimitry Andric     return PythonInteger(PyRefType::Borrowed, m_py_obj)
184435933ddSDimitry Andric         .CreateStructuredInteger();
1859f2f44ceSEd Maste   case PyObjectType::List:
1869f2f44ceSEd Maste     return PythonList(PyRefType::Borrowed, m_py_obj).CreateStructuredArray();
1879f2f44ceSEd Maste   case PyObjectType::String:
1889f2f44ceSEd Maste     return PythonString(PyRefType::Borrowed, m_py_obj).CreateStructuredString();
189444ed5c5SDimitry Andric   case PyObjectType::Bytes:
190444ed5c5SDimitry Andric     return PythonBytes(PyRefType::Borrowed, m_py_obj).CreateStructuredString();
1914bb0738eSEd Maste   case PyObjectType::ByteArray:
192435933ddSDimitry Andric     return PythonByteArray(PyRefType::Borrowed, m_py_obj)
193435933ddSDimitry Andric         .CreateStructuredString();
1949f2f44ceSEd Maste   case PyObjectType::None:
1959f2f44ceSEd Maste     return StructuredData::ObjectSP();
1969f2f44ceSEd Maste   default:
1979f2f44ceSEd Maste     return StructuredData::ObjectSP(new StructuredPythonObject(m_py_obj));
1989f2f44ceSEd Maste   }
1999f2f44ceSEd Maste }
2009f2f44ceSEd Maste 
2019f2f44ceSEd Maste //----------------------------------------------------------------------
2029f2f44ceSEd Maste // PythonString
2039f2f44ceSEd Maste //----------------------------------------------------------------------
PythonBytes()204435933ddSDimitry Andric PythonBytes::PythonBytes() : PythonObject() {}
205444ed5c5SDimitry Andric 
PythonBytes(llvm::ArrayRef<uint8_t> bytes)206435933ddSDimitry Andric PythonBytes::PythonBytes(llvm::ArrayRef<uint8_t> bytes) : PythonObject() {
207444ed5c5SDimitry Andric   SetBytes(bytes);
208444ed5c5SDimitry Andric }
209444ed5c5SDimitry Andric 
PythonBytes(const uint8_t * bytes,size_t length)210435933ddSDimitry Andric PythonBytes::PythonBytes(const uint8_t *bytes, size_t length) : PythonObject() {
211444ed5c5SDimitry Andric   SetBytes(llvm::ArrayRef<uint8_t>(bytes, length));
212444ed5c5SDimitry Andric }
213444ed5c5SDimitry Andric 
PythonBytes(PyRefType type,PyObject * py_obj)214435933ddSDimitry Andric PythonBytes::PythonBytes(PyRefType type, PyObject *py_obj) : PythonObject() {
215444ed5c5SDimitry Andric   Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string
216444ed5c5SDimitry Andric }
217444ed5c5SDimitry Andric 
PythonBytes(const PythonBytes & object)218435933ddSDimitry Andric PythonBytes::PythonBytes(const PythonBytes &object) : PythonObject(object) {}
219444ed5c5SDimitry Andric 
~PythonBytes()220435933ddSDimitry Andric PythonBytes::~PythonBytes() {}
221444ed5c5SDimitry Andric 
Check(PyObject * py_obj)222435933ddSDimitry Andric bool PythonBytes::Check(PyObject *py_obj) {
223444ed5c5SDimitry Andric   if (!py_obj)
224444ed5c5SDimitry Andric     return false;
225*b5893f02SDimitry Andric   return PyBytes_Check(py_obj);
226444ed5c5SDimitry Andric }
227444ed5c5SDimitry Andric 
Reset(PyRefType type,PyObject * py_obj)228435933ddSDimitry Andric void PythonBytes::Reset(PyRefType type, PyObject *py_obj) {
2294ba319b5SDimitry Andric   // Grab the desired reference type so that if we end up rejecting `py_obj` it
2304ba319b5SDimitry Andric   // still gets decremented if necessary.
231444ed5c5SDimitry Andric   PythonObject result(type, py_obj);
232444ed5c5SDimitry Andric 
233435933ddSDimitry Andric   if (!PythonBytes::Check(py_obj)) {
234444ed5c5SDimitry Andric     PythonObject::Reset();
235444ed5c5SDimitry Andric     return;
236444ed5c5SDimitry Andric   }
237444ed5c5SDimitry Andric 
238435933ddSDimitry Andric   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
2394ba319b5SDimitry Andric   // overflow since it calls back into the virtual implementation.
240444ed5c5SDimitry Andric   PythonObject::Reset(PyRefType::Borrowed, result.get());
241444ed5c5SDimitry Andric }
242444ed5c5SDimitry Andric 
GetBytes() const243435933ddSDimitry Andric llvm::ArrayRef<uint8_t> PythonBytes::GetBytes() const {
244444ed5c5SDimitry Andric   if (!IsValid())
245444ed5c5SDimitry Andric     return llvm::ArrayRef<uint8_t>();
246444ed5c5SDimitry Andric 
247444ed5c5SDimitry Andric   Py_ssize_t size;
248444ed5c5SDimitry Andric   char *c;
249444ed5c5SDimitry Andric 
250444ed5c5SDimitry Andric   PyBytes_AsStringAndSize(m_py_obj, &c, &size);
251444ed5c5SDimitry Andric   return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size);
252444ed5c5SDimitry Andric }
253444ed5c5SDimitry Andric 
GetSize() const254435933ddSDimitry Andric size_t PythonBytes::GetSize() const {
255444ed5c5SDimitry Andric   if (!IsValid())
256444ed5c5SDimitry Andric     return 0;
257444ed5c5SDimitry Andric   return PyBytes_Size(m_py_obj);
258444ed5c5SDimitry Andric }
259444ed5c5SDimitry Andric 
SetBytes(llvm::ArrayRef<uint8_t> bytes)260435933ddSDimitry Andric void PythonBytes::SetBytes(llvm::ArrayRef<uint8_t> bytes) {
261444ed5c5SDimitry Andric   const char *data = reinterpret_cast<const char *>(bytes.data());
262444ed5c5SDimitry Andric   PyObject *py_bytes = PyBytes_FromStringAndSize(data, bytes.size());
263444ed5c5SDimitry Andric   PythonObject::Reset(PyRefType::Owned, py_bytes);
264444ed5c5SDimitry Andric }
265444ed5c5SDimitry Andric 
CreateStructuredString() const266435933ddSDimitry Andric StructuredData::StringSP PythonBytes::CreateStructuredString() const {
267444ed5c5SDimitry Andric   StructuredData::StringSP result(new StructuredData::String);
268444ed5c5SDimitry Andric   Py_ssize_t size;
269444ed5c5SDimitry Andric   char *c;
270444ed5c5SDimitry Andric   PyBytes_AsStringAndSize(m_py_obj, &c, &size);
271444ed5c5SDimitry Andric   result->SetValue(std::string(c, size));
272444ed5c5SDimitry Andric   return result;
273444ed5c5SDimitry Andric }
274444ed5c5SDimitry Andric 
PythonByteArray(llvm::ArrayRef<uint8_t> bytes)275435933ddSDimitry Andric PythonByteArray::PythonByteArray(llvm::ArrayRef<uint8_t> bytes)
276435933ddSDimitry Andric     : PythonByteArray(bytes.data(), bytes.size()) {}
2774bb0738eSEd Maste 
PythonByteArray(const uint8_t * bytes,size_t length)278435933ddSDimitry Andric PythonByteArray::PythonByteArray(const uint8_t *bytes, size_t length) {
2794bb0738eSEd Maste   const char *str = reinterpret_cast<const char *>(bytes);
2804bb0738eSEd Maste   Reset(PyRefType::Owned, PyByteArray_FromStringAndSize(str, length));
2814bb0738eSEd Maste }
2824bb0738eSEd Maste 
PythonByteArray(PyRefType type,PyObject * o)283435933ddSDimitry Andric PythonByteArray::PythonByteArray(PyRefType type, PyObject *o) {
2844bb0738eSEd Maste   Reset(type, o);
2854bb0738eSEd Maste }
2864bb0738eSEd Maste 
PythonByteArray(const PythonBytes & object)287435933ddSDimitry Andric PythonByteArray::PythonByteArray(const PythonBytes &object)
288435933ddSDimitry Andric     : PythonObject(object) {}
2894bb0738eSEd Maste 
~PythonByteArray()290435933ddSDimitry Andric PythonByteArray::~PythonByteArray() {}
2914bb0738eSEd Maste 
Check(PyObject * py_obj)292435933ddSDimitry Andric bool PythonByteArray::Check(PyObject *py_obj) {
2934bb0738eSEd Maste   if (!py_obj)
2944bb0738eSEd Maste     return false;
295*b5893f02SDimitry Andric   return PyByteArray_Check(py_obj);
2964bb0738eSEd Maste }
2974bb0738eSEd Maste 
Reset(PyRefType type,PyObject * py_obj)298435933ddSDimitry Andric void PythonByteArray::Reset(PyRefType type, PyObject *py_obj) {
2994ba319b5SDimitry Andric   // Grab the desired reference type so that if we end up rejecting `py_obj` it
3004ba319b5SDimitry Andric   // still gets decremented if necessary.
3014bb0738eSEd Maste   PythonObject result(type, py_obj);
3024bb0738eSEd Maste 
303435933ddSDimitry Andric   if (!PythonByteArray::Check(py_obj)) {
3044bb0738eSEd Maste     PythonObject::Reset();
3054bb0738eSEd Maste     return;
3064bb0738eSEd Maste   }
3074bb0738eSEd Maste 
308435933ddSDimitry Andric   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
3094ba319b5SDimitry Andric   // overflow since it calls back into the virtual implementation.
3104bb0738eSEd Maste   PythonObject::Reset(PyRefType::Borrowed, result.get());
3114bb0738eSEd Maste }
3124bb0738eSEd Maste 
GetBytes() const313435933ddSDimitry Andric llvm::ArrayRef<uint8_t> PythonByteArray::GetBytes() const {
3144bb0738eSEd Maste   if (!IsValid())
3154bb0738eSEd Maste     return llvm::ArrayRef<uint8_t>();
3164bb0738eSEd Maste 
3174bb0738eSEd Maste   char *c = PyByteArray_AsString(m_py_obj);
3184bb0738eSEd Maste   size_t size = GetSize();
3194bb0738eSEd Maste   return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size);
3204bb0738eSEd Maste }
3214bb0738eSEd Maste 
GetSize() const322435933ddSDimitry Andric size_t PythonByteArray::GetSize() const {
3234bb0738eSEd Maste   if (!IsValid())
3244bb0738eSEd Maste     return 0;
3254bb0738eSEd Maste 
3264bb0738eSEd Maste   return PyByteArray_Size(m_py_obj);
3274bb0738eSEd Maste }
3284bb0738eSEd Maste 
CreateStructuredString() const329435933ddSDimitry Andric StructuredData::StringSP PythonByteArray::CreateStructuredString() const {
3304bb0738eSEd Maste   StructuredData::StringSP result(new StructuredData::String);
3314bb0738eSEd Maste   llvm::ArrayRef<uint8_t> bytes = GetBytes();
3324bb0738eSEd Maste   const char *str = reinterpret_cast<const char *>(bytes.data());
3334bb0738eSEd Maste   result->SetValue(std::string(str, bytes.size()));
3344bb0738eSEd Maste   return result;
3354bb0738eSEd Maste }
3364bb0738eSEd Maste 
337444ed5c5SDimitry Andric //----------------------------------------------------------------------
338444ed5c5SDimitry Andric // PythonString
339444ed5c5SDimitry Andric //----------------------------------------------------------------------
3409f2f44ceSEd Maste 
PythonString(PyRefType type,PyObject * py_obj)341435933ddSDimitry Andric PythonString::PythonString(PyRefType type, PyObject *py_obj) : PythonObject() {
3429f2f44ceSEd Maste   Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string
3439f2f44ceSEd Maste }
3449f2f44ceSEd Maste 
PythonString(const PythonString & object)345435933ddSDimitry Andric PythonString::PythonString(const PythonString &object) : PythonObject(object) {}
3469f2f44ceSEd Maste 
PythonString(llvm::StringRef string)347435933ddSDimitry Andric PythonString::PythonString(llvm::StringRef string) : PythonObject() {
3489f2f44ceSEd Maste   SetString(string);
3499f2f44ceSEd Maste }
3509f2f44ceSEd Maste 
PythonString(const char * string)351435933ddSDimitry Andric PythonString::PythonString(const char *string) : PythonObject() {
3529f2f44ceSEd Maste   SetString(llvm::StringRef(string));
3539f2f44ceSEd Maste }
3549f2f44ceSEd Maste 
PythonString()355435933ddSDimitry Andric PythonString::PythonString() : PythonObject() {}
3569f2f44ceSEd Maste 
~PythonString()357435933ddSDimitry Andric PythonString::~PythonString() {}
3589f2f44ceSEd Maste 
Check(PyObject * py_obj)359435933ddSDimitry Andric bool PythonString::Check(PyObject *py_obj) {
3609f2f44ceSEd Maste   if (!py_obj)
3619f2f44ceSEd Maste     return false;
3629f2f44ceSEd Maste 
3639f2f44ceSEd Maste   if (PyUnicode_Check(py_obj))
3649f2f44ceSEd Maste     return true;
3659f2f44ceSEd Maste #if PY_MAJOR_VERSION < 3
3669f2f44ceSEd Maste   if (PyString_Check(py_obj))
3679f2f44ceSEd Maste     return true;
3689f2f44ceSEd Maste #endif
3699f2f44ceSEd Maste   return false;
3709f2f44ceSEd Maste }
3719f2f44ceSEd Maste 
Reset(PyRefType type,PyObject * py_obj)372435933ddSDimitry Andric void PythonString::Reset(PyRefType type, PyObject *py_obj) {
3734ba319b5SDimitry Andric   // Grab the desired reference type so that if we end up rejecting `py_obj` it
3744ba319b5SDimitry Andric   // still gets decremented if necessary.
3759f2f44ceSEd Maste   PythonObject result(type, py_obj);
3769f2f44ceSEd Maste 
377435933ddSDimitry Andric   if (!PythonString::Check(py_obj)) {
3789f2f44ceSEd Maste     PythonObject::Reset();
3799f2f44ceSEd Maste     return;
3809f2f44ceSEd Maste   }
3819f2f44ceSEd Maste #if PY_MAJOR_VERSION < 3
3829f2f44ceSEd Maste   // In Python 2, Don't store PyUnicode objects directly, because we need
3839f2f44ceSEd Maste   // access to their underlying character buffers which Python 2 doesn't
3849f2f44ceSEd Maste   // provide.
3859f2f44ceSEd Maste   if (PyUnicode_Check(py_obj))
3869f2f44ceSEd Maste     result.Reset(PyRefType::Owned, PyUnicode_AsUTF8String(result.get()));
3879f2f44ceSEd Maste #endif
388435933ddSDimitry Andric   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
3894ba319b5SDimitry Andric   // overflow since it calls back into the virtual implementation.
3909f2f44ceSEd Maste   PythonObject::Reset(PyRefType::Borrowed, result.get());
3919f2f44ceSEd Maste }
3929f2f44ceSEd Maste 
GetString() const393435933ddSDimitry Andric llvm::StringRef PythonString::GetString() const {
3949f2f44ceSEd Maste   if (!IsValid())
3959f2f44ceSEd Maste     return llvm::StringRef();
3969f2f44ceSEd Maste 
3979f2f44ceSEd Maste   Py_ssize_t size;
3984ba319b5SDimitry Andric   const char *data;
3999f2f44ceSEd Maste 
4009f2f44ceSEd Maste #if PY_MAJOR_VERSION >= 3
4014ba319b5SDimitry Andric   data = PyUnicode_AsUTF8AndSize(m_py_obj, &size);
4029f2f44ceSEd Maste #else
4034ba319b5SDimitry Andric   char *c;
4049f2f44ceSEd Maste   PyString_AsStringAndSize(m_py_obj, &c, &size);
4054ba319b5SDimitry Andric   data = c;
4069f2f44ceSEd Maste #endif
4074ba319b5SDimitry Andric   return llvm::StringRef(data, size);
4089f2f44ceSEd Maste }
4099f2f44ceSEd Maste 
GetSize() const410435933ddSDimitry Andric size_t PythonString::GetSize() const {
411435933ddSDimitry Andric   if (IsValid()) {
4129f2f44ceSEd Maste #if PY_MAJOR_VERSION >= 3
4139f2f44ceSEd Maste     return PyUnicode_GetSize(m_py_obj);
4149f2f44ceSEd Maste #else
4159f2f44ceSEd Maste     return PyString_Size(m_py_obj);
4169f2f44ceSEd Maste #endif
4179f2f44ceSEd Maste   }
4189f2f44ceSEd Maste   return 0;
4199f2f44ceSEd Maste }
4209f2f44ceSEd Maste 
SetString(llvm::StringRef string)421435933ddSDimitry Andric void PythonString::SetString(llvm::StringRef string) {
4229f2f44ceSEd Maste #if PY_MAJOR_VERSION >= 3
4239f2f44ceSEd Maste   PyObject *unicode = PyUnicode_FromStringAndSize(string.data(), string.size());
4249f2f44ceSEd Maste   PythonObject::Reset(PyRefType::Owned, unicode);
4259f2f44ceSEd Maste #else
4269f2f44ceSEd Maste   PyObject *str = PyString_FromStringAndSize(string.data(), string.size());
4279f2f44ceSEd Maste   PythonObject::Reset(PyRefType::Owned, str);
4289f2f44ceSEd Maste #endif
4299f2f44ceSEd Maste }
4309f2f44ceSEd Maste 
CreateStructuredString() const431435933ddSDimitry Andric StructuredData::StringSP PythonString::CreateStructuredString() const {
4329f2f44ceSEd Maste   StructuredData::StringSP result(new StructuredData::String);
4339f2f44ceSEd Maste   result->SetValue(GetString());
4349f2f44ceSEd Maste   return result;
4359f2f44ceSEd Maste }
4369f2f44ceSEd Maste 
4379f2f44ceSEd Maste //----------------------------------------------------------------------
4389f2f44ceSEd Maste // PythonInteger
4399f2f44ceSEd Maste //----------------------------------------------------------------------
4409f2f44ceSEd Maste 
PythonInteger()441435933ddSDimitry Andric PythonInteger::PythonInteger() : PythonObject() {}
4429f2f44ceSEd Maste 
PythonInteger(PyRefType type,PyObject * py_obj)4439f2f44ceSEd Maste PythonInteger::PythonInteger(PyRefType type, PyObject *py_obj)
444435933ddSDimitry Andric     : PythonObject() {
4459f2f44ceSEd Maste   Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a integer type
4469f2f44ceSEd Maste }
4479f2f44ceSEd Maste 
PythonInteger(const PythonInteger & object)4489f2f44ceSEd Maste PythonInteger::PythonInteger(const PythonInteger &object)
449435933ddSDimitry Andric     : PythonObject(object) {}
4509f2f44ceSEd Maste 
PythonInteger(int64_t value)451435933ddSDimitry Andric PythonInteger::PythonInteger(int64_t value) : PythonObject() {
4529f2f44ceSEd Maste   SetInteger(value);
4539f2f44ceSEd Maste }
4549f2f44ceSEd Maste 
~PythonInteger()455435933ddSDimitry Andric PythonInteger::~PythonInteger() {}
4569f2f44ceSEd Maste 
Check(PyObject * py_obj)457435933ddSDimitry Andric bool PythonInteger::Check(PyObject *py_obj) {
4589f2f44ceSEd Maste   if (!py_obj)
4599f2f44ceSEd Maste     return false;
4609f2f44ceSEd Maste 
4619f2f44ceSEd Maste #if PY_MAJOR_VERSION >= 3
4624ba319b5SDimitry Andric   // Python 3 does not have PyInt_Check.  There is only one type of integral
4634ba319b5SDimitry Andric   // value, long.
4649f2f44ceSEd Maste   return PyLong_Check(py_obj);
4659f2f44ceSEd Maste #else
4669f2f44ceSEd Maste   return PyLong_Check(py_obj) || PyInt_Check(py_obj);
4679f2f44ceSEd Maste #endif
4689f2f44ceSEd Maste }
4699f2f44ceSEd Maste 
Reset(PyRefType type,PyObject * py_obj)470435933ddSDimitry Andric void PythonInteger::Reset(PyRefType type, PyObject *py_obj) {
4714ba319b5SDimitry Andric   // Grab the desired reference type so that if we end up rejecting `py_obj` it
4724ba319b5SDimitry Andric   // still gets decremented if necessary.
4739f2f44ceSEd Maste   PythonObject result(type, py_obj);
4749f2f44ceSEd Maste 
475435933ddSDimitry Andric   if (!PythonInteger::Check(py_obj)) {
4769f2f44ceSEd Maste     PythonObject::Reset();
4779f2f44ceSEd Maste     return;
4789f2f44ceSEd Maste   }
4799f2f44ceSEd Maste 
4809f2f44ceSEd Maste #if PY_MAJOR_VERSION < 3
4814ba319b5SDimitry Andric   // Always store this as a PyLong, which makes interoperability between Python
4824ba319b5SDimitry Andric   // 2.x and Python 3.x easier.  This is only necessary in 2.x, since 3.x
4834ba319b5SDimitry Andric   // doesn't even have a PyInt.
484435933ddSDimitry Andric   if (PyInt_Check(py_obj)) {
4859f2f44ceSEd Maste     // Since we converted the original object to a different type, the new
4864ba319b5SDimitry Andric     // object is an owned object regardless of the ownership semantics
4874ba319b5SDimitry Andric     // requested by the user.
4889f2f44ceSEd Maste     result.Reset(PyRefType::Owned, PyLong_FromLongLong(PyInt_AsLong(py_obj)));
4899f2f44ceSEd Maste   }
4909f2f44ceSEd Maste #endif
4919f2f44ceSEd Maste 
492435933ddSDimitry Andric   assert(PyLong_Check(result.get()) &&
493435933ddSDimitry Andric          "Couldn't get a PyLong from this PyObject");
4949f2f44ceSEd Maste 
495435933ddSDimitry Andric   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
4964ba319b5SDimitry Andric   // overflow since it calls back into the virtual implementation.
4979f2f44ceSEd Maste   PythonObject::Reset(PyRefType::Borrowed, result.get());
4989f2f44ceSEd Maste }
4999f2f44ceSEd Maste 
GetInteger() const500435933ddSDimitry Andric int64_t PythonInteger::GetInteger() const {
501435933ddSDimitry Andric   if (m_py_obj) {
502435933ddSDimitry Andric     assert(PyLong_Check(m_py_obj) &&
503435933ddSDimitry Andric            "PythonInteger::GetInteger has a PyObject that isn't a PyLong");
5049f2f44ceSEd Maste 
505435933ddSDimitry Andric     int overflow = 0;
506435933ddSDimitry Andric     int64_t result = PyLong_AsLongLongAndOverflow(m_py_obj, &overflow);
507435933ddSDimitry Andric     if (overflow != 0) {
5084ba319b5SDimitry Andric       // We got an integer that overflows, like 18446744072853913392L we can't
5094ba319b5SDimitry Andric       // use PyLong_AsLongLong() as it will return 0xffffffffffffffff. If we
5104ba319b5SDimitry Andric       // use the unsigned long long it will work as expected.
511435933ddSDimitry Andric       const uint64_t uval = PyLong_AsUnsignedLongLong(m_py_obj);
512435933ddSDimitry Andric       result = static_cast<int64_t>(uval);
513435933ddSDimitry Andric     }
514435933ddSDimitry Andric     return result;
5159f2f44ceSEd Maste   }
5169f2f44ceSEd Maste   return UINT64_MAX;
5179f2f44ceSEd Maste }
5189f2f44ceSEd Maste 
SetInteger(int64_t value)519435933ddSDimitry Andric void PythonInteger::SetInteger(int64_t value) {
5209f2f44ceSEd Maste   PythonObject::Reset(PyRefType::Owned, PyLong_FromLongLong(value));
5219f2f44ceSEd Maste }
5229f2f44ceSEd Maste 
CreateStructuredInteger() const523435933ddSDimitry Andric StructuredData::IntegerSP PythonInteger::CreateStructuredInteger() const {
5249f2f44ceSEd Maste   StructuredData::IntegerSP result(new StructuredData::Integer);
5259f2f44ceSEd Maste   result->SetValue(GetInteger());
5269f2f44ceSEd Maste   return result;
5279f2f44ceSEd Maste }
5289f2f44ceSEd Maste 
5299f2f44ceSEd Maste //----------------------------------------------------------------------
5309f2f44ceSEd Maste // PythonList
5319f2f44ceSEd Maste //----------------------------------------------------------------------
5329f2f44ceSEd Maste 
PythonList(PyInitialValue value)533435933ddSDimitry Andric PythonList::PythonList(PyInitialValue value) : PythonObject() {
5349f2f44ceSEd Maste   if (value == PyInitialValue::Empty)
5359f2f44ceSEd Maste     Reset(PyRefType::Owned, PyList_New(0));
5369f2f44ceSEd Maste }
5379f2f44ceSEd Maste 
PythonList(int list_size)538435933ddSDimitry Andric PythonList::PythonList(int list_size) : PythonObject() {
5399f2f44ceSEd Maste   Reset(PyRefType::Owned, PyList_New(list_size));
5409f2f44ceSEd Maste }
5419f2f44ceSEd Maste 
PythonList(PyRefType type,PyObject * py_obj)542435933ddSDimitry Andric PythonList::PythonList(PyRefType type, PyObject *py_obj) : PythonObject() {
5439f2f44ceSEd Maste   Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a list
5449f2f44ceSEd Maste }
5459f2f44ceSEd Maste 
PythonList(const PythonList & list)546435933ddSDimitry Andric PythonList::PythonList(const PythonList &list) : PythonObject(list) {}
5479f2f44ceSEd Maste 
~PythonList()548435933ddSDimitry Andric PythonList::~PythonList() {}
5499f2f44ceSEd Maste 
Check(PyObject * py_obj)550435933ddSDimitry Andric bool PythonList::Check(PyObject *py_obj) {
5519f2f44ceSEd Maste   if (!py_obj)
5529f2f44ceSEd Maste     return false;
5539f2f44ceSEd Maste   return PyList_Check(py_obj);
5549f2f44ceSEd Maste }
5559f2f44ceSEd Maste 
Reset(PyRefType type,PyObject * py_obj)556435933ddSDimitry Andric void PythonList::Reset(PyRefType type, PyObject *py_obj) {
5574ba319b5SDimitry Andric   // Grab the desired reference type so that if we end up rejecting `py_obj` it
5584ba319b5SDimitry Andric   // still gets decremented if necessary.
5599f2f44ceSEd Maste   PythonObject result(type, py_obj);
5609f2f44ceSEd Maste 
561435933ddSDimitry Andric   if (!PythonList::Check(py_obj)) {
5629f2f44ceSEd Maste     PythonObject::Reset();
5639f2f44ceSEd Maste     return;
5649f2f44ceSEd Maste   }
5659f2f44ceSEd Maste 
566435933ddSDimitry Andric   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
5674ba319b5SDimitry Andric   // overflow since it calls back into the virtual implementation.
5689f2f44ceSEd Maste   PythonObject::Reset(PyRefType::Borrowed, result.get());
5699f2f44ceSEd Maste }
5709f2f44ceSEd Maste 
GetSize() const571435933ddSDimitry Andric uint32_t PythonList::GetSize() const {
5729f2f44ceSEd Maste   if (IsValid())
5739f2f44ceSEd Maste     return PyList_GET_SIZE(m_py_obj);
5749f2f44ceSEd Maste   return 0;
5759f2f44ceSEd Maste }
5769f2f44ceSEd Maste 
GetItemAtIndex(uint32_t index) const577435933ddSDimitry Andric PythonObject PythonList::GetItemAtIndex(uint32_t index) const {
5789f2f44ceSEd Maste   if (IsValid())
5799f2f44ceSEd Maste     return PythonObject(PyRefType::Borrowed, PyList_GetItem(m_py_obj, index));
5809f2f44ceSEd Maste   return PythonObject();
5819f2f44ceSEd Maste }
5829f2f44ceSEd Maste 
SetItemAtIndex(uint32_t index,const PythonObject & object)583435933ddSDimitry Andric void PythonList::SetItemAtIndex(uint32_t index, const PythonObject &object) {
584435933ddSDimitry Andric   if (IsAllocated() && object.IsValid()) {
5859f2f44ceSEd Maste     // PyList_SetItem is documented to "steal" a reference, so we need to
5869f2f44ceSEd Maste     // convert it to an owned reference by incrementing it.
5879f2f44ceSEd Maste     Py_INCREF(object.get());
5889f2f44ceSEd Maste     PyList_SetItem(m_py_obj, index, object.get());
5899f2f44ceSEd Maste   }
5909f2f44ceSEd Maste }
5919f2f44ceSEd Maste 
AppendItem(const PythonObject & object)592435933ddSDimitry Andric void PythonList::AppendItem(const PythonObject &object) {
593435933ddSDimitry Andric   if (IsAllocated() && object.IsValid()) {
5949f2f44ceSEd Maste     // `PyList_Append` does *not* steal a reference, so do not call `Py_INCREF`
5959f2f44ceSEd Maste     // here like we do with `PyList_SetItem`.
5969f2f44ceSEd Maste     PyList_Append(m_py_obj, object.get());
5979f2f44ceSEd Maste   }
5989f2f44ceSEd Maste }
5999f2f44ceSEd Maste 
CreateStructuredArray() const600435933ddSDimitry Andric StructuredData::ArraySP PythonList::CreateStructuredArray() const {
6019f2f44ceSEd Maste   StructuredData::ArraySP result(new StructuredData::Array);
6029f2f44ceSEd Maste   uint32_t count = GetSize();
603435933ddSDimitry Andric   for (uint32_t i = 0; i < count; ++i) {
6049f2f44ceSEd Maste     PythonObject obj = GetItemAtIndex(i);
6059f2f44ceSEd Maste     result->AddItem(obj.CreateStructuredObject());
6069f2f44ceSEd Maste   }
6079f2f44ceSEd Maste   return result;
6089f2f44ceSEd Maste }
6099f2f44ceSEd Maste 
6109f2f44ceSEd Maste //----------------------------------------------------------------------
6119f2f44ceSEd Maste // PythonTuple
6129f2f44ceSEd Maste //----------------------------------------------------------------------
6139f2f44ceSEd Maste 
PythonTuple(PyInitialValue value)614435933ddSDimitry Andric PythonTuple::PythonTuple(PyInitialValue value) : PythonObject() {
6159f2f44ceSEd Maste   if (value == PyInitialValue::Empty)
6169f2f44ceSEd Maste     Reset(PyRefType::Owned, PyTuple_New(0));
6179f2f44ceSEd Maste }
6189f2f44ceSEd Maste 
PythonTuple(int tuple_size)619435933ddSDimitry Andric PythonTuple::PythonTuple(int tuple_size) : PythonObject() {
6209f2f44ceSEd Maste   Reset(PyRefType::Owned, PyTuple_New(tuple_size));
6219f2f44ceSEd Maste }
6229f2f44ceSEd Maste 
PythonTuple(PyRefType type,PyObject * py_obj)623435933ddSDimitry Andric PythonTuple::PythonTuple(PyRefType type, PyObject *py_obj) : PythonObject() {
6249f2f44ceSEd Maste   Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a tuple
6259f2f44ceSEd Maste }
6269f2f44ceSEd Maste 
PythonTuple(const PythonTuple & tuple)627435933ddSDimitry Andric PythonTuple::PythonTuple(const PythonTuple &tuple) : PythonObject(tuple) {}
6289f2f44ceSEd Maste 
PythonTuple(std::initializer_list<PythonObject> objects)629435933ddSDimitry Andric PythonTuple::PythonTuple(std::initializer_list<PythonObject> objects) {
6309f2f44ceSEd Maste   m_py_obj = PyTuple_New(objects.size());
6319f2f44ceSEd Maste 
6329f2f44ceSEd Maste   uint32_t idx = 0;
633435933ddSDimitry Andric   for (auto object : objects) {
6349f2f44ceSEd Maste     if (object.IsValid())
6359f2f44ceSEd Maste       SetItemAtIndex(idx, object);
6369f2f44ceSEd Maste     idx++;
6379f2f44ceSEd Maste   }
6389f2f44ceSEd Maste }
6399f2f44ceSEd Maste 
PythonTuple(std::initializer_list<PyObject * > objects)640435933ddSDimitry Andric PythonTuple::PythonTuple(std::initializer_list<PyObject *> objects) {
6419f2f44ceSEd Maste   m_py_obj = PyTuple_New(objects.size());
6429f2f44ceSEd Maste 
6439f2f44ceSEd Maste   uint32_t idx = 0;
644435933ddSDimitry Andric   for (auto py_object : objects) {
6459f2f44ceSEd Maste     PythonObject object(PyRefType::Borrowed, py_object);
6469f2f44ceSEd Maste     if (object.IsValid())
6479f2f44ceSEd Maste       SetItemAtIndex(idx, object);
6489f2f44ceSEd Maste     idx++;
6499f2f44ceSEd Maste   }
6509f2f44ceSEd Maste }
6519f2f44ceSEd Maste 
~PythonTuple()652435933ddSDimitry Andric PythonTuple::~PythonTuple() {}
6539f2f44ceSEd Maste 
Check(PyObject * py_obj)654435933ddSDimitry Andric bool PythonTuple::Check(PyObject *py_obj) {
6559f2f44ceSEd Maste   if (!py_obj)
6569f2f44ceSEd Maste     return false;
6579f2f44ceSEd Maste   return PyTuple_Check(py_obj);
6589f2f44ceSEd Maste }
6599f2f44ceSEd Maste 
Reset(PyRefType type,PyObject * py_obj)660435933ddSDimitry Andric void PythonTuple::Reset(PyRefType type, PyObject *py_obj) {
6614ba319b5SDimitry Andric   // Grab the desired reference type so that if we end up rejecting `py_obj` it
6624ba319b5SDimitry Andric   // still gets decremented if necessary.
6639f2f44ceSEd Maste   PythonObject result(type, py_obj);
6649f2f44ceSEd Maste 
665435933ddSDimitry Andric   if (!PythonTuple::Check(py_obj)) {
6669f2f44ceSEd Maste     PythonObject::Reset();
6679f2f44ceSEd Maste     return;
6689f2f44ceSEd Maste   }
6699f2f44ceSEd Maste 
670435933ddSDimitry Andric   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
6714ba319b5SDimitry Andric   // overflow since it calls back into the virtual implementation.
6729f2f44ceSEd Maste   PythonObject::Reset(PyRefType::Borrowed, result.get());
6739f2f44ceSEd Maste }
6749f2f44ceSEd Maste 
GetSize() const675435933ddSDimitry Andric uint32_t PythonTuple::GetSize() const {
6769f2f44ceSEd Maste   if (IsValid())
6779f2f44ceSEd Maste     return PyTuple_GET_SIZE(m_py_obj);
6789f2f44ceSEd Maste   return 0;
6799f2f44ceSEd Maste }
6809f2f44ceSEd Maste 
GetItemAtIndex(uint32_t index) const681435933ddSDimitry Andric PythonObject PythonTuple::GetItemAtIndex(uint32_t index) const {
6829f2f44ceSEd Maste   if (IsValid())
6839f2f44ceSEd Maste     return PythonObject(PyRefType::Borrowed, PyTuple_GetItem(m_py_obj, index));
6849f2f44ceSEd Maste   return PythonObject();
6859f2f44ceSEd Maste }
6869f2f44ceSEd Maste 
SetItemAtIndex(uint32_t index,const PythonObject & object)687435933ddSDimitry Andric void PythonTuple::SetItemAtIndex(uint32_t index, const PythonObject &object) {
688435933ddSDimitry Andric   if (IsAllocated() && object.IsValid()) {
6899f2f44ceSEd Maste     // PyTuple_SetItem is documented to "steal" a reference, so we need to
6909f2f44ceSEd Maste     // convert it to an owned reference by incrementing it.
6919f2f44ceSEd Maste     Py_INCREF(object.get());
6929f2f44ceSEd Maste     PyTuple_SetItem(m_py_obj, index, object.get());
6939f2f44ceSEd Maste   }
6949f2f44ceSEd Maste }
6959f2f44ceSEd Maste 
CreateStructuredArray() const696435933ddSDimitry Andric StructuredData::ArraySP PythonTuple::CreateStructuredArray() const {
6979f2f44ceSEd Maste   StructuredData::ArraySP result(new StructuredData::Array);
6989f2f44ceSEd Maste   uint32_t count = GetSize();
699435933ddSDimitry Andric   for (uint32_t i = 0; i < count; ++i) {
7009f2f44ceSEd Maste     PythonObject obj = GetItemAtIndex(i);
7019f2f44ceSEd Maste     result->AddItem(obj.CreateStructuredObject());
7029f2f44ceSEd Maste   }
7039f2f44ceSEd Maste   return result;
7049f2f44ceSEd Maste }
7059f2f44ceSEd Maste 
7069f2f44ceSEd Maste //----------------------------------------------------------------------
7079f2f44ceSEd Maste // PythonDictionary
7089f2f44ceSEd Maste //----------------------------------------------------------------------
7099f2f44ceSEd Maste 
PythonDictionary(PyInitialValue value)710435933ddSDimitry Andric PythonDictionary::PythonDictionary(PyInitialValue value) : PythonObject() {
7119f2f44ceSEd Maste   if (value == PyInitialValue::Empty)
7129f2f44ceSEd Maste     Reset(PyRefType::Owned, PyDict_New());
7139f2f44ceSEd Maste }
7149f2f44ceSEd Maste 
PythonDictionary(PyRefType type,PyObject * py_obj)7159f2f44ceSEd Maste PythonDictionary::PythonDictionary(PyRefType type, PyObject *py_obj)
716435933ddSDimitry Andric     : PythonObject() {
7179f2f44ceSEd Maste   Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a dictionary
7189f2f44ceSEd Maste }
7199f2f44ceSEd Maste 
PythonDictionary(const PythonDictionary & object)7209f2f44ceSEd Maste PythonDictionary::PythonDictionary(const PythonDictionary &object)
721435933ddSDimitry Andric     : PythonObject(object) {}
7229f2f44ceSEd Maste 
~PythonDictionary()723435933ddSDimitry Andric PythonDictionary::~PythonDictionary() {}
7249f2f44ceSEd Maste 
Check(PyObject * py_obj)725435933ddSDimitry Andric bool PythonDictionary::Check(PyObject *py_obj) {
7269f2f44ceSEd Maste   if (!py_obj)
7279f2f44ceSEd Maste     return false;
7289f2f44ceSEd Maste 
7299f2f44ceSEd Maste   return PyDict_Check(py_obj);
7309f2f44ceSEd Maste }
7319f2f44ceSEd Maste 
Reset(PyRefType type,PyObject * py_obj)732435933ddSDimitry Andric void PythonDictionary::Reset(PyRefType type, PyObject *py_obj) {
7334ba319b5SDimitry Andric   // Grab the desired reference type so that if we end up rejecting `py_obj` it
7344ba319b5SDimitry Andric   // still gets decremented if necessary.
7359f2f44ceSEd Maste   PythonObject result(type, py_obj);
7369f2f44ceSEd Maste 
737435933ddSDimitry Andric   if (!PythonDictionary::Check(py_obj)) {
7389f2f44ceSEd Maste     PythonObject::Reset();
7399f2f44ceSEd Maste     return;
7409f2f44ceSEd Maste   }
7419f2f44ceSEd Maste 
742435933ddSDimitry Andric   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
7434ba319b5SDimitry Andric   // overflow since it calls back into the virtual implementation.
7449f2f44ceSEd Maste   PythonObject::Reset(PyRefType::Borrowed, result.get());
7459f2f44ceSEd Maste }
7469f2f44ceSEd Maste 
GetSize() const747435933ddSDimitry Andric uint32_t PythonDictionary::GetSize() const {
7489f2f44ceSEd Maste   if (IsValid())
7499f2f44ceSEd Maste     return PyDict_Size(m_py_obj);
7509f2f44ceSEd Maste   return 0;
7519f2f44ceSEd Maste }
7529f2f44ceSEd Maste 
GetKeys() const753435933ddSDimitry Andric PythonList PythonDictionary::GetKeys() const {
7549f2f44ceSEd Maste   if (IsValid())
7559f2f44ceSEd Maste     return PythonList(PyRefType::Owned, PyDict_Keys(m_py_obj));
7569f2f44ceSEd Maste   return PythonList(PyInitialValue::Invalid);
7579f2f44ceSEd Maste }
7589f2f44ceSEd Maste 
GetItemForKey(const PythonObject & key) const759435933ddSDimitry Andric PythonObject PythonDictionary::GetItemForKey(const PythonObject &key) const {
7609f2f44ceSEd Maste   if (IsAllocated() && key.IsValid())
761435933ddSDimitry Andric     return PythonObject(PyRefType::Borrowed,
762435933ddSDimitry Andric                         PyDict_GetItem(m_py_obj, key.get()));
7639f2f44ceSEd Maste   return PythonObject();
7649f2f44ceSEd Maste }
7659f2f44ceSEd Maste 
SetItemForKey(const PythonObject & key,const PythonObject & value)766435933ddSDimitry Andric void PythonDictionary::SetItemForKey(const PythonObject &key,
767435933ddSDimitry Andric                                      const PythonObject &value) {
7689f2f44ceSEd Maste   if (IsAllocated() && key.IsValid() && value.IsValid())
7699f2f44ceSEd Maste     PyDict_SetItem(m_py_obj, key.get(), value.get());
7709f2f44ceSEd Maste }
7719f2f44ceSEd Maste 
7729f2f44ceSEd Maste StructuredData::DictionarySP
CreateStructuredDictionary() const773435933ddSDimitry Andric PythonDictionary::CreateStructuredDictionary() const {
7749f2f44ceSEd Maste   StructuredData::DictionarySP result(new StructuredData::Dictionary);
7759f2f44ceSEd Maste   PythonList keys(GetKeys());
7769f2f44ceSEd Maste   uint32_t num_keys = keys.GetSize();
777435933ddSDimitry Andric   for (uint32_t i = 0; i < num_keys; ++i) {
7789f2f44ceSEd Maste     PythonObject key = keys.GetItemAtIndex(i);
7799f2f44ceSEd Maste     PythonObject value = GetItemForKey(key);
7809f2f44ceSEd Maste     StructuredData::ObjectSP structured_value = value.CreateStructuredObject();
7819f2f44ceSEd Maste     result->AddItem(key.Str().GetString(), structured_value);
7829f2f44ceSEd Maste   }
7839f2f44ceSEd Maste   return result;
7849f2f44ceSEd Maste }
7859f2f44ceSEd Maste 
PythonModule()786435933ddSDimitry Andric PythonModule::PythonModule() : PythonObject() {}
7879f2f44ceSEd Maste 
PythonModule(PyRefType type,PyObject * py_obj)788435933ddSDimitry Andric PythonModule::PythonModule(PyRefType type, PyObject *py_obj) {
7899f2f44ceSEd Maste   Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a module
7909f2f44ceSEd Maste }
7919f2f44ceSEd Maste 
PythonModule(const PythonModule & dict)792435933ddSDimitry Andric PythonModule::PythonModule(const PythonModule &dict) : PythonObject(dict) {}
7939f2f44ceSEd Maste 
~PythonModule()794435933ddSDimitry Andric PythonModule::~PythonModule() {}
7959f2f44ceSEd Maste 
BuiltinsModule()796435933ddSDimitry Andric PythonModule PythonModule::BuiltinsModule() {
7979f2f44ceSEd Maste #if PY_MAJOR_VERSION >= 3
7989f2f44ceSEd Maste   return AddModule("builtins");
7999f2f44ceSEd Maste #else
8009f2f44ceSEd Maste   return AddModule("__builtin__");
8019f2f44ceSEd Maste #endif
8029f2f44ceSEd Maste }
8039f2f44ceSEd Maste 
MainModule()804435933ddSDimitry Andric PythonModule PythonModule::MainModule() { return AddModule("__main__"); }
8059f2f44ceSEd Maste 
AddModule(llvm::StringRef module)806435933ddSDimitry Andric PythonModule PythonModule::AddModule(llvm::StringRef module) {
8079f2f44ceSEd Maste   std::string str = module.str();
8089f2f44ceSEd Maste   return PythonModule(PyRefType::Borrowed, PyImport_AddModule(str.c_str()));
8099f2f44ceSEd Maste }
8109f2f44ceSEd Maste 
ImportModule(llvm::StringRef module)811435933ddSDimitry Andric PythonModule PythonModule::ImportModule(llvm::StringRef module) {
8129f2f44ceSEd Maste   std::string str = module.str();
8139f2f44ceSEd Maste   return PythonModule(PyRefType::Owned, PyImport_ImportModule(str.c_str()));
8149f2f44ceSEd Maste }
8159f2f44ceSEd Maste 
Check(PyObject * py_obj)816435933ddSDimitry Andric bool PythonModule::Check(PyObject *py_obj) {
8179f2f44ceSEd Maste   if (!py_obj)
8189f2f44ceSEd Maste     return false;
8199f2f44ceSEd Maste 
8209f2f44ceSEd Maste   return PyModule_Check(py_obj);
8219f2f44ceSEd Maste }
8229f2f44ceSEd Maste 
Reset(PyRefType type,PyObject * py_obj)823435933ddSDimitry Andric void PythonModule::Reset(PyRefType type, PyObject *py_obj) {
8244ba319b5SDimitry Andric   // Grab the desired reference type so that if we end up rejecting `py_obj` it
8254ba319b5SDimitry Andric   // still gets decremented if necessary.
8269f2f44ceSEd Maste   PythonObject result(type, py_obj);
8279f2f44ceSEd Maste 
828435933ddSDimitry Andric   if (!PythonModule::Check(py_obj)) {
8299f2f44ceSEd Maste     PythonObject::Reset();
8309f2f44ceSEd Maste     return;
8319f2f44ceSEd Maste   }
8329f2f44ceSEd Maste 
833435933ddSDimitry Andric   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
8344ba319b5SDimitry Andric   // overflow since it calls back into the virtual implementation.
8359f2f44ceSEd Maste   PythonObject::Reset(PyRefType::Borrowed, result.get());
8369f2f44ceSEd Maste }
8379f2f44ceSEd Maste 
GetDictionary() const838435933ddSDimitry Andric PythonDictionary PythonModule::GetDictionary() const {
8399f2f44ceSEd Maste   return PythonDictionary(PyRefType::Borrowed, PyModule_GetDict(m_py_obj));
8409f2f44ceSEd Maste }
8419f2f44ceSEd Maste 
PythonCallable()842435933ddSDimitry Andric PythonCallable::PythonCallable() : PythonObject() {}
8439f2f44ceSEd Maste 
PythonCallable(PyRefType type,PyObject * py_obj)844435933ddSDimitry Andric PythonCallable::PythonCallable(PyRefType type, PyObject *py_obj) {
8459f2f44ceSEd Maste   Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a callable
8469f2f44ceSEd Maste }
8479f2f44ceSEd Maste 
PythonCallable(const PythonCallable & callable)8489f2f44ceSEd Maste PythonCallable::PythonCallable(const PythonCallable &callable)
849435933ddSDimitry Andric     : PythonObject(callable) {}
8509f2f44ceSEd Maste 
~PythonCallable()851435933ddSDimitry Andric PythonCallable::~PythonCallable() {}
8529f2f44ceSEd Maste 
Check(PyObject * py_obj)853435933ddSDimitry Andric bool PythonCallable::Check(PyObject *py_obj) {
8549f2f44ceSEd Maste   if (!py_obj)
8559f2f44ceSEd Maste     return false;
8569f2f44ceSEd Maste 
8579f2f44ceSEd Maste   return PyCallable_Check(py_obj);
8589f2f44ceSEd Maste }
8599f2f44ceSEd Maste 
Reset(PyRefType type,PyObject * py_obj)860435933ddSDimitry Andric void PythonCallable::Reset(PyRefType type, PyObject *py_obj) {
8614ba319b5SDimitry Andric   // Grab the desired reference type so that if we end up rejecting `py_obj` it
8624ba319b5SDimitry Andric   // still gets decremented if necessary.
8639f2f44ceSEd Maste   PythonObject result(type, py_obj);
8649f2f44ceSEd Maste 
865435933ddSDimitry Andric   if (!PythonCallable::Check(py_obj)) {
8669f2f44ceSEd Maste     PythonObject::Reset();
8679f2f44ceSEd Maste     return;
8689f2f44ceSEd Maste   }
8699f2f44ceSEd Maste 
870435933ddSDimitry Andric   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
8714ba319b5SDimitry Andric   // overflow since it calls back into the virtual implementation.
8729f2f44ceSEd Maste   PythonObject::Reset(PyRefType::Borrowed, result.get());
8739f2f44ceSEd Maste }
8749f2f44ceSEd Maste 
GetNumArguments() const875435933ddSDimitry Andric PythonCallable::ArgInfo PythonCallable::GetNumArguments() const {
8764bb0738eSEd Maste   ArgInfo result = {0, false, false, false};
8779f2f44ceSEd Maste   if (!IsValid())
8789f2f44ceSEd Maste     return result;
8799f2f44ceSEd Maste 
8809f2f44ceSEd Maste   PyObject *py_func_obj = m_py_obj;
881435933ddSDimitry Andric   if (PyMethod_Check(py_func_obj)) {
8829f2f44ceSEd Maste     py_func_obj = PyMethod_GET_FUNCTION(py_func_obj);
8834bb0738eSEd Maste     PythonObject im_self = GetAttributeValue("im_self");
8844bb0738eSEd Maste     if (im_self.IsValid() && !im_self.IsNone())
8854bb0738eSEd Maste       result.is_bound_method = true;
886435933ddSDimitry Andric   } else {
8874bb0738eSEd Maste     // see if this is a callable object with an __call__ method
888435933ddSDimitry Andric     if (!PyFunction_Check(py_func_obj)) {
8894bb0738eSEd Maste       PythonObject __call__ = GetAttributeValue("__call__");
890435933ddSDimitry Andric       if (__call__.IsValid()) {
8914bb0738eSEd Maste         auto __callable__ = __call__.AsType<PythonCallable>();
892435933ddSDimitry Andric         if (__callable__.IsValid()) {
8934bb0738eSEd Maste           py_func_obj = PyMethod_GET_FUNCTION(__callable__.get());
8944bb0738eSEd Maste           PythonObject im_self = GetAttributeValue("im_self");
8954bb0738eSEd Maste           if (im_self.IsValid() && !im_self.IsNone())
8964bb0738eSEd Maste             result.is_bound_method = true;
8974bb0738eSEd Maste         }
8984bb0738eSEd Maste       }
8994bb0738eSEd Maste     }
9004bb0738eSEd Maste   }
9019f2f44ceSEd Maste 
9029f2f44ceSEd Maste   if (!py_func_obj)
9039f2f44ceSEd Maste     return result;
9049f2f44ceSEd Maste 
9059f2f44ceSEd Maste   PyCodeObject *code = (PyCodeObject *)PyFunction_GET_CODE(py_func_obj);
9069f2f44ceSEd Maste   if (!code)
9079f2f44ceSEd Maste     return result;
9089f2f44ceSEd Maste 
9099f2f44ceSEd Maste   result.count = code->co_argcount;
9109f2f44ceSEd Maste   result.has_varargs = !!(code->co_flags & CO_VARARGS);
9119f2f44ceSEd Maste   result.has_kwargs = !!(code->co_flags & CO_VARKEYWORDS);
9129f2f44ceSEd Maste   return result;
9139f2f44ceSEd Maste }
9149f2f44ceSEd Maste 
operator ()()915435933ddSDimitry Andric PythonObject PythonCallable::operator()() {
916435933ddSDimitry Andric   return PythonObject(PyRefType::Owned, PyObject_CallObject(m_py_obj, nullptr));
9179f2f44ceSEd Maste }
9189f2f44ceSEd Maste 
919435933ddSDimitry Andric PythonObject PythonCallable::
operator ()(std::initializer_list<PyObject * > args)920435933ddSDimitry Andric operator()(std::initializer_list<PyObject *> args) {
9219f2f44ceSEd Maste   PythonTuple arg_tuple(args);
9229f2f44ceSEd Maste   return PythonObject(PyRefType::Owned,
9239f2f44ceSEd Maste                       PyObject_CallObject(m_py_obj, arg_tuple.get()));
9249f2f44ceSEd Maste }
9259f2f44ceSEd Maste 
926435933ddSDimitry Andric PythonObject PythonCallable::
operator ()(std::initializer_list<PythonObject> args)927435933ddSDimitry Andric operator()(std::initializer_list<PythonObject> args) {
9289f2f44ceSEd Maste   PythonTuple arg_tuple(args);
9299f2f44ceSEd Maste   return PythonObject(PyRefType::Owned,
9309f2f44ceSEd Maste                       PyObject_CallObject(m_py_obj, arg_tuple.get()));
9319f2f44ceSEd Maste }
9329f2f44ceSEd Maste 
PythonFile()933435933ddSDimitry Andric PythonFile::PythonFile() : PythonObject() {}
9349f2f44ceSEd Maste 
PythonFile(File & file,const char * mode)935435933ddSDimitry Andric PythonFile::PythonFile(File &file, const char *mode) { Reset(file, mode); }
9369f2f44ceSEd Maste 
PythonFile(const char * path,const char * mode)937435933ddSDimitry Andric PythonFile::PythonFile(const char *path, const char *mode) {
938*b5893f02SDimitry Andric   lldb_private::File file;
939*b5893f02SDimitry Andric   FileSystem::Instance().Open(file, FileSpec(path), GetOptionsFromMode(mode));
9409f2f44ceSEd Maste   Reset(file, mode);
9419f2f44ceSEd Maste }
9429f2f44ceSEd Maste 
PythonFile(PyRefType type,PyObject * o)943435933ddSDimitry Andric PythonFile::PythonFile(PyRefType type, PyObject *o) { Reset(type, o); }
9449f2f44ceSEd Maste 
~PythonFile()945435933ddSDimitry Andric PythonFile::~PythonFile() {}
9469f2f44ceSEd Maste 
Check(PyObject * py_obj)947435933ddSDimitry Andric bool PythonFile::Check(PyObject *py_obj) {
9489f2f44ceSEd Maste #if PY_MAJOR_VERSION < 3
9499f2f44ceSEd Maste   return PyFile_Check(py_obj);
9509f2f44ceSEd Maste #else
9519f2f44ceSEd Maste   // In Python 3, there is no `PyFile_Check`, and in fact PyFile is not even a
9529f2f44ceSEd Maste   // first-class object type anymore.  `PyFile_FromFd` is just a thin wrapper
9534ba319b5SDimitry Andric   // over `io.open()`, which returns some object derived from `io.IOBase`. As a
9544ba319b5SDimitry Andric   // result, the only way to detect a file in Python 3 is to check whether it
9554ba319b5SDimitry Andric   // inherits from `io.IOBase`.  Since it is possible for non-files to also
9569f2f44ceSEd Maste   // inherit from `io.IOBase`, we additionally verify that it has the `fileno`
9579f2f44ceSEd Maste   // attribute, which should guarantee that it is backed by the file system.
9589f2f44ceSEd Maste   PythonObject io_module(PyRefType::Owned, PyImport_ImportModule("io"));
959435933ddSDimitry Andric   PythonDictionary io_dict(PyRefType::Borrowed,
960435933ddSDimitry Andric                            PyModule_GetDict(io_module.get()));
9619f2f44ceSEd Maste   PythonObject io_base_class = io_dict.GetItemForKey(PythonString("IOBase"));
9629f2f44ceSEd Maste 
9639f2f44ceSEd Maste   PythonObject object_type(PyRefType::Owned, PyObject_Type(py_obj));
9649f2f44ceSEd Maste 
9659f2f44ceSEd Maste   if (1 != PyObject_IsSubclass(object_type.get(), io_base_class.get()))
9669f2f44ceSEd Maste     return false;
9679f2f44ceSEd Maste   if (!object_type.HasAttribute("fileno"))
9689f2f44ceSEd Maste     return false;
9699f2f44ceSEd Maste 
9709f2f44ceSEd Maste   return true;
9719f2f44ceSEd Maste #endif
9729f2f44ceSEd Maste }
9739f2f44ceSEd Maste 
Reset(PyRefType type,PyObject * py_obj)974435933ddSDimitry Andric void PythonFile::Reset(PyRefType type, PyObject *py_obj) {
9754ba319b5SDimitry Andric   // Grab the desired reference type so that if we end up rejecting `py_obj` it
9764ba319b5SDimitry Andric   // still gets decremented if necessary.
9779f2f44ceSEd Maste   PythonObject result(type, py_obj);
9789f2f44ceSEd Maste 
979435933ddSDimitry Andric   if (!PythonFile::Check(py_obj)) {
9809f2f44ceSEd Maste     PythonObject::Reset();
9819f2f44ceSEd Maste     return;
9829f2f44ceSEd Maste   }
9839f2f44ceSEd Maste 
9849f2f44ceSEd Maste   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
9859f2f44ceSEd Maste   // overflow since it calls back into the virtual implementation.
9869f2f44ceSEd Maste   PythonObject::Reset(PyRefType::Borrowed, result.get());
9879f2f44ceSEd Maste }
9889f2f44ceSEd Maste 
Reset(File & file,const char * mode)989435933ddSDimitry Andric void PythonFile::Reset(File &file, const char *mode) {
990435933ddSDimitry Andric   if (!file.IsValid()) {
9919f2f44ceSEd Maste     Reset();
9929f2f44ceSEd Maste     return;
9939f2f44ceSEd Maste   }
9949f2f44ceSEd Maste 
9959f2f44ceSEd Maste   char *cmode = const_cast<char *>(mode);
9969f2f44ceSEd Maste #if PY_MAJOR_VERSION >= 3
997435933ddSDimitry Andric   Reset(PyRefType::Owned, PyFile_FromFd(file.GetDescriptor(), nullptr, cmode,
998435933ddSDimitry Andric                                         -1, nullptr, "ignore", nullptr, 0));
9999f2f44ceSEd Maste #else
10009f2f44ceSEd Maste   // Read through the Python source, doesn't seem to modify these strings
10019f2f44ceSEd Maste   Reset(PyRefType::Owned,
1002435933ddSDimitry Andric         PyFile_FromFile(file.GetStream(), const_cast<char *>(""), cmode,
1003435933ddSDimitry Andric                         nullptr));
10049f2f44ceSEd Maste #endif
10059f2f44ceSEd Maste }
10069f2f44ceSEd Maste 
GetOptionsFromMode(llvm::StringRef mode)1007435933ddSDimitry Andric uint32_t PythonFile::GetOptionsFromMode(llvm::StringRef mode) {
10084bb0738eSEd Maste   if (mode.empty())
10094bb0738eSEd Maste     return 0;
10104bb0738eSEd Maste 
1011435933ddSDimitry Andric   return llvm::StringSwitch<uint32_t>(mode.str())
10124bb0738eSEd Maste       .Case("r", File::eOpenOptionRead)
10134bb0738eSEd Maste       .Case("w", File::eOpenOptionWrite)
1014435933ddSDimitry Andric       .Case("a", File::eOpenOptionWrite | File::eOpenOptionAppend |
1015435933ddSDimitry Andric                      File::eOpenOptionCanCreate)
10164bb0738eSEd Maste       .Case("r+", File::eOpenOptionRead | File::eOpenOptionWrite)
1017435933ddSDimitry Andric       .Case("w+", File::eOpenOptionRead | File::eOpenOptionWrite |
1018435933ddSDimitry Andric                       File::eOpenOptionCanCreate | File::eOpenOptionTruncate)
1019435933ddSDimitry Andric       .Case("a+", File::eOpenOptionRead | File::eOpenOptionWrite |
1020435933ddSDimitry Andric                       File::eOpenOptionAppend | File::eOpenOptionCanCreate)
10214bb0738eSEd Maste       .Default(0);
10224bb0738eSEd Maste }
10234bb0738eSEd Maste 
GetUnderlyingFile(File & file) const1024435933ddSDimitry Andric bool PythonFile::GetUnderlyingFile(File &file) const {
10259f2f44ceSEd Maste   if (!IsValid())
10269f2f44ceSEd Maste     return false;
10279f2f44ceSEd Maste 
10289f2f44ceSEd Maste   file.Close();
10299f2f44ceSEd Maste   // We don't own the file descriptor returned by this function, make sure the
10309f2f44ceSEd Maste   // File object knows about that.
10319f2f44ceSEd Maste   file.SetDescriptor(PyObject_AsFileDescriptor(m_py_obj), false);
10324bb0738eSEd Maste   PythonString py_mode = GetAttributeValue("mode").AsType<PythonString>();
10334bb0738eSEd Maste   file.SetOptions(PythonFile::GetOptionsFromMode(py_mode.GetString()));
10349f2f44ceSEd Maste   return file.IsValid();
10359f2f44ceSEd Maste }
10369f2f44ceSEd Maste 
10379f2f44ceSEd Maste #endif
1038