/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===-- PythonDataObjects.cpp ---------------------------------------------===// |
2 | | // |
3 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | | // See https://llvm.org/LICENSE.txt for license information. |
5 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | |
9 | | #include "lldb/Host/Config.h" |
10 | | |
11 | | #if LLDB_ENABLE_PYTHON |
12 | | |
13 | | #include "PythonDataObjects.h" |
14 | | #include "ScriptInterpreterPython.h" |
15 | | |
16 | | #include "lldb/Host/File.h" |
17 | | #include "lldb/Host/FileSystem.h" |
18 | | #include "lldb/Interpreter/ScriptInterpreter.h" |
19 | | #include "lldb/Utility/LLDBLog.h" |
20 | | #include "lldb/Utility/Log.h" |
21 | | #include "lldb/Utility/Stream.h" |
22 | | |
23 | | #include "llvm/Support/Casting.h" |
24 | | #include "llvm/Support/ConvertUTF.h" |
25 | | #include "llvm/Support/Errno.h" |
26 | | |
27 | | #include <cstdio> |
28 | | #include <variant> |
29 | | |
30 | | using namespace lldb_private; |
31 | | using namespace lldb; |
32 | | using namespace lldb_private::python; |
33 | | using llvm::cantFail; |
34 | | using llvm::Error; |
35 | | using llvm::Expected; |
36 | | using llvm::Twine; |
37 | | |
38 | 791 | template <> Expected<bool> python::As<bool>(Expected<PythonObject> &&obj) { |
39 | 791 | if (!obj) |
40 | 1 | return obj.takeError(); |
41 | 790 | return obj.get().IsTrue(); |
42 | 791 | } |
43 | | |
44 | | template <> |
45 | 1.04k | Expected<long long> python::As<long long>(Expected<PythonObject> &&obj) { |
46 | 1.04k | if (!obj) |
47 | 2 | return obj.takeError(); |
48 | 1.04k | return obj->AsLongLong(); |
49 | 1.04k | } |
50 | | |
51 | | template <> |
52 | | Expected<unsigned long long> |
53 | 59 | python::As<unsigned long long>(Expected<PythonObject> &&obj) { |
54 | 59 | if (!obj) |
55 | 0 | return obj.takeError(); |
56 | 59 | return obj->AsUnsignedLongLong(); |
57 | 59 | } |
58 | | |
59 | | template <> |
60 | 8 | Expected<std::string> python::As<std::string>(Expected<PythonObject> &&obj) { |
61 | 8 | if (!obj) |
62 | 0 | return obj.takeError(); |
63 | 8 | PyObject *str_obj = PyObject_Str(obj.get().get()); |
64 | 8 | if (!obj) |
65 | 0 | return llvm::make_error<PythonException>(); |
66 | 8 | auto str = Take<PythonString>(str_obj); |
67 | 8 | auto utf8 = str.AsUTF8(); |
68 | 8 | if (!utf8) |
69 | 0 | return utf8.takeError(); |
70 | 8 | return std::string(utf8.get()); |
71 | 8 | } |
72 | | |
73 | 202k | static bool python_is_finalizing() { |
74 | | #if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 7 |
75 | | return _Py_Finalizing != nullptr; |
76 | | #else |
77 | 202k | return _Py_IsFinalizing(); |
78 | 202k | #endif |
79 | 202k | } |
80 | | |
81 | 913k | void PythonObject::Reset() { |
82 | 913k | if (m_py_obj && Py_IsInitialized()202k ) { |
83 | 202k | if (python_is_finalizing()) { |
84 | | // Leak m_py_obj rather than crashing the process. |
85 | | // https://docs.python.org/3/c-api/init.html#c.PyGILState_Ensure |
86 | 202k | } else { |
87 | 202k | PyGILState_STATE state = PyGILState_Ensure(); |
88 | 202k | Py_DECREF(m_py_obj); |
89 | 202k | PyGILState_Release(state); |
90 | 202k | } |
91 | 202k | } |
92 | 913k | m_py_obj = nullptr; |
93 | 913k | } |
94 | | |
95 | 1.04k | Expected<long long> PythonObject::AsLongLong() const { |
96 | 1.04k | if (!m_py_obj) |
97 | 0 | return nullDeref(); |
98 | 1.04k | assert(!PyErr_Occurred()); |
99 | 1.04k | long long r = PyLong_AsLongLong(m_py_obj); |
100 | 1.04k | if (PyErr_Occurred()) |
101 | 1 | return exception(); |
102 | 1.04k | return r; |
103 | 1.04k | } |
104 | | |
105 | 518 | Expected<unsigned long long> PythonObject::AsUnsignedLongLong() const { |
106 | 518 | if (!m_py_obj) |
107 | 0 | return nullDeref(); |
108 | 518 | assert(!PyErr_Occurred()); |
109 | 518 | long long r = PyLong_AsUnsignedLongLong(m_py_obj); |
110 | 518 | if (PyErr_Occurred()) |
111 | 2 | return exception(); |
112 | 516 | return r; |
113 | 518 | } |
114 | | |
115 | | // wraps on overflow, instead of raising an error. |
116 | 0 | Expected<unsigned long long> PythonObject::AsModuloUnsignedLongLong() const { |
117 | 0 | if (!m_py_obj) |
118 | 0 | return nullDeref(); |
119 | 0 | assert(!PyErr_Occurred()); |
120 | 0 | unsigned long long r = PyLong_AsUnsignedLongLongMask(m_py_obj); |
121 | | // FIXME: We should fetch the exception message and hoist it. |
122 | 0 | if (PyErr_Occurred()) |
123 | 0 | return exception(); |
124 | 0 | return r; |
125 | 0 | } |
126 | | |
127 | 0 | void StructuredPythonObject::Serialize(llvm::json::OStream &s) const { |
128 | 0 | s.value(llvm::formatv("Python Obj: {0:X}", GetValue()).str()); |
129 | 0 | } |
130 | | |
131 | | // PythonObject |
132 | | |
133 | 0 | void PythonObject::Dump(Stream &strm) const { |
134 | 0 | if (m_py_obj) { |
135 | 0 | FILE *file = llvm::sys::RetryAfterSignal(nullptr, ::tmpfile); |
136 | 0 | if (file) { |
137 | 0 | ::PyObject_Print(m_py_obj, file, 0); |
138 | 0 | const long length = ftell(file); |
139 | 0 | if (length) { |
140 | 0 | ::rewind(file); |
141 | 0 | std::vector<char> file_contents(length, '\0'); |
142 | 0 | const size_t length_read = |
143 | 0 | ::fread(file_contents.data(), 1, file_contents.size(), file); |
144 | 0 | if (length_read > 0) |
145 | 0 | strm.Write(file_contents.data(), length_read); |
146 | 0 | } |
147 | 0 | ::fclose(file); |
148 | 0 | } |
149 | 0 | } else |
150 | 0 | strm.PutCString("NULL"); |
151 | 0 | } |
152 | | |
153 | 1.06k | PyObjectType PythonObject::GetObjectType() const { |
154 | 1.06k | if (!IsAllocated()) |
155 | 0 | return PyObjectType::None; |
156 | | |
157 | 1.06k | if (PythonModule::Check(m_py_obj)) |
158 | 0 | return PyObjectType::Module; |
159 | 1.06k | if (PythonList::Check(m_py_obj)) |
160 | 10 | return PyObjectType::List; |
161 | 1.05k | if (PythonTuple::Check(m_py_obj)) |
162 | 0 | return PyObjectType::Tuple; |
163 | 1.05k | if (PythonDictionary::Check(m_py_obj)) |
164 | 116 | return PyObjectType::Dictionary; |
165 | 940 | if (PythonString::Check(m_py_obj)) |
166 | 444 | return PyObjectType::String; |
167 | 496 | if (PythonBytes::Check(m_py_obj)) |
168 | 5 | return PyObjectType::Bytes; |
169 | 491 | if (PythonByteArray::Check(m_py_obj)) |
170 | 1 | return PyObjectType::ByteArray; |
171 | 490 | if (PythonBoolean::Check(m_py_obj)) |
172 | 15 | return PyObjectType::Boolean; |
173 | 475 | if (PythonInteger::Check(m_py_obj)) |
174 | 458 | return PyObjectType::Integer; |
175 | 17 | if (PythonFile::Check(m_py_obj)) |
176 | 0 | return PyObjectType::File; |
177 | 17 | if (PythonCallable::Check(m_py_obj)) |
178 | 0 | return PyObjectType::Callable; |
179 | 17 | return PyObjectType::Unknown; |
180 | 17 | } |
181 | | |
182 | 0 | PythonString PythonObject::Repr() const { |
183 | 0 | if (!m_py_obj) |
184 | 0 | return PythonString(); |
185 | 0 | PyObject *repr = PyObject_Repr(m_py_obj); |
186 | 0 | if (!repr) |
187 | 0 | return PythonString(); |
188 | 0 | return PythonString(PyRefType::Owned, repr); |
189 | 0 | } |
190 | | |
191 | 992 | PythonString PythonObject::Str() const { |
192 | 992 | if (!m_py_obj) |
193 | 0 | return PythonString(); |
194 | 992 | PyObject *str = PyObject_Str(m_py_obj); |
195 | 992 | if (!str) |
196 | 0 | return PythonString(); |
197 | 992 | return PythonString(PyRefType::Owned, str); |
198 | 992 | } |
199 | | |
200 | | PythonObject |
201 | | PythonObject::ResolveNameWithDictionary(llvm::StringRef name, |
202 | 492 | const PythonDictionary &dict) { |
203 | 492 | size_t dot_pos = name.find('.'); |
204 | 492 | llvm::StringRef piece = name.substr(0, dot_pos); |
205 | 492 | PythonObject result = dict.GetItemForKey(PythonString(piece)); |
206 | 492 | if (dot_pos == llvm::StringRef::npos) { |
207 | | // There was no dot, we're done. |
208 | 106 | return result; |
209 | 106 | } |
210 | | |
211 | | // There was a dot. The remaining portion of the name should be looked up in |
212 | | // the context of the object that was found in the dictionary. |
213 | 386 | return result.ResolveName(name.substr(dot_pos + 1)); |
214 | 492 | } |
215 | | |
216 | 4.26k | PythonObject PythonObject::ResolveName(llvm::StringRef name) const { |
217 | | // Resolve the name in the context of the specified object. If, for example, |
218 | | // `this` refers to a PyModule, then this will look for `name` in this |
219 | | // module. If `this` refers to a PyType, then it will resolve `name` as an |
220 | | // attribute of that type. If `this` refers to an instance of an object, |
221 | | // then it will resolve `name` as the value of the specified field. |
222 | | // |
223 | | // This function handles dotted names so that, for example, if `m_py_obj` |
224 | | // refers to the `sys` module, and `name` == "path.append", then it will find |
225 | | // the function `sys.path.append`. |
226 | | |
227 | 4.26k | size_t dot_pos = name.find('.'); |
228 | 4.26k | if (dot_pos == llvm::StringRef::npos) { |
229 | | // No dots in the name, we should be able to find the value immediately as |
230 | | // an attribute of `m_py_obj`. |
231 | 4.09k | return GetAttributeValue(name); |
232 | 4.09k | } |
233 | | |
234 | | // Look up the first piece of the name, and resolve the rest as a child of |
235 | | // that. |
236 | 173 | PythonObject parent = ResolveName(name.substr(0, dot_pos)); |
237 | 173 | if (!parent.IsAllocated()) |
238 | 0 | return PythonObject(); |
239 | | |
240 | | // Tail recursion.. should be optimized by the compiler |
241 | 173 | return parent.ResolveName(name.substr(dot_pos + 1)); |
242 | 173 | } |
243 | | |
244 | 2 | bool PythonObject::HasAttribute(llvm::StringRef attr) const { |
245 | 2 | if (!IsValid()) |
246 | 0 | return false; |
247 | 2 | PythonString py_attr(attr); |
248 | 2 | return !!PyObject_HasAttr(m_py_obj, py_attr.get()); |
249 | 2 | } |
250 | | |
251 | 4.09k | PythonObject PythonObject::GetAttributeValue(llvm::StringRef attr) const { |
252 | 4.09k | if (!IsValid()) |
253 | 5 | return PythonObject(); |
254 | | |
255 | 4.08k | PythonString py_attr(attr); |
256 | 4.08k | if (!PyObject_HasAttr(m_py_obj, py_attr.get())) |
257 | 1.05k | return PythonObject(); |
258 | | |
259 | 3.03k | return PythonObject(PyRefType::Owned, |
260 | 3.03k | PyObject_GetAttr(m_py_obj, py_attr.get())); |
261 | 4.08k | } |
262 | | |
263 | 1.05k | StructuredData::ObjectSP PythonObject::CreateStructuredObject() const { |
264 | 1.05k | assert(PyGILState_Check()); |
265 | 1.05k | switch (GetObjectType()) { |
266 | 115 | case PyObjectType::Dictionary: |
267 | 115 | return PythonDictionary(PyRefType::Borrowed, m_py_obj) |
268 | 115 | .CreateStructuredDictionary(); |
269 | 10 | case PyObjectType::Boolean: |
270 | 10 | return PythonBoolean(PyRefType::Borrowed, m_py_obj) |
271 | 10 | .CreateStructuredBoolean(); |
272 | 457 | case PyObjectType::Integer: { |
273 | 457 | StructuredData::IntegerSP int_sp = |
274 | 457 | PythonInteger(PyRefType::Borrowed, m_py_obj).CreateStructuredInteger(); |
275 | 457 | if (std::holds_alternative<StructuredData::UnsignedIntegerSP>(int_sp)) |
276 | 456 | return std::get<StructuredData::UnsignedIntegerSP>(int_sp); |
277 | 1 | if (std::holds_alternative<StructuredData::SignedIntegerSP>(int_sp)) |
278 | 1 | return std::get<StructuredData::SignedIntegerSP>(int_sp); |
279 | 0 | return nullptr; |
280 | 1 | }; |
281 | 9 | case PyObjectType::List: |
282 | 9 | return PythonList(PyRefType::Borrowed, m_py_obj).CreateStructuredArray(); |
283 | 443 | case PyObjectType::String: |
284 | 443 | return PythonString(PyRefType::Borrowed, m_py_obj).CreateStructuredString(); |
285 | 4 | case PyObjectType::Bytes: |
286 | 4 | return PythonBytes(PyRefType::Borrowed, m_py_obj).CreateStructuredString(); |
287 | 0 | case PyObjectType::ByteArray: |
288 | 0 | return PythonByteArray(PyRefType::Borrowed, m_py_obj) |
289 | 0 | .CreateStructuredString(); |
290 | 0 | case PyObjectType::None: |
291 | 0 | return StructuredData::ObjectSP(); |
292 | 17 | default: |
293 | 17 | return StructuredData::ObjectSP(new StructuredPythonObject( |
294 | 17 | PythonObject(PyRefType::Borrowed, m_py_obj))); |
295 | 1.05k | } |
296 | 1.05k | } |
297 | | |
298 | | // PythonString |
299 | | |
300 | 0 | PythonBytes::PythonBytes(llvm::ArrayRef<uint8_t> bytes) { SetBytes(bytes); } |
301 | | |
302 | 15 | PythonBytes::PythonBytes(const uint8_t *bytes, size_t length) { |
303 | 15 | SetBytes(llvm::ArrayRef<uint8_t>(bytes, length)); |
304 | 15 | } |
305 | | |
306 | 533 | bool PythonBytes::Check(PyObject *py_obj) { |
307 | 533 | if (!py_obj) |
308 | 0 | return false; |
309 | 533 | return PyBytes_Check(py_obj); |
310 | 533 | } |
311 | | |
312 | 7 | llvm::ArrayRef<uint8_t> PythonBytes::GetBytes() const { |
313 | 7 | if (!IsValid()) |
314 | 0 | return llvm::ArrayRef<uint8_t>(); |
315 | | |
316 | 7 | Py_ssize_t size; |
317 | 7 | char *c; |
318 | | |
319 | 7 | PyBytes_AsStringAndSize(m_py_obj, &c, &size); |
320 | 7 | return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size); |
321 | 7 | } |
322 | | |
323 | 6 | size_t PythonBytes::GetSize() const { |
324 | 6 | if (!IsValid()) |
325 | 0 | return 0; |
326 | 6 | return PyBytes_Size(m_py_obj); |
327 | 6 | } |
328 | | |
329 | 15 | void PythonBytes::SetBytes(llvm::ArrayRef<uint8_t> bytes) { |
330 | 15 | const char *data = reinterpret_cast<const char *>(bytes.data()); |
331 | 15 | *this = Take<PythonBytes>(PyBytes_FromStringAndSize(data, bytes.size())); |
332 | 15 | } |
333 | | |
334 | 7 | StructuredData::StringSP PythonBytes::CreateStructuredString() const { |
335 | 7 | StructuredData::StringSP result(new StructuredData::String); |
336 | 7 | Py_ssize_t size; |
337 | 7 | char *c; |
338 | 7 | PyBytes_AsStringAndSize(m_py_obj, &c, &size); |
339 | 7 | result->SetValue(std::string(c, size)); |
340 | 7 | return result; |
341 | 7 | } |
342 | | |
343 | | PythonByteArray::PythonByteArray(llvm::ArrayRef<uint8_t> bytes) |
344 | 0 | : PythonByteArray(bytes.data(), bytes.size()) {} Unexecuted instantiation: lldb_private::python::PythonByteArray::PythonByteArray(llvm::ArrayRef<unsigned char>) Unexecuted instantiation: lldb_private::python::PythonByteArray::PythonByteArray(llvm::ArrayRef<unsigned char>) |
345 | | |
346 | 0 | PythonByteArray::PythonByteArray(const uint8_t *bytes, size_t length) { |
347 | 0 | const char *str = reinterpret_cast<const char *>(bytes); |
348 | 0 | *this = Take<PythonByteArray>(PyByteArray_FromStringAndSize(str, length)); |
349 | 0 | } |
350 | | |
351 | 512 | bool PythonByteArray::Check(PyObject *py_obj) { |
352 | 512 | if (!py_obj) |
353 | 0 | return false; |
354 | 512 | return PyByteArray_Check(py_obj); |
355 | 512 | } |
356 | | |
357 | 7 | llvm::ArrayRef<uint8_t> PythonByteArray::GetBytes() const { |
358 | 7 | if (!IsValid()) |
359 | 0 | return llvm::ArrayRef<uint8_t>(); |
360 | | |
361 | 7 | char *c = PyByteArray_AsString(m_py_obj); |
362 | 7 | size_t size = GetSize(); |
363 | 7 | return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size); |
364 | 7 | } |
365 | | |
366 | 13 | size_t PythonByteArray::GetSize() const { |
367 | 13 | if (!IsValid()) |
368 | 0 | return 0; |
369 | | |
370 | 13 | return PyByteArray_Size(m_py_obj); |
371 | 13 | } |
372 | | |
373 | 0 | StructuredData::StringSP PythonByteArray::CreateStructuredString() const { |
374 | 0 | StructuredData::StringSP result(new StructuredData::String); |
375 | 0 | llvm::ArrayRef<uint8_t> bytes = GetBytes(); |
376 | 0 | const char *str = reinterpret_cast<const char *>(bytes.data()); |
377 | 0 | result->SetValue(std::string(str, bytes.size())); |
378 | 0 | return result; |
379 | 0 | } |
380 | | |
381 | | // PythonString |
382 | | |
383 | 63.1k | Expected<PythonString> PythonString::FromUTF8(llvm::StringRef string) { |
384 | 63.1k | PyObject *str = PyUnicode_FromStringAndSize(string.data(), string.size()); |
385 | 63.1k | if (!str) |
386 | 0 | return llvm::make_error<PythonException>(); |
387 | 63.1k | return Take<PythonString>(str); |
388 | 63.1k | } |
389 | | |
390 | 62.9k | PythonString::PythonString(llvm::StringRef string) { SetString(string); } |
391 | | |
392 | 66.0k | bool PythonString::Check(PyObject *py_obj) { |
393 | 66.0k | if (!py_obj) |
394 | 0 | return false; |
395 | | |
396 | 66.0k | if (PyUnicode_Check(py_obj)) |
397 | 65.5k | return true; |
398 | 510 | return false; |
399 | 66.0k | } |
400 | | |
401 | 1.62k | llvm::StringRef PythonString::GetString() const { |
402 | 1.62k | auto s = AsUTF8(); |
403 | 1.62k | if (!s) { |
404 | 0 | llvm::consumeError(s.takeError()); |
405 | 0 | return llvm::StringRef(""); |
406 | 0 | } |
407 | 1.62k | return s.get(); |
408 | 1.62k | } |
409 | | |
410 | 1.63k | Expected<llvm::StringRef> PythonString::AsUTF8() const { |
411 | 1.63k | if (!IsValid()) |
412 | 0 | return nullDeref(); |
413 | | |
414 | 1.63k | Py_ssize_t size; |
415 | 1.63k | const char *data; |
416 | | |
417 | 1.63k | data = PyUnicode_AsUTF8AndSize(m_py_obj, &size); |
418 | | |
419 | 1.63k | if (!data) |
420 | 0 | return exception(); |
421 | | |
422 | 1.63k | return llvm::StringRef(data, size); |
423 | 1.63k | } |
424 | | |
425 | 26 | size_t PythonString::GetSize() const { |
426 | 26 | if (IsValid()) { |
427 | 26 | #if PY_MINOR_VERSION >= 3 |
428 | 26 | return PyUnicode_GetLength(m_py_obj); |
429 | | #else |
430 | | return PyUnicode_GetSize(m_py_obj); |
431 | | #endif |
432 | 26 | } |
433 | 0 | return 0; |
434 | 26 | } |
435 | | |
436 | 62.9k | void PythonString::SetString(llvm::StringRef string) { |
437 | 62.9k | auto s = FromUTF8(string); |
438 | 62.9k | if (!s) { |
439 | 0 | llvm::consumeError(s.takeError()); |
440 | 0 | Reset(); |
441 | 62.9k | } else { |
442 | 62.9k | *this = std::move(s.get()); |
443 | 62.9k | } |
444 | 62.9k | } |
445 | | |
446 | 444 | StructuredData::StringSP PythonString::CreateStructuredString() const { |
447 | 444 | StructuredData::StringSP result(new StructuredData::String); |
448 | 444 | result->SetValue(GetString()); |
449 | 444 | return result; |
450 | 444 | } |
451 | | |
452 | | // PythonInteger |
453 | | |
454 | 1.02k | PythonInteger::PythonInteger(int64_t value) { SetInteger(value); } |
455 | | |
456 | 1.96k | bool PythonInteger::Check(PyObject *py_obj) { |
457 | 1.96k | if (!py_obj) |
458 | 0 | return false; |
459 | | |
460 | | // Python 3 does not have PyInt_Check. There is only one type of integral |
461 | | // value, long. |
462 | 1.96k | return PyLong_Check(py_obj); |
463 | 1.96k | } |
464 | | |
465 | 1.02k | void PythonInteger::SetInteger(int64_t value) { |
466 | 1.02k | *this = Take<PythonInteger>(PyLong_FromLongLong(value)); |
467 | 1.02k | } |
468 | | |
469 | 459 | StructuredData::IntegerSP PythonInteger::CreateStructuredInteger() const { |
470 | 459 | StructuredData::UnsignedIntegerSP uint_sp = CreateStructuredUnsignedInteger(); |
471 | 459 | return uint_sp ? StructuredData::IntegerSP(uint_sp)457 |
472 | 459 | : CreateStructuredSignedInteger()2 ; |
473 | 459 | } |
474 | | |
475 | | StructuredData::UnsignedIntegerSP |
476 | 459 | PythonInteger::CreateStructuredUnsignedInteger() const { |
477 | 459 | StructuredData::UnsignedIntegerSP result = nullptr; |
478 | 459 | llvm::Expected<unsigned long long> value = AsUnsignedLongLong(); |
479 | 459 | if (!value) |
480 | 2 | llvm::consumeError(value.takeError()); |
481 | 457 | else |
482 | 457 | result = std::make_shared<StructuredData::UnsignedInteger>(value.get()); |
483 | | |
484 | 459 | return result; |
485 | 459 | } |
486 | | |
487 | | StructuredData::SignedIntegerSP |
488 | 2 | PythonInteger::CreateStructuredSignedInteger() const { |
489 | 2 | StructuredData::SignedIntegerSP result = nullptr; |
490 | 2 | llvm::Expected<long long> value = AsLongLong(); |
491 | 2 | if (!value) |
492 | 0 | llvm::consumeError(value.takeError()); |
493 | 2 | else |
494 | 2 | result = std::make_shared<StructuredData::SignedInteger>(value.get()); |
495 | | |
496 | 2 | return result; |
497 | 2 | } |
498 | | |
499 | | // PythonBoolean |
500 | | |
501 | 2 | PythonBoolean::PythonBoolean(bool value) { |
502 | 2 | SetValue(value); |
503 | 2 | } |
504 | | |
505 | 514 | bool PythonBoolean::Check(PyObject *py_obj) { |
506 | 514 | return py_obj ? PyBool_Check(py_obj) : false0 ; |
507 | 514 | } |
508 | | |
509 | 15 | bool PythonBoolean::GetValue() const { |
510 | 15 | return m_py_obj ? PyObject_IsTrue(m_py_obj) : false0 ; |
511 | 15 | } |
512 | | |
513 | 2 | void PythonBoolean::SetValue(bool value) { |
514 | 2 | *this = Take<PythonBoolean>(PyBool_FromLong(value)); |
515 | 2 | } |
516 | | |
517 | 10 | StructuredData::BooleanSP PythonBoolean::CreateStructuredBoolean() const { |
518 | 10 | StructuredData::BooleanSP result(new StructuredData::Boolean); |
519 | 10 | result->SetValue(GetValue()); |
520 | 10 | return result; |
521 | 10 | } |
522 | | |
523 | | // PythonList |
524 | | |
525 | 2 | PythonList::PythonList(PyInitialValue value) { |
526 | 2 | if (value == PyInitialValue::Empty) |
527 | 2 | *this = Take<PythonList>(PyList_New(0)); |
528 | 2 | } |
529 | | |
530 | 0 | PythonList::PythonList(int list_size) { |
531 | 0 | *this = Take<PythonList>(PyList_New(list_size)); |
532 | 0 | } |
533 | | |
534 | 2.44k | bool PythonList::Check(PyObject *py_obj) { |
535 | 2.44k | if (!py_obj) |
536 | 0 | return false; |
537 | 2.44k | return PyList_Check(py_obj); |
538 | 2.44k | } |
539 | | |
540 | 299 | uint32_t PythonList::GetSize() const { |
541 | 299 | if (IsValid()) |
542 | 299 | return PyList_GET_SIZE(m_py_obj); |
543 | 0 | return 0; |
544 | 299 | } |
545 | | |
546 | 1.20k | PythonObject PythonList::GetItemAtIndex(uint32_t index) const { |
547 | 1.20k | if (IsValid()) |
548 | 1.20k | return PythonObject(PyRefType::Borrowed, PyList_GetItem(m_py_obj, index)); |
549 | 0 | return PythonObject(); |
550 | 1.20k | } |
551 | | |
552 | 2 | void PythonList::SetItemAtIndex(uint32_t index, const PythonObject &object) { |
553 | 2 | if (IsAllocated() && object.IsValid()) { |
554 | | // PyList_SetItem is documented to "steal" a reference, so we need to |
555 | | // convert it to an owned reference by incrementing it. |
556 | 2 | Py_INCREF(object.get()); |
557 | 2 | PyList_SetItem(m_py_obj, index, object.get()); |
558 | 2 | } |
559 | 2 | } |
560 | | |
561 | 4 | void PythonList::AppendItem(const PythonObject &object) { |
562 | 4 | if (IsAllocated() && object.IsValid()) { |
563 | | // `PyList_Append` does *not* steal a reference, so do not call `Py_INCREF` |
564 | | // here like we do with `PyList_SetItem`. |
565 | 4 | PyList_Append(m_py_obj, object.get()); |
566 | 4 | } |
567 | 4 | } |
568 | | |
569 | 30 | StructuredData::ArraySP PythonList::CreateStructuredArray() const { |
570 | 30 | StructuredData::ArraySP result(new StructuredData::Array); |
571 | 30 | uint32_t count = GetSize(); |
572 | 148 | for (uint32_t i = 0; i < count; ++i118 ) { |
573 | 118 | PythonObject obj = GetItemAtIndex(i); |
574 | 118 | result->AddItem(obj.CreateStructuredObject()); |
575 | 118 | } |
576 | 30 | return result; |
577 | 30 | } |
578 | | |
579 | | // PythonTuple |
580 | | |
581 | 1 | PythonTuple::PythonTuple(PyInitialValue value) { |
582 | 1 | if (value == PyInitialValue::Empty) |
583 | 1 | *this = Take<PythonTuple>(PyTuple_New(0)); |
584 | 1 | } |
585 | | |
586 | 2 | PythonTuple::PythonTuple(int tuple_size) { |
587 | 2 | *this = Take<PythonTuple>(PyTuple_New(tuple_size)); |
588 | 2 | } |
589 | | |
590 | 1.98k | PythonTuple::PythonTuple(std::initializer_list<PythonObject> objects) { |
591 | 1.98k | m_py_obj = PyTuple_New(objects.size()); |
592 | | |
593 | 1.98k | uint32_t idx = 0; |
594 | 2.68k | for (auto object : objects) { |
595 | 2.68k | if (object.IsValid()) |
596 | 2.68k | SetItemAtIndex(idx, object); |
597 | 2.68k | idx++; |
598 | 2.68k | } |
599 | 1.98k | } |
600 | | |
601 | 2 | PythonTuple::PythonTuple(std::initializer_list<PyObject *> objects) { |
602 | 2 | m_py_obj = PyTuple_New(objects.size()); |
603 | | |
604 | 2 | uint32_t idx = 0; |
605 | 5 | for (auto py_object : objects) { |
606 | 5 | PythonObject object(PyRefType::Borrowed, py_object); |
607 | 5 | if (object.IsValid()) |
608 | 5 | SetItemAtIndex(idx, object); |
609 | 5 | idx++; |
610 | 5 | } |
611 | 2 | } |
612 | | |
613 | 1.05k | bool PythonTuple::Check(PyObject *py_obj) { |
614 | 1.05k | if (!py_obj) |
615 | 0 | return false; |
616 | 1.05k | return PyTuple_Check(py_obj); |
617 | 1.05k | } |
618 | | |
619 | 6 | uint32_t PythonTuple::GetSize() const { |
620 | 6 | if (IsValid()) |
621 | 6 | return PyTuple_GET_SIZE(m_py_obj); |
622 | 0 | return 0; |
623 | 6 | } |
624 | | |
625 | 11 | PythonObject PythonTuple::GetItemAtIndex(uint32_t index) const { |
626 | 11 | if (IsValid()) |
627 | 11 | return PythonObject(PyRefType::Borrowed, PyTuple_GetItem(m_py_obj, index)); |
628 | 0 | return PythonObject(); |
629 | 11 | } |
630 | | |
631 | 2.69k | void PythonTuple::SetItemAtIndex(uint32_t index, const PythonObject &object) { |
632 | 2.69k | if (IsAllocated() && object.IsValid()) { |
633 | | // PyTuple_SetItem is documented to "steal" a reference, so we need to |
634 | | // convert it to an owned reference by incrementing it. |
635 | 2.69k | Py_INCREF(object.get()); |
636 | 2.69k | PyTuple_SetItem(m_py_obj, index, object.get()); |
637 | 2.69k | } |
638 | 2.69k | } |
639 | | |
640 | 1 | StructuredData::ArraySP PythonTuple::CreateStructuredArray() const { |
641 | 1 | StructuredData::ArraySP result(new StructuredData::Array); |
642 | 1 | uint32_t count = GetSize(); |
643 | 3 | for (uint32_t i = 0; i < count; ++i2 ) { |
644 | 2 | PythonObject obj = GetItemAtIndex(i); |
645 | 2 | result->AddItem(obj.CreateStructuredObject()); |
646 | 2 | } |
647 | 1 | return result; |
648 | 1 | } |
649 | | |
650 | | // PythonDictionary |
651 | | |
652 | 3.66k | PythonDictionary::PythonDictionary(PyInitialValue value) { |
653 | 3.66k | if (value == PyInitialValue::Empty) |
654 | 62 | *this = Take<PythonDictionary>(PyDict_New()); |
655 | 3.66k | } |
656 | | |
657 | 14.1k | bool PythonDictionary::Check(PyObject *py_obj) { |
658 | 14.1k | if (!py_obj) |
659 | 0 | return false; |
660 | | |
661 | 14.1k | return PyDict_Check(py_obj); |
662 | 14.1k | } |
663 | | |
664 | 2 | uint32_t PythonDictionary::GetSize() const { |
665 | 2 | if (IsValid()) |
666 | 2 | return PyDict_Size(m_py_obj); |
667 | 0 | return 0; |
668 | 2 | } |
669 | | |
670 | 139 | PythonList PythonDictionary::GetKeys() const { |
671 | 139 | if (IsValid()) |
672 | 139 | return PythonList(PyRefType::Owned, PyDict_Keys(m_py_obj)); |
673 | 0 | return PythonList(PyInitialValue::Invalid); |
674 | 139 | } |
675 | | |
676 | 20.7k | PythonObject PythonDictionary::GetItemForKey(const PythonObject &key) const { |
677 | 20.7k | auto item = GetItem(key); |
678 | 20.7k | if (!item) { |
679 | 114 | llvm::consumeError(item.takeError()); |
680 | 114 | return PythonObject(); |
681 | 114 | } |
682 | 20.6k | return std::move(item.get()); |
683 | 20.7k | } |
684 | | |
685 | | Expected<PythonObject> |
686 | 20.7k | PythonDictionary::GetItem(const PythonObject &key) const { |
687 | 20.7k | if (!IsValid()) |
688 | 0 | return nullDeref(); |
689 | 20.7k | PyObject *o = PyDict_GetItemWithError(m_py_obj, key.get()); |
690 | 20.7k | if (PyErr_Occurred()) |
691 | 0 | return exception(); |
692 | 20.7k | if (!o) |
693 | 114 | return keyError(); |
694 | 20.6k | return Retain<PythonObject>(o); |
695 | 20.7k | } |
696 | | |
697 | 1.47k | Expected<PythonObject> PythonDictionary::GetItem(const Twine &key) const { |
698 | 1.47k | if (!IsValid()) |
699 | 0 | return nullDeref(); |
700 | 1.47k | PyObject *o = PyDict_GetItemString(m_py_obj, NullTerminated(key)); |
701 | 1.47k | if (PyErr_Occurred()) |
702 | 0 | return exception(); |
703 | 1.47k | if (!o) |
704 | 0 | return keyError(); |
705 | 1.47k | return Retain<PythonObject>(o); |
706 | 1.47k | } |
707 | | |
708 | | Error PythonDictionary::SetItem(const PythonObject &key, |
709 | 38.2k | const PythonObject &value) const { |
710 | 38.2k | if (!IsValid() || !value.IsValid()) |
711 | 0 | return nullDeref(); |
712 | 38.2k | int r = PyDict_SetItem(m_py_obj, key.get(), value.get()); |
713 | 38.2k | if (r < 0) |
714 | 0 | return exception(); |
715 | 38.2k | return Error::success(); |
716 | 38.2k | } |
717 | | |
718 | | Error PythonDictionary::SetItem(const Twine &key, |
719 | 56 | const PythonObject &value) const { |
720 | 56 | if (!IsValid() || !value.IsValid()) |
721 | 0 | return nullDeref(); |
722 | 56 | int r = PyDict_SetItemString(m_py_obj, NullTerminated(key), value.get()); |
723 | 56 | if (r < 0) |
724 | 0 | return exception(); |
725 | 56 | return Error::success(); |
726 | 56 | } |
727 | | |
728 | | void PythonDictionary::SetItemForKey(const PythonObject &key, |
729 | 38.2k | const PythonObject &value) { |
730 | 38.2k | Error error = SetItem(key, value); |
731 | 38.2k | if (error) |
732 | 0 | llvm::consumeError(std::move(error)); |
733 | 38.2k | } |
734 | | |
735 | | StructuredData::DictionarySP |
736 | 139 | PythonDictionary::CreateStructuredDictionary() const { |
737 | 139 | StructuredData::DictionarySP result(new StructuredData::Dictionary); |
738 | 139 | PythonList keys(GetKeys()); |
739 | 139 | uint32_t num_keys = keys.GetSize(); |
740 | 1.03k | for (uint32_t i = 0; i < num_keys; ++i898 ) { |
741 | 898 | PythonObject key = keys.GetItemAtIndex(i); |
742 | 898 | PythonObject value = GetItemForKey(key); |
743 | 898 | StructuredData::ObjectSP structured_value = value.CreateStructuredObject(); |
744 | 898 | result->AddItem(key.Str().GetString(), structured_value); |
745 | 898 | } |
746 | 139 | return result; |
747 | 139 | } |
748 | | |
749 | 96 | PythonModule PythonModule::BuiltinsModule() { return AddModule("builtins"); } |
750 | | |
751 | 496 | PythonModule PythonModule::MainModule() { return AddModule("__main__"); } |
752 | | |
753 | 592 | PythonModule PythonModule::AddModule(llvm::StringRef module) { |
754 | 592 | std::string str = module.str(); |
755 | 592 | return PythonModule(PyRefType::Borrowed, PyImport_AddModule(str.c_str())); |
756 | 592 | } |
757 | | |
758 | 22.3k | Expected<PythonModule> PythonModule::Import(const Twine &name) { |
759 | 22.3k | PyObject *mod = PyImport_ImportModule(NullTerminated(name)); |
760 | 22.3k | if (!mod) |
761 | 0 | return exception(); |
762 | 22.3k | return Take<PythonModule>(mod); |
763 | 22.3k | } |
764 | | |
765 | 19.5k | Expected<PythonObject> PythonModule::Get(const Twine &name) { |
766 | 19.5k | if (!IsValid()) |
767 | 0 | return nullDeref(); |
768 | 19.5k | PyObject *dict = PyModule_GetDict(m_py_obj); |
769 | 19.5k | if (!dict) |
770 | 0 | return exception(); |
771 | 19.5k | PyObject *item = PyDict_GetItemString(dict, NullTerminated(name)); |
772 | 19.5k | if (!item) |
773 | 0 | return exception(); |
774 | 19.5k | return Retain<PythonObject>(item); |
775 | 19.5k | } |
776 | | |
777 | 24.0k | bool PythonModule::Check(PyObject *py_obj) { |
778 | 24.0k | if (!py_obj) |
779 | 0 | return false; |
780 | | |
781 | 24.0k | return PyModule_Check(py_obj); |
782 | 24.0k | } |
783 | | |
784 | 7.50k | PythonDictionary PythonModule::GetDictionary() const { |
785 | 7.50k | if (!IsValid()) |
786 | 0 | return PythonDictionary(); |
787 | 7.50k | return Retain<PythonDictionary>(PyModule_GetDict(m_py_obj)); |
788 | 7.50k | } |
789 | | |
790 | 6.29k | bool PythonCallable::Check(PyObject *py_obj) { |
791 | 6.29k | if (!py_obj) |
792 | 1.05k | return false; |
793 | | |
794 | 5.23k | return PyCallable_Check(py_obj); |
795 | 6.29k | } |
796 | | |
797 | | #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3 |
798 | | static const char get_arg_info_script[] = R"( |
799 | | from inspect import signature, Parameter, ismethod |
800 | | from collections import namedtuple |
801 | | ArgInfo = namedtuple('ArgInfo', ['count', 'has_varargs']) |
802 | | def main(f): |
803 | | count = 0 |
804 | | varargs = False |
805 | | for parameter in signature(f).parameters.values(): |
806 | | kind = parameter.kind |
807 | | if kind in (Parameter.POSITIONAL_ONLY, |
808 | | Parameter.POSITIONAL_OR_KEYWORD): |
809 | | count += 1 |
810 | | elif kind == Parameter.VAR_POSITIONAL: |
811 | | varargs = True |
812 | | elif kind in (Parameter.KEYWORD_ONLY, |
813 | | Parameter.VAR_KEYWORD): |
814 | | pass |
815 | | else: |
816 | | raise Exception(f'unknown parameter kind: {kind}') |
817 | | return ArgInfo(count, varargs) |
818 | | )"; |
819 | | #endif |
820 | | |
821 | 332 | Expected<PythonCallable::ArgInfo> PythonCallable::GetArgInfo() const { |
822 | 332 | ArgInfo result = {}; |
823 | 332 | if (!IsValid()) |
824 | 0 | return nullDeref(); |
825 | | |
826 | 332 | #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3 |
827 | | |
828 | | // no need to synchronize access to this global, we already have the GIL |
829 | 332 | static PythonScript get_arg_info(get_arg_info_script); |
830 | 332 | Expected<PythonObject> pyarginfo = get_arg_info(*this); |
831 | 332 | if (!pyarginfo) |
832 | 0 | return pyarginfo.takeError(); |
833 | 332 | long long count = |
834 | 332 | cantFail(As<long long>(pyarginfo.get().GetAttribute("count"))); |
835 | 332 | bool has_varargs = |
836 | 332 | cantFail(As<bool>(pyarginfo.get().GetAttribute("has_varargs"))); |
837 | 332 | result.max_positional_args = has_varargs ? ArgInfo::UNBOUNDED4 : count328 ; |
838 | | |
839 | | #else |
840 | | PyObject *py_func_obj; |
841 | | bool is_bound_method = false; |
842 | | bool is_class = false; |
843 | | |
844 | | if (PyType_Check(m_py_obj) || PyClass_Check(m_py_obj)) { |
845 | | auto init = GetAttribute("__init__"); |
846 | | if (!init) |
847 | | return init.takeError(); |
848 | | py_func_obj = init.get().get(); |
849 | | is_class = true; |
850 | | } else { |
851 | | py_func_obj = m_py_obj; |
852 | | } |
853 | | |
854 | | if (PyMethod_Check(py_func_obj)) { |
855 | | py_func_obj = PyMethod_GET_FUNCTION(py_func_obj); |
856 | | PythonObject im_self = GetAttributeValue("im_self"); |
857 | | if (im_self.IsValid() && !im_self.IsNone()) |
858 | | is_bound_method = true; |
859 | | } else { |
860 | | // see if this is a callable object with an __call__ method |
861 | | if (!PyFunction_Check(py_func_obj)) { |
862 | | PythonObject __call__ = GetAttributeValue("__call__"); |
863 | | if (__call__.IsValid()) { |
864 | | auto __callable__ = __call__.AsType<PythonCallable>(); |
865 | | if (__callable__.IsValid()) { |
866 | | py_func_obj = PyMethod_GET_FUNCTION(__callable__.get()); |
867 | | PythonObject im_self = __callable__.GetAttributeValue("im_self"); |
868 | | if (im_self.IsValid() && !im_self.IsNone()) |
869 | | is_bound_method = true; |
870 | | } |
871 | | } |
872 | | } |
873 | | } |
874 | | |
875 | | if (!py_func_obj) |
876 | | return result; |
877 | | |
878 | | PyCodeObject *code = (PyCodeObject *)PyFunction_GET_CODE(py_func_obj); |
879 | | if (!code) |
880 | | return result; |
881 | | |
882 | | auto count = code->co_argcount; |
883 | | bool has_varargs = !!(code->co_flags & CO_VARARGS); |
884 | | result.max_positional_args = |
885 | | has_varargs ? ArgInfo::UNBOUNDED |
886 | | : (count - (int)is_bound_method) - (int)is_class; |
887 | | |
888 | | #endif |
889 | | |
890 | 332 | return result; |
891 | 332 | } |
892 | | |
893 | | constexpr unsigned |
894 | | PythonCallable::ArgInfo::UNBOUNDED; // FIXME delete after c++17 |
895 | | |
896 | 413 | PythonObject PythonCallable::operator()() { |
897 | 413 | return PythonObject(PyRefType::Owned, PyObject_CallObject(m_py_obj, nullptr)); |
898 | 413 | } |
899 | | |
900 | | PythonObject PythonCallable:: |
901 | 0 | operator()(std::initializer_list<PyObject *> args) { |
902 | 0 | PythonTuple arg_tuple(args); |
903 | 0 | return PythonObject(PyRefType::Owned, |
904 | 0 | PyObject_CallObject(m_py_obj, arg_tuple.get())); |
905 | 0 | } |
906 | | |
907 | | PythonObject PythonCallable:: |
908 | 1.98k | operator()(std::initializer_list<PythonObject> args) { |
909 | 1.98k | PythonTuple arg_tuple(args); |
910 | 1.98k | return PythonObject(PyRefType::Owned, |
911 | 1.98k | PyObject_CallObject(m_py_obj, arg_tuple.get())); |
912 | 1.98k | } |
913 | | |
914 | 19.4k | bool PythonFile::Check(PyObject *py_obj) { |
915 | 19.4k | if (!py_obj) |
916 | 0 | return false; |
917 | | // In Python 3, there is no `PyFile_Check`, and in fact PyFile is not even a |
918 | | // first-class object type anymore. `PyFile_FromFd` is just a thin wrapper |
919 | | // over `io.open()`, which returns some object derived from `io.IOBase`. As a |
920 | | // result, the only way to detect a file in Python 3 is to check whether it |
921 | | // inherits from `io.IOBase`. |
922 | 19.4k | auto io_module = PythonModule::Import("io"); |
923 | 19.4k | if (!io_module) { |
924 | 0 | llvm::consumeError(io_module.takeError()); |
925 | 0 | return false; |
926 | 0 | } |
927 | 19.4k | auto iobase = io_module.get().Get("IOBase"); |
928 | 19.4k | if (!iobase) { |
929 | 0 | llvm::consumeError(iobase.takeError()); |
930 | 0 | return false; |
931 | 0 | } |
932 | 19.4k | int r = PyObject_IsInstance(py_obj, iobase.get().get()); |
933 | 19.4k | if (r < 0) { |
934 | 0 | llvm::consumeError(exception()); // clear the exception and log it. |
935 | 0 | return false; |
936 | 0 | } |
937 | 19.4k | return !!r; |
938 | 19.4k | } |
939 | | |
940 | 22 | const char *PythonException::toCString() const { |
941 | 22 | if (!m_repr_bytes) |
942 | 0 | return "unknown exception"; |
943 | 22 | return PyBytes_AS_STRING(m_repr_bytes); |
944 | 22 | } |
945 | | |
946 | 170 | PythonException::PythonException(const char *caller) { |
947 | 170 | assert(PyErr_Occurred()); |
948 | 170 | m_exception_type = m_exception = m_traceback = m_repr_bytes = nullptr; |
949 | 170 | PyErr_Fetch(&m_exception_type, &m_exception, &m_traceback); |
950 | 170 | PyErr_NormalizeException(&m_exception_type, &m_exception, &m_traceback); |
951 | 170 | PyErr_Clear(); |
952 | 170 | if (m_exception) { |
953 | 170 | PyObject *repr = PyObject_Repr(m_exception); |
954 | 170 | if (repr) { |
955 | 170 | m_repr_bytes = PyUnicode_AsEncodedString(repr, "utf-8", nullptr); |
956 | 170 | if (!m_repr_bytes) { |
957 | 0 | PyErr_Clear(); |
958 | 0 | } |
959 | 170 | Py_XDECREF(repr); |
960 | 170 | } else { |
961 | 0 | PyErr_Clear(); |
962 | 0 | } |
963 | 170 | } |
964 | 170 | Log *log = GetLog(LLDBLog::Script); |
965 | 170 | if (caller) |
966 | 0 | LLDB_LOGF(log, "%s failed with exception: %s", caller, toCString()); |
967 | 170 | else |
968 | 170 | LLDB_LOGF(log, "python exception: %s", toCString()); |
969 | 170 | } |
970 | 5 | void PythonException::Restore() { |
971 | 5 | if (m_exception_type && m_exception) { |
972 | 5 | PyErr_Restore(m_exception_type, m_exception, m_traceback); |
973 | 5 | } else { |
974 | 0 | PyErr_SetString(PyExc_Exception, toCString()); |
975 | 0 | } |
976 | 5 | m_exception_type = m_exception = m_traceback = nullptr; |
977 | 5 | } |
978 | | |
979 | 170 | PythonException::~PythonException() { |
980 | 170 | Py_XDECREF(m_exception_type); |
981 | 170 | Py_XDECREF(m_exception); |
982 | 170 | Py_XDECREF(m_traceback); |
983 | 170 | Py_XDECREF(m_repr_bytes); |
984 | 170 | } |
985 | | |
986 | 15 | void PythonException::log(llvm::raw_ostream &OS) const { OS << toCString(); } |
987 | | |
988 | 0 | std::error_code PythonException::convertToErrorCode() const { |
989 | 0 | return llvm::inconvertibleErrorCode(); |
990 | 0 | } |
991 | | |
992 | 3 | bool PythonException::Matches(PyObject *exc) const { |
993 | 3 | return PyErr_GivenExceptionMatches(m_exception_type, exc); |
994 | 3 | } |
995 | | |
996 | | const char read_exception_script[] = R"( |
997 | | import sys |
998 | | from traceback import print_exception |
999 | | if sys.version_info.major < 3: |
1000 | | from StringIO import StringIO |
1001 | | else: |
1002 | | from io import StringIO |
1003 | | def main(exc_type, exc_value, tb): |
1004 | | f = StringIO() |
1005 | | print_exception(exc_type, exc_value, tb, file=f) |
1006 | | return f.getvalue() |
1007 | | )"; |
1008 | | |
1009 | 8 | std::string PythonException::ReadBacktrace() const { |
1010 | | |
1011 | 8 | if (!m_traceback) |
1012 | 1 | return toCString(); |
1013 | | |
1014 | | // no need to synchronize access to this global, we already have the GIL |
1015 | 7 | static PythonScript read_exception(read_exception_script); |
1016 | | |
1017 | 7 | Expected<std::string> backtrace = As<std::string>( |
1018 | 7 | read_exception(m_exception_type, m_exception, m_traceback)); |
1019 | | |
1020 | 7 | if (!backtrace) { |
1021 | 0 | std::string message = |
1022 | 0 | std::string(toCString()) + "\n" + |
1023 | 0 | "Traceback unavailable, an error occurred while reading it:\n"; |
1024 | 0 | return (message + llvm::toString(backtrace.takeError())); |
1025 | 0 | } |
1026 | | |
1027 | 7 | return std::move(backtrace.get()); |
1028 | 7 | } |
1029 | | |
1030 | | char PythonException::ID = 0; |
1031 | | |
1032 | | llvm::Expected<File::OpenOptions> |
1033 | 168 | GetOptionsForPyObject(const PythonObject &obj) { |
1034 | 168 | auto options = File::OpenOptions(0); |
1035 | 168 | auto readable = As<bool>(obj.CallMethod("readable")); |
1036 | 168 | if (!readable) |
1037 | 0 | return readable.takeError(); |
1038 | 168 | auto writable = As<bool>(obj.CallMethod("writable")); |
1039 | 168 | if (!writable) |
1040 | 1 | return writable.takeError(); |
1041 | 167 | if (readable.get() && writable.get()66 ) |
1042 | 4 | options |= File::eOpenOptionReadWrite; |
1043 | 163 | else if (writable.get()) |
1044 | 101 | options |= File::eOpenOptionWriteOnly; |
1045 | 62 | else if (readable.get()) |
1046 | 62 | options |= File::eOpenOptionReadOnly; |
1047 | 167 | return options; |
1048 | 168 | } |
1049 | | |
1050 | | // Base class template for python files. All it knows how to do |
1051 | | // is hold a reference to the python object and close or flush it |
1052 | | // when the File is closed. |
1053 | | namespace { |
1054 | | template <typename Base> class OwnedPythonFile : public Base { |
1055 | | public: |
1056 | | template <typename... Args> |
1057 | | OwnedPythonFile(const PythonFile &file, bool borrowed, Args... args) |
1058 | 56 | : Base(args...), m_py_obj(file), m_borrowed(borrowed) { |
1059 | 56 | assert(m_py_obj); |
1060 | 56 | } PythonDataObjects.cpp:(anonymous namespace)::OwnedPythonFile<lldb_private::NativeFile>::OwnedPythonFile<int, lldb_private::File::OpenOptions, bool>(lldb_private::python::PythonFile const&, bool, int, lldb_private::File::OpenOptions, bool) Line | Count | Source | 1058 | 24 | : Base(args...), m_py_obj(file), m_borrowed(borrowed) { | 1059 | 24 | assert(m_py_obj); | 1060 | 24 | } |
PythonDataObjects.cpp:(anonymous namespace)::OwnedPythonFile<lldb_private::File>::OwnedPythonFile<>(lldb_private::python::PythonFile const&, bool) Line | Count | Source | 1058 | 32 | : Base(args...), m_py_obj(file), m_borrowed(borrowed) { | 1059 | 32 | assert(m_py_obj); | 1060 | 32 | } |
|
1061 | | |
1062 | 56 | ~OwnedPythonFile() override { |
1063 | 56 | assert(m_py_obj); |
1064 | 56 | GIL takeGIL; |
1065 | 56 | Close(); |
1066 | | // we need to ensure the python object is released while we still |
1067 | | // hold the GIL |
1068 | 56 | m_py_obj.Reset(); |
1069 | 56 | } PythonDataObjects.cpp:(anonymous namespace)::OwnedPythonFile<lldb_private::NativeFile>::~OwnedPythonFile() Line | Count | Source | 1062 | 24 | ~OwnedPythonFile() override { | 1063 | 24 | assert(m_py_obj); | 1064 | 24 | GIL takeGIL; | 1065 | 24 | Close(); | 1066 | | // we need to ensure the python object is released while we still | 1067 | | // hold the GIL | 1068 | 24 | m_py_obj.Reset(); | 1069 | 24 | } |
PythonDataObjects.cpp:(anonymous namespace)::OwnedPythonFile<lldb_private::File>::~OwnedPythonFile() Line | Count | Source | 1062 | 32 | ~OwnedPythonFile() override { | 1063 | 32 | assert(m_py_obj); | 1064 | 32 | GIL takeGIL; | 1065 | 32 | Close(); | 1066 | | // we need to ensure the python object is released while we still | 1067 | | // hold the GIL | 1068 | 32 | m_py_obj.Reset(); | 1069 | 32 | } |
|
1070 | | |
1071 | 123 | bool IsPythonSideValid() const { |
1072 | 123 | GIL takeGIL; |
1073 | 123 | auto closed = As<bool>(m_py_obj.GetAttribute("closed")); |
1074 | 123 | if (!closed) { |
1075 | 0 | llvm::consumeError(closed.takeError()); |
1076 | 0 | return false; |
1077 | 0 | } |
1078 | 123 | return !closed.get(); |
1079 | 123 | } PythonDataObjects.cpp:(anonymous namespace)::OwnedPythonFile<lldb_private::NativeFile>::IsPythonSideValid() const Line | Count | Source | 1071 | 62 | bool IsPythonSideValid() const { | 1072 | 62 | GIL takeGIL; | 1073 | 62 | auto closed = As<bool>(m_py_obj.GetAttribute("closed")); | 1074 | 62 | if (!closed) { | 1075 | 0 | llvm::consumeError(closed.takeError()); | 1076 | 0 | return false; | 1077 | 0 | } | 1078 | 62 | return !closed.get(); | 1079 | 62 | } |
PythonDataObjects.cpp:(anonymous namespace)::OwnedPythonFile<lldb_private::File>::IsPythonSideValid() const Line | Count | Source | 1071 | 61 | bool IsPythonSideValid() const { | 1072 | 61 | GIL takeGIL; | 1073 | 61 | auto closed = As<bool>(m_py_obj.GetAttribute("closed")); | 1074 | 61 | if (!closed) { | 1075 | 0 | llvm::consumeError(closed.takeError()); | 1076 | 0 | return false; | 1077 | 0 | } | 1078 | 61 | return !closed.get(); | 1079 | 61 | } |
|
1080 | | |
1081 | 62 | bool IsValid() const override { |
1082 | 62 | return IsPythonSideValid() && Base::IsValid(); |
1083 | 62 | } PythonDataObjects.cpp:(anonymous namespace)::OwnedPythonFile<lldb_private::NativeFile>::IsValid() const Line | Count | Source | 1081 | 62 | bool IsValid() const override { | 1082 | 62 | return IsPythonSideValid() && Base::IsValid(); | 1083 | 62 | } |
Unexecuted instantiation: PythonDataObjects.cpp:(anonymous namespace)::OwnedPythonFile<lldb_private::File>::IsValid() const |
1084 | | |
1085 | 62 | Status Close() override { |
1086 | 62 | assert(m_py_obj); |
1087 | 62 | Status py_error, base_error; |
1088 | 62 | GIL takeGIL; |
1089 | 62 | if (!m_borrowed) { |
1090 | 50 | auto r = m_py_obj.CallMethod("close"); |
1091 | 50 | if (!r) |
1092 | 0 | py_error = Status(r.takeError()); |
1093 | 50 | } |
1094 | 62 | base_error = Base::Close(); |
1095 | 62 | if (py_error.Fail()) |
1096 | 0 | return py_error; |
1097 | 62 | return base_error; |
1098 | 62 | }; PythonDataObjects.cpp:(anonymous namespace)::OwnedPythonFile<lldb_private::NativeFile>::Close() Line | Count | Source | 1085 | 30 | Status Close() override { | 1086 | 30 | assert(m_py_obj); | 1087 | 30 | Status py_error, base_error; | 1088 | 30 | GIL takeGIL; | 1089 | 30 | if (!m_borrowed) { | 1090 | 30 | auto r = m_py_obj.CallMethod("close"); | 1091 | 30 | if (!r) | 1092 | 0 | py_error = Status(r.takeError()); | 1093 | 30 | } | 1094 | 30 | base_error = Base::Close(); | 1095 | 30 | if (py_error.Fail()) | 1096 | 0 | return py_error; | 1097 | 30 | return base_error; | 1098 | 30 | }; |
PythonDataObjects.cpp:(anonymous namespace)::OwnedPythonFile<lldb_private::File>::Close() Line | Count | Source | 1085 | 32 | Status Close() override { | 1086 | 32 | assert(m_py_obj); | 1087 | 32 | Status py_error, base_error; | 1088 | 32 | GIL takeGIL; | 1089 | 32 | if (!m_borrowed) { | 1090 | 20 | auto r = m_py_obj.CallMethod("close"); | 1091 | 20 | if (!r) | 1092 | 0 | py_error = Status(r.takeError()); | 1093 | 20 | } | 1094 | 32 | base_error = Base::Close(); | 1095 | 32 | if (py_error.Fail()) | 1096 | 0 | return py_error; | 1097 | 32 | return base_error; | 1098 | 32 | }; |
|
1099 | | |
1100 | 7 | PyObject *GetPythonObject() const { |
1101 | 7 | assert(m_py_obj.IsValid()); |
1102 | 7 | return m_py_obj.get(); |
1103 | 7 | } PythonDataObjects.cpp:(anonymous namespace)::OwnedPythonFile<lldb_private::NativeFile>::GetPythonObject() const Line | Count | Source | 1100 | 1 | PyObject *GetPythonObject() const { | 1101 | 1 | assert(m_py_obj.IsValid()); | 1102 | 1 | return m_py_obj.get(); | 1103 | 1 | } |
PythonDataObjects.cpp:(anonymous namespace)::OwnedPythonFile<lldb_private::File>::GetPythonObject() const Line | Count | Source | 1100 | 6 | PyObject *GetPythonObject() const { | 1101 | 6 | assert(m_py_obj.IsValid()); | 1102 | 6 | return m_py_obj.get(); | 1103 | 6 | } |
|
1104 | | |
1105 | | static bool classof(const File *file) = delete; |
1106 | | |
1107 | | protected: |
1108 | | PythonFile m_py_obj; |
1109 | | bool m_borrowed; |
1110 | | }; |
1111 | | } // namespace |
1112 | | |
1113 | | // A SimplePythonFile is a OwnedPythonFile that just does all I/O as |
1114 | | // a NativeFile |
1115 | | namespace { |
1116 | | class SimplePythonFile : public OwnedPythonFile<NativeFile> { |
1117 | | public: |
1118 | | SimplePythonFile(const PythonFile &file, bool borrowed, int fd, |
1119 | | File::OpenOptions options) |
1120 | 24 | : OwnedPythonFile(file, borrowed, fd, options, false) {} |
1121 | | |
1122 | | static char ID; |
1123 | 1 | bool isA(const void *classID) const override { |
1124 | 1 | return classID == &ID || NativeFile::isA(classID)0 ; |
1125 | 1 | } |
1126 | 19.1k | static bool classof(const File *file) { return file->isA(&ID); } |
1127 | | }; |
1128 | | char SimplePythonFile::ID = 0; |
1129 | | } // namespace |
1130 | | |
1131 | | namespace { |
1132 | | class PythonBuffer { |
1133 | | public: |
1134 | | PythonBuffer &operator=(const PythonBuffer &) = delete; |
1135 | | PythonBuffer(const PythonBuffer &) = delete; |
1136 | | |
1137 | | static Expected<PythonBuffer> Create(PythonObject &obj, |
1138 | 3 | int flags = PyBUF_SIMPLE) { |
1139 | 3 | Py_buffer py_buffer = {}; |
1140 | 3 | PyObject_GetBuffer(obj.get(), &py_buffer, flags); |
1141 | 3 | if (!py_buffer.obj) |
1142 | 0 | return llvm::make_error<PythonException>(); |
1143 | 3 | return PythonBuffer(py_buffer); |
1144 | 3 | } |
1145 | | |
1146 | 3 | PythonBuffer(PythonBuffer &&other) { |
1147 | 3 | m_buffer = other.m_buffer; |
1148 | 3 | other.m_buffer.obj = nullptr; |
1149 | 3 | } |
1150 | | |
1151 | 6 | ~PythonBuffer() { |
1152 | 6 | if (m_buffer.obj) |
1153 | 3 | PyBuffer_Release(&m_buffer); |
1154 | 6 | } |
1155 | | |
1156 | 9 | Py_buffer &get() { return m_buffer; } |
1157 | | |
1158 | | private: |
1159 | | // takes ownership of the buffer. |
1160 | 3 | PythonBuffer(const Py_buffer &py_buffer) : m_buffer(py_buffer) {} |
1161 | | Py_buffer m_buffer; |
1162 | | }; |
1163 | | } // namespace |
1164 | | |
1165 | | // Shared methods between TextPythonFile and BinaryPythonFile |
1166 | | namespace { |
1167 | | class PythonIOFile : public OwnedPythonFile<File> { |
1168 | | public: |
1169 | | PythonIOFile(const PythonFile &file, bool borrowed) |
1170 | 32 | : OwnedPythonFile(file, borrowed) {} |
1171 | | |
1172 | 32 | ~PythonIOFile() override { Close(); } |
1173 | | |
1174 | 61 | bool IsValid() const override { return IsPythonSideValid(); } |
1175 | | |
1176 | 42 | Status Close() override { |
1177 | 42 | assert(m_py_obj); |
1178 | 42 | GIL takeGIL; |
1179 | 42 | if (m_borrowed) |
1180 | 15 | return Flush(); |
1181 | 27 | auto r = m_py_obj.CallMethod("close"); |
1182 | 27 | if (!r) |
1183 | 3 | return Status(r.takeError()); |
1184 | 24 | return Status(); |
1185 | 27 | } |
1186 | | |
1187 | 28 | Status Flush() override { |
1188 | 28 | GIL takeGIL; |
1189 | 28 | auto r = m_py_obj.CallMethod("flush"); |
1190 | 28 | if (!r) |
1191 | 4 | return Status(r.takeError()); |
1192 | 24 | return Status(); |
1193 | 28 | } |
1194 | | |
1195 | 0 | Expected<File::OpenOptions> GetOptions() const override { |
1196 | 0 | GIL takeGIL; |
1197 | 0 | return GetOptionsForPyObject(m_py_obj); |
1198 | 0 | } |
1199 | | |
1200 | | static char ID; |
1201 | 12 | bool isA(const void *classID) const override { |
1202 | 12 | return classID == &ID || File::isA(classID)6 ; |
1203 | 12 | } |
1204 | 19.1k | static bool classof(const File *file) { return file->isA(&ID); } |
1205 | | }; |
1206 | | char PythonIOFile::ID = 0; |
1207 | | } // namespace |
1208 | | |
1209 | | namespace { |
1210 | | class BinaryPythonFile : public PythonIOFile { |
1211 | | protected: |
1212 | | int m_descriptor; |
1213 | | |
1214 | | public: |
1215 | | BinaryPythonFile(int fd, const PythonFile &file, bool borrowed) |
1216 | 6 | : PythonIOFile(file, borrowed), |
1217 | 6 | m_descriptor(File::DescriptorIsValid(fd) ? fd2 |
1218 | 6 | : File::kInvalidDescriptor4 ) {} |
1219 | | |
1220 | 2 | int GetDescriptor() const override { return m_descriptor; } |
1221 | | |
1222 | 107 | Status Write(const void *buf, size_t &num_bytes) override { |
1223 | 107 | GIL takeGIL; |
1224 | 107 | PyObject *pybuffer_p = PyMemoryView_FromMemory( |
1225 | 107 | const_cast<char *>((const char *)buf), num_bytes, PyBUF_READ); |
1226 | 107 | if (!pybuffer_p) |
1227 | 0 | return Status(llvm::make_error<PythonException>()); |
1228 | 107 | auto pybuffer = Take<PythonObject>(pybuffer_p); |
1229 | 107 | num_bytes = 0; |
1230 | 107 | auto bytes_written = As<long long>(m_py_obj.CallMethod("write", pybuffer)); |
1231 | 107 | if (!bytes_written) |
1232 | 0 | return Status(bytes_written.takeError()); |
1233 | 107 | if (bytes_written.get() < 0) |
1234 | 0 | return Status(".write() method returned a negative number!"); |
1235 | 107 | static_assert(sizeof(long long) >= sizeof(size_t), "overflow"); |
1236 | 107 | num_bytes = bytes_written.get(); |
1237 | 107 | return Status(); |
1238 | 107 | } |
1239 | | |
1240 | 3 | Status Read(void *buf, size_t &num_bytes) override { |
1241 | 3 | GIL takeGIL; |
1242 | 3 | static_assert(sizeof(long long) >= sizeof(size_t), "overflow"); |
1243 | 3 | auto pybuffer_obj = |
1244 | 3 | m_py_obj.CallMethod("read", (unsigned long long)num_bytes); |
1245 | 3 | if (!pybuffer_obj) |
1246 | 0 | return Status(pybuffer_obj.takeError()); |
1247 | 3 | num_bytes = 0; |
1248 | 3 | if (pybuffer_obj.get().IsNone()) { |
1249 | | // EOF |
1250 | 0 | num_bytes = 0; |
1251 | 0 | return Status(); |
1252 | 0 | } |
1253 | 3 | auto pybuffer = PythonBuffer::Create(pybuffer_obj.get()); |
1254 | 3 | if (!pybuffer) |
1255 | 0 | return Status(pybuffer.takeError()); |
1256 | 3 | memcpy(buf, pybuffer.get().get().buf, pybuffer.get().get().len); |
1257 | 3 | num_bytes = pybuffer.get().get().len; |
1258 | 3 | return Status(); |
1259 | 3 | } |
1260 | | }; |
1261 | | } // namespace |
1262 | | |
1263 | | namespace { |
1264 | | class TextPythonFile : public PythonIOFile { |
1265 | | protected: |
1266 | | int m_descriptor; |
1267 | | |
1268 | | public: |
1269 | | TextPythonFile(int fd, const PythonFile &file, bool borrowed) |
1270 | 26 | : PythonIOFile(file, borrowed), |
1271 | 26 | m_descriptor(File::DescriptorIsValid(fd) ? fd2 |
1272 | 26 | : File::kInvalidDescriptor24 ) {} |
1273 | | |
1274 | 2 | int GetDescriptor() const override { return m_descriptor; } |
1275 | | |
1276 | 206 | Status Write(const void *buf, size_t &num_bytes) override { |
1277 | 206 | GIL takeGIL; |
1278 | 206 | auto pystring = |
1279 | 206 | PythonString::FromUTF8(llvm::StringRef((const char *)buf, num_bytes)); |
1280 | 206 | if (!pystring) |
1281 | 0 | return Status(pystring.takeError()); |
1282 | 206 | num_bytes = 0; |
1283 | 206 | auto bytes_written = |
1284 | 206 | As<long long>(m_py_obj.CallMethod("write", pystring.get())); |
1285 | 206 | if (!bytes_written) |
1286 | 2 | return Status(bytes_written.takeError()); |
1287 | 204 | if (bytes_written.get() < 0) |
1288 | 0 | return Status(".write() method returned a negative number!"); |
1289 | 204 | static_assert(sizeof(long long) >= sizeof(size_t), "overflow"); |
1290 | 204 | num_bytes = bytes_written.get(); |
1291 | 204 | return Status(); |
1292 | 204 | } |
1293 | | |
1294 | 5 | Status Read(void *buf, size_t &num_bytes) override { |
1295 | 5 | GIL takeGIL; |
1296 | 5 | size_t num_chars = num_bytes / 6; |
1297 | 5 | size_t orig_num_bytes = num_bytes; |
1298 | 5 | num_bytes = 0; |
1299 | 5 | if (orig_num_bytes < 6) { |
1300 | 1 | return Status("can't read less than 6 bytes from a utf8 text stream"); |
1301 | 1 | } |
1302 | 4 | auto pystring = As<PythonString>( |
1303 | 4 | m_py_obj.CallMethod("read", (unsigned long long)num_chars)); |
1304 | 4 | if (!pystring) |
1305 | 1 | return Status(pystring.takeError()); |
1306 | 3 | if (pystring.get().IsNone()) { |
1307 | | // EOF |
1308 | 0 | return Status(); |
1309 | 0 | } |
1310 | 3 | auto stringref = pystring.get().AsUTF8(); |
1311 | 3 | if (!stringref) |
1312 | 0 | return Status(stringref.takeError()); |
1313 | 3 | num_bytes = stringref.get().size(); |
1314 | 3 | memcpy(buf, stringref.get().begin(), num_bytes); |
1315 | 3 | return Status(); |
1316 | 3 | } |
1317 | | }; |
1318 | | } // namespace |
1319 | | |
1320 | 196 | llvm::Expected<FileSP> PythonFile::ConvertToFile(bool borrowed) { |
1321 | 196 | if (!IsValid()) |
1322 | 0 | return llvm::createStringError(llvm::inconvertibleErrorCode(), |
1323 | 0 | "invalid PythonFile"); |
1324 | | |
1325 | 196 | int fd = PyObject_AsFileDescriptor(m_py_obj); |
1326 | 196 | if (fd < 0) { |
1327 | 28 | PyErr_Clear(); |
1328 | 28 | return ConvertToFileForcingUseOfScriptingIOMethods(borrowed); |
1329 | 28 | } |
1330 | 168 | auto options = GetOptionsForPyObject(*this); |
1331 | 168 | if (!options) |
1332 | 1 | return options.takeError(); |
1333 | | |
1334 | 167 | File::OpenOptions rw = |
1335 | 167 | options.get() & (File::eOpenOptionReadOnly | File::eOpenOptionWriteOnly | |
1336 | 167 | File::eOpenOptionReadWrite); |
1337 | 167 | if (rw == File::eOpenOptionWriteOnly || rw == File::eOpenOptionReadWrite66 ) { |
1338 | | // LLDB and python will not share I/O buffers. We should probably |
1339 | | // flush the python buffers now. |
1340 | 105 | auto r = CallMethod("flush"); |
1341 | 105 | if (!r) |
1342 | 0 | return r.takeError(); |
1343 | 105 | } |
1344 | | |
1345 | 167 | FileSP file_sp; |
1346 | 167 | if (borrowed) { |
1347 | | // In this case we don't need to retain the python |
1348 | | // object at all. |
1349 | 143 | file_sp = std::make_shared<NativeFile>(fd, options.get(), false); |
1350 | 143 | } else { |
1351 | 24 | file_sp = std::static_pointer_cast<File>( |
1352 | 24 | std::make_shared<SimplePythonFile>(*this, borrowed, fd, options.get())); |
1353 | 24 | } |
1354 | 167 | if (!file_sp->IsValid()) |
1355 | 0 | return llvm::createStringError(llvm::inconvertibleErrorCode(), |
1356 | 0 | "invalid File"); |
1357 | | |
1358 | 167 | return file_sp; |
1359 | 167 | } |
1360 | | |
1361 | | llvm::Expected<FileSP> |
1362 | 32 | PythonFile::ConvertToFileForcingUseOfScriptingIOMethods(bool borrowed) { |
1363 | | |
1364 | 32 | assert(!PyErr_Occurred()); |
1365 | | |
1366 | 32 | if (!IsValid()) |
1367 | 0 | return llvm::createStringError(llvm::inconvertibleErrorCode(), |
1368 | 0 | "invalid PythonFile"); |
1369 | | |
1370 | 32 | int fd = PyObject_AsFileDescriptor(m_py_obj); |
1371 | 32 | if (fd < 0) { |
1372 | 28 | PyErr_Clear(); |
1373 | 28 | fd = File::kInvalidDescriptor; |
1374 | 28 | } |
1375 | | |
1376 | 32 | auto io_module = PythonModule::Import("io"); |
1377 | 32 | if (!io_module) |
1378 | 0 | return io_module.takeError(); |
1379 | 32 | auto textIOBase = io_module.get().Get("TextIOBase"); |
1380 | 32 | if (!textIOBase) |
1381 | 0 | return textIOBase.takeError(); |
1382 | 32 | auto rawIOBase = io_module.get().Get("RawIOBase"); |
1383 | 32 | if (!rawIOBase) |
1384 | 0 | return rawIOBase.takeError(); |
1385 | 32 | auto bufferedIOBase = io_module.get().Get("BufferedIOBase"); |
1386 | 32 | if (!bufferedIOBase) |
1387 | 0 | return bufferedIOBase.takeError(); |
1388 | | |
1389 | 32 | FileSP file_sp; |
1390 | | |
1391 | 32 | auto isTextIO = IsInstance(textIOBase.get()); |
1392 | 32 | if (!isTextIO) |
1393 | 0 | return isTextIO.takeError(); |
1394 | 32 | if (isTextIO.get()) |
1395 | 26 | file_sp = std::static_pointer_cast<File>( |
1396 | 26 | std::make_shared<TextPythonFile>(fd, *this, borrowed)); |
1397 | | |
1398 | 32 | auto isRawIO = IsInstance(rawIOBase.get()); |
1399 | 32 | if (!isRawIO) |
1400 | 0 | return isRawIO.takeError(); |
1401 | 32 | auto isBufferedIO = IsInstance(bufferedIOBase.get()); |
1402 | 32 | if (!isBufferedIO) |
1403 | 0 | return isBufferedIO.takeError(); |
1404 | | |
1405 | 32 | if (isRawIO.get() || isBufferedIO.get()) { |
1406 | 6 | file_sp = std::static_pointer_cast<File>( |
1407 | 6 | std::make_shared<BinaryPythonFile>(fd, *this, borrowed)); |
1408 | 6 | } |
1409 | | |
1410 | 32 | if (!file_sp) |
1411 | 0 | return llvm::createStringError(llvm::inconvertibleErrorCode(), |
1412 | 0 | "python file is neither text nor binary"); |
1413 | | |
1414 | 32 | if (!file_sp->IsValid()) |
1415 | 0 | return llvm::createStringError(llvm::inconvertibleErrorCode(), |
1416 | 0 | "invalid File"); |
1417 | | |
1418 | 32 | return file_sp; |
1419 | 32 | } |
1420 | | |
1421 | 19.1k | Expected<PythonFile> PythonFile::FromFile(File &file, const char *mode) { |
1422 | 19.1k | if (!file.IsValid()) |
1423 | 0 | return llvm::createStringError(llvm::inconvertibleErrorCode(), |
1424 | 0 | "invalid file"); |
1425 | | |
1426 | 19.1k | if (auto *simple = llvm::dyn_cast<SimplePythonFile>(&file)) |
1427 | 1 | return Retain<PythonFile>(simple->GetPythonObject()); |
1428 | 19.1k | if (auto *pythonio = llvm::dyn_cast<PythonIOFile>(&file)) |
1429 | 6 | return Retain<PythonFile>(pythonio->GetPythonObject()); |
1430 | | |
1431 | 19.1k | if (!mode) { |
1432 | 18 | auto m = file.GetOpenMode(); |
1433 | 18 | if (!m) |
1434 | 0 | return m.takeError(); |
1435 | 18 | mode = m.get(); |
1436 | 18 | } |
1437 | | |
1438 | 19.1k | PyObject *file_obj; |
1439 | 19.1k | file_obj = PyFile_FromFd(file.GetDescriptor(), nullptr, mode, -1, nullptr, |
1440 | 19.1k | "ignore", nullptr, /*closefd=*/0); |
1441 | | |
1442 | 19.1k | if (!file_obj) |
1443 | 0 | return exception(); |
1444 | | |
1445 | 19.1k | return Take<PythonFile>(file_obj); |
1446 | 19.1k | } |
1447 | | |
1448 | 343 | Error PythonScript::Init() { |
1449 | 343 | if (function.IsValid()) |
1450 | 288 | return Error::success(); |
1451 | | |
1452 | 55 | PythonDictionary globals(PyInitialValue::Empty); |
1453 | 55 | auto builtins = PythonModule::BuiltinsModule(); |
1454 | 55 | if (Error error = globals.SetItem("__builtins__", builtins)) |
1455 | 0 | return error; |
1456 | 55 | PyObject *o = |
1457 | 55 | PyRun_String(script, Py_file_input, globals.get(), globals.get()); |
1458 | 55 | if (!o) |
1459 | 0 | return exception(); |
1460 | 55 | Take<PythonObject>(o); |
1461 | 55 | auto f = As<PythonCallable>(globals.GetItem("main")); |
1462 | 55 | if (!f) |
1463 | 0 | return f.takeError(); |
1464 | 55 | function = std::move(f.get()); |
1465 | | |
1466 | 55 | return Error::success(); |
1467 | 55 | } |
1468 | | |
1469 | | llvm::Expected<PythonObject> |
1470 | | python::runStringOneLine(const llvm::Twine &string, |
1471 | | const PythonDictionary &globals, |
1472 | 5.81k | const PythonDictionary &locals) { |
1473 | 5.81k | if (!globals.IsValid() || !locals.IsValid()) |
1474 | 0 | return nullDeref(); |
1475 | | |
1476 | 5.81k | PyObject *code = |
1477 | 5.81k | Py_CompileString(NullTerminated(string), "<string>", Py_eval_input); |
1478 | 5.81k | if (!code) { |
1479 | 1 | PyErr_Clear(); |
1480 | 1 | code = |
1481 | 1 | Py_CompileString(NullTerminated(string), "<string>", Py_single_input); |
1482 | 1 | } |
1483 | 5.81k | if (!code) |
1484 | 0 | return exception(); |
1485 | 5.81k | auto code_ref = Take<PythonObject>(code); |
1486 | | |
1487 | 5.81k | PyObject *result = PyEval_EvalCode(code, globals.get(), locals.get()); |
1488 | | |
1489 | 5.81k | if (!result) |
1490 | 3 | return exception(); |
1491 | | |
1492 | 5.80k | return Take<PythonObject>(result); |
1493 | 5.81k | } |
1494 | | |
1495 | | llvm::Expected<PythonObject> |
1496 | | python::runStringMultiLine(const llvm::Twine &string, |
1497 | | const PythonDictionary &globals, |
1498 | 276 | const PythonDictionary &locals) { |
1499 | 276 | if (!globals.IsValid() || !locals.IsValid()) |
1500 | 0 | return nullDeref(); |
1501 | 276 | PyObject *result = PyRun_String(NullTerminated(string), Py_file_input, |
1502 | 276 | globals.get(), locals.get()); |
1503 | 276 | if (!result) |
1504 | 5 | return exception(); |
1505 | 271 | return Take<PythonObject>(result); |
1506 | 276 | } |
1507 | | |
1508 | | #endif |