xref: /llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp (revision 744959b9c9d7700a567926a4829f2e8cc6dc3cec)
1 //===-- PythonDataObjects.cpp ------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #ifdef LLDB_DISABLE_PYTHON
11 
12 // Python is disabled in this build
13 
14 #else
15 
16 #include "lldb-python.h"
17 #include "PythonDataObjects.h"
18 #include "ScriptInterpreterPython.h"
19 
20 #include "lldb/Core/Stream.h"
21 #include "lldb/Host/File.h"
22 #include "lldb/Interpreter/ScriptInterpreter.h"
23 
24 #include <stdio.h>
25 
26 #include "llvm/ADT/StringSwitch.h"
27 
28 using namespace lldb_private;
29 using namespace lldb;
30 
31 void
32 StructuredPythonObject::Dump(Stream &s) const
33 {
34     s << "Python Obj: 0x" << GetValue();
35 }
36 
37 //----------------------------------------------------------------------
38 // PythonObject
39 //----------------------------------------------------------------------
40 
41 void
42 PythonObject::Dump(Stream &strm) const
43 {
44     if (m_py_obj)
45     {
46         FILE *file = ::tmpfile();
47         if (file)
48         {
49             ::PyObject_Print (m_py_obj, file, 0);
50             const long length = ftell (file);
51             if (length)
52             {
53                 ::rewind(file);
54                 std::vector<char> file_contents (length,'\0');
55                 const size_t length_read = ::fread (file_contents.data(), 1, file_contents.size(), file);
56                 if (length_read > 0)
57                     strm.Write (file_contents.data(), length_read);
58             }
59             ::fclose (file);
60         }
61     }
62     else
63         strm.PutCString ("NULL");
64 }
65 
66 PyObjectType
67 PythonObject::GetObjectType() const
68 {
69     if (!IsAllocated())
70         return PyObjectType::None;
71 
72     if (PythonModule::Check(m_py_obj))
73         return PyObjectType::Module;
74     if (PythonList::Check(m_py_obj))
75         return PyObjectType::List;
76     if (PythonTuple::Check(m_py_obj))
77         return PyObjectType::Tuple;
78     if (PythonDictionary::Check(m_py_obj))
79         return PyObjectType::Dictionary;
80     if (PythonString::Check(m_py_obj))
81         return PyObjectType::String;
82 #if PY_MAJOR_VERSION >= 3
83     if (PythonBytes::Check(m_py_obj))
84         return PyObjectType::Bytes;
85 #endif
86     if (PythonInteger::Check(m_py_obj))
87         return PyObjectType::Integer;
88     if (PythonFile::Check(m_py_obj))
89         return PyObjectType::File;
90     if (PythonCallable::Check(m_py_obj))
91         return PyObjectType::Callable;
92     return PyObjectType::Unknown;
93 }
94 
95 PythonString
96 PythonObject::Repr() const
97 {
98     if (!m_py_obj)
99         return PythonString();
100     PyObject *repr = PyObject_Repr(m_py_obj);
101     if (!repr)
102         return PythonString();
103     return PythonString(PyRefType::Owned, repr);
104 }
105 
106 PythonString
107 PythonObject::Str() const
108 {
109     if (!m_py_obj)
110         return PythonString();
111     PyObject *str = PyObject_Str(m_py_obj);
112     if (!str)
113         return PythonString();
114     return PythonString(PyRefType::Owned, str);
115 }
116 
117 PythonObject
118 PythonObject::ResolveNameWithDictionary(llvm::StringRef name, const PythonDictionary &dict)
119 {
120     size_t dot_pos = name.find_first_of('.');
121     llvm::StringRef piece = name.substr(0, dot_pos);
122     PythonObject result = dict.GetItemForKey(PythonString(piece));
123     if (dot_pos == llvm::StringRef::npos)
124     {
125         // There was no dot, we're done.
126         return result;
127     }
128 
129     // There was a dot.  The remaining portion of the name should be looked up in
130     // the context of the object that was found in the dictionary.
131     return result.ResolveName(name.substr(dot_pos + 1));
132 }
133 
134 PythonObject
135 PythonObject::ResolveName(llvm::StringRef name) const
136 {
137     // Resolve the name in the context of the specified object.  If,
138     // for example, `this` refers to a PyModule, then this will look for
139     // `name` in this module.  If `this` refers to a PyType, then it will
140     // resolve `name` as an attribute of that type.  If `this` refers to
141     // an instance of an object, then it will resolve `name` as the value
142     // of the specified field.
143     //
144     // This function handles dotted names so that, for example, if `m_py_obj`
145     // refers to the `sys` module, and `name` == "path.append", then it
146     // will find the function `sys.path.append`.
147 
148     size_t dot_pos = name.find_first_of('.');
149     if (dot_pos == llvm::StringRef::npos)
150     {
151         // No dots in the name, we should be able to find the value immediately
152         // as an attribute of `m_py_obj`.
153         return GetAttributeValue(name);
154     }
155 
156     // Look up the first piece of the name, and resolve the rest as a child of that.
157     PythonObject parent = ResolveName(name.substr(0, dot_pos));
158     if (!parent.IsAllocated())
159         return PythonObject();
160 
161     // Tail recursion.. should be optimized by the compiler
162     return parent.ResolveName(name.substr(dot_pos + 1));
163 }
164 
165 bool
166 PythonObject::HasAttribute(llvm::StringRef attr) const
167 {
168     if (!IsValid())
169         return false;
170     PythonString py_attr(attr);
171     return !!PyObject_HasAttr(m_py_obj, py_attr.get());
172 }
173 
174 PythonObject
175 PythonObject::GetAttributeValue(llvm::StringRef attr) const
176 {
177     if (!IsValid())
178         return PythonObject();
179 
180     PythonString py_attr(attr);
181     if (!PyObject_HasAttr(m_py_obj, py_attr.get()))
182         return PythonObject();
183 
184     return PythonObject(PyRefType::Owned,
185         PyObject_GetAttr(m_py_obj, py_attr.get()));
186 }
187 
188 bool
189 PythonObject::IsNone() const
190 {
191     return m_py_obj == Py_None;
192 }
193 
194 bool
195 PythonObject::IsValid() const
196 {
197     return m_py_obj != nullptr;
198 }
199 
200 bool
201 PythonObject::IsAllocated() const
202 {
203     return IsValid() && !IsNone();
204 }
205 
206 StructuredData::ObjectSP
207 PythonObject::CreateStructuredObject() const
208 {
209     switch (GetObjectType())
210     {
211         case PyObjectType::Dictionary:
212             return PythonDictionary(PyRefType::Borrowed, m_py_obj).CreateStructuredDictionary();
213         case PyObjectType::Integer:
214             return PythonInteger(PyRefType::Borrowed, m_py_obj).CreateStructuredInteger();
215         case PyObjectType::List:
216             return PythonList(PyRefType::Borrowed, m_py_obj).CreateStructuredArray();
217         case PyObjectType::String:
218             return PythonString(PyRefType::Borrowed, m_py_obj).CreateStructuredString();
219         case PyObjectType::Bytes:
220             return PythonBytes(PyRefType::Borrowed, m_py_obj).CreateStructuredString();
221         case PyObjectType::None:
222             return StructuredData::ObjectSP();
223         default:
224             return StructuredData::ObjectSP(new StructuredPythonObject(m_py_obj));
225     }
226 }
227 
228 //----------------------------------------------------------------------
229 // PythonString
230 //----------------------------------------------------------------------
231 PythonBytes::PythonBytes() : PythonObject()
232 {
233 }
234 
235 PythonBytes::PythonBytes(llvm::ArrayRef<uint8_t> bytes) : PythonObject()
236 {
237     SetBytes(bytes);
238 }
239 
240 PythonBytes::PythonBytes(const uint8_t *bytes, size_t length) : PythonObject()
241 {
242     SetBytes(llvm::ArrayRef<uint8_t>(bytes, length));
243 }
244 
245 PythonBytes::PythonBytes(PyRefType type, PyObject *py_obj) : PythonObject()
246 {
247     Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string
248 }
249 
250 PythonBytes::PythonBytes(const PythonBytes &object) : PythonObject(object)
251 {
252 }
253 
254 PythonBytes::~PythonBytes()
255 {
256 }
257 
258 bool
259 PythonBytes::Check(PyObject *py_obj)
260 {
261     if (!py_obj)
262         return false;
263     if (PyBytes_Check(py_obj))
264         return true;
265     return false;
266 }
267 
268 void
269 PythonBytes::Reset(PyRefType type, PyObject *py_obj)
270 {
271     // Grab the desired reference type so that if we end up rejecting
272     // `py_obj` it still gets decremented if necessary.
273     PythonObject result(type, py_obj);
274 
275     if (!PythonBytes::Check(py_obj))
276     {
277         PythonObject::Reset();
278         return;
279     }
280 
281     // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
282     // back into the virtual implementation.
283     PythonObject::Reset(PyRefType::Borrowed, result.get());
284 }
285 
286 llvm::ArrayRef<uint8_t>
287 PythonBytes::GetBytes() const
288 {
289     if (!IsValid())
290         return llvm::ArrayRef<uint8_t>();
291 
292     Py_ssize_t size;
293     char *c;
294 
295     PyBytes_AsStringAndSize(m_py_obj, &c, &size);
296     return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size);
297 }
298 
299 size_t
300 PythonBytes::GetSize() const
301 {
302     if (!IsValid())
303         return 0;
304     return PyBytes_Size(m_py_obj);
305 }
306 
307 void
308 PythonBytes::SetBytes(llvm::ArrayRef<uint8_t> bytes)
309 {
310     const char *data = reinterpret_cast<const char *>(bytes.data());
311     PyObject *py_bytes = PyBytes_FromStringAndSize(data, bytes.size());
312     PythonObject::Reset(PyRefType::Owned, py_bytes);
313 }
314 
315 StructuredData::StringSP
316 PythonBytes::CreateStructuredString() const
317 {
318     StructuredData::StringSP result(new StructuredData::String);
319     Py_ssize_t size;
320     char *c;
321     PyBytes_AsStringAndSize(m_py_obj, &c, &size);
322     result->SetValue(std::string(c, size));
323     return result;
324 }
325 
326 //----------------------------------------------------------------------
327 // PythonString
328 //----------------------------------------------------------------------
329 
330 PythonString::PythonString(PyRefType type, PyObject *py_obj)
331     : PythonObject()
332 {
333     Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string
334 }
335 
336 PythonString::PythonString(const PythonString &object)
337     : PythonObject(object)
338 {
339 }
340 
341 PythonString::PythonString(llvm::StringRef string)
342     : PythonObject()
343 {
344     SetString(string);
345 }
346 
347 PythonString::PythonString(const char *string)
348     : PythonObject()
349 {
350     SetString(llvm::StringRef(string));
351 }
352 
353 PythonString::PythonString()
354     : PythonObject()
355 {
356 }
357 
358 PythonString::~PythonString ()
359 {
360 }
361 
362 bool
363 PythonString::Check(PyObject *py_obj)
364 {
365     if (!py_obj)
366         return false;
367 
368     if (PyUnicode_Check(py_obj))
369         return true;
370 #if PY_MAJOR_VERSION < 3
371     if (PyString_Check(py_obj))
372         return true;
373 #endif
374     return false;
375 }
376 
377 void
378 PythonString::Reset(PyRefType type, PyObject *py_obj)
379 {
380     // Grab the desired reference type so that if we end up rejecting
381     // `py_obj` it still gets decremented if necessary.
382     PythonObject result(type, py_obj);
383 
384     if (!PythonString::Check(py_obj))
385     {
386         PythonObject::Reset();
387         return;
388     }
389 #if PY_MAJOR_VERSION < 3
390     // In Python 2, Don't store PyUnicode objects directly, because we need
391     // access to their underlying character buffers which Python 2 doesn't
392     // provide.
393     if (PyUnicode_Check(py_obj))
394         result.Reset(PyRefType::Owned, PyUnicode_AsUTF8String(result.get()));
395 #endif
396     // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
397     // back into the virtual implementation.
398     PythonObject::Reset(PyRefType::Borrowed, result.get());
399 }
400 
401 llvm::StringRef
402 PythonString::GetString() const
403 {
404     if (!IsValid())
405         return llvm::StringRef();
406 
407     Py_ssize_t size;
408     char *c;
409 
410 #if PY_MAJOR_VERSION >= 3
411     c = PyUnicode_AsUTF8AndSize(m_py_obj, &size);
412 #else
413     PyString_AsStringAndSize(m_py_obj, &c, &size);
414 #endif
415     return llvm::StringRef(c, size);
416 }
417 
418 size_t
419 PythonString::GetSize() const
420 {
421     if (IsValid())
422     {
423 #if PY_MAJOR_VERSION >= 3
424         return PyUnicode_GetSize(m_py_obj);
425 #else
426         return PyString_Size(m_py_obj);
427 #endif
428     }
429     return 0;
430 }
431 
432 void
433 PythonString::SetString (llvm::StringRef string)
434 {
435 #if PY_MAJOR_VERSION >= 3
436     PyObject *unicode = PyUnicode_FromStringAndSize(string.data(), string.size());
437     PythonObject::Reset(PyRefType::Owned, unicode);
438 #else
439     PyObject *str = PyString_FromStringAndSize(string.data(), string.size());
440     PythonObject::Reset(PyRefType::Owned, str);
441 #endif
442 }
443 
444 StructuredData::StringSP
445 PythonString::CreateStructuredString() const
446 {
447     StructuredData::StringSP result(new StructuredData::String);
448     result->SetValue(GetString());
449     return result;
450 }
451 
452 //----------------------------------------------------------------------
453 // PythonInteger
454 //----------------------------------------------------------------------
455 
456 PythonInteger::PythonInteger()
457     : PythonObject()
458 {
459 
460 }
461 
462 PythonInteger::PythonInteger(PyRefType type, PyObject *py_obj)
463     : PythonObject()
464 {
465     Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a integer type
466 }
467 
468 PythonInteger::PythonInteger(const PythonInteger &object)
469     : PythonObject(object)
470 {
471 }
472 
473 PythonInteger::PythonInteger(int64_t value)
474     : PythonObject()
475 {
476     SetInteger(value);
477 }
478 
479 
480 PythonInteger::~PythonInteger ()
481 {
482 }
483 
484 bool
485 PythonInteger::Check(PyObject *py_obj)
486 {
487     if (!py_obj)
488         return false;
489 
490 #if PY_MAJOR_VERSION >= 3
491     // Python 3 does not have PyInt_Check.  There is only one type of
492     // integral value, long.
493     return PyLong_Check(py_obj);
494 #else
495     return PyLong_Check(py_obj) || PyInt_Check(py_obj);
496 #endif
497 }
498 
499 void
500 PythonInteger::Reset(PyRefType type, PyObject *py_obj)
501 {
502     // Grab the desired reference type so that if we end up rejecting
503     // `py_obj` it still gets decremented if necessary.
504     PythonObject result(type, py_obj);
505 
506     if (!PythonInteger::Check(py_obj))
507     {
508         PythonObject::Reset();
509         return;
510     }
511 
512 #if PY_MAJOR_VERSION < 3
513     // Always store this as a PyLong, which makes interoperability between
514     // Python 2.x and Python 3.x easier.  This is only necessary in 2.x,
515     // since 3.x doesn't even have a PyInt.
516     if (PyInt_Check(py_obj))
517     {
518         // Since we converted the original object to a different type, the new
519         // object is an owned object regardless of the ownership semantics requested
520         // by the user.
521         result.Reset(PyRefType::Owned, PyLong_FromLongLong(PyInt_AsLong(py_obj)));
522     }
523 #endif
524 
525     assert(PyLong_Check(result.get()) && "Couldn't get a PyLong from this PyObject");
526 
527     // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
528     // back into the virtual implementation.
529     PythonObject::Reset(PyRefType::Borrowed, result.get());
530 }
531 
532 int64_t
533 PythonInteger::GetInteger() const
534 {
535     if (m_py_obj)
536     {
537         assert(PyLong_Check(m_py_obj) && "PythonInteger::GetInteger has a PyObject that isn't a PyLong");
538 
539         return PyLong_AsLongLong(m_py_obj);
540     }
541     return UINT64_MAX;
542 }
543 
544 void
545 PythonInteger::SetInteger(int64_t value)
546 {
547     PythonObject::Reset(PyRefType::Owned, PyLong_FromLongLong(value));
548 }
549 
550 StructuredData::IntegerSP
551 PythonInteger::CreateStructuredInteger() const
552 {
553     StructuredData::IntegerSP result(new StructuredData::Integer);
554     result->SetValue(GetInteger());
555     return result;
556 }
557 
558 //----------------------------------------------------------------------
559 // PythonList
560 //----------------------------------------------------------------------
561 
562 PythonList::PythonList(PyInitialValue value)
563     : PythonObject()
564 {
565     if (value == PyInitialValue::Empty)
566         Reset(PyRefType::Owned, PyList_New(0));
567 }
568 
569 PythonList::PythonList(int list_size)
570     : PythonObject()
571 {
572     Reset(PyRefType::Owned, PyList_New(list_size));
573 }
574 
575 PythonList::PythonList(PyRefType type, PyObject *py_obj)
576     : PythonObject()
577 {
578     Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a list
579 }
580 
581 PythonList::PythonList(const PythonList &list)
582     : PythonObject(list)
583 {
584 }
585 
586 PythonList::~PythonList ()
587 {
588 }
589 
590 bool
591 PythonList::Check(PyObject *py_obj)
592 {
593     if (!py_obj)
594         return false;
595     return PyList_Check(py_obj);
596 }
597 
598 void
599 PythonList::Reset(PyRefType type, PyObject *py_obj)
600 {
601     // Grab the desired reference type so that if we end up rejecting
602     // `py_obj` it still gets decremented if necessary.
603     PythonObject result(type, py_obj);
604 
605     if (!PythonList::Check(py_obj))
606     {
607         PythonObject::Reset();
608         return;
609     }
610 
611     // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
612     // back into the virtual implementation.
613     PythonObject::Reset(PyRefType::Borrowed, result.get());
614 }
615 
616 uint32_t
617 PythonList::GetSize() const
618 {
619     if (IsValid())
620         return PyList_GET_SIZE(m_py_obj);
621     return 0;
622 }
623 
624 PythonObject
625 PythonList::GetItemAtIndex(uint32_t index) const
626 {
627     if (IsValid())
628         return PythonObject(PyRefType::Borrowed, PyList_GetItem(m_py_obj, index));
629     return PythonObject();
630 }
631 
632 void
633 PythonList::SetItemAtIndex(uint32_t index, const PythonObject &object)
634 {
635     if (IsAllocated() && object.IsValid())
636     {
637         // PyList_SetItem is documented to "steal" a reference, so we need to
638         // convert it to an owned reference by incrementing it.
639         Py_INCREF(object.get());
640         PyList_SetItem(m_py_obj, index, object.get());
641     }
642 }
643 
644 void
645 PythonList::AppendItem(const PythonObject &object)
646 {
647     if (IsAllocated() && object.IsValid())
648     {
649         // `PyList_Append` does *not* steal a reference, so do not call `Py_INCREF`
650         // here like we do with `PyList_SetItem`.
651         PyList_Append(m_py_obj, object.get());
652     }
653 }
654 
655 StructuredData::ArraySP
656 PythonList::CreateStructuredArray() const
657 {
658     StructuredData::ArraySP result(new StructuredData::Array);
659     uint32_t count = GetSize();
660     for (uint32_t i = 0; i < count; ++i)
661     {
662         PythonObject obj = GetItemAtIndex(i);
663         result->AddItem(obj.CreateStructuredObject());
664     }
665     return result;
666 }
667 
668 //----------------------------------------------------------------------
669 // PythonTuple
670 //----------------------------------------------------------------------
671 
672 PythonTuple::PythonTuple(PyInitialValue value)
673     : PythonObject()
674 {
675     if (value == PyInitialValue::Empty)
676         Reset(PyRefType::Owned, PyTuple_New(0));
677 }
678 
679 PythonTuple::PythonTuple(int tuple_size)
680     : PythonObject()
681 {
682     Reset(PyRefType::Owned, PyTuple_New(tuple_size));
683 }
684 
685 PythonTuple::PythonTuple(PyRefType type, PyObject *py_obj)
686     : PythonObject()
687 {
688     Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a tuple
689 }
690 
691 PythonTuple::PythonTuple(const PythonTuple &tuple)
692     : PythonObject(tuple)
693 {
694 }
695 
696 PythonTuple::PythonTuple(std::initializer_list<PythonObject> objects)
697 {
698     m_py_obj = PyTuple_New(objects.size());
699 
700     uint32_t idx = 0;
701     for (auto object : objects)
702     {
703         if (object.IsValid())
704             SetItemAtIndex(idx, object);
705         idx++;
706     }
707 }
708 
709 PythonTuple::PythonTuple(std::initializer_list<PyObject*> objects)
710 {
711     m_py_obj = PyTuple_New(objects.size());
712 
713     uint32_t idx = 0;
714     for (auto py_object : objects)
715     {
716         PythonObject object(PyRefType::Borrowed, py_object);
717         if (object.IsValid())
718             SetItemAtIndex(idx, object);
719         idx++;
720     }
721 }
722 
723 PythonTuple::~PythonTuple()
724 {
725 }
726 
727 bool
728 PythonTuple::Check(PyObject *py_obj)
729 {
730     if (!py_obj)
731         return false;
732     return PyTuple_Check(py_obj);
733 }
734 
735 void
736 PythonTuple::Reset(PyRefType type, PyObject *py_obj)
737 {
738     // Grab the desired reference type so that if we end up rejecting
739     // `py_obj` it still gets decremented if necessary.
740     PythonObject result(type, py_obj);
741 
742     if (!PythonTuple::Check(py_obj))
743     {
744         PythonObject::Reset();
745         return;
746     }
747 
748     // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
749     // back into the virtual implementation.
750     PythonObject::Reset(PyRefType::Borrowed, result.get());
751 }
752 
753 uint32_t
754 PythonTuple::GetSize() const
755 {
756     if (IsValid())
757         return PyTuple_GET_SIZE(m_py_obj);
758     return 0;
759 }
760 
761 PythonObject
762 PythonTuple::GetItemAtIndex(uint32_t index) const
763 {
764     if (IsValid())
765         return PythonObject(PyRefType::Borrowed, PyTuple_GetItem(m_py_obj, index));
766     return PythonObject();
767 }
768 
769 void
770 PythonTuple::SetItemAtIndex(uint32_t index, const PythonObject &object)
771 {
772     if (IsAllocated() && object.IsValid())
773     {
774         // PyTuple_SetItem is documented to "steal" a reference, so we need to
775         // convert it to an owned reference by incrementing it.
776         Py_INCREF(object.get());
777         PyTuple_SetItem(m_py_obj, index, object.get());
778     }
779 }
780 
781 StructuredData::ArraySP
782 PythonTuple::CreateStructuredArray() const
783 {
784     StructuredData::ArraySP result(new StructuredData::Array);
785     uint32_t count = GetSize();
786     for (uint32_t i = 0; i < count; ++i)
787     {
788         PythonObject obj = GetItemAtIndex(i);
789         result->AddItem(obj.CreateStructuredObject());
790     }
791     return result;
792 }
793 
794 //----------------------------------------------------------------------
795 // PythonDictionary
796 //----------------------------------------------------------------------
797 
798 PythonDictionary::PythonDictionary(PyInitialValue value)
799     : PythonObject()
800 {
801     if (value == PyInitialValue::Empty)
802         Reset(PyRefType::Owned, PyDict_New());
803 }
804 
805 PythonDictionary::PythonDictionary(PyRefType type, PyObject *py_obj)
806     : PythonObject()
807 {
808     Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a dictionary
809 }
810 
811 PythonDictionary::PythonDictionary(const PythonDictionary &object)
812     : PythonObject(object)
813 {
814 }
815 
816 PythonDictionary::~PythonDictionary ()
817 {
818 }
819 
820 bool
821 PythonDictionary::Check(PyObject *py_obj)
822 {
823     if (!py_obj)
824         return false;
825 
826     return PyDict_Check(py_obj);
827 }
828 
829 void
830 PythonDictionary::Reset(PyRefType type, PyObject *py_obj)
831 {
832     // Grab the desired reference type so that if we end up rejecting
833     // `py_obj` it still gets decremented if necessary.
834     PythonObject result(type, py_obj);
835 
836     if (!PythonDictionary::Check(py_obj))
837     {
838         PythonObject::Reset();
839         return;
840     }
841 
842     // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
843     // back into the virtual implementation.
844     PythonObject::Reset(PyRefType::Borrowed, result.get());
845 }
846 
847 uint32_t
848 PythonDictionary::GetSize() const
849 {
850     if (IsValid())
851         return PyDict_Size(m_py_obj);
852     return 0;
853 }
854 
855 PythonList
856 PythonDictionary::GetKeys() const
857 {
858     if (IsValid())
859         return PythonList(PyRefType::Owned, PyDict_Keys(m_py_obj));
860     return PythonList(PyInitialValue::Invalid);
861 }
862 
863 PythonObject
864 PythonDictionary::GetItemForKey(const PythonObject &key) const
865 {
866     if (IsAllocated() && key.IsValid())
867         return PythonObject(PyRefType::Borrowed, PyDict_GetItem(m_py_obj, key.get()));
868     return PythonObject();
869 }
870 
871 void
872 PythonDictionary::SetItemForKey(const PythonObject &key, const PythonObject &value)
873 {
874     if (IsAllocated() && key.IsValid() && value.IsValid())
875         PyDict_SetItem(m_py_obj, key.get(), value.get());
876 }
877 
878 StructuredData::DictionarySP
879 PythonDictionary::CreateStructuredDictionary() const
880 {
881     StructuredData::DictionarySP result(new StructuredData::Dictionary);
882     PythonList keys(GetKeys());
883     uint32_t num_keys = keys.GetSize();
884     for (uint32_t i = 0; i < num_keys; ++i)
885     {
886         PythonObject key = keys.GetItemAtIndex(i);
887         PythonObject value = GetItemForKey(key);
888         StructuredData::ObjectSP structured_value = value.CreateStructuredObject();
889         result->AddItem(key.Str().GetString(), structured_value);
890     }
891     return result;
892 }
893 
894 PythonModule::PythonModule() : PythonObject()
895 {
896 }
897 
898 PythonModule::PythonModule(PyRefType type, PyObject *py_obj)
899 {
900     Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a module
901 }
902 
903 PythonModule::PythonModule(const PythonModule &dict) : PythonObject(dict)
904 {
905 }
906 
907 PythonModule::~PythonModule()
908 {
909 }
910 
911 PythonModule
912 PythonModule::BuiltinsModule()
913 {
914 #if PY_MAJOR_VERSION >= 3
915     return AddModule("builtins");
916 #else
917     return AddModule("__builtin__");
918 #endif
919 }
920 
921 PythonModule
922 PythonModule::MainModule()
923 {
924     return AddModule("__main__");
925 }
926 
927 PythonModule
928 PythonModule::AddModule(llvm::StringRef module)
929 {
930     std::string str = module.str();
931     return PythonModule(PyRefType::Borrowed, PyImport_AddModule(str.c_str()));
932 }
933 
934 
935 PythonModule
936 PythonModule::ImportModule(llvm::StringRef module)
937 {
938     std::string str = module.str();
939     return PythonModule(PyRefType::Owned, PyImport_ImportModule(str.c_str()));
940 }
941 
942 bool
943 PythonModule::Check(PyObject *py_obj)
944 {
945     if (!py_obj)
946         return false;
947 
948     return PyModule_Check(py_obj);
949 }
950 
951 void
952 PythonModule::Reset(PyRefType type, PyObject *py_obj)
953 {
954     // Grab the desired reference type so that if we end up rejecting
955     // `py_obj` it still gets decremented if necessary.
956     PythonObject result(type, py_obj);
957 
958     if (!PythonModule::Check(py_obj))
959     {
960         PythonObject::Reset();
961         return;
962     }
963 
964     // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
965     // back into the virtual implementation.
966     PythonObject::Reset(PyRefType::Borrowed, result.get());
967 }
968 
969 PythonDictionary
970 PythonModule::GetDictionary() const
971 {
972     return PythonDictionary(PyRefType::Borrowed, PyModule_GetDict(m_py_obj));
973 }
974 
975 PythonCallable::PythonCallable() : PythonObject()
976 {
977 }
978 
979 PythonCallable::PythonCallable(PyRefType type, PyObject *py_obj)
980 {
981     Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a callable
982 }
983 
984 PythonCallable::PythonCallable(const PythonCallable &callable)
985     : PythonObject(callable)
986 {
987 }
988 
989 PythonCallable::~PythonCallable()
990 {
991 }
992 
993 bool
994 PythonCallable::Check(PyObject *py_obj)
995 {
996     if (!py_obj)
997         return false;
998 
999     return PyCallable_Check(py_obj);
1000 }
1001 
1002 void
1003 PythonCallable::Reset(PyRefType type, PyObject *py_obj)
1004 {
1005     // Grab the desired reference type so that if we end up rejecting
1006     // `py_obj` it still gets decremented if necessary.
1007     PythonObject result(type, py_obj);
1008 
1009     if (!PythonCallable::Check(py_obj))
1010     {
1011         PythonObject::Reset();
1012         return;
1013     }
1014 
1015     // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
1016     // back into the virtual implementation.
1017     PythonObject::Reset(PyRefType::Borrowed, result.get());
1018 }
1019 
1020 
1021 PythonCallable::ArgInfo
1022 PythonCallable::GetNumArguments() const
1023 {
1024     ArgInfo result = { 0, false, false };
1025     if (!IsValid())
1026         return result;
1027 
1028     PyObject *py_func_obj = m_py_obj;
1029     if (PyMethod_Check(py_func_obj))
1030         py_func_obj = PyMethod_GET_FUNCTION(py_func_obj);
1031 
1032     if (!py_func_obj)
1033         return result;
1034 
1035     PyCodeObject* code = (PyCodeObject*)PyFunction_GET_CODE(py_func_obj);
1036     if (!code)
1037         return result;
1038 
1039     result.count = code->co_argcount;
1040     result.has_varargs = !!(code->co_flags & CO_VARARGS);
1041     result.has_kwargs = !!(code->co_flags & CO_VARKEYWORDS);
1042     return result;
1043 }
1044 
1045 PythonObject
1046 PythonCallable::operator ()()
1047 {
1048     return PythonObject(PyRefType::Owned,
1049         PyObject_CallObject(m_py_obj, nullptr));
1050 }
1051 
1052 PythonObject
1053 PythonCallable::operator ()(std::initializer_list<PyObject*> args)
1054 {
1055     PythonTuple arg_tuple(args);
1056     return PythonObject(PyRefType::Owned,
1057         PyObject_CallObject(m_py_obj, arg_tuple.get()));
1058 }
1059 
1060 PythonObject
1061 PythonCallable::operator ()(std::initializer_list<PythonObject> args)
1062 {
1063     PythonTuple arg_tuple(args);
1064     return PythonObject(PyRefType::Owned,
1065         PyObject_CallObject(m_py_obj, arg_tuple.get()));
1066 }
1067 
1068 PythonFile::PythonFile()
1069     : PythonObject()
1070 {
1071 }
1072 
1073 PythonFile::PythonFile(File &file, const char *mode)
1074 {
1075     Reset(file, mode);
1076 }
1077 
1078 PythonFile::PythonFile(const char *path, const char *mode)
1079 {
1080     FILE *fp = nullptr;
1081     fp = fopen(path, mode);
1082     lldb_private::File file(fp, true);
1083     Reset(file, mode);
1084 }
1085 
1086 PythonFile::PythonFile(PyRefType type, PyObject *o)
1087 {
1088     Reset(type, o);
1089 }
1090 
1091 PythonFile::~PythonFile()
1092 {
1093 }
1094 
1095 bool
1096 PythonFile::Check(PyObject *py_obj)
1097 {
1098 #if PY_MAJOR_VERSION < 3
1099     return PyFile_Check(py_obj);
1100 #else
1101     // In Python 3, there is no `PyFile_Check`, and in fact PyFile is not even a
1102     // first-class object type anymore.  `PyFile_FromFd` is just a thin wrapper
1103     // over `io.open()`, which returns some object derived from `io.IOBase`.
1104     // As a result, the only way to detect a file in Python 3 is to check whether
1105     // it inherits from `io.IOBase`.  Since it is possible for non-files to also
1106     // inherit from `io.IOBase`, we additionally verify that it has the `fileno`
1107     // attribute, which should guarantee that it is backed by the file system.
1108     PythonObject io_module(PyRefType::Owned, PyImport_ImportModule("io"));
1109     PythonDictionary io_dict(PyRefType::Borrowed, PyModule_GetDict(io_module.get()));
1110     PythonObject io_base_class = io_dict.GetItemForKey(PythonString("IOBase"));
1111 
1112     PythonObject object_type(PyRefType::Owned, PyObject_Type(py_obj));
1113 
1114     if (1 != PyObject_IsSubclass(object_type.get(), io_base_class.get()))
1115         return false;
1116     if (!object_type.HasAttribute("fileno"))
1117         return false;
1118 
1119     return true;
1120 #endif
1121 }
1122 
1123 void
1124 PythonFile::Reset(PyRefType type, PyObject *py_obj)
1125 {
1126     // Grab the desired reference type so that if we end up rejecting
1127     // `py_obj` it still gets decremented if necessary.
1128     PythonObject result(type, py_obj);
1129 
1130     if (!PythonFile::Check(py_obj))
1131     {
1132         PythonObject::Reset();
1133         return;
1134     }
1135 
1136     // Calling PythonObject::Reset(const PythonObject&) will lead to stack
1137     // overflow since it calls back into the virtual implementation.
1138     PythonObject::Reset(PyRefType::Borrowed, result.get());
1139 }
1140 
1141 void
1142 PythonFile::Reset(File &file, const char *mode)
1143 {
1144     if (!file.IsValid())
1145     {
1146         Reset();
1147         return;
1148     }
1149 
1150     char *cmode = const_cast<char *>(mode);
1151 #if PY_MAJOR_VERSION >= 3
1152     Reset(PyRefType::Owned,
1153         PyFile_FromFd(file.GetDescriptor(), nullptr, cmode, -1, nullptr, "ignore", nullptr, 0));
1154 #else
1155     // Read through the Python source, doesn't seem to modify these strings
1156     Reset(PyRefType::Owned,
1157         PyFile_FromFile(file.GetStream(), const_cast<char *>(""), cmode, nullptr));
1158 #endif
1159 }
1160 
1161 uint32_t
1162 PythonFile::GetOptionsFromMode(llvm::StringRef mode)
1163 {
1164     if (mode.empty())
1165         return 0;
1166 
1167     return llvm::StringSwitch<uint32_t>(mode.str().c_str())
1168     .Case("r",   File::eOpenOptionRead)
1169     .Case("w",   File::eOpenOptionWrite)
1170     .Case("a",   File::eOpenOptionAppend|File::eOpenOptionCanCreate)
1171     .Case("r+",  File::eOpenOptionRead|File::eOpenOptionWrite)
1172     .Case("w+",  File::eOpenOptionRead|File::eOpenOptionWrite|File::eOpenOptionCanCreate|File::eOpenOptionTruncate)
1173     .Case("a+",  File::eOpenOptionRead|File::eOpenOptionWrite|File::eOpenOptionCanCreate)
1174     .Default(0);
1175 }
1176 
1177 bool
1178 PythonFile::GetUnderlyingFile(File &file) const
1179 {
1180     if (!IsValid())
1181         return false;
1182 
1183     file.Close();
1184     // We don't own the file descriptor returned by this function, make sure the
1185     // File object knows about that.
1186     file.SetDescriptor(PyObject_AsFileDescriptor(m_py_obj), false);
1187     PythonString py_mode = GetAttributeValue("mode").AsType<PythonString>();
1188     file.SetOptions(PythonFile::GetOptionsFromMode(py_mode.GetString()));
1189     return file.IsValid();
1190 }
1191 
1192 
1193 #endif
1194