remove multi-argument form of PythonObject::Reset()

Summary:
With this patch, only the no-argument form of `Reset()` remains in
PythonDataObjects.   It also deletes PythonExceptionState in favor of
PythonException, because the only call-site of PythonExceptionState was
also using Reset, so I cleaned up both while I was there.

Reviewers: JDevlieghere, clayborg, labath, jingham

Reviewed By: labath

Subscribers: mgorny, lldb-commits

Tags: #lldb

Differential Revision: https://reviews.llvm.org/D69214

llvm-svn: 375475
This commit is contained in:
Lawrence D'Anna
2019-10-22 02:32:37 +00:00
parent b94ac8a263
commit 04edd1893c
15 changed files with 451 additions and 866 deletions

View File

@@ -261,8 +261,7 @@ size_t PythonBytes::GetSize() const {
void PythonBytes::SetBytes(llvm::ArrayRef<uint8_t> bytes) {
const char *data = reinterpret_cast<const char *>(bytes.data());
PyObject *py_bytes = PyBytes_FromStringAndSize(data, bytes.size());
PythonObject::Reset(PyRefType::Owned, py_bytes);
*this = Take<PythonBytes>(PyBytes_FromStringAndSize(data, bytes.size()));
}
StructuredData::StringSP PythonBytes::CreateStructuredString() const {
@@ -486,7 +485,7 @@ int64_t PythonInteger::GetInteger() const {
}
void PythonInteger::SetInteger(int64_t value) {
PythonObject::Reset(PyRefType::Owned, PyLong_FromLongLong(value));
*this = Take<PythonInteger>(PyLong_FromLongLong(value));
}
StructuredData::IntegerSP PythonInteger::CreateStructuredInteger() const {
@@ -510,7 +509,7 @@ bool PythonBoolean::GetValue() const {
}
void PythonBoolean::SetValue(bool value) {
PythonObject::Reset(PyRefType::Owned, PyBool_FromLong(value));
*this = Take<PythonBoolean>(PyBool_FromLong(value));
}
StructuredData::BooleanSP PythonBoolean::CreateStructuredBoolean() const {
@@ -826,7 +825,7 @@ static const char get_arg_info_script[] = R"(
from inspect import signature, Parameter, ismethod
from collections import namedtuple
ArgInfo = namedtuple('ArgInfo', ['count', 'has_varargs', 'is_bound_method'])
def get_arg_info(f):
def main(f):
count = 0
varargs = False
for parameter in signature(f).parameters.values():
@@ -852,28 +851,9 @@ Expected<PythonCallable::ArgInfo> PythonCallable::GetArgInfo() const {
#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3
// this global is protected by the GIL
static PythonCallable get_arg_info;
if (!get_arg_info.IsValid()) {
PythonDictionary globals(PyInitialValue::Empty);
auto builtins = PythonModule::BuiltinsModule();
Error error = globals.SetItem("__builtins__", builtins);
if (error)
return std::move(error);
PyObject *o = PyRun_String(get_arg_info_script, Py_file_input,
globals.get(), globals.get());
if (!o)
return exception();
Take<PythonObject>(o);
auto function = As<PythonCallable>(globals.GetItem("get_arg_info"));
if (!function)
return function.takeError();
get_arg_info = std::move(function.get());
}
Expected<PythonObject> pyarginfo = get_arg_info.Call(*this);
// no need to synchronize access to this global, we already have the GIL
static PythonScript get_arg_info(get_arg_info_script);
Expected<PythonObject> pyarginfo = get_arg_info(*this);
if (!pyarginfo)
return pyarginfo.takeError();
result.count = cantFail(As<long long>(pyarginfo.get().GetAttribute("count")));
@@ -1056,6 +1036,44 @@ std::error_code PythonException::convertToErrorCode() const {
return llvm::inconvertibleErrorCode();
}
bool PythonException::Matches(PyObject *exc) const {
return PyErr_GivenExceptionMatches(m_exception_type, exc);
}
const char read_exception_script[] = R"(
import sys
from traceback import print_exception
if sys.version_info.major < 3:
from StringIO import StringIO
else:
from io import StringIO
def main(exc_type, exc_value, tb):
f = StringIO()
print_exception(exc_type, exc_value, tb, file=f)
return f.getvalue()
)";
std::string PythonException::ReadBacktrace() const {
if (!m_traceback)
return toCString();
// no need to synchronize access to this global, we already have the GIL
static PythonScript read_exception(read_exception_script);
Expected<std::string> backtrace = As<std::string>(
read_exception(m_exception_type, m_exception, m_traceback));
if (!backtrace) {
std::string message =
std::string(toCString()) + "\n" +
"Traceback unavailble, an error occurred while reading it:\n";
return (message + llvm::toString(backtrace.takeError()));
}
return std::move(backtrace.get());
}
char PythonException::ID = 0;
llvm::Expected<File::OpenOptions>
@@ -1496,4 +1514,69 @@ Expected<PythonFile> PythonFile::FromFile(File &file, const char *mode) {
return Take<PythonFile>(file_obj);
}
Error PythonScript::Init() {
if (function.IsValid())
return Error::success();
PythonDictionary globals(PyInitialValue::Empty);
auto builtins = PythonModule::BuiltinsModule();
if (Error error = globals.SetItem("__builtins__", builtins))
return error;
PyObject *o =
PyRun_String(script, Py_file_input, globals.get(), globals.get());
if (!o)
return exception();
Take<PythonObject>(o);
auto f = As<PythonCallable>(globals.GetItem("main"));
if (!f)
return f.takeError();
function = std::move(f.get());
return Error::success();
}
llvm::Expected<PythonObject>
python::runStringOneLine(const llvm::Twine &string,
const PythonDictionary &globals,
const PythonDictionary &locals) {
if (!globals.IsValid() || !locals.IsValid())
return nullDeref();
PyObject *code =
Py_CompileString(NullTerminated(string), "<string>", Py_eval_input);
if (!code) {
PyErr_Clear();
code =
Py_CompileString(NullTerminated(string), "<string>", Py_single_input);
}
if (!code)
return exception();
auto code_ref = Take<PythonObject>(code);
#if PY_MAJOR_VERSION < 3
PyObject *result =
PyEval_EvalCode((PyCodeObject *)code, globals.get(), locals.get());
#else
PyObject *result = PyEval_EvalCode(code, globals.get(), locals.get());
#endif
if (!result)
return exception();
return Take<PythonObject>(result);
}
llvm::Expected<PythonObject>
python::runStringMultiLine(const llvm::Twine &string,
const PythonDictionary &globals,
const PythonDictionary &locals) {
if (!globals.IsValid() || !locals.IsValid())
return nullDeref();
PyObject *result = PyRun_String(NullTerminated(string), Py_file_input,
globals.get(), locals.get());
if (!result)
return exception();
return Take<PythonObject>(result);
}
#endif