1*0b57cec5SDimitry Andric //===-- PythonDataObjects.cpp -----------------------------------*- C++ -*-===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric 9*0b57cec5SDimitry Andric #ifdef LLDB_DISABLE_PYTHON 10*0b57cec5SDimitry Andric 11*0b57cec5SDimitry Andric // Python is disabled in this build 12*0b57cec5SDimitry Andric 13*0b57cec5SDimitry Andric #else 14*0b57cec5SDimitry Andric 15*0b57cec5SDimitry Andric #include "PythonDataObjects.h" 16*0b57cec5SDimitry Andric #include "ScriptInterpreterPython.h" 17*0b57cec5SDimitry Andric 18*0b57cec5SDimitry Andric #include "lldb/Host/File.h" 19*0b57cec5SDimitry Andric #include "lldb/Host/FileSystem.h" 20*0b57cec5SDimitry Andric #include "lldb/Interpreter/ScriptInterpreter.h" 219dba64beSDimitry Andric #include "lldb/Utility/Log.h" 22*0b57cec5SDimitry Andric #include "lldb/Utility/Stream.h" 23*0b57cec5SDimitry Andric 24*0b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h" 259dba64beSDimitry Andric #include "llvm/Support/Casting.h" 26*0b57cec5SDimitry Andric #include "llvm/Support/ConvertUTF.h" 27*0b57cec5SDimitry Andric #include "llvm/Support/Errno.h" 28*0b57cec5SDimitry Andric 29*0b57cec5SDimitry Andric #include <stdio.h> 30*0b57cec5SDimitry Andric 31*0b57cec5SDimitry Andric using namespace lldb_private; 32*0b57cec5SDimitry Andric using namespace lldb; 339dba64beSDimitry Andric using namespace lldb_private::python; 349dba64beSDimitry Andric using llvm::cantFail; 359dba64beSDimitry Andric using llvm::Error; 369dba64beSDimitry Andric using llvm::Expected; 379dba64beSDimitry Andric using llvm::Twine; 38*0b57cec5SDimitry Andric 399dba64beSDimitry Andric template <> Expected<bool> python::As<bool>(Expected<PythonObject> &&obj) { 409dba64beSDimitry Andric if (!obj) 419dba64beSDimitry Andric return obj.takeError(); 429dba64beSDimitry Andric return obj.get().IsTrue(); 439dba64beSDimitry Andric } 449dba64beSDimitry Andric 459dba64beSDimitry Andric template <> 469dba64beSDimitry Andric Expected<long long> python::As<long long>(Expected<PythonObject> &&obj) { 479dba64beSDimitry Andric if (!obj) 489dba64beSDimitry Andric return obj.takeError(); 499dba64beSDimitry Andric return obj.get().AsLongLong(); 509dba64beSDimitry Andric } 519dba64beSDimitry Andric 529dba64beSDimitry Andric template <> 539dba64beSDimitry Andric Expected<std::string> python::As<std::string>(Expected<PythonObject> &&obj) { 549dba64beSDimitry Andric if (!obj) 559dba64beSDimitry Andric return obj.takeError(); 569dba64beSDimitry Andric PyObject *str_obj = PyObject_Str(obj.get().get()); 579dba64beSDimitry Andric if (!obj) 589dba64beSDimitry Andric return llvm::make_error<PythonException>(); 599dba64beSDimitry Andric auto str = Take<PythonString>(str_obj); 609dba64beSDimitry Andric auto utf8 = str.AsUTF8(); 619dba64beSDimitry Andric if (!utf8) 629dba64beSDimitry Andric return utf8.takeError(); 639dba64beSDimitry Andric return utf8.get(); 649dba64beSDimitry Andric } 659dba64beSDimitry Andric 669dba64beSDimitry Andric void StructuredPythonObject::Serialize(llvm::json::OStream &s) const { 679dba64beSDimitry Andric s.value(llvm::formatv("Python Obj: {0:X}", GetValue()).str()); 68*0b57cec5SDimitry Andric } 69*0b57cec5SDimitry Andric 70*0b57cec5SDimitry Andric // PythonObject 71*0b57cec5SDimitry Andric 72*0b57cec5SDimitry Andric void PythonObject::Dump(Stream &strm) const { 73*0b57cec5SDimitry Andric if (m_py_obj) { 74*0b57cec5SDimitry Andric FILE *file = llvm::sys::RetryAfterSignal(nullptr, ::tmpfile); 75*0b57cec5SDimitry Andric if (file) { 76*0b57cec5SDimitry Andric ::PyObject_Print(m_py_obj, file, 0); 77*0b57cec5SDimitry Andric const long length = ftell(file); 78*0b57cec5SDimitry Andric if (length) { 79*0b57cec5SDimitry Andric ::rewind(file); 80*0b57cec5SDimitry Andric std::vector<char> file_contents(length, '\0'); 81*0b57cec5SDimitry Andric const size_t length_read = 82*0b57cec5SDimitry Andric ::fread(file_contents.data(), 1, file_contents.size(), file); 83*0b57cec5SDimitry Andric if (length_read > 0) 84*0b57cec5SDimitry Andric strm.Write(file_contents.data(), length_read); 85*0b57cec5SDimitry Andric } 86*0b57cec5SDimitry Andric ::fclose(file); 87*0b57cec5SDimitry Andric } 88*0b57cec5SDimitry Andric } else 89*0b57cec5SDimitry Andric strm.PutCString("NULL"); 90*0b57cec5SDimitry Andric } 91*0b57cec5SDimitry Andric 92*0b57cec5SDimitry Andric PyObjectType PythonObject::GetObjectType() const { 93*0b57cec5SDimitry Andric if (!IsAllocated()) 94*0b57cec5SDimitry Andric return PyObjectType::None; 95*0b57cec5SDimitry Andric 96*0b57cec5SDimitry Andric if (PythonModule::Check(m_py_obj)) 97*0b57cec5SDimitry Andric return PyObjectType::Module; 98*0b57cec5SDimitry Andric if (PythonList::Check(m_py_obj)) 99*0b57cec5SDimitry Andric return PyObjectType::List; 100*0b57cec5SDimitry Andric if (PythonTuple::Check(m_py_obj)) 101*0b57cec5SDimitry Andric return PyObjectType::Tuple; 102*0b57cec5SDimitry Andric if (PythonDictionary::Check(m_py_obj)) 103*0b57cec5SDimitry Andric return PyObjectType::Dictionary; 104*0b57cec5SDimitry Andric if (PythonString::Check(m_py_obj)) 105*0b57cec5SDimitry Andric return PyObjectType::String; 106*0b57cec5SDimitry Andric #if PY_MAJOR_VERSION >= 3 107*0b57cec5SDimitry Andric if (PythonBytes::Check(m_py_obj)) 108*0b57cec5SDimitry Andric return PyObjectType::Bytes; 109*0b57cec5SDimitry Andric #endif 110*0b57cec5SDimitry Andric if (PythonByteArray::Check(m_py_obj)) 111*0b57cec5SDimitry Andric return PyObjectType::ByteArray; 112*0b57cec5SDimitry Andric if (PythonBoolean::Check(m_py_obj)) 113*0b57cec5SDimitry Andric return PyObjectType::Boolean; 114*0b57cec5SDimitry Andric if (PythonInteger::Check(m_py_obj)) 115*0b57cec5SDimitry Andric return PyObjectType::Integer; 116*0b57cec5SDimitry Andric if (PythonFile::Check(m_py_obj)) 117*0b57cec5SDimitry Andric return PyObjectType::File; 118*0b57cec5SDimitry Andric if (PythonCallable::Check(m_py_obj)) 119*0b57cec5SDimitry Andric return PyObjectType::Callable; 120*0b57cec5SDimitry Andric return PyObjectType::Unknown; 121*0b57cec5SDimitry Andric } 122*0b57cec5SDimitry Andric 123*0b57cec5SDimitry Andric PythonString PythonObject::Repr() const { 124*0b57cec5SDimitry Andric if (!m_py_obj) 125*0b57cec5SDimitry Andric return PythonString(); 126*0b57cec5SDimitry Andric PyObject *repr = PyObject_Repr(m_py_obj); 127*0b57cec5SDimitry Andric if (!repr) 128*0b57cec5SDimitry Andric return PythonString(); 129*0b57cec5SDimitry Andric return PythonString(PyRefType::Owned, repr); 130*0b57cec5SDimitry Andric } 131*0b57cec5SDimitry Andric 132*0b57cec5SDimitry Andric PythonString PythonObject::Str() const { 133*0b57cec5SDimitry Andric if (!m_py_obj) 134*0b57cec5SDimitry Andric return PythonString(); 135*0b57cec5SDimitry Andric PyObject *str = PyObject_Str(m_py_obj); 136*0b57cec5SDimitry Andric if (!str) 137*0b57cec5SDimitry Andric return PythonString(); 138*0b57cec5SDimitry Andric return PythonString(PyRefType::Owned, str); 139*0b57cec5SDimitry Andric } 140*0b57cec5SDimitry Andric 141*0b57cec5SDimitry Andric PythonObject 142*0b57cec5SDimitry Andric PythonObject::ResolveNameWithDictionary(llvm::StringRef name, 143*0b57cec5SDimitry Andric const PythonDictionary &dict) { 144*0b57cec5SDimitry Andric size_t dot_pos = name.find('.'); 145*0b57cec5SDimitry Andric llvm::StringRef piece = name.substr(0, dot_pos); 146*0b57cec5SDimitry Andric PythonObject result = dict.GetItemForKey(PythonString(piece)); 147*0b57cec5SDimitry Andric if (dot_pos == llvm::StringRef::npos) { 148*0b57cec5SDimitry Andric // There was no dot, we're done. 149*0b57cec5SDimitry Andric return result; 150*0b57cec5SDimitry Andric } 151*0b57cec5SDimitry Andric 152*0b57cec5SDimitry Andric // There was a dot. The remaining portion of the name should be looked up in 153*0b57cec5SDimitry Andric // the context of the object that was found in the dictionary. 154*0b57cec5SDimitry Andric return result.ResolveName(name.substr(dot_pos + 1)); 155*0b57cec5SDimitry Andric } 156*0b57cec5SDimitry Andric 157*0b57cec5SDimitry Andric PythonObject PythonObject::ResolveName(llvm::StringRef name) const { 158*0b57cec5SDimitry Andric // Resolve the name in the context of the specified object. If, for example, 159*0b57cec5SDimitry Andric // `this` refers to a PyModule, then this will look for `name` in this 160*0b57cec5SDimitry Andric // module. If `this` refers to a PyType, then it will resolve `name` as an 161*0b57cec5SDimitry Andric // attribute of that type. If `this` refers to an instance of an object, 162*0b57cec5SDimitry Andric // then it will resolve `name` as the value of the specified field. 163*0b57cec5SDimitry Andric // 164*0b57cec5SDimitry Andric // This function handles dotted names so that, for example, if `m_py_obj` 165*0b57cec5SDimitry Andric // refers to the `sys` module, and `name` == "path.append", then it will find 166*0b57cec5SDimitry Andric // the function `sys.path.append`. 167*0b57cec5SDimitry Andric 168*0b57cec5SDimitry Andric size_t dot_pos = name.find('.'); 169*0b57cec5SDimitry Andric if (dot_pos == llvm::StringRef::npos) { 170*0b57cec5SDimitry Andric // No dots in the name, we should be able to find the value immediately as 171*0b57cec5SDimitry Andric // an attribute of `m_py_obj`. 172*0b57cec5SDimitry Andric return GetAttributeValue(name); 173*0b57cec5SDimitry Andric } 174*0b57cec5SDimitry Andric 175*0b57cec5SDimitry Andric // Look up the first piece of the name, and resolve the rest as a child of 176*0b57cec5SDimitry Andric // that. 177*0b57cec5SDimitry Andric PythonObject parent = ResolveName(name.substr(0, dot_pos)); 178*0b57cec5SDimitry Andric if (!parent.IsAllocated()) 179*0b57cec5SDimitry Andric return PythonObject(); 180*0b57cec5SDimitry Andric 181*0b57cec5SDimitry Andric // Tail recursion.. should be optimized by the compiler 182*0b57cec5SDimitry Andric return parent.ResolveName(name.substr(dot_pos + 1)); 183*0b57cec5SDimitry Andric } 184*0b57cec5SDimitry Andric 185*0b57cec5SDimitry Andric bool PythonObject::HasAttribute(llvm::StringRef attr) const { 186*0b57cec5SDimitry Andric if (!IsValid()) 187*0b57cec5SDimitry Andric return false; 188*0b57cec5SDimitry Andric PythonString py_attr(attr); 189*0b57cec5SDimitry Andric return !!PyObject_HasAttr(m_py_obj, py_attr.get()); 190*0b57cec5SDimitry Andric } 191*0b57cec5SDimitry Andric 192*0b57cec5SDimitry Andric PythonObject PythonObject::GetAttributeValue(llvm::StringRef attr) const { 193*0b57cec5SDimitry Andric if (!IsValid()) 194*0b57cec5SDimitry Andric return PythonObject(); 195*0b57cec5SDimitry Andric 196*0b57cec5SDimitry Andric PythonString py_attr(attr); 197*0b57cec5SDimitry Andric if (!PyObject_HasAttr(m_py_obj, py_attr.get())) 198*0b57cec5SDimitry Andric return PythonObject(); 199*0b57cec5SDimitry Andric 200*0b57cec5SDimitry Andric return PythonObject(PyRefType::Owned, 201*0b57cec5SDimitry Andric PyObject_GetAttr(m_py_obj, py_attr.get())); 202*0b57cec5SDimitry Andric } 203*0b57cec5SDimitry Andric 204*0b57cec5SDimitry Andric StructuredData::ObjectSP PythonObject::CreateStructuredObject() const { 205*0b57cec5SDimitry Andric switch (GetObjectType()) { 206*0b57cec5SDimitry Andric case PyObjectType::Dictionary: 207*0b57cec5SDimitry Andric return PythonDictionary(PyRefType::Borrowed, m_py_obj) 208*0b57cec5SDimitry Andric .CreateStructuredDictionary(); 209*0b57cec5SDimitry Andric case PyObjectType::Boolean: 210*0b57cec5SDimitry Andric return PythonBoolean(PyRefType::Borrowed, m_py_obj) 211*0b57cec5SDimitry Andric .CreateStructuredBoolean(); 212*0b57cec5SDimitry Andric case PyObjectType::Integer: 213*0b57cec5SDimitry Andric return PythonInteger(PyRefType::Borrowed, m_py_obj) 214*0b57cec5SDimitry Andric .CreateStructuredInteger(); 215*0b57cec5SDimitry Andric case PyObjectType::List: 216*0b57cec5SDimitry Andric return PythonList(PyRefType::Borrowed, m_py_obj).CreateStructuredArray(); 217*0b57cec5SDimitry Andric case PyObjectType::String: 218*0b57cec5SDimitry Andric return PythonString(PyRefType::Borrowed, m_py_obj).CreateStructuredString(); 219*0b57cec5SDimitry Andric case PyObjectType::Bytes: 220*0b57cec5SDimitry Andric return PythonBytes(PyRefType::Borrowed, m_py_obj).CreateStructuredString(); 221*0b57cec5SDimitry Andric case PyObjectType::ByteArray: 222*0b57cec5SDimitry Andric return PythonByteArray(PyRefType::Borrowed, m_py_obj) 223*0b57cec5SDimitry Andric .CreateStructuredString(); 224*0b57cec5SDimitry Andric case PyObjectType::None: 225*0b57cec5SDimitry Andric return StructuredData::ObjectSP(); 226*0b57cec5SDimitry Andric default: 227*0b57cec5SDimitry Andric return StructuredData::ObjectSP(new StructuredPythonObject(m_py_obj)); 228*0b57cec5SDimitry Andric } 229*0b57cec5SDimitry Andric } 230*0b57cec5SDimitry Andric 231*0b57cec5SDimitry Andric // PythonString 232*0b57cec5SDimitry Andric 2339dba64beSDimitry Andric PythonBytes::PythonBytes(llvm::ArrayRef<uint8_t> bytes) { SetBytes(bytes); } 234*0b57cec5SDimitry Andric 2359dba64beSDimitry Andric PythonBytes::PythonBytes(const uint8_t *bytes, size_t length) { 236*0b57cec5SDimitry Andric SetBytes(llvm::ArrayRef<uint8_t>(bytes, length)); 237*0b57cec5SDimitry Andric } 238*0b57cec5SDimitry Andric 239*0b57cec5SDimitry Andric bool PythonBytes::Check(PyObject *py_obj) { 240*0b57cec5SDimitry Andric if (!py_obj) 241*0b57cec5SDimitry Andric return false; 242*0b57cec5SDimitry Andric return PyBytes_Check(py_obj); 243*0b57cec5SDimitry Andric } 244*0b57cec5SDimitry Andric 245*0b57cec5SDimitry Andric llvm::ArrayRef<uint8_t> PythonBytes::GetBytes() const { 246*0b57cec5SDimitry Andric if (!IsValid()) 247*0b57cec5SDimitry Andric return llvm::ArrayRef<uint8_t>(); 248*0b57cec5SDimitry Andric 249*0b57cec5SDimitry Andric Py_ssize_t size; 250*0b57cec5SDimitry Andric char *c; 251*0b57cec5SDimitry Andric 252*0b57cec5SDimitry Andric PyBytes_AsStringAndSize(m_py_obj, &c, &size); 253*0b57cec5SDimitry Andric return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size); 254*0b57cec5SDimitry Andric } 255*0b57cec5SDimitry Andric 256*0b57cec5SDimitry Andric size_t PythonBytes::GetSize() const { 257*0b57cec5SDimitry Andric if (!IsValid()) 258*0b57cec5SDimitry Andric return 0; 259*0b57cec5SDimitry Andric return PyBytes_Size(m_py_obj); 260*0b57cec5SDimitry Andric } 261*0b57cec5SDimitry Andric 262*0b57cec5SDimitry Andric void PythonBytes::SetBytes(llvm::ArrayRef<uint8_t> bytes) { 263*0b57cec5SDimitry Andric const char *data = reinterpret_cast<const char *>(bytes.data()); 2649dba64beSDimitry Andric *this = Take<PythonBytes>(PyBytes_FromStringAndSize(data, bytes.size())); 265*0b57cec5SDimitry Andric } 266*0b57cec5SDimitry Andric 267*0b57cec5SDimitry Andric StructuredData::StringSP PythonBytes::CreateStructuredString() const { 268*0b57cec5SDimitry Andric StructuredData::StringSP result(new StructuredData::String); 269*0b57cec5SDimitry Andric Py_ssize_t size; 270*0b57cec5SDimitry Andric char *c; 271*0b57cec5SDimitry Andric PyBytes_AsStringAndSize(m_py_obj, &c, &size); 272*0b57cec5SDimitry Andric result->SetValue(std::string(c, size)); 273*0b57cec5SDimitry Andric return result; 274*0b57cec5SDimitry Andric } 275*0b57cec5SDimitry Andric 276*0b57cec5SDimitry Andric PythonByteArray::PythonByteArray(llvm::ArrayRef<uint8_t> bytes) 277*0b57cec5SDimitry Andric : PythonByteArray(bytes.data(), bytes.size()) {} 278*0b57cec5SDimitry Andric 279*0b57cec5SDimitry Andric PythonByteArray::PythonByteArray(const uint8_t *bytes, size_t length) { 280*0b57cec5SDimitry Andric const char *str = reinterpret_cast<const char *>(bytes); 2819dba64beSDimitry Andric *this = Take<PythonByteArray>(PyByteArray_FromStringAndSize(str, length)); 282*0b57cec5SDimitry Andric } 283*0b57cec5SDimitry Andric 284*0b57cec5SDimitry Andric bool PythonByteArray::Check(PyObject *py_obj) { 285*0b57cec5SDimitry Andric if (!py_obj) 286*0b57cec5SDimitry Andric return false; 287*0b57cec5SDimitry Andric return PyByteArray_Check(py_obj); 288*0b57cec5SDimitry Andric } 289*0b57cec5SDimitry Andric 290*0b57cec5SDimitry Andric llvm::ArrayRef<uint8_t> PythonByteArray::GetBytes() const { 291*0b57cec5SDimitry Andric if (!IsValid()) 292*0b57cec5SDimitry Andric return llvm::ArrayRef<uint8_t>(); 293*0b57cec5SDimitry Andric 294*0b57cec5SDimitry Andric char *c = PyByteArray_AsString(m_py_obj); 295*0b57cec5SDimitry Andric size_t size = GetSize(); 296*0b57cec5SDimitry Andric return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size); 297*0b57cec5SDimitry Andric } 298*0b57cec5SDimitry Andric 299*0b57cec5SDimitry Andric size_t PythonByteArray::GetSize() const { 300*0b57cec5SDimitry Andric if (!IsValid()) 301*0b57cec5SDimitry Andric return 0; 302*0b57cec5SDimitry Andric 303*0b57cec5SDimitry Andric return PyByteArray_Size(m_py_obj); 304*0b57cec5SDimitry Andric } 305*0b57cec5SDimitry Andric 306*0b57cec5SDimitry Andric StructuredData::StringSP PythonByteArray::CreateStructuredString() const { 307*0b57cec5SDimitry Andric StructuredData::StringSP result(new StructuredData::String); 308*0b57cec5SDimitry Andric llvm::ArrayRef<uint8_t> bytes = GetBytes(); 309*0b57cec5SDimitry Andric const char *str = reinterpret_cast<const char *>(bytes.data()); 310*0b57cec5SDimitry Andric result->SetValue(std::string(str, bytes.size())); 311*0b57cec5SDimitry Andric return result; 312*0b57cec5SDimitry Andric } 313*0b57cec5SDimitry Andric 314*0b57cec5SDimitry Andric // PythonString 315*0b57cec5SDimitry Andric 3169dba64beSDimitry Andric Expected<PythonString> PythonString::FromUTF8(llvm::StringRef string) { 3179dba64beSDimitry Andric #if PY_MAJOR_VERSION >= 3 3189dba64beSDimitry Andric PyObject *str = PyUnicode_FromStringAndSize(string.data(), string.size()); 3199dba64beSDimitry Andric #else 3209dba64beSDimitry Andric PyObject *str = PyString_FromStringAndSize(string.data(), string.size()); 3219dba64beSDimitry Andric #endif 3229dba64beSDimitry Andric if (!str) 3239dba64beSDimitry Andric return llvm::make_error<PythonException>(); 3249dba64beSDimitry Andric return Take<PythonString>(str); 325*0b57cec5SDimitry Andric } 326*0b57cec5SDimitry Andric 3279dba64beSDimitry Andric PythonString::PythonString(llvm::StringRef string) { SetString(string); } 328*0b57cec5SDimitry Andric 329*0b57cec5SDimitry Andric bool PythonString::Check(PyObject *py_obj) { 330*0b57cec5SDimitry Andric if (!py_obj) 331*0b57cec5SDimitry Andric return false; 332*0b57cec5SDimitry Andric 333*0b57cec5SDimitry Andric if (PyUnicode_Check(py_obj)) 334*0b57cec5SDimitry Andric return true; 335*0b57cec5SDimitry Andric #if PY_MAJOR_VERSION < 3 336*0b57cec5SDimitry Andric if (PyString_Check(py_obj)) 337*0b57cec5SDimitry Andric return true; 338*0b57cec5SDimitry Andric #endif 339*0b57cec5SDimitry Andric return false; 340*0b57cec5SDimitry Andric } 341*0b57cec5SDimitry Andric 3429dba64beSDimitry Andric void PythonString::Convert(PyRefType &type, PyObject *&py_obj) { 343*0b57cec5SDimitry Andric #if PY_MAJOR_VERSION < 3 344*0b57cec5SDimitry Andric // In Python 2, Don't store PyUnicode objects directly, because we need 345*0b57cec5SDimitry Andric // access to their underlying character buffers which Python 2 doesn't 346*0b57cec5SDimitry Andric // provide. 3479dba64beSDimitry Andric if (PyUnicode_Check(py_obj)) { 3489dba64beSDimitry Andric PyObject *s = PyUnicode_AsUTF8String(py_obj); 3499dba64beSDimitry Andric if (s == nullptr) { 3509dba64beSDimitry Andric PyErr_Clear(); 3519dba64beSDimitry Andric if (type == PyRefType::Owned) 3529dba64beSDimitry Andric Py_DECREF(py_obj); 3539dba64beSDimitry Andric return; 3549dba64beSDimitry Andric } 3559dba64beSDimitry Andric if (type == PyRefType::Owned) 3569dba64beSDimitry Andric Py_DECREF(py_obj); 3579dba64beSDimitry Andric else 3589dba64beSDimitry Andric type = PyRefType::Owned; 3599dba64beSDimitry Andric py_obj = s; 3609dba64beSDimitry Andric } 361*0b57cec5SDimitry Andric #endif 362*0b57cec5SDimitry Andric } 363*0b57cec5SDimitry Andric 364*0b57cec5SDimitry Andric llvm::StringRef PythonString::GetString() const { 3659dba64beSDimitry Andric auto s = AsUTF8(); 3669dba64beSDimitry Andric if (!s) { 3679dba64beSDimitry Andric llvm::consumeError(s.takeError()); 3689dba64beSDimitry Andric return llvm::StringRef(""); 3699dba64beSDimitry Andric } 3709dba64beSDimitry Andric return s.get(); 3719dba64beSDimitry Andric } 3729dba64beSDimitry Andric 3739dba64beSDimitry Andric Expected<llvm::StringRef> PythonString::AsUTF8() const { 374*0b57cec5SDimitry Andric if (!IsValid()) 3759dba64beSDimitry Andric return nullDeref(); 376*0b57cec5SDimitry Andric 377*0b57cec5SDimitry Andric Py_ssize_t size; 378*0b57cec5SDimitry Andric const char *data; 379*0b57cec5SDimitry Andric 380*0b57cec5SDimitry Andric #if PY_MAJOR_VERSION >= 3 381*0b57cec5SDimitry Andric data = PyUnicode_AsUTF8AndSize(m_py_obj, &size); 382*0b57cec5SDimitry Andric #else 3839dba64beSDimitry Andric char *c = NULL; 3849dba64beSDimitry Andric int r = PyString_AsStringAndSize(m_py_obj, &c, &size); 3859dba64beSDimitry Andric if (r < 0) 3869dba64beSDimitry Andric c = NULL; 387*0b57cec5SDimitry Andric data = c; 388*0b57cec5SDimitry Andric #endif 3899dba64beSDimitry Andric 3909dba64beSDimitry Andric if (!data) 3919dba64beSDimitry Andric return exception(); 3929dba64beSDimitry Andric 393*0b57cec5SDimitry Andric return llvm::StringRef(data, size); 394*0b57cec5SDimitry Andric } 395*0b57cec5SDimitry Andric 396*0b57cec5SDimitry Andric size_t PythonString::GetSize() const { 397*0b57cec5SDimitry Andric if (IsValid()) { 398*0b57cec5SDimitry Andric #if PY_MAJOR_VERSION >= 3 399*0b57cec5SDimitry Andric return PyUnicode_GetSize(m_py_obj); 400*0b57cec5SDimitry Andric #else 401*0b57cec5SDimitry Andric return PyString_Size(m_py_obj); 402*0b57cec5SDimitry Andric #endif 403*0b57cec5SDimitry Andric } 404*0b57cec5SDimitry Andric return 0; 405*0b57cec5SDimitry Andric } 406*0b57cec5SDimitry Andric 407*0b57cec5SDimitry Andric void PythonString::SetString(llvm::StringRef string) { 4089dba64beSDimitry Andric auto s = FromUTF8(string); 4099dba64beSDimitry Andric if (!s) { 4109dba64beSDimitry Andric llvm::consumeError(s.takeError()); 4119dba64beSDimitry Andric Reset(); 4129dba64beSDimitry Andric } else { 4139dba64beSDimitry Andric *this = std::move(s.get()); 4149dba64beSDimitry Andric } 415*0b57cec5SDimitry Andric } 416*0b57cec5SDimitry Andric 417*0b57cec5SDimitry Andric StructuredData::StringSP PythonString::CreateStructuredString() const { 418*0b57cec5SDimitry Andric StructuredData::StringSP result(new StructuredData::String); 419*0b57cec5SDimitry Andric result->SetValue(GetString()); 420*0b57cec5SDimitry Andric return result; 421*0b57cec5SDimitry Andric } 422*0b57cec5SDimitry Andric 423*0b57cec5SDimitry Andric // PythonInteger 424*0b57cec5SDimitry Andric 4259dba64beSDimitry Andric PythonInteger::PythonInteger(int64_t value) { SetInteger(value); } 426*0b57cec5SDimitry Andric 427*0b57cec5SDimitry Andric bool PythonInteger::Check(PyObject *py_obj) { 428*0b57cec5SDimitry Andric if (!py_obj) 429*0b57cec5SDimitry Andric return false; 430*0b57cec5SDimitry Andric 431*0b57cec5SDimitry Andric #if PY_MAJOR_VERSION >= 3 432*0b57cec5SDimitry Andric // Python 3 does not have PyInt_Check. There is only one type of integral 433*0b57cec5SDimitry Andric // value, long. 434*0b57cec5SDimitry Andric return PyLong_Check(py_obj); 435*0b57cec5SDimitry Andric #else 436*0b57cec5SDimitry Andric return PyLong_Check(py_obj) || PyInt_Check(py_obj); 437*0b57cec5SDimitry Andric #endif 438*0b57cec5SDimitry Andric } 439*0b57cec5SDimitry Andric 4409dba64beSDimitry Andric void PythonInteger::Convert(PyRefType &type, PyObject *&py_obj) { 441*0b57cec5SDimitry Andric #if PY_MAJOR_VERSION < 3 442*0b57cec5SDimitry Andric // Always store this as a PyLong, which makes interoperability between Python 443*0b57cec5SDimitry Andric // 2.x and Python 3.x easier. This is only necessary in 2.x, since 3.x 444*0b57cec5SDimitry Andric // doesn't even have a PyInt. 445*0b57cec5SDimitry Andric if (PyInt_Check(py_obj)) { 446*0b57cec5SDimitry Andric // Since we converted the original object to a different type, the new 447*0b57cec5SDimitry Andric // object is an owned object regardless of the ownership semantics 448*0b57cec5SDimitry Andric // requested by the user. 4499dba64beSDimitry Andric long long value = PyInt_AsLong(py_obj); 4509dba64beSDimitry Andric PyObject *l = nullptr; 4519dba64beSDimitry Andric if (!PyErr_Occurred()) 4529dba64beSDimitry Andric l = PyLong_FromLongLong(value); 4539dba64beSDimitry Andric if (l == nullptr) { 4549dba64beSDimitry Andric PyErr_Clear(); 4559dba64beSDimitry Andric if (type == PyRefType::Owned) 4569dba64beSDimitry Andric Py_DECREF(py_obj); 4579dba64beSDimitry Andric return; 4589dba64beSDimitry Andric } 4599dba64beSDimitry Andric if (type == PyRefType::Owned) 4609dba64beSDimitry Andric Py_DECREF(py_obj); 4619dba64beSDimitry Andric else 4629dba64beSDimitry Andric type = PyRefType::Owned; 4639dba64beSDimitry Andric py_obj = l; 464*0b57cec5SDimitry Andric } 465*0b57cec5SDimitry Andric #endif 466*0b57cec5SDimitry Andric } 467*0b57cec5SDimitry Andric 468*0b57cec5SDimitry Andric int64_t PythonInteger::GetInteger() const { 469*0b57cec5SDimitry Andric if (m_py_obj) { 470*0b57cec5SDimitry Andric assert(PyLong_Check(m_py_obj) && 471*0b57cec5SDimitry Andric "PythonInteger::GetInteger has a PyObject that isn't a PyLong"); 472*0b57cec5SDimitry Andric 473*0b57cec5SDimitry Andric int overflow = 0; 474*0b57cec5SDimitry Andric int64_t result = PyLong_AsLongLongAndOverflow(m_py_obj, &overflow); 475*0b57cec5SDimitry Andric if (overflow != 0) { 476*0b57cec5SDimitry Andric // We got an integer that overflows, like 18446744072853913392L we can't 477*0b57cec5SDimitry Andric // use PyLong_AsLongLong() as it will return 0xffffffffffffffff. If we 478*0b57cec5SDimitry Andric // use the unsigned long long it will work as expected. 479*0b57cec5SDimitry Andric const uint64_t uval = PyLong_AsUnsignedLongLong(m_py_obj); 480*0b57cec5SDimitry Andric result = static_cast<int64_t>(uval); 481*0b57cec5SDimitry Andric } 482*0b57cec5SDimitry Andric return result; 483*0b57cec5SDimitry Andric } 484*0b57cec5SDimitry Andric return UINT64_MAX; 485*0b57cec5SDimitry Andric } 486*0b57cec5SDimitry Andric 487*0b57cec5SDimitry Andric void PythonInteger::SetInteger(int64_t value) { 4889dba64beSDimitry Andric *this = Take<PythonInteger>(PyLong_FromLongLong(value)); 489*0b57cec5SDimitry Andric } 490*0b57cec5SDimitry Andric 491*0b57cec5SDimitry Andric StructuredData::IntegerSP PythonInteger::CreateStructuredInteger() const { 492*0b57cec5SDimitry Andric StructuredData::IntegerSP result(new StructuredData::Integer); 493*0b57cec5SDimitry Andric result->SetValue(GetInteger()); 494*0b57cec5SDimitry Andric return result; 495*0b57cec5SDimitry Andric } 496*0b57cec5SDimitry Andric 497*0b57cec5SDimitry Andric // PythonBoolean 498*0b57cec5SDimitry Andric 499*0b57cec5SDimitry Andric PythonBoolean::PythonBoolean(bool value) { 500*0b57cec5SDimitry Andric SetValue(value); 501*0b57cec5SDimitry Andric } 502*0b57cec5SDimitry Andric 503*0b57cec5SDimitry Andric bool PythonBoolean::Check(PyObject *py_obj) { 504*0b57cec5SDimitry Andric return py_obj ? PyBool_Check(py_obj) : false; 505*0b57cec5SDimitry Andric } 506*0b57cec5SDimitry Andric 507*0b57cec5SDimitry Andric bool PythonBoolean::GetValue() const { 508*0b57cec5SDimitry Andric return m_py_obj ? PyObject_IsTrue(m_py_obj) : false; 509*0b57cec5SDimitry Andric } 510*0b57cec5SDimitry Andric 511*0b57cec5SDimitry Andric void PythonBoolean::SetValue(bool value) { 5129dba64beSDimitry Andric *this = Take<PythonBoolean>(PyBool_FromLong(value)); 513*0b57cec5SDimitry Andric } 514*0b57cec5SDimitry Andric 515*0b57cec5SDimitry Andric StructuredData::BooleanSP PythonBoolean::CreateStructuredBoolean() const { 516*0b57cec5SDimitry Andric StructuredData::BooleanSP result(new StructuredData::Boolean); 517*0b57cec5SDimitry Andric result->SetValue(GetValue()); 518*0b57cec5SDimitry Andric return result; 519*0b57cec5SDimitry Andric } 520*0b57cec5SDimitry Andric 521*0b57cec5SDimitry Andric // PythonList 522*0b57cec5SDimitry Andric 5239dba64beSDimitry Andric PythonList::PythonList(PyInitialValue value) { 524*0b57cec5SDimitry Andric if (value == PyInitialValue::Empty) 5259dba64beSDimitry Andric *this = Take<PythonList>(PyList_New(0)); 526*0b57cec5SDimitry Andric } 527*0b57cec5SDimitry Andric 5289dba64beSDimitry Andric PythonList::PythonList(int list_size) { 5299dba64beSDimitry Andric *this = Take<PythonList>(PyList_New(list_size)); 530*0b57cec5SDimitry Andric } 531*0b57cec5SDimitry Andric 532*0b57cec5SDimitry Andric bool PythonList::Check(PyObject *py_obj) { 533*0b57cec5SDimitry Andric if (!py_obj) 534*0b57cec5SDimitry Andric return false; 535*0b57cec5SDimitry Andric return PyList_Check(py_obj); 536*0b57cec5SDimitry Andric } 537*0b57cec5SDimitry Andric 538*0b57cec5SDimitry Andric uint32_t PythonList::GetSize() const { 539*0b57cec5SDimitry Andric if (IsValid()) 540*0b57cec5SDimitry Andric return PyList_GET_SIZE(m_py_obj); 541*0b57cec5SDimitry Andric return 0; 542*0b57cec5SDimitry Andric } 543*0b57cec5SDimitry Andric 544*0b57cec5SDimitry Andric PythonObject PythonList::GetItemAtIndex(uint32_t index) const { 545*0b57cec5SDimitry Andric if (IsValid()) 546*0b57cec5SDimitry Andric return PythonObject(PyRefType::Borrowed, PyList_GetItem(m_py_obj, index)); 547*0b57cec5SDimitry Andric return PythonObject(); 548*0b57cec5SDimitry Andric } 549*0b57cec5SDimitry Andric 550*0b57cec5SDimitry Andric void PythonList::SetItemAtIndex(uint32_t index, const PythonObject &object) { 551*0b57cec5SDimitry Andric if (IsAllocated() && object.IsValid()) { 552*0b57cec5SDimitry Andric // PyList_SetItem is documented to "steal" a reference, so we need to 553*0b57cec5SDimitry Andric // convert it to an owned reference by incrementing it. 554*0b57cec5SDimitry Andric Py_INCREF(object.get()); 555*0b57cec5SDimitry Andric PyList_SetItem(m_py_obj, index, object.get()); 556*0b57cec5SDimitry Andric } 557*0b57cec5SDimitry Andric } 558*0b57cec5SDimitry Andric 559*0b57cec5SDimitry Andric void PythonList::AppendItem(const PythonObject &object) { 560*0b57cec5SDimitry Andric if (IsAllocated() && object.IsValid()) { 561*0b57cec5SDimitry Andric // `PyList_Append` does *not* steal a reference, so do not call `Py_INCREF` 562*0b57cec5SDimitry Andric // here like we do with `PyList_SetItem`. 563*0b57cec5SDimitry Andric PyList_Append(m_py_obj, object.get()); 564*0b57cec5SDimitry Andric } 565*0b57cec5SDimitry Andric } 566*0b57cec5SDimitry Andric 567*0b57cec5SDimitry Andric StructuredData::ArraySP PythonList::CreateStructuredArray() const { 568*0b57cec5SDimitry Andric StructuredData::ArraySP result(new StructuredData::Array); 569*0b57cec5SDimitry Andric uint32_t count = GetSize(); 570*0b57cec5SDimitry Andric for (uint32_t i = 0; i < count; ++i) { 571*0b57cec5SDimitry Andric PythonObject obj = GetItemAtIndex(i); 572*0b57cec5SDimitry Andric result->AddItem(obj.CreateStructuredObject()); 573*0b57cec5SDimitry Andric } 574*0b57cec5SDimitry Andric return result; 575*0b57cec5SDimitry Andric } 576*0b57cec5SDimitry Andric 577*0b57cec5SDimitry Andric // PythonTuple 578*0b57cec5SDimitry Andric 5799dba64beSDimitry Andric PythonTuple::PythonTuple(PyInitialValue value) { 580*0b57cec5SDimitry Andric if (value == PyInitialValue::Empty) 5819dba64beSDimitry Andric *this = Take<PythonTuple>(PyTuple_New(0)); 582*0b57cec5SDimitry Andric } 583*0b57cec5SDimitry Andric 5849dba64beSDimitry Andric PythonTuple::PythonTuple(int tuple_size) { 5859dba64beSDimitry Andric *this = Take<PythonTuple>(PyTuple_New(tuple_size)); 586*0b57cec5SDimitry Andric } 587*0b57cec5SDimitry Andric 588*0b57cec5SDimitry Andric PythonTuple::PythonTuple(std::initializer_list<PythonObject> objects) { 589*0b57cec5SDimitry Andric m_py_obj = PyTuple_New(objects.size()); 590*0b57cec5SDimitry Andric 591*0b57cec5SDimitry Andric uint32_t idx = 0; 592*0b57cec5SDimitry Andric for (auto object : objects) { 593*0b57cec5SDimitry Andric if (object.IsValid()) 594*0b57cec5SDimitry Andric SetItemAtIndex(idx, object); 595*0b57cec5SDimitry Andric idx++; 596*0b57cec5SDimitry Andric } 597*0b57cec5SDimitry Andric } 598*0b57cec5SDimitry Andric 599*0b57cec5SDimitry Andric PythonTuple::PythonTuple(std::initializer_list<PyObject *> objects) { 600*0b57cec5SDimitry Andric m_py_obj = PyTuple_New(objects.size()); 601*0b57cec5SDimitry Andric 602*0b57cec5SDimitry Andric uint32_t idx = 0; 603*0b57cec5SDimitry Andric for (auto py_object : objects) { 604*0b57cec5SDimitry Andric PythonObject object(PyRefType::Borrowed, py_object); 605*0b57cec5SDimitry Andric if (object.IsValid()) 606*0b57cec5SDimitry Andric SetItemAtIndex(idx, object); 607*0b57cec5SDimitry Andric idx++; 608*0b57cec5SDimitry Andric } 609*0b57cec5SDimitry Andric } 610*0b57cec5SDimitry Andric 611*0b57cec5SDimitry Andric bool PythonTuple::Check(PyObject *py_obj) { 612*0b57cec5SDimitry Andric if (!py_obj) 613*0b57cec5SDimitry Andric return false; 614*0b57cec5SDimitry Andric return PyTuple_Check(py_obj); 615*0b57cec5SDimitry Andric } 616*0b57cec5SDimitry Andric 617*0b57cec5SDimitry Andric uint32_t PythonTuple::GetSize() const { 618*0b57cec5SDimitry Andric if (IsValid()) 619*0b57cec5SDimitry Andric return PyTuple_GET_SIZE(m_py_obj); 620*0b57cec5SDimitry Andric return 0; 621*0b57cec5SDimitry Andric } 622*0b57cec5SDimitry Andric 623*0b57cec5SDimitry Andric PythonObject PythonTuple::GetItemAtIndex(uint32_t index) const { 624*0b57cec5SDimitry Andric if (IsValid()) 625*0b57cec5SDimitry Andric return PythonObject(PyRefType::Borrowed, PyTuple_GetItem(m_py_obj, index)); 626*0b57cec5SDimitry Andric return PythonObject(); 627*0b57cec5SDimitry Andric } 628*0b57cec5SDimitry Andric 629*0b57cec5SDimitry Andric void PythonTuple::SetItemAtIndex(uint32_t index, const PythonObject &object) { 630*0b57cec5SDimitry Andric if (IsAllocated() && object.IsValid()) { 631*0b57cec5SDimitry Andric // PyTuple_SetItem is documented to "steal" a reference, so we need to 632*0b57cec5SDimitry Andric // convert it to an owned reference by incrementing it. 633*0b57cec5SDimitry Andric Py_INCREF(object.get()); 634*0b57cec5SDimitry Andric PyTuple_SetItem(m_py_obj, index, object.get()); 635*0b57cec5SDimitry Andric } 636*0b57cec5SDimitry Andric } 637*0b57cec5SDimitry Andric 638*0b57cec5SDimitry Andric StructuredData::ArraySP PythonTuple::CreateStructuredArray() const { 639*0b57cec5SDimitry Andric StructuredData::ArraySP result(new StructuredData::Array); 640*0b57cec5SDimitry Andric uint32_t count = GetSize(); 641*0b57cec5SDimitry Andric for (uint32_t i = 0; i < count; ++i) { 642*0b57cec5SDimitry Andric PythonObject obj = GetItemAtIndex(i); 643*0b57cec5SDimitry Andric result->AddItem(obj.CreateStructuredObject()); 644*0b57cec5SDimitry Andric } 645*0b57cec5SDimitry Andric return result; 646*0b57cec5SDimitry Andric } 647*0b57cec5SDimitry Andric 648*0b57cec5SDimitry Andric // PythonDictionary 649*0b57cec5SDimitry Andric 6509dba64beSDimitry Andric PythonDictionary::PythonDictionary(PyInitialValue value) { 651*0b57cec5SDimitry Andric if (value == PyInitialValue::Empty) 6529dba64beSDimitry Andric *this = Take<PythonDictionary>(PyDict_New()); 653*0b57cec5SDimitry Andric } 654*0b57cec5SDimitry Andric 655*0b57cec5SDimitry Andric bool PythonDictionary::Check(PyObject *py_obj) { 656*0b57cec5SDimitry Andric if (!py_obj) 657*0b57cec5SDimitry Andric return false; 658*0b57cec5SDimitry Andric 659*0b57cec5SDimitry Andric return PyDict_Check(py_obj); 660*0b57cec5SDimitry Andric } 661*0b57cec5SDimitry Andric 662*0b57cec5SDimitry Andric uint32_t PythonDictionary::GetSize() const { 663*0b57cec5SDimitry Andric if (IsValid()) 664*0b57cec5SDimitry Andric return PyDict_Size(m_py_obj); 665*0b57cec5SDimitry Andric return 0; 666*0b57cec5SDimitry Andric } 667*0b57cec5SDimitry Andric 668*0b57cec5SDimitry Andric PythonList PythonDictionary::GetKeys() const { 669*0b57cec5SDimitry Andric if (IsValid()) 670*0b57cec5SDimitry Andric return PythonList(PyRefType::Owned, PyDict_Keys(m_py_obj)); 671*0b57cec5SDimitry Andric return PythonList(PyInitialValue::Invalid); 672*0b57cec5SDimitry Andric } 673*0b57cec5SDimitry Andric 674*0b57cec5SDimitry Andric PythonObject PythonDictionary::GetItemForKey(const PythonObject &key) const { 6759dba64beSDimitry Andric auto item = GetItem(key); 6769dba64beSDimitry Andric if (!item) { 6779dba64beSDimitry Andric llvm::consumeError(item.takeError()); 678*0b57cec5SDimitry Andric return PythonObject(); 679*0b57cec5SDimitry Andric } 6809dba64beSDimitry Andric return std::move(item.get()); 6819dba64beSDimitry Andric } 6829dba64beSDimitry Andric 6839dba64beSDimitry Andric Expected<PythonObject> 6849dba64beSDimitry Andric PythonDictionary::GetItem(const PythonObject &key) const { 6859dba64beSDimitry Andric if (!IsValid()) 6869dba64beSDimitry Andric return nullDeref(); 6879dba64beSDimitry Andric #if PY_MAJOR_VERSION >= 3 6889dba64beSDimitry Andric PyObject *o = PyDict_GetItemWithError(m_py_obj, key.get()); 6899dba64beSDimitry Andric if (PyErr_Occurred()) 6909dba64beSDimitry Andric return exception(); 6919dba64beSDimitry Andric #else 6929dba64beSDimitry Andric PyObject *o = PyDict_GetItem(m_py_obj, key.get()); 6939dba64beSDimitry Andric #endif 6949dba64beSDimitry Andric if (!o) 6959dba64beSDimitry Andric return keyError(); 6969dba64beSDimitry Andric return Retain<PythonObject>(o); 6979dba64beSDimitry Andric } 6989dba64beSDimitry Andric 6999dba64beSDimitry Andric Expected<PythonObject> PythonDictionary::GetItem(const Twine &key) const { 7009dba64beSDimitry Andric if (!IsValid()) 7019dba64beSDimitry Andric return nullDeref(); 7029dba64beSDimitry Andric PyObject *o = PyDict_GetItemString(m_py_obj, NullTerminated(key)); 7039dba64beSDimitry Andric if (PyErr_Occurred()) 7049dba64beSDimitry Andric return exception(); 7059dba64beSDimitry Andric if (!o) 7069dba64beSDimitry Andric return keyError(); 7079dba64beSDimitry Andric return Retain<PythonObject>(o); 7089dba64beSDimitry Andric } 7099dba64beSDimitry Andric 7109dba64beSDimitry Andric Error PythonDictionary::SetItem(const PythonObject &key, 7119dba64beSDimitry Andric const PythonObject &value) const { 7129dba64beSDimitry Andric if (!IsValid() || !value.IsValid()) 7139dba64beSDimitry Andric return nullDeref(); 7149dba64beSDimitry Andric int r = PyDict_SetItem(m_py_obj, key.get(), value.get()); 7159dba64beSDimitry Andric if (r < 0) 7169dba64beSDimitry Andric return exception(); 7179dba64beSDimitry Andric return Error::success(); 7189dba64beSDimitry Andric } 7199dba64beSDimitry Andric 7209dba64beSDimitry Andric Error PythonDictionary::SetItem(const Twine &key, 7219dba64beSDimitry Andric const PythonObject &value) const { 7229dba64beSDimitry Andric if (!IsValid() || !value.IsValid()) 7239dba64beSDimitry Andric return nullDeref(); 7249dba64beSDimitry Andric int r = PyDict_SetItemString(m_py_obj, NullTerminated(key), value.get()); 7259dba64beSDimitry Andric if (r < 0) 7269dba64beSDimitry Andric return exception(); 7279dba64beSDimitry Andric return Error::success(); 7289dba64beSDimitry Andric } 729*0b57cec5SDimitry Andric 730*0b57cec5SDimitry Andric void PythonDictionary::SetItemForKey(const PythonObject &key, 731*0b57cec5SDimitry Andric const PythonObject &value) { 7329dba64beSDimitry Andric Error error = SetItem(key, value); 7339dba64beSDimitry Andric if (error) 7349dba64beSDimitry Andric llvm::consumeError(std::move(error)); 735*0b57cec5SDimitry Andric } 736*0b57cec5SDimitry Andric 737*0b57cec5SDimitry Andric StructuredData::DictionarySP 738*0b57cec5SDimitry Andric PythonDictionary::CreateStructuredDictionary() const { 739*0b57cec5SDimitry Andric StructuredData::DictionarySP result(new StructuredData::Dictionary); 740*0b57cec5SDimitry Andric PythonList keys(GetKeys()); 741*0b57cec5SDimitry Andric uint32_t num_keys = keys.GetSize(); 742*0b57cec5SDimitry Andric for (uint32_t i = 0; i < num_keys; ++i) { 743*0b57cec5SDimitry Andric PythonObject key = keys.GetItemAtIndex(i); 744*0b57cec5SDimitry Andric PythonObject value = GetItemForKey(key); 745*0b57cec5SDimitry Andric StructuredData::ObjectSP structured_value = value.CreateStructuredObject(); 746*0b57cec5SDimitry Andric result->AddItem(key.Str().GetString(), structured_value); 747*0b57cec5SDimitry Andric } 748*0b57cec5SDimitry Andric return result; 749*0b57cec5SDimitry Andric } 750*0b57cec5SDimitry Andric 751*0b57cec5SDimitry Andric PythonModule PythonModule::BuiltinsModule() { 752*0b57cec5SDimitry Andric #if PY_MAJOR_VERSION >= 3 753*0b57cec5SDimitry Andric return AddModule("builtins"); 754*0b57cec5SDimitry Andric #else 755*0b57cec5SDimitry Andric return AddModule("__builtin__"); 756*0b57cec5SDimitry Andric #endif 757*0b57cec5SDimitry Andric } 758*0b57cec5SDimitry Andric 759*0b57cec5SDimitry Andric PythonModule PythonModule::MainModule() { return AddModule("__main__"); } 760*0b57cec5SDimitry Andric 761*0b57cec5SDimitry Andric PythonModule PythonModule::AddModule(llvm::StringRef module) { 762*0b57cec5SDimitry Andric std::string str = module.str(); 763*0b57cec5SDimitry Andric return PythonModule(PyRefType::Borrowed, PyImport_AddModule(str.c_str())); 764*0b57cec5SDimitry Andric } 765*0b57cec5SDimitry Andric 7669dba64beSDimitry Andric Expected<PythonModule> PythonModule::Import(const Twine &name) { 7679dba64beSDimitry Andric PyObject *mod = PyImport_ImportModule(NullTerminated(name)); 7689dba64beSDimitry Andric if (!mod) 7699dba64beSDimitry Andric return exception(); 7709dba64beSDimitry Andric return Take<PythonModule>(mod); 7719dba64beSDimitry Andric } 7729dba64beSDimitry Andric 7739dba64beSDimitry Andric Expected<PythonObject> PythonModule::Get(const Twine &name) { 7749dba64beSDimitry Andric if (!IsValid()) 7759dba64beSDimitry Andric return nullDeref(); 7769dba64beSDimitry Andric PyObject *dict = PyModule_GetDict(m_py_obj); 7779dba64beSDimitry Andric if (!dict) 7789dba64beSDimitry Andric return exception(); 7799dba64beSDimitry Andric PyObject *item = PyDict_GetItemString(dict, NullTerminated(name)); 7809dba64beSDimitry Andric if (!item) 7819dba64beSDimitry Andric return exception(); 7829dba64beSDimitry Andric return Retain<PythonObject>(item); 783*0b57cec5SDimitry Andric } 784*0b57cec5SDimitry Andric 785*0b57cec5SDimitry Andric bool PythonModule::Check(PyObject *py_obj) { 786*0b57cec5SDimitry Andric if (!py_obj) 787*0b57cec5SDimitry Andric return false; 788*0b57cec5SDimitry Andric 789*0b57cec5SDimitry Andric return PyModule_Check(py_obj); 790*0b57cec5SDimitry Andric } 791*0b57cec5SDimitry Andric 792*0b57cec5SDimitry Andric PythonDictionary PythonModule::GetDictionary() const { 7939dba64beSDimitry Andric if (!IsValid()) 7949dba64beSDimitry Andric return PythonDictionary(); 7959dba64beSDimitry Andric return Retain<PythonDictionary>(PyModule_GetDict(m_py_obj)); 796*0b57cec5SDimitry Andric } 797*0b57cec5SDimitry Andric 798*0b57cec5SDimitry Andric bool PythonCallable::Check(PyObject *py_obj) { 799*0b57cec5SDimitry Andric if (!py_obj) 800*0b57cec5SDimitry Andric return false; 801*0b57cec5SDimitry Andric 802*0b57cec5SDimitry Andric return PyCallable_Check(py_obj); 803*0b57cec5SDimitry Andric } 804*0b57cec5SDimitry Andric 8059dba64beSDimitry Andric PythonCallable::ArgInfo PythonCallable::GetNumInitArguments() const { 8069dba64beSDimitry Andric auto arginfo = GetInitArgInfo(); 8079dba64beSDimitry Andric if (!arginfo) { 8089dba64beSDimitry Andric llvm::consumeError(arginfo.takeError()); 8099dba64beSDimitry Andric return ArgInfo{}; 8109dba64beSDimitry Andric } 8119dba64beSDimitry Andric return arginfo.get(); 812*0b57cec5SDimitry Andric } 813*0b57cec5SDimitry Andric 8149dba64beSDimitry Andric Expected<PythonCallable::ArgInfo> PythonCallable::GetInitArgInfo() const { 815*0b57cec5SDimitry Andric if (!IsValid()) 8169dba64beSDimitry Andric return nullDeref(); 8179dba64beSDimitry Andric auto init = As<PythonCallable>(GetAttribute("__init__")); 8189dba64beSDimitry Andric if (!init) 8199dba64beSDimitry Andric return init.takeError(); 8209dba64beSDimitry Andric return init.get().GetArgInfo(); 8219dba64beSDimitry Andric } 822*0b57cec5SDimitry Andric 8239dba64beSDimitry Andric #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3 8249dba64beSDimitry Andric static const char get_arg_info_script[] = R"( 8259dba64beSDimitry Andric from inspect import signature, Parameter, ismethod 8269dba64beSDimitry Andric from collections import namedtuple 8279dba64beSDimitry Andric ArgInfo = namedtuple('ArgInfo', ['count', 'has_varargs', 'is_bound_method']) 8289dba64beSDimitry Andric def main(f): 8299dba64beSDimitry Andric count = 0 8309dba64beSDimitry Andric varargs = False 8319dba64beSDimitry Andric for parameter in signature(f).parameters.values(): 8329dba64beSDimitry Andric kind = parameter.kind 8339dba64beSDimitry Andric if kind in (Parameter.POSITIONAL_ONLY, 8349dba64beSDimitry Andric Parameter.POSITIONAL_OR_KEYWORD): 8359dba64beSDimitry Andric count += 1 8369dba64beSDimitry Andric elif kind == Parameter.VAR_POSITIONAL: 8379dba64beSDimitry Andric varargs = True 8389dba64beSDimitry Andric elif kind in (Parameter.KEYWORD_ONLY, 8399dba64beSDimitry Andric Parameter.VAR_KEYWORD): 8409dba64beSDimitry Andric pass 8419dba64beSDimitry Andric else: 8429dba64beSDimitry Andric raise Exception(f'unknown parameter kind: {kind}') 8439dba64beSDimitry Andric return ArgInfo(count, varargs, ismethod(f)) 8449dba64beSDimitry Andric )"; 8459dba64beSDimitry Andric #endif 8469dba64beSDimitry Andric 8479dba64beSDimitry Andric Expected<PythonCallable::ArgInfo> PythonCallable::GetArgInfo() const { 8489dba64beSDimitry Andric ArgInfo result = {}; 8499dba64beSDimitry Andric if (!IsValid()) 8509dba64beSDimitry Andric return nullDeref(); 8519dba64beSDimitry Andric 8529dba64beSDimitry Andric #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3 8539dba64beSDimitry Andric 8549dba64beSDimitry Andric // no need to synchronize access to this global, we already have the GIL 8559dba64beSDimitry Andric static PythonScript get_arg_info(get_arg_info_script); 8569dba64beSDimitry Andric Expected<PythonObject> pyarginfo = get_arg_info(*this); 8579dba64beSDimitry Andric if (!pyarginfo) 8589dba64beSDimitry Andric return pyarginfo.takeError(); 8599dba64beSDimitry Andric result.count = cantFail(As<long long>(pyarginfo.get().GetAttribute("count"))); 8609dba64beSDimitry Andric result.has_varargs = 8619dba64beSDimitry Andric cantFail(As<bool>(pyarginfo.get().GetAttribute("has_varargs"))); 8629dba64beSDimitry Andric bool is_method = 8639dba64beSDimitry Andric cantFail(As<bool>(pyarginfo.get().GetAttribute("is_bound_method"))); 8649dba64beSDimitry Andric result.max_positional_args = 8659dba64beSDimitry Andric result.has_varargs ? ArgInfo::UNBOUNDED : result.count; 8669dba64beSDimitry Andric 8679dba64beSDimitry Andric // FIXME emulate old broken behavior 8689dba64beSDimitry Andric if (is_method) 8699dba64beSDimitry Andric result.count++; 8709dba64beSDimitry Andric 8719dba64beSDimitry Andric #else 8729dba64beSDimitry Andric bool is_bound_method = false; 873*0b57cec5SDimitry Andric PyObject *py_func_obj = m_py_obj; 874*0b57cec5SDimitry Andric if (PyMethod_Check(py_func_obj)) { 875*0b57cec5SDimitry Andric py_func_obj = PyMethod_GET_FUNCTION(py_func_obj); 876*0b57cec5SDimitry Andric PythonObject im_self = GetAttributeValue("im_self"); 877*0b57cec5SDimitry Andric if (im_self.IsValid() && !im_self.IsNone()) 8789dba64beSDimitry Andric is_bound_method = true; 879*0b57cec5SDimitry Andric } else { 880*0b57cec5SDimitry Andric // see if this is a callable object with an __call__ method 881*0b57cec5SDimitry Andric if (!PyFunction_Check(py_func_obj)) { 882*0b57cec5SDimitry Andric PythonObject __call__ = GetAttributeValue("__call__"); 883*0b57cec5SDimitry Andric if (__call__.IsValid()) { 884*0b57cec5SDimitry Andric auto __callable__ = __call__.AsType<PythonCallable>(); 885*0b57cec5SDimitry Andric if (__callable__.IsValid()) { 886*0b57cec5SDimitry Andric py_func_obj = PyMethod_GET_FUNCTION(__callable__.get()); 8879dba64beSDimitry Andric PythonObject im_self = __callable__.GetAttributeValue("im_self"); 888*0b57cec5SDimitry Andric if (im_self.IsValid() && !im_self.IsNone()) 8899dba64beSDimitry Andric is_bound_method = true; 890*0b57cec5SDimitry Andric } 891*0b57cec5SDimitry Andric } 892*0b57cec5SDimitry Andric } 893*0b57cec5SDimitry Andric } 894*0b57cec5SDimitry Andric 895*0b57cec5SDimitry Andric if (!py_func_obj) 896*0b57cec5SDimitry Andric return result; 897*0b57cec5SDimitry Andric 898*0b57cec5SDimitry Andric PyCodeObject *code = (PyCodeObject *)PyFunction_GET_CODE(py_func_obj); 899*0b57cec5SDimitry Andric if (!code) 900*0b57cec5SDimitry Andric return result; 901*0b57cec5SDimitry Andric 902*0b57cec5SDimitry Andric result.count = code->co_argcount; 903*0b57cec5SDimitry Andric result.has_varargs = !!(code->co_flags & CO_VARARGS); 9049dba64beSDimitry Andric result.max_positional_args = result.has_varargs 9059dba64beSDimitry Andric ? ArgInfo::UNBOUNDED 9069dba64beSDimitry Andric : (result.count - (int)is_bound_method); 9079dba64beSDimitry Andric 9089dba64beSDimitry Andric #endif 9099dba64beSDimitry Andric 910*0b57cec5SDimitry Andric return result; 911*0b57cec5SDimitry Andric } 912*0b57cec5SDimitry Andric 9139dba64beSDimitry Andric constexpr unsigned 9149dba64beSDimitry Andric PythonCallable::ArgInfo::UNBOUNDED; // FIXME delete after c++17 9159dba64beSDimitry Andric 9169dba64beSDimitry Andric PythonCallable::ArgInfo PythonCallable::GetNumArguments() const { 9179dba64beSDimitry Andric auto arginfo = GetArgInfo(); 9189dba64beSDimitry Andric if (!arginfo) { 9199dba64beSDimitry Andric llvm::consumeError(arginfo.takeError()); 9209dba64beSDimitry Andric return ArgInfo{}; 9219dba64beSDimitry Andric } 9229dba64beSDimitry Andric return arginfo.get(); 9239dba64beSDimitry Andric } 9249dba64beSDimitry Andric 925*0b57cec5SDimitry Andric PythonObject PythonCallable::operator()() { 926*0b57cec5SDimitry Andric return PythonObject(PyRefType::Owned, PyObject_CallObject(m_py_obj, nullptr)); 927*0b57cec5SDimitry Andric } 928*0b57cec5SDimitry Andric 929*0b57cec5SDimitry Andric PythonObject PythonCallable:: 930*0b57cec5SDimitry Andric operator()(std::initializer_list<PyObject *> args) { 931*0b57cec5SDimitry Andric PythonTuple arg_tuple(args); 932*0b57cec5SDimitry Andric return PythonObject(PyRefType::Owned, 933*0b57cec5SDimitry Andric PyObject_CallObject(m_py_obj, arg_tuple.get())); 934*0b57cec5SDimitry Andric } 935*0b57cec5SDimitry Andric 936*0b57cec5SDimitry Andric PythonObject PythonCallable:: 937*0b57cec5SDimitry Andric operator()(std::initializer_list<PythonObject> args) { 938*0b57cec5SDimitry Andric PythonTuple arg_tuple(args); 939*0b57cec5SDimitry Andric return PythonObject(PyRefType::Owned, 940*0b57cec5SDimitry Andric PyObject_CallObject(m_py_obj, arg_tuple.get())); 941*0b57cec5SDimitry Andric } 942*0b57cec5SDimitry Andric 943*0b57cec5SDimitry Andric bool PythonFile::Check(PyObject *py_obj) { 9449dba64beSDimitry Andric if (!py_obj) 9459dba64beSDimitry Andric return false; 946*0b57cec5SDimitry Andric #if PY_MAJOR_VERSION < 3 947*0b57cec5SDimitry Andric return PyFile_Check(py_obj); 948*0b57cec5SDimitry Andric #else 949*0b57cec5SDimitry Andric // In Python 3, there is no `PyFile_Check`, and in fact PyFile is not even a 950*0b57cec5SDimitry Andric // first-class object type anymore. `PyFile_FromFd` is just a thin wrapper 951*0b57cec5SDimitry Andric // over `io.open()`, which returns some object derived from `io.IOBase`. As a 952*0b57cec5SDimitry Andric // result, the only way to detect a file in Python 3 is to check whether it 9539dba64beSDimitry Andric // inherits from `io.IOBase`. 9549dba64beSDimitry Andric auto io_module = PythonModule::Import("io"); 9559dba64beSDimitry Andric if (!io_module) { 9569dba64beSDimitry Andric llvm::consumeError(io_module.takeError()); 957*0b57cec5SDimitry Andric return false; 9589dba64beSDimitry Andric } 9599dba64beSDimitry Andric auto iobase = io_module.get().Get("IOBase"); 9609dba64beSDimitry Andric if (!iobase) { 9619dba64beSDimitry Andric llvm::consumeError(iobase.takeError()); 962*0b57cec5SDimitry Andric return false; 9639dba64beSDimitry Andric } 9649dba64beSDimitry Andric int r = PyObject_IsInstance(py_obj, iobase.get().get()); 9659dba64beSDimitry Andric if (r < 0) { 9669dba64beSDimitry Andric llvm::consumeError(exception()); // clear the exception and log it. 9679dba64beSDimitry Andric return false; 9689dba64beSDimitry Andric } 9699dba64beSDimitry Andric return !!r; 970*0b57cec5SDimitry Andric #endif 971*0b57cec5SDimitry Andric } 972*0b57cec5SDimitry Andric 9739dba64beSDimitry Andric namespace { 9749dba64beSDimitry Andric class GIL { 9759dba64beSDimitry Andric public: 9769dba64beSDimitry Andric GIL() { 9779dba64beSDimitry Andric m_state = PyGILState_Ensure(); 9789dba64beSDimitry Andric assert(!PyErr_Occurred()); 9799dba64beSDimitry Andric } 9809dba64beSDimitry Andric ~GIL() { PyGILState_Release(m_state); } 981*0b57cec5SDimitry Andric 9829dba64beSDimitry Andric protected: 9839dba64beSDimitry Andric PyGILState_STATE m_state; 9849dba64beSDimitry Andric }; 9859dba64beSDimitry Andric } // namespace 9869dba64beSDimitry Andric 9879dba64beSDimitry Andric const char *PythonException::toCString() const { 9889dba64beSDimitry Andric if (!m_repr_bytes) 9899dba64beSDimitry Andric return "unknown exception"; 9909dba64beSDimitry Andric return PyBytes_AS_STRING(m_repr_bytes); 991*0b57cec5SDimitry Andric } 992*0b57cec5SDimitry Andric 9939dba64beSDimitry Andric PythonException::PythonException(const char *caller) { 9949dba64beSDimitry Andric assert(PyErr_Occurred()); 9959dba64beSDimitry Andric m_exception_type = m_exception = m_traceback = m_repr_bytes = NULL; 9969dba64beSDimitry Andric PyErr_Fetch(&m_exception_type, &m_exception, &m_traceback); 9979dba64beSDimitry Andric PyErr_NormalizeException(&m_exception_type, &m_exception, &m_traceback); 9989dba64beSDimitry Andric PyErr_Clear(); 9999dba64beSDimitry Andric if (m_exception) { 10009dba64beSDimitry Andric PyObject *repr = PyObject_Repr(m_exception); 10019dba64beSDimitry Andric if (repr) { 10029dba64beSDimitry Andric m_repr_bytes = PyUnicode_AsEncodedString(repr, "utf-8", nullptr); 10039dba64beSDimitry Andric if (!m_repr_bytes) { 10049dba64beSDimitry Andric PyErr_Clear(); 10059dba64beSDimitry Andric } 10069dba64beSDimitry Andric Py_XDECREF(repr); 10079dba64beSDimitry Andric } else { 10089dba64beSDimitry Andric PyErr_Clear(); 10099dba64beSDimitry Andric } 10109dba64beSDimitry Andric } 10119dba64beSDimitry Andric Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT); 10129dba64beSDimitry Andric if (caller) 10139dba64beSDimitry Andric LLDB_LOGF(log, "%s failed with exception: %s", caller, toCString()); 10149dba64beSDimitry Andric else 10159dba64beSDimitry Andric LLDB_LOGF(log, "python exception: %s", toCString()); 10169dba64beSDimitry Andric } 10179dba64beSDimitry Andric void PythonException::Restore() { 10189dba64beSDimitry Andric if (m_exception_type && m_exception) { 10199dba64beSDimitry Andric PyErr_Restore(m_exception_type, m_exception, m_traceback); 10209dba64beSDimitry Andric } else { 10219dba64beSDimitry Andric PyErr_SetString(PyExc_Exception, toCString()); 10229dba64beSDimitry Andric } 10239dba64beSDimitry Andric m_exception_type = m_exception = m_traceback = NULL; 1024*0b57cec5SDimitry Andric } 1025*0b57cec5SDimitry Andric 10269dba64beSDimitry Andric PythonException::~PythonException() { 10279dba64beSDimitry Andric Py_XDECREF(m_exception_type); 10289dba64beSDimitry Andric Py_XDECREF(m_exception); 10299dba64beSDimitry Andric Py_XDECREF(m_traceback); 10309dba64beSDimitry Andric Py_XDECREF(m_repr_bytes); 1031*0b57cec5SDimitry Andric } 1032*0b57cec5SDimitry Andric 10339dba64beSDimitry Andric void PythonException::log(llvm::raw_ostream &OS) const { OS << toCString(); } 10349dba64beSDimitry Andric 10359dba64beSDimitry Andric std::error_code PythonException::convertToErrorCode() const { 10369dba64beSDimitry Andric return llvm::inconvertibleErrorCode(); 10379dba64beSDimitry Andric } 10389dba64beSDimitry Andric 10399dba64beSDimitry Andric bool PythonException::Matches(PyObject *exc) const { 10409dba64beSDimitry Andric return PyErr_GivenExceptionMatches(m_exception_type, exc); 10419dba64beSDimitry Andric } 10429dba64beSDimitry Andric 10439dba64beSDimitry Andric const char read_exception_script[] = R"( 10449dba64beSDimitry Andric import sys 10459dba64beSDimitry Andric from traceback import print_exception 10469dba64beSDimitry Andric if sys.version_info.major < 3: 10479dba64beSDimitry Andric from StringIO import StringIO 10489dba64beSDimitry Andric else: 10499dba64beSDimitry Andric from io import StringIO 10509dba64beSDimitry Andric def main(exc_type, exc_value, tb): 10519dba64beSDimitry Andric f = StringIO() 10529dba64beSDimitry Andric print_exception(exc_type, exc_value, tb, file=f) 10539dba64beSDimitry Andric return f.getvalue() 10549dba64beSDimitry Andric )"; 10559dba64beSDimitry Andric 10569dba64beSDimitry Andric std::string PythonException::ReadBacktrace() const { 10579dba64beSDimitry Andric 10589dba64beSDimitry Andric if (!m_traceback) 10599dba64beSDimitry Andric return toCString(); 10609dba64beSDimitry Andric 10619dba64beSDimitry Andric // no need to synchronize access to this global, we already have the GIL 10629dba64beSDimitry Andric static PythonScript read_exception(read_exception_script); 10639dba64beSDimitry Andric 10649dba64beSDimitry Andric Expected<std::string> backtrace = As<std::string>( 10659dba64beSDimitry Andric read_exception(m_exception_type, m_exception, m_traceback)); 10669dba64beSDimitry Andric 10679dba64beSDimitry Andric if (!backtrace) { 10689dba64beSDimitry Andric std::string message = 10699dba64beSDimitry Andric std::string(toCString()) + "\n" + 10709dba64beSDimitry Andric "Traceback unavailble, an error occurred while reading it:\n"; 10719dba64beSDimitry Andric return (message + llvm::toString(backtrace.takeError())); 10729dba64beSDimitry Andric } 10739dba64beSDimitry Andric 10749dba64beSDimitry Andric return std::move(backtrace.get()); 10759dba64beSDimitry Andric } 10769dba64beSDimitry Andric 10779dba64beSDimitry Andric char PythonException::ID = 0; 10789dba64beSDimitry Andric 10799dba64beSDimitry Andric llvm::Expected<File::OpenOptions> 10809dba64beSDimitry Andric GetOptionsForPyObject(const PythonObject &obj) { 1081*0b57cec5SDimitry Andric #if PY_MAJOR_VERSION >= 3 10829dba64beSDimitry Andric auto options = File::OpenOptions(0); 10839dba64beSDimitry Andric auto readable = As<bool>(obj.CallMethod("readable")); 10849dba64beSDimitry Andric if (!readable) 10859dba64beSDimitry Andric return readable.takeError(); 10869dba64beSDimitry Andric auto writable = As<bool>(obj.CallMethod("writable")); 10879dba64beSDimitry Andric if (!writable) 10889dba64beSDimitry Andric return writable.takeError(); 10899dba64beSDimitry Andric if (readable.get()) 10909dba64beSDimitry Andric options |= File::eOpenOptionRead; 10919dba64beSDimitry Andric if (writable.get()) 10929dba64beSDimitry Andric options |= File::eOpenOptionWrite; 10939dba64beSDimitry Andric return options; 10949dba64beSDimitry Andric #else 10959dba64beSDimitry Andric PythonString py_mode = obj.GetAttributeValue("mode").AsType<PythonString>(); 10969dba64beSDimitry Andric return File::GetOptionsFromMode(py_mode.GetString()); 10979dba64beSDimitry Andric #endif 10989dba64beSDimitry Andric } 10999dba64beSDimitry Andric 11009dba64beSDimitry Andric // Base class template for python files. All it knows how to do 11019dba64beSDimitry Andric // is hold a reference to the python object and close or flush it 11029dba64beSDimitry Andric // when the File is closed. 11039dba64beSDimitry Andric namespace { 11049dba64beSDimitry Andric template <typename Base> class OwnedPythonFile : public Base { 11059dba64beSDimitry Andric public: 11069dba64beSDimitry Andric template <typename... Args> 11079dba64beSDimitry Andric OwnedPythonFile(const PythonFile &file, bool borrowed, Args... args) 11089dba64beSDimitry Andric : Base(args...), m_py_obj(file), m_borrowed(borrowed) { 11099dba64beSDimitry Andric assert(m_py_obj); 11109dba64beSDimitry Andric } 11119dba64beSDimitry Andric 11129dba64beSDimitry Andric ~OwnedPythonFile() override { 11139dba64beSDimitry Andric assert(m_py_obj); 11149dba64beSDimitry Andric GIL takeGIL; 11159dba64beSDimitry Andric Close(); 11169dba64beSDimitry Andric // we need to ensure the python object is released while we still 11179dba64beSDimitry Andric // hold the GIL 11189dba64beSDimitry Andric m_py_obj.Reset(); 11199dba64beSDimitry Andric } 11209dba64beSDimitry Andric 11219dba64beSDimitry Andric bool IsPythonSideValid() const { 11229dba64beSDimitry Andric GIL takeGIL; 11239dba64beSDimitry Andric auto closed = As<bool>(m_py_obj.GetAttribute("closed")); 11249dba64beSDimitry Andric if (!closed) { 11259dba64beSDimitry Andric llvm::consumeError(closed.takeError()); 11269dba64beSDimitry Andric return false; 11279dba64beSDimitry Andric } 11289dba64beSDimitry Andric return !closed.get(); 11299dba64beSDimitry Andric } 11309dba64beSDimitry Andric 11319dba64beSDimitry Andric bool IsValid() const override { 11329dba64beSDimitry Andric return IsPythonSideValid() && Base::IsValid(); 11339dba64beSDimitry Andric } 11349dba64beSDimitry Andric 11359dba64beSDimitry Andric Status Close() override { 11369dba64beSDimitry Andric assert(m_py_obj); 11379dba64beSDimitry Andric Status py_error, base_error; 11389dba64beSDimitry Andric GIL takeGIL; 11399dba64beSDimitry Andric if (!m_borrowed) { 11409dba64beSDimitry Andric auto r = m_py_obj.CallMethod("close"); 11419dba64beSDimitry Andric if (!r) 11429dba64beSDimitry Andric py_error = Status(r.takeError()); 11439dba64beSDimitry Andric } 11449dba64beSDimitry Andric base_error = Base::Close(); 11459dba64beSDimitry Andric if (py_error.Fail()) 11469dba64beSDimitry Andric return py_error; 11479dba64beSDimitry Andric return base_error; 11489dba64beSDimitry Andric }; 11499dba64beSDimitry Andric 11509dba64beSDimitry Andric PyObject *GetPythonObject() const { 11519dba64beSDimitry Andric assert(m_py_obj.IsValid()); 11529dba64beSDimitry Andric return m_py_obj.get(); 11539dba64beSDimitry Andric } 11549dba64beSDimitry Andric 11559dba64beSDimitry Andric static bool classof(const File *file) = delete; 11569dba64beSDimitry Andric 11579dba64beSDimitry Andric protected: 11589dba64beSDimitry Andric PythonFile m_py_obj; 11599dba64beSDimitry Andric bool m_borrowed; 11609dba64beSDimitry Andric }; 11619dba64beSDimitry Andric } // namespace 11629dba64beSDimitry Andric 11639dba64beSDimitry Andric // A SimplePythonFile is a OwnedPythonFile that just does all I/O as 11649dba64beSDimitry Andric // a NativeFile 11659dba64beSDimitry Andric namespace { 11669dba64beSDimitry Andric class SimplePythonFile : public OwnedPythonFile<NativeFile> { 11679dba64beSDimitry Andric public: 11689dba64beSDimitry Andric SimplePythonFile(const PythonFile &file, bool borrowed, int fd, 11699dba64beSDimitry Andric File::OpenOptions options) 11709dba64beSDimitry Andric : OwnedPythonFile(file, borrowed, fd, options, false) {} 11719dba64beSDimitry Andric 11729dba64beSDimitry Andric static char ID; 11739dba64beSDimitry Andric bool isA(const void *classID) const override { 11749dba64beSDimitry Andric return classID == &ID || NativeFile::isA(classID); 11759dba64beSDimitry Andric } 11769dba64beSDimitry Andric static bool classof(const File *file) { return file->isA(&ID); } 11779dba64beSDimitry Andric }; 11789dba64beSDimitry Andric char SimplePythonFile::ID = 0; 11799dba64beSDimitry Andric } // namespace 11809dba64beSDimitry Andric 11819dba64beSDimitry Andric #if PY_MAJOR_VERSION >= 3 11829dba64beSDimitry Andric 11839dba64beSDimitry Andric namespace { 11849dba64beSDimitry Andric class PythonBuffer { 11859dba64beSDimitry Andric public: 11869dba64beSDimitry Andric PythonBuffer &operator=(const PythonBuffer &) = delete; 11879dba64beSDimitry Andric PythonBuffer(const PythonBuffer &) = delete; 11889dba64beSDimitry Andric 11899dba64beSDimitry Andric static Expected<PythonBuffer> Create(PythonObject &obj, 11909dba64beSDimitry Andric int flags = PyBUF_SIMPLE) { 11919dba64beSDimitry Andric Py_buffer py_buffer = {}; 11929dba64beSDimitry Andric PyObject_GetBuffer(obj.get(), &py_buffer, flags); 11939dba64beSDimitry Andric if (!py_buffer.obj) 11949dba64beSDimitry Andric return llvm::make_error<PythonException>(); 11959dba64beSDimitry Andric return PythonBuffer(py_buffer); 11969dba64beSDimitry Andric } 11979dba64beSDimitry Andric 11989dba64beSDimitry Andric PythonBuffer(PythonBuffer &&other) { 11999dba64beSDimitry Andric m_buffer = other.m_buffer; 12009dba64beSDimitry Andric other.m_buffer.obj = nullptr; 12019dba64beSDimitry Andric } 12029dba64beSDimitry Andric 12039dba64beSDimitry Andric ~PythonBuffer() { 12049dba64beSDimitry Andric if (m_buffer.obj) 12059dba64beSDimitry Andric PyBuffer_Release(&m_buffer); 12069dba64beSDimitry Andric } 12079dba64beSDimitry Andric 12089dba64beSDimitry Andric Py_buffer &get() { return m_buffer; } 12099dba64beSDimitry Andric 12109dba64beSDimitry Andric private: 12119dba64beSDimitry Andric // takes ownership of the buffer. 12129dba64beSDimitry Andric PythonBuffer(const Py_buffer &py_buffer) : m_buffer(py_buffer) {} 12139dba64beSDimitry Andric Py_buffer m_buffer; 12149dba64beSDimitry Andric }; 12159dba64beSDimitry Andric } // namespace 12169dba64beSDimitry Andric 12179dba64beSDimitry Andric // Shared methods between TextPythonFile and BinaryPythonFile 12189dba64beSDimitry Andric namespace { 12199dba64beSDimitry Andric class PythonIOFile : public OwnedPythonFile<File> { 12209dba64beSDimitry Andric public: 12219dba64beSDimitry Andric PythonIOFile(const PythonFile &file, bool borrowed) 12229dba64beSDimitry Andric : OwnedPythonFile(file, borrowed) {} 12239dba64beSDimitry Andric 12249dba64beSDimitry Andric ~PythonIOFile() override { Close(); } 12259dba64beSDimitry Andric 12269dba64beSDimitry Andric bool IsValid() const override { return IsPythonSideValid(); } 12279dba64beSDimitry Andric 12289dba64beSDimitry Andric Status Close() override { 12299dba64beSDimitry Andric assert(m_py_obj); 12309dba64beSDimitry Andric GIL takeGIL; 12319dba64beSDimitry Andric if (m_borrowed) 12329dba64beSDimitry Andric return Flush(); 12339dba64beSDimitry Andric auto r = m_py_obj.CallMethod("close"); 12349dba64beSDimitry Andric if (!r) 12359dba64beSDimitry Andric return Status(r.takeError()); 12369dba64beSDimitry Andric return Status(); 12379dba64beSDimitry Andric } 12389dba64beSDimitry Andric 12399dba64beSDimitry Andric Status Flush() override { 12409dba64beSDimitry Andric GIL takeGIL; 12419dba64beSDimitry Andric auto r = m_py_obj.CallMethod("flush"); 12429dba64beSDimitry Andric if (!r) 12439dba64beSDimitry Andric return Status(r.takeError()); 12449dba64beSDimitry Andric return Status(); 12459dba64beSDimitry Andric } 12469dba64beSDimitry Andric 12479dba64beSDimitry Andric Expected<File::OpenOptions> GetOptions() const override { 12489dba64beSDimitry Andric GIL takeGIL; 12499dba64beSDimitry Andric return GetOptionsForPyObject(m_py_obj); 12509dba64beSDimitry Andric } 12519dba64beSDimitry Andric 12529dba64beSDimitry Andric static char ID; 12539dba64beSDimitry Andric bool isA(const void *classID) const override { 12549dba64beSDimitry Andric return classID == &ID || File::isA(classID); 12559dba64beSDimitry Andric } 12569dba64beSDimitry Andric static bool classof(const File *file) { return file->isA(&ID); } 12579dba64beSDimitry Andric }; 12589dba64beSDimitry Andric char PythonIOFile::ID = 0; 12599dba64beSDimitry Andric } // namespace 12609dba64beSDimitry Andric 12619dba64beSDimitry Andric namespace { 12629dba64beSDimitry Andric class BinaryPythonFile : public PythonIOFile { 12639dba64beSDimitry Andric protected: 12649dba64beSDimitry Andric int m_descriptor; 12659dba64beSDimitry Andric 12669dba64beSDimitry Andric public: 12679dba64beSDimitry Andric BinaryPythonFile(int fd, const PythonFile &file, bool borrowed) 12689dba64beSDimitry Andric : PythonIOFile(file, borrowed), 12699dba64beSDimitry Andric m_descriptor(File::DescriptorIsValid(fd) ? fd 12709dba64beSDimitry Andric : File::kInvalidDescriptor) {} 12719dba64beSDimitry Andric 12729dba64beSDimitry Andric int GetDescriptor() const override { return m_descriptor; } 12739dba64beSDimitry Andric 12749dba64beSDimitry Andric Status Write(const void *buf, size_t &num_bytes) override { 12759dba64beSDimitry Andric GIL takeGIL; 12769dba64beSDimitry Andric PyObject *pybuffer_p = PyMemoryView_FromMemory( 12779dba64beSDimitry Andric const_cast<char *>((const char *)buf), num_bytes, PyBUF_READ); 12789dba64beSDimitry Andric if (!pybuffer_p) 12799dba64beSDimitry Andric return Status(llvm::make_error<PythonException>()); 12809dba64beSDimitry Andric auto pybuffer = Take<PythonObject>(pybuffer_p); 12819dba64beSDimitry Andric num_bytes = 0; 12829dba64beSDimitry Andric auto bytes_written = As<long long>(m_py_obj.CallMethod("write", pybuffer)); 12839dba64beSDimitry Andric if (!bytes_written) 12849dba64beSDimitry Andric return Status(bytes_written.takeError()); 12859dba64beSDimitry Andric if (bytes_written.get() < 0) 12869dba64beSDimitry Andric return Status(".write() method returned a negative number!"); 12879dba64beSDimitry Andric static_assert(sizeof(long long) >= sizeof(size_t), "overflow"); 12889dba64beSDimitry Andric num_bytes = bytes_written.get(); 12899dba64beSDimitry Andric return Status(); 12909dba64beSDimitry Andric } 12919dba64beSDimitry Andric 12929dba64beSDimitry Andric Status Read(void *buf, size_t &num_bytes) override { 12939dba64beSDimitry Andric GIL takeGIL; 12949dba64beSDimitry Andric static_assert(sizeof(long long) >= sizeof(size_t), "overflow"); 12959dba64beSDimitry Andric auto pybuffer_obj = 12969dba64beSDimitry Andric m_py_obj.CallMethod("read", (unsigned long long)num_bytes); 12979dba64beSDimitry Andric if (!pybuffer_obj) 12989dba64beSDimitry Andric return Status(pybuffer_obj.takeError()); 12999dba64beSDimitry Andric num_bytes = 0; 13009dba64beSDimitry Andric if (pybuffer_obj.get().IsNone()) { 13019dba64beSDimitry Andric // EOF 13029dba64beSDimitry Andric num_bytes = 0; 13039dba64beSDimitry Andric return Status(); 13049dba64beSDimitry Andric } 13059dba64beSDimitry Andric auto pybuffer = PythonBuffer::Create(pybuffer_obj.get()); 13069dba64beSDimitry Andric if (!pybuffer) 13079dba64beSDimitry Andric return Status(pybuffer.takeError()); 13089dba64beSDimitry Andric memcpy(buf, pybuffer.get().get().buf, pybuffer.get().get().len); 13099dba64beSDimitry Andric num_bytes = pybuffer.get().get().len; 13109dba64beSDimitry Andric return Status(); 13119dba64beSDimitry Andric } 13129dba64beSDimitry Andric }; 13139dba64beSDimitry Andric } // namespace 13149dba64beSDimitry Andric 13159dba64beSDimitry Andric namespace { 13169dba64beSDimitry Andric class TextPythonFile : public PythonIOFile { 13179dba64beSDimitry Andric protected: 13189dba64beSDimitry Andric int m_descriptor; 13199dba64beSDimitry Andric 13209dba64beSDimitry Andric public: 13219dba64beSDimitry Andric TextPythonFile(int fd, const PythonFile &file, bool borrowed) 13229dba64beSDimitry Andric : PythonIOFile(file, borrowed), 13239dba64beSDimitry Andric m_descriptor(File::DescriptorIsValid(fd) ? fd 13249dba64beSDimitry Andric : File::kInvalidDescriptor) {} 13259dba64beSDimitry Andric 13269dba64beSDimitry Andric int GetDescriptor() const override { return m_descriptor; } 13279dba64beSDimitry Andric 13289dba64beSDimitry Andric Status Write(const void *buf, size_t &num_bytes) override { 13299dba64beSDimitry Andric GIL takeGIL; 13309dba64beSDimitry Andric auto pystring = 13319dba64beSDimitry Andric PythonString::FromUTF8(llvm::StringRef((const char *)buf, num_bytes)); 13329dba64beSDimitry Andric if (!pystring) 13339dba64beSDimitry Andric return Status(pystring.takeError()); 13349dba64beSDimitry Andric num_bytes = 0; 13359dba64beSDimitry Andric auto bytes_written = 13369dba64beSDimitry Andric As<long long>(m_py_obj.CallMethod("write", pystring.get())); 13379dba64beSDimitry Andric if (!bytes_written) 13389dba64beSDimitry Andric return Status(bytes_written.takeError()); 13399dba64beSDimitry Andric if (bytes_written.get() < 0) 13409dba64beSDimitry Andric return Status(".write() method returned a negative number!"); 13419dba64beSDimitry Andric static_assert(sizeof(long long) >= sizeof(size_t), "overflow"); 13429dba64beSDimitry Andric num_bytes = bytes_written.get(); 13439dba64beSDimitry Andric return Status(); 13449dba64beSDimitry Andric } 13459dba64beSDimitry Andric 13469dba64beSDimitry Andric Status Read(void *buf, size_t &num_bytes) override { 13479dba64beSDimitry Andric GIL takeGIL; 13489dba64beSDimitry Andric size_t num_chars = num_bytes / 6; 13499dba64beSDimitry Andric size_t orig_num_bytes = num_bytes; 13509dba64beSDimitry Andric num_bytes = 0; 13519dba64beSDimitry Andric if (orig_num_bytes < 6) { 13529dba64beSDimitry Andric return Status("can't read less than 6 bytes from a utf8 text stream"); 13539dba64beSDimitry Andric } 13549dba64beSDimitry Andric auto pystring = As<PythonString>( 13559dba64beSDimitry Andric m_py_obj.CallMethod("read", (unsigned long long)num_chars)); 13569dba64beSDimitry Andric if (!pystring) 13579dba64beSDimitry Andric return Status(pystring.takeError()); 13589dba64beSDimitry Andric if (pystring.get().IsNone()) { 13599dba64beSDimitry Andric // EOF 13609dba64beSDimitry Andric return Status(); 13619dba64beSDimitry Andric } 13629dba64beSDimitry Andric auto stringref = pystring.get().AsUTF8(); 13639dba64beSDimitry Andric if (!stringref) 13649dba64beSDimitry Andric return Status(stringref.takeError()); 13659dba64beSDimitry Andric num_bytes = stringref.get().size(); 13669dba64beSDimitry Andric memcpy(buf, stringref.get().begin(), num_bytes); 13679dba64beSDimitry Andric return Status(); 13689dba64beSDimitry Andric } 13699dba64beSDimitry Andric }; 13709dba64beSDimitry Andric } // namespace 13719dba64beSDimitry Andric 13729dba64beSDimitry Andric #endif 13739dba64beSDimitry Andric 13749dba64beSDimitry Andric llvm::Expected<FileSP> PythonFile::ConvertToFile(bool borrowed) { 13759dba64beSDimitry Andric if (!IsValid()) 13769dba64beSDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(), 13779dba64beSDimitry Andric "invalid PythonFile"); 13789dba64beSDimitry Andric 13799dba64beSDimitry Andric int fd = PyObject_AsFileDescriptor(m_py_obj); 13809dba64beSDimitry Andric if (fd < 0) { 13819dba64beSDimitry Andric PyErr_Clear(); 13829dba64beSDimitry Andric return ConvertToFileForcingUseOfScriptingIOMethods(borrowed); 13839dba64beSDimitry Andric } 13849dba64beSDimitry Andric auto options = GetOptionsForPyObject(*this); 13859dba64beSDimitry Andric if (!options) 13869dba64beSDimitry Andric return options.takeError(); 13879dba64beSDimitry Andric 13889dba64beSDimitry Andric // LLDB and python will not share I/O buffers. We should probably 13899dba64beSDimitry Andric // flush the python buffers now. 13909dba64beSDimitry Andric auto r = CallMethod("flush"); 13919dba64beSDimitry Andric if (!r) 13929dba64beSDimitry Andric return r.takeError(); 13939dba64beSDimitry Andric 13949dba64beSDimitry Andric FileSP file_sp; 13959dba64beSDimitry Andric if (borrowed) { 13969dba64beSDimitry Andric // In this case we we don't need to retain the python 13979dba64beSDimitry Andric // object at all. 13989dba64beSDimitry Andric file_sp = std::make_shared<NativeFile>(fd, options.get(), false); 13999dba64beSDimitry Andric } else { 14009dba64beSDimitry Andric file_sp = std::static_pointer_cast<File>( 14019dba64beSDimitry Andric std::make_shared<SimplePythonFile>(*this, borrowed, fd, options.get())); 14029dba64beSDimitry Andric } 14039dba64beSDimitry Andric if (!file_sp->IsValid()) 14049dba64beSDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(), 14059dba64beSDimitry Andric "invalid File"); 14069dba64beSDimitry Andric 14079dba64beSDimitry Andric return file_sp; 14089dba64beSDimitry Andric } 14099dba64beSDimitry Andric 14109dba64beSDimitry Andric llvm::Expected<FileSP> 14119dba64beSDimitry Andric PythonFile::ConvertToFileForcingUseOfScriptingIOMethods(bool borrowed) { 14129dba64beSDimitry Andric 14139dba64beSDimitry Andric assert(!PyErr_Occurred()); 14149dba64beSDimitry Andric 14159dba64beSDimitry Andric if (!IsValid()) 14169dba64beSDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(), 14179dba64beSDimitry Andric "invalid PythonFile"); 14189dba64beSDimitry Andric 14199dba64beSDimitry Andric #if PY_MAJOR_VERSION < 3 14209dba64beSDimitry Andric 14219dba64beSDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(), 14229dba64beSDimitry Andric "not supported on python 2"); 14239dba64beSDimitry Andric 14249dba64beSDimitry Andric #else 14259dba64beSDimitry Andric 14269dba64beSDimitry Andric int fd = PyObject_AsFileDescriptor(m_py_obj); 14279dba64beSDimitry Andric if (fd < 0) { 14289dba64beSDimitry Andric PyErr_Clear(); 14299dba64beSDimitry Andric fd = File::kInvalidDescriptor; 14309dba64beSDimitry Andric } 14319dba64beSDimitry Andric 14329dba64beSDimitry Andric auto io_module = PythonModule::Import("io"); 14339dba64beSDimitry Andric if (!io_module) 14349dba64beSDimitry Andric return io_module.takeError(); 14359dba64beSDimitry Andric auto textIOBase = io_module.get().Get("TextIOBase"); 14369dba64beSDimitry Andric if (!textIOBase) 14379dba64beSDimitry Andric return textIOBase.takeError(); 14389dba64beSDimitry Andric auto rawIOBase = io_module.get().Get("RawIOBase"); 14399dba64beSDimitry Andric if (!rawIOBase) 14409dba64beSDimitry Andric return rawIOBase.takeError(); 14419dba64beSDimitry Andric auto bufferedIOBase = io_module.get().Get("BufferedIOBase"); 14429dba64beSDimitry Andric if (!bufferedIOBase) 14439dba64beSDimitry Andric return bufferedIOBase.takeError(); 14449dba64beSDimitry Andric 14459dba64beSDimitry Andric FileSP file_sp; 14469dba64beSDimitry Andric 14479dba64beSDimitry Andric auto isTextIO = IsInstance(textIOBase.get()); 14489dba64beSDimitry Andric if (!isTextIO) 14499dba64beSDimitry Andric return isTextIO.takeError(); 14509dba64beSDimitry Andric if (isTextIO.get()) 14519dba64beSDimitry Andric file_sp = std::static_pointer_cast<File>( 14529dba64beSDimitry Andric std::make_shared<TextPythonFile>(fd, *this, borrowed)); 14539dba64beSDimitry Andric 14549dba64beSDimitry Andric auto isRawIO = IsInstance(rawIOBase.get()); 14559dba64beSDimitry Andric if (!isRawIO) 14569dba64beSDimitry Andric return isRawIO.takeError(); 14579dba64beSDimitry Andric auto isBufferedIO = IsInstance(bufferedIOBase.get()); 14589dba64beSDimitry Andric if (!isBufferedIO) 14599dba64beSDimitry Andric return isBufferedIO.takeError(); 14609dba64beSDimitry Andric 14619dba64beSDimitry Andric if (isRawIO.get() || isBufferedIO.get()) { 14629dba64beSDimitry Andric file_sp = std::static_pointer_cast<File>( 14639dba64beSDimitry Andric std::make_shared<BinaryPythonFile>(fd, *this, borrowed)); 14649dba64beSDimitry Andric } 14659dba64beSDimitry Andric 14669dba64beSDimitry Andric if (!file_sp) 14679dba64beSDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(), 14689dba64beSDimitry Andric "python file is neither text nor binary"); 14699dba64beSDimitry Andric 14709dba64beSDimitry Andric if (!file_sp->IsValid()) 14719dba64beSDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(), 14729dba64beSDimitry Andric "invalid File"); 14739dba64beSDimitry Andric 14749dba64beSDimitry Andric return file_sp; 14759dba64beSDimitry Andric 14769dba64beSDimitry Andric #endif 14779dba64beSDimitry Andric } 14789dba64beSDimitry Andric 14799dba64beSDimitry Andric Expected<PythonFile> PythonFile::FromFile(File &file, const char *mode) { 14809dba64beSDimitry Andric if (!file.IsValid()) 14819dba64beSDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(), 14829dba64beSDimitry Andric "invalid file"); 14839dba64beSDimitry Andric 14849dba64beSDimitry Andric if (auto *simple = llvm::dyn_cast<SimplePythonFile>(&file)) 14859dba64beSDimitry Andric return Retain<PythonFile>(simple->GetPythonObject()); 14869dba64beSDimitry Andric #if PY_MAJOR_VERSION >= 3 14879dba64beSDimitry Andric if (auto *pythonio = llvm::dyn_cast<PythonIOFile>(&file)) 14889dba64beSDimitry Andric return Retain<PythonFile>(pythonio->GetPythonObject()); 14899dba64beSDimitry Andric #endif 14909dba64beSDimitry Andric 14919dba64beSDimitry Andric if (!mode) { 14929dba64beSDimitry Andric auto m = file.GetOpenMode(); 14939dba64beSDimitry Andric if (!m) 14949dba64beSDimitry Andric return m.takeError(); 14959dba64beSDimitry Andric mode = m.get(); 14969dba64beSDimitry Andric } 14979dba64beSDimitry Andric 14989dba64beSDimitry Andric PyObject *file_obj; 14999dba64beSDimitry Andric #if PY_MAJOR_VERSION >= 3 15009dba64beSDimitry Andric file_obj = PyFile_FromFd(file.GetDescriptor(), nullptr, mode, -1, nullptr, 15019dba64beSDimitry Andric "ignore", nullptr, 0); 1502*0b57cec5SDimitry Andric #else 1503*0b57cec5SDimitry Andric // Read through the Python source, doesn't seem to modify these strings 15049dba64beSDimitry Andric char *cmode = const_cast<char *>(mode); 15059dba64beSDimitry Andric // We pass ::flush instead of ::fclose here so we borrow the FILE* -- 15069dba64beSDimitry Andric // the lldb_private::File still owns it. 15079dba64beSDimitry Andric file_obj = 15089dba64beSDimitry Andric PyFile_FromFile(file.GetStream(), const_cast<char *>(""), cmode, ::fflush); 1509*0b57cec5SDimitry Andric #endif 15109dba64beSDimitry Andric 15119dba64beSDimitry Andric if (!file_obj) 15129dba64beSDimitry Andric return exception(); 15139dba64beSDimitry Andric 15149dba64beSDimitry Andric return Take<PythonFile>(file_obj); 1515*0b57cec5SDimitry Andric } 1516*0b57cec5SDimitry Andric 15179dba64beSDimitry Andric Error PythonScript::Init() { 15189dba64beSDimitry Andric if (function.IsValid()) 15199dba64beSDimitry Andric return Error::success(); 1520*0b57cec5SDimitry Andric 15219dba64beSDimitry Andric PythonDictionary globals(PyInitialValue::Empty); 15229dba64beSDimitry Andric auto builtins = PythonModule::BuiltinsModule(); 15239dba64beSDimitry Andric if (Error error = globals.SetItem("__builtins__", builtins)) 15249dba64beSDimitry Andric return error; 15259dba64beSDimitry Andric PyObject *o = 15269dba64beSDimitry Andric PyRun_String(script, Py_file_input, globals.get(), globals.get()); 15279dba64beSDimitry Andric if (!o) 15289dba64beSDimitry Andric return exception(); 15299dba64beSDimitry Andric Take<PythonObject>(o); 15309dba64beSDimitry Andric auto f = As<PythonCallable>(globals.GetItem("main")); 15319dba64beSDimitry Andric if (!f) 15329dba64beSDimitry Andric return f.takeError(); 15339dba64beSDimitry Andric function = std::move(f.get()); 15349dba64beSDimitry Andric 15359dba64beSDimitry Andric return Error::success(); 1536*0b57cec5SDimitry Andric } 1537*0b57cec5SDimitry Andric 15389dba64beSDimitry Andric llvm::Expected<PythonObject> 15399dba64beSDimitry Andric python::runStringOneLine(const llvm::Twine &string, 15409dba64beSDimitry Andric const PythonDictionary &globals, 15419dba64beSDimitry Andric const PythonDictionary &locals) { 15429dba64beSDimitry Andric if (!globals.IsValid() || !locals.IsValid()) 15439dba64beSDimitry Andric return nullDeref(); 1544*0b57cec5SDimitry Andric 15459dba64beSDimitry Andric PyObject *code = 15469dba64beSDimitry Andric Py_CompileString(NullTerminated(string), "<string>", Py_eval_input); 15479dba64beSDimitry Andric if (!code) { 15489dba64beSDimitry Andric PyErr_Clear(); 15499dba64beSDimitry Andric code = 15509dba64beSDimitry Andric Py_CompileString(NullTerminated(string), "<string>", Py_single_input); 15519dba64beSDimitry Andric } 15529dba64beSDimitry Andric if (!code) 15539dba64beSDimitry Andric return exception(); 15549dba64beSDimitry Andric auto code_ref = Take<PythonObject>(code); 15559dba64beSDimitry Andric 15569dba64beSDimitry Andric #if PY_MAJOR_VERSION < 3 15579dba64beSDimitry Andric PyObject *result = 15589dba64beSDimitry Andric PyEval_EvalCode((PyCodeObject *)code, globals.get(), locals.get()); 15599dba64beSDimitry Andric #else 15609dba64beSDimitry Andric PyObject *result = PyEval_EvalCode(code, globals.get(), locals.get()); 15619dba64beSDimitry Andric #endif 15629dba64beSDimitry Andric 15639dba64beSDimitry Andric if (!result) 15649dba64beSDimitry Andric return exception(); 15659dba64beSDimitry Andric 15669dba64beSDimitry Andric return Take<PythonObject>(result); 15679dba64beSDimitry Andric } 15689dba64beSDimitry Andric 15699dba64beSDimitry Andric llvm::Expected<PythonObject> 15709dba64beSDimitry Andric python::runStringMultiLine(const llvm::Twine &string, 15719dba64beSDimitry Andric const PythonDictionary &globals, 15729dba64beSDimitry Andric const PythonDictionary &locals) { 15739dba64beSDimitry Andric if (!globals.IsValid() || !locals.IsValid()) 15749dba64beSDimitry Andric return nullDeref(); 15759dba64beSDimitry Andric PyObject *result = PyRun_String(NullTerminated(string), Py_file_input, 15769dba64beSDimitry Andric globals.get(), locals.get()); 15779dba64beSDimitry Andric if (!result) 15789dba64beSDimitry Andric return exception(); 15799dba64beSDimitry Andric return Take<PythonObject>(result); 1580*0b57cec5SDimitry Andric } 1581*0b57cec5SDimitry Andric 1582*0b57cec5SDimitry Andric #endif 1583