summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLawrence D'Anna <lawrence_danna@apple.com>2019-10-22 02:32:37 +0000
committerLawrence D'Anna <lawrence_danna@apple.com>2019-10-22 02:32:37 +0000
commitc302ff31dafa5b645899fcd2f2173d11f3264fc9 (patch)
treebe419f4cec9dfec09d34553cac17df89b35bbc81
parent72350e6ea8b317aeb75b709075601a842b807d18 (diff)
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 git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@375475 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/lldb/Interpreter/ScriptInterpreter.h3
-rw-r--r--scripts/Python/python-extensions.swig205
-rw-r--r--scripts/Python/python-typemaps.swig21
-rw-r--r--scripts/Python/python-wrapper.swig43
-rw-r--r--scripts/lldb.swig5
-rw-r--r--source/Plugins/ScriptInterpreter/Python/CMakeLists.txt1
-rw-r--r--source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp137
-rw-r--r--source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h115
-rw-r--r--source/Plugins/ScriptInterpreter/Python/PythonExceptionState.cpp169
-rw-r--r--source/Plugins/ScriptInterpreter/Python/PythonExceptionState.h56
-rw-r--r--source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp291
-rw-r--r--source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h26
-rw-r--r--unittests/ScriptInterpreter/Python/CMakeLists.txt1
-rw-r--r--unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp84
-rw-r--r--unittests/ScriptInterpreter/Python/PythonExceptionStateTests.cpp164
15 files changed, 453 insertions, 868 deletions
diff --git a/include/lldb/Interpreter/ScriptInterpreter.h b/include/lldb/Interpreter/ScriptInterpreter.h
index 3dd75b558..23fadf02e 100644
--- a/include/lldb/Interpreter/ScriptInterpreter.h
+++ b/include/lldb/Interpreter/ScriptInterpreter.h
@@ -65,6 +65,9 @@ public:
bool GetSetLLDBGlobals() const { return m_set_lldb_globals; }
+ // If this is true then any exceptions raised by the script will be
+ // cleared with PyErr_Clear(). If false then they will be left for
+ // the caller to clean up
bool GetMaskoutErrors() const { return m_maskout_errors; }
ExecuteScriptOptions &SetEnableIO(bool enable) {
diff --git a/scripts/Python/python-extensions.swig b/scripts/Python/python-extensions.swig
index 7823dc4ad..c10c32b44 100644
--- a/scripts/Python/python-extensions.swig
+++ b/scripts/Python/python-extensions.swig
@@ -8,10 +8,7 @@
size_t desc_len = description.GetSize();
if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r'))
--desc_len;
- if (desc_len > 0)
- return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release();
- else
- return lldb_private::PythonString("").release();
+ return PythonString(llvm::StringRef(desc, desc_len)).release();
}
%clearnothreadallow;
}
@@ -24,10 +21,7 @@
size_t desc_len = description.GetSize();
if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r'))
--desc_len;
- if (desc_len > 0)
- return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release();
- else
- return lldb_private::PythonString("").release();
+ return PythonString(llvm::StringRef(desc, desc_len)).release();
}
%clearnothreadallow;
}
@@ -40,10 +34,7 @@
size_t desc_len = description.GetSize();
if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r'))
--desc_len;
- if (desc_len > 0)
- return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release();
- else
- return lldb_private::PythonString("").release();
+ return PythonString(llvm::StringRef(desc, desc_len)).release();
}
%clearnothreadallow;
@@ -71,10 +62,7 @@
size_t desc_len = description.GetSize();
if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r'))
--desc_len;
- if (desc_len > 0)
- return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release();
- else
- return lldb_private::PythonString("").release();
+ return PythonString(llvm::StringRef(desc, desc_len)).release();
}
%clearnothreadallow;
}
@@ -88,10 +76,7 @@
size_t desc_len = description.GetSize();
if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r'))
--desc_len;
- if (desc_len > 0)
- return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release();
- else
- return lldb_private::PythonString("").release();
+ return PythonString(llvm::StringRef(desc, desc_len)).release();
}
%clearnothreadallow;
}
@@ -121,10 +106,7 @@
size_t desc_len = description.GetSize();
if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r'))
--desc_len;
- if (desc_len > 0)
- return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release();
- else
- return lldb_private::PythonString("").release();
+ return PythonString(llvm::StringRef(desc, desc_len)).release();
}
%clearnothreadallow;
@@ -150,10 +132,7 @@
size_t desc_len = description.GetSize();
if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r'))
--desc_len;
- if (desc_len > 0)
- return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release();
- else
- return lldb_private::PythonString("").release();
+ return PythonString(llvm::StringRef(desc, desc_len)).release();
}
%clearnothreadallow;
%pythoncode %{
@@ -179,10 +158,7 @@
size_t desc_len = description.GetSize();
if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r'))
--desc_len;
- if (desc_len > 0)
- return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release();
- else
- return lldb_private::PythonString("").release();
+ return PythonString(llvm::StringRef(desc, desc_len)).release();
}
%clearnothreadallow;
}
@@ -195,10 +171,7 @@
size_t desc_len = description.GetSize();
if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r'))
--desc_len;
- if (desc_len > 0)
- return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release();
- else
- return lldb_private::PythonString("").release();
+ return PythonString(llvm::StringRef(desc, desc_len)).release();
}
%clearnothreadallow;
}
@@ -211,10 +184,7 @@
size_t desc_len = description.GetSize();
if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r'))
--desc_len;
- if (desc_len > 0)
- return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release();
- else
- return lldb_private::PythonString("").release();
+ return PythonString(llvm::StringRef(desc, desc_len)).release();
}
%clearnothreadallow;
@@ -242,10 +212,7 @@
size_t desc_len = description.GetSize();
if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r'))
--desc_len;
- if (desc_len > 0)
- return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release();
- else
- return lldb_private::PythonString("").release();
+ return PythonString(llvm::StringRef(desc, desc_len)).release();
}
%clearnothreadallow;
}
@@ -258,10 +225,7 @@
size_t desc_len = description.GetSize();
if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r'))
--desc_len;
- if (desc_len > 0)
- return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release();
- else
- return lldb_private::PythonString("").release();
+ return PythonString(llvm::StringRef(desc, desc_len)).release();
}
%clearnothreadallow;
}
@@ -274,10 +238,7 @@
size_t desc_len = description.GetSize();
if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r'))
--desc_len;
- if (desc_len > 0)
- return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release();
- else
- return lldb_private::PythonString("").release();
+ return PythonString(llvm::StringRef(desc, desc_len)).release();
}
%clearnothreadallow;
}
@@ -290,10 +251,7 @@
size_t desc_len = description.GetSize();
if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r'))
--desc_len;
- if (desc_len > 0)
- return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release();
- else
- return lldb_private::PythonString("").release();
+ return PythonString(llvm::StringRef(desc, desc_len)).release();
}
%clearnothreadallow;
@@ -321,10 +279,7 @@
size_t desc_len = description.GetSize();
if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r'))
--desc_len;
- if (desc_len > 0)
- return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release();
- else
- return lldb_private::PythonString("").release();
+ return PythonString(llvm::StringRef(desc, desc_len)).release();
}
%clearnothreadallow;
}
@@ -337,10 +292,7 @@
size_t desc_len = description.GetSize();
if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r'))
--desc_len;
- if (desc_len > 0)
- return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release();
- else
- return lldb_private::PythonString("").release();
+ return PythonString(llvm::StringRef(desc, desc_len)).release();
}
%clearnothreadallow;
}
@@ -353,10 +305,7 @@
size_t desc_len = description.GetSize();
if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r'))
--desc_len;
- if (desc_len > 0)
- return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release();
- else
- return lldb_private::PythonString("").release();
+ return PythonString(llvm::StringRef(desc, desc_len)).release();
}
%clearnothreadallow;
@@ -384,10 +333,7 @@
size_t desc_len = description.GetSize();
if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r'))
--desc_len;
- if (desc_len > 0)
- return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release();
- else
- return lldb_private::PythonString("").release();
+ return PythonString(llvm::StringRef(desc, desc_len)).release();
}
%clearnothreadallow;
}
@@ -401,10 +347,7 @@
size_t desc_len = description.GetSize();
if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r'))
--desc_len;
- if (desc_len > 0)
- return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release();
- else
- return lldb_private::PythonString("").release();
+ return PythonString(llvm::StringRef(desc, desc_len)).release();
}
%clearnothreadallow;
@@ -432,10 +375,7 @@
size_t desc_len = description.GetSize();
if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r'))
--desc_len;
- if (desc_len > 0)
- return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release();
- else
- return lldb_private::PythonString("").release();
+ return PythonString(llvm::StringRef(desc, desc_len)).release();
}
%clearnothreadallow;
}
@@ -449,10 +389,7 @@
size_t desc_len = description.GetSize();
if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r'))
--desc_len;
- if (desc_len > 0)
- return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release();
- else
- return lldb_private::PythonString("").release();
+ return PythonString(llvm::StringRef(desc, desc_len)).release();
}
%clearnothreadallow;
}
@@ -466,10 +403,7 @@
size_t desc_len = description.GetSize();
if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r'))
--desc_len;
- if (desc_len > 0)
- return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release();
- else
- return lldb_private::PythonString("").release();
+ return PythonString(llvm::StringRef(desc, desc_len)).release();
}
%clearnothreadallow;
}
@@ -482,10 +416,7 @@
size_t desc_len = description.GetSize();
if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r'))
--desc_len;
- if (desc_len > 0)
- return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release();
- else
- return lldb_private::PythonString("").release();
+ return PythonString(llvm::StringRef(desc, desc_len)).release();
}
%clearnothreadallow;
@@ -526,10 +457,7 @@
size_t desc_len = description.GetSize();
if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r'))
--desc_len;
- if (desc_len > 0)
- return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release();
- else
- return lldb_private::PythonString("").release();
+ return PythonString(llvm::StringRef(desc, desc_len)).release();
}
%clearnothreadallow;
%pythoncode %{
@@ -555,10 +483,7 @@
size_t desc_len = description.GetSize();
if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r'))
--desc_len;
- if (desc_len > 0)
- return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release();
- else
- return lldb_private::PythonString("").release();
+ return PythonString(llvm::StringRef(desc, desc_len)).release();
}
%clearnothreadallow;
}
@@ -571,10 +496,7 @@
size_t desc_len = description.GetSize();
if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r'))
--desc_len;
- if (desc_len > 0)
- return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release();
- else
- return lldb_private::PythonString("").release();
+ return PythonString(llvm::StringRef(desc, desc_len)).release();
}
%clearnothreadallow;
}
@@ -588,10 +510,7 @@
size_t desc_len = description.GetSize();
if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r'))
--desc_len;
- if (desc_len > 0)
- return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release();
- else
- return lldb_private::PythonString("").release();
+ return PythonString(llvm::StringRef(desc, desc_len)).release();
}
%clearnothreadallow;
@@ -619,10 +538,7 @@
size_t desc_len = description.GetSize();
if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r'))
--desc_len;
- if (desc_len > 0)
- return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release();
- else
- return lldb_private::PythonString("").release();
+ return PythonString(llvm::StringRef(desc, desc_len)).release();
}
%clearnothreadallow;
}
@@ -635,10 +551,7 @@
size_t desc_len = description.GetSize();
if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r'))
--desc_len;
- if (desc_len > 0)
- return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release();
- else
- return lldb_private::PythonString("").release();
+ return PythonString(llvm::StringRef(desc, desc_len)).release();
}
%clearnothreadallow;
}
@@ -651,10 +564,7 @@
size_t desc_len = description.GetSize();
if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r'))
--desc_len;
- if (desc_len > 0)
- return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release();
- else
- return lldb_private::PythonString("").release();
+ return PythonString(llvm::StringRef(desc, desc_len)).release();
}
%clearnothreadallow;
%pythoncode %{
@@ -680,10 +590,7 @@
size_t desc_len = description.GetSize();
if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r'))
--desc_len;
- if (desc_len > 0)
- return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release();
- else
- return lldb_private::PythonString("").release();
+ return PythonString(llvm::StringRef(desc, desc_len)).release();
}
%clearnothreadallow;
}
@@ -696,10 +603,7 @@
size_t desc_len = description.GetSize();
if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r'))
--desc_len;
- if (desc_len > 0)
- return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release();
- else
- return lldb_private::PythonString("").release();
+ return PythonString(llvm::StringRef(desc, desc_len)).release();
}
%clearnothreadallow;
}
@@ -712,10 +616,7 @@
size_t desc_len = description.GetSize();
if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r'))
--desc_len;
- if (desc_len > 0)
- return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release();
- else
- return lldb_private::PythonString("").release();
+ return PythonString(llvm::StringRef(desc, desc_len)).release();
}
%clearnothreadallow;
}
@@ -728,10 +629,7 @@
size_t desc_len = description.GetSize();
if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r'))
--desc_len;
- if (desc_len > 0)
- return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release();
- else
- return lldb_private::PythonString("").release();
+ return PythonString(llvm::StringRef(desc, desc_len)).release();
}
%clearnothreadallow;
}
@@ -744,10 +642,7 @@
size_t desc_len = description.GetSize();
if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r'))
--desc_len;
- if (desc_len > 0)
- return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release();
- else
- return lldb_private::PythonString("").release();
+ return PythonString(llvm::StringRef(desc, desc_len)).release();
}
%clearnothreadallow;
%pythoncode %{
@@ -773,10 +668,7 @@
size_t desc_len = description.GetSize();
if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r'))
--desc_len;
- if (desc_len > 0)
- return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release();
- else
- return lldb_private::PythonString("").release();
+ return PythonString(llvm::StringRef(desc, desc_len)).release();
}
%clearnothreadallow;
%pythoncode %{
@@ -802,10 +694,7 @@
size_t desc_len = description.GetSize();
if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r'))
--desc_len;
- if (desc_len > 0)
- return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release();
- else
- return lldb_private::PythonString("").release();
+ return PythonString(llvm::StringRef(desc, desc_len)).release();
}
%clearnothreadallow;
%pythoncode %{
@@ -831,10 +720,7 @@
size_t desc_len = description.GetSize();
if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r'))
--desc_len;
- if (desc_len > 0)
- return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release();
- else
- return lldb_private::PythonString("").release();
+ return PythonString(llvm::StringRef(desc, desc_len)).release();
}
%clearnothreadallow;
%pythoncode %{
@@ -860,10 +746,7 @@
size_t desc_len = description.GetSize();
if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r'))
--desc_len;
- if (desc_len > 0)
- return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release();
- else
- return lldb_private::PythonString("").release();
+ return PythonString(llvm::StringRef(desc, desc_len)).release();
}
%clearnothreadallow;
}
@@ -885,10 +768,7 @@
size_t desc_len = description.GetSize();
if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r'))
--desc_len;
- if (desc_len > 0)
- return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release();
- else
- return lldb_private::PythonString("").release();
+ return PythonString(llvm::StringRef(desc, desc_len)).release();
}
%clearnothreadallow;
}
@@ -901,10 +781,7 @@
size_t desc_len = description.GetSize();
if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r'))
--desc_len;
- if (desc_len > 0)
- return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release();
- else
- return lldb_private::PythonString("").release();
+ return PythonString(llvm::StringRef(desc, desc_len)).release();
}
%clearnothreadallow;
}
diff --git a/scripts/Python/python-typemaps.swig b/scripts/Python/python-typemaps.swig
index 8ff178bc5..2ba380bdf 100644
--- a/scripts/Python/python-typemaps.swig
+++ b/scripts/Python/python-typemaps.swig
@@ -1,7 +1,6 @@
/* Typemap definitions, to allow SWIG to properly handle 'char**' data types. */
%typemap(in) char ** {
- using namespace lldb_private;
/* Check if is a list */
if (PythonList::Check($input)) {
PythonList list(PyRefType::Borrowed, $input);
@@ -30,7 +29,6 @@
%typemap(typecheck) char ** {
/* Check if is a list */
$1 = 1;
- using namespace lldb_private;
if (PythonList::Check($input)) {
PythonList list(PyRefType::Borrowed, $input);
int size = list.GetSize();
@@ -55,7 +53,6 @@
int i;
len = 0;
while ($1[len]) len++;
- using namespace lldb_private;
PythonList list(len);
for (i = 0; i < len; i++)
list.SetItemAtIndex(i, PythonString($1[i]));
@@ -64,7 +61,6 @@
%typemap(in) lldb::tid_t {
- using namespace lldb_private;
if (PythonInteger::Check($input))
{
PythonInteger py_int(PyRefType::Borrowed, $input);
@@ -78,7 +74,6 @@
}
%typemap(in) lldb::StateType {
- using namespace lldb_private;
if (PythonInteger::Check($input))
{
PythonInteger py_int(PyRefType::Borrowed, $input);
@@ -122,12 +117,12 @@
%typemap(argout) (char *dst, size_t dst_len) {
Py_XDECREF($result); /* Blow away any previous result */
if (result == 0) {
- lldb_private::PythonString string("");
+ PythonString string("");
$result = string.release();
Py_INCREF($result);
} else {
llvm::StringRef ref(static_cast<const char*>($1), result);
- lldb_private::PythonString string(ref);
+ PythonString string(ref);
$result = string.release();
}
free($1);
@@ -142,7 +137,6 @@
// Ditto for SBProcess::PutSTDIN(const char *src, size_t src_len).
%typemap(in) (const char *cstr, uint32_t cstr_len),
(const char *src, size_t src_len) {
- using namespace lldb_private;
if (PythonString::Check($input)) {
PythonString str(PyRefType::Borrowed, $input);
$1 = (char*)str.GetString().data();
@@ -166,7 +160,6 @@
// For SBProcess::WriteMemory, SBTarget::GetInstructions and SBDebugger::DispatchInput.
%typemap(in) (const void *buf, size_t size),
(const void *data, size_t data_len) {
- using namespace lldb_private;
if (PythonString::Check($input)) {
PythonString str(PyRefType::Borrowed, $input);
$1 = (void*)str.GetString().data();
@@ -214,7 +207,7 @@
$result = Py_None;
Py_INCREF($result);
} else {
- lldb_private::PythonBytes bytes(static_cast<const uint8_t*>($1), result);
+ PythonBytes bytes(static_cast<const uint8_t*>($1), result);
$result = bytes.release();
}
free($1);
@@ -374,7 +367,6 @@ bool SetNumberFromPyObject<double>(double &number, PyObject *obj) {
%typemap(in) lldb::FileSP {
- using namespace lldb_private;
PythonFile py_file(PyRefType::Borrowed, $input);
if (!py_file) {
PyErr_SetString(PyExc_TypeError, "not a file");
@@ -387,7 +379,6 @@ bool SetNumberFromPyObject<double>(double &number, PyObject *obj) {
}
%typemap(in) lldb::FileSP FORCE_IO_METHODS {
- using namespace lldb_private;
PythonFile py_file(PyRefType::Borrowed, $input);
if (!py_file) {
PyErr_SetString(PyExc_TypeError, "not a file");
@@ -400,7 +391,6 @@ bool SetNumberFromPyObject<double>(double &number, PyObject *obj) {
}
%typemap(in) lldb::FileSP BORROWED {
- using namespace lldb_private;
PythonFile py_file(PyRefType::Borrowed, $input);
if (!py_file) {
PyErr_SetString(PyExc_TypeError, "not a file");
@@ -413,7 +403,6 @@ bool SetNumberFromPyObject<double>(double &number, PyObject *obj) {
}
%typemap(in) lldb::FileSP BORROWED_FORCE_IO_METHODS {
- using namespace lldb_private;
PythonFile py_file(PyRefType::Borrowed, $input);
if (!py_file) {
PyErr_SetString(PyExc_TypeError, "not a file");
@@ -426,7 +415,7 @@ bool SetNumberFromPyObject<double>(double &number, PyObject *obj) {
}
%typecheck(SWIG_TYPECHECK_POINTER) lldb::FileSP {
- if (lldb_private::PythonFile::Check($input)) {
+ if (PythonFile::Check($input)) {
$1 = 1;
} else {
PyErr_Clear();
@@ -435,7 +424,6 @@ bool SetNumberFromPyObject<double>(double &number, PyObject *obj) {
}
%typemap(out) lldb::FileSP {
- using namespace lldb_private;
$result = nullptr;
lldb::FileSP &sp = $1;
if (sp) {
@@ -452,7 +440,6 @@ bool SetNumberFromPyObject<double>(double &number, PyObject *obj) {
}
%typemap(in) (const char* string, int len) {
- using namespace lldb_private;
if ($input == Py_None)
{
$1 = NULL;
diff --git a/scripts/Python/python-wrapper.swig b/scripts/Python/python-wrapper.swig
index 277b8657d..8bb746477 100644
--- a/scripts/Python/python-wrapper.swig
+++ b/scripts/Python/python-wrapper.swig
@@ -48,7 +48,6 @@ LLDBSwigPythonBreakpointCallbackFunction
const lldb::BreakpointLocationSP& bp_loc_sp
)
{
- using namespace lldb_private;
lldb::SBFrame sb_frame (frame_sp);
lldb::SBBreakpointLocation sb_bp_loc(bp_loc_sp);
@@ -83,7 +82,6 @@ LLDBSwigPythonWatchpointCallbackFunction
const lldb::WatchpointSP& wp_sp
)
{
- using namespace lldb_private;
lldb::SBFrame sb_frame (frame_sp);
lldb::SBWatchpoint sb_wp(wp_sp);
@@ -118,7 +116,6 @@ LLDBSwigPythonCallTypeScript
std::string& retval
)
{
- using namespace lldb_private;
lldb::SBValue sb_value (valobj_sp);
lldb::SBTypeSummaryOptions sb_options(options_sp.get());
@@ -190,8 +187,6 @@ LLDBSwigPythonCreateSyntheticProvider
const lldb::ValueObjectSP& valobj_sp
)
{
- using namespace lldb_private;
-
if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name)
Py_RETURN_NONE;
@@ -228,8 +223,6 @@ LLDBSwigPythonCreateCommandObject
const lldb::DebuggerSP debugger_sp
)
{
- using namespace lldb_private;
-
if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name)
Py_RETURN_NONE;
@@ -260,8 +253,6 @@ LLDBSwigPythonCreateScriptedThreadPlan
const lldb::ThreadPlanSP& thread_plan_sp
)
{
- using namespace lldb_private;
-
if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name)
Py_RETURN_NONE;
@@ -319,8 +310,6 @@ LLDBSWIGPythonCallThreadPlan
bool &got_error
)
{
- using namespace lldb_private;
-
got_error = false;
PyErr_Cleaner py_err_cleaner(false);
@@ -368,8 +357,6 @@ LLDBSwigPythonCreateScriptedBreakpointResolver
lldb::BreakpointSP &breakpoint_sp
)
{
- using namespace lldb_private;
-
if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name)
Py_RETURN_NONE;
@@ -412,8 +399,6 @@ LLDBSwigPythonCallBreakpointResolver
lldb_private::SymbolContext *sym_ctx
)
{
- using namespace lldb_private;
-
PyErr_Cleaner py_err_cleaner(false);
PythonObject self(PyRefType::Borrowed, static_cast<PyObject*>(implementor));
auto pfunc = self.ResolveName<PythonCallable>(method_name);
@@ -464,8 +449,6 @@ LLDBSwigPython_CallOptionalMember
bool* was_found = NULL
)
{
- using namespace lldb_private;
-
PyErr_Cleaner py_err_cleaner(false);
PythonObject self(PyRefType::Borrowed, static_cast<PyObject*>(implementor));
@@ -493,8 +476,6 @@ LLDBSwigPython_CalculateNumChildren
uint32_t max
)
{
- using namespace lldb_private;
-
PythonObject self(PyRefType::Borrowed, implementor);
auto pfunc = self.ResolveName<PythonCallable>("num_children");
@@ -536,7 +517,6 @@ LLDBSwigPython_GetChildAtIndex
uint32_t idx
)
{
- using namespace lldb_private;
PyErr_Cleaner py_err_cleaner(true);
PythonObject self(PyRefType::Borrowed, implementor);
@@ -567,7 +547,6 @@ LLDBSwigPython_GetIndexOfChildWithName
const char* child_name
)
{
- using namespace lldb_private;
PyErr_Cleaner py_err_cleaner(true);
PythonObject self(PyRefType::Borrowed, implementor);
@@ -687,7 +666,6 @@ LLDBSwigPythonCallCommand
lldb::ExecutionContextRefSP exe_ctx_ref_sp
)
{
- using namespace lldb_private;
lldb::SBCommandReturnObject cmd_retobj_sb(cmd_retobj);
lldb::SBDebugger debugger_sb(debugger);
lldb::SBExecutionContext exe_ctx_sb(exe_ctx_ref_sp);
@@ -728,7 +706,6 @@ LLDBSwigPythonCallCommandObject
lldb::ExecutionContextRefSP exe_ctx_ref_sp
)
{
- using namespace lldb_private;
lldb::SBCommandReturnObject cmd_retobj_sb(cmd_retobj);
lldb::SBDebugger debugger_sb(debugger);
lldb::SBExecutionContext exe_ctx_sb(exe_ctx_ref_sp);
@@ -760,8 +737,6 @@ LLDBSWIGPythonCreateOSPlugin
const lldb::ProcessSP& process_sp
)
{
- using namespace lldb_private;
-
if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name)
Py_RETURN_NONE;
@@ -795,8 +770,6 @@ LLDBSWIGPython_CreateFrameRecognizer
const char *session_dictionary_name
)
{
- using namespace lldb_private;
-
if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name)
Py_RETURN_NONE;
@@ -823,8 +796,6 @@ LLDBSwigPython_GetRecognizedArguments
const lldb::StackFrameSP& frame_sp
)
{
- using namespace lldb_private;
-
static char callee_name[] = "get_recognized_arguments";
lldb::SBFrame frame_sb(frame_sp);
@@ -839,8 +810,6 @@ LLDBSwigPython_GetRecognizedArguments
SWIGEXPORT void*
LLDBSWIGPython_GetDynamicSetting (void* module, const char* setting, const lldb::TargetSP& target_sp)
{
- using namespace lldb_private;
-
if (!module || !setting)
Py_RETURN_NONE;
@@ -866,8 +835,6 @@ lldb::ProcessSP& process,
std::string& output)
{
- using namespace lldb_private;
-
if (python_function_name == NULL || python_function_name[0] == '\0' || !session_dictionary_name)
return false;
@@ -896,8 +863,6 @@ lldb::ThreadSP& thread,
std::string& output)
{
- using namespace lldb_private;
-
if (python_function_name == NULL || python_function_name[0] == '\0' || !session_dictionary_name)
return false;
@@ -926,8 +891,6 @@ lldb::TargetSP& target,
std::string& output)
{
- using namespace lldb_private;
-
if (python_function_name == NULL || python_function_name[0] == '\0' || !session_dictionary_name)
return false;
@@ -956,8 +919,6 @@ lldb::StackFrameSP& frame,
std::string& output)
{
- using namespace lldb_private;
-
if (python_function_name == NULL || python_function_name[0] == '\0' || !session_dictionary_name)
return false;
@@ -986,8 +947,6 @@ lldb::ValueObjectSP& value,
std::string& output)
{
- using namespace lldb_private;
-
if (python_function_name == NULL || python_function_name[0] == '\0' || !session_dictionary_name)
return false;
@@ -1016,8 +975,6 @@ LLDBSwigPythonCallModuleInit
lldb::DebuggerSP& debugger
)
{
- using namespace lldb_private;
-
std::string python_function_name_string = python_module_name;
python_function_name_string += ".__lldb_init_module";
const char* python_function_name = python_function_name_string.c_str();
diff --git a/scripts/lldb.swig b/scripts/lldb.swig
index 1634e1884..7bbf7f1ee 100644
--- a/scripts/lldb.swig
+++ b/scripts/lldb.swig
@@ -174,6 +174,11 @@ def lldb_iter(obj, getsize, getelem):
#include "../source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h"
#include "../scripts/Python/python-swigsafecast.swig"
+
+using namespace lldb_private;
+using namespace lldb_private::python;
+using namespace lldb;
+
%}
/* Various liblldb typedefs that SWIG needs to know about. */
diff --git a/source/Plugins/ScriptInterpreter/Python/CMakeLists.txt b/source/Plugins/ScriptInterpreter/Python/CMakeLists.txt
index 2c5071bc7..54b5c236f 100644
--- a/source/Plugins/ScriptInterpreter/Python/CMakeLists.txt
+++ b/source/Plugins/ScriptInterpreter/Python/CMakeLists.txt
@@ -5,7 +5,6 @@ add_definitions(-DLLDB_PYTHON_RELATIVE_LIBDIR="${LLDB_PYTHON_RELATIVE_PATH}")
add_lldb_library(lldbPluginScriptInterpreterPython PLUGIN
PythonDataObjects.cpp
- PythonExceptionState.cpp
ScriptInterpreterPython.cpp
LINK_LIBS
diff --git a/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp b/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
index d0d593656..70d93424f 100644
--- a/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
+++ b/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
@@ -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
diff --git a/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h b/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
index 634d6e896..373d32126 100644
--- a/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
+++ b/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
@@ -59,6 +59,7 @@
#include "llvm/ADT/ArrayRef.h"
namespace lldb_private {
+namespace python {
class PythonObject;
class PythonBytes;
@@ -113,7 +114,6 @@ enum class PyRefType {
// not call Py_INCREF.
};
-namespace python {
// Take a reference that you already own, and turn it into
// a PythonObject.
@@ -175,7 +175,19 @@ public:
operator const char *() { return str; }
};
-} // namespace python
+inline llvm::Error nullDeref() {
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "A NULL PyObject* was dereferenced");
+}
+
+inline llvm::Error exception(const char *s = nullptr) {
+ return llvm::make_error<PythonException>(s);
+}
+
+inline llvm::Error keyError() {
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "key not in dict");
+}
enum class PyInitialValue { Invalid, Empty };
@@ -191,6 +203,11 @@ template <> struct PythonFormat<long long> {
static auto get(long long value) { return value; }
};
+template <> struct PythonFormat<PyObject *> {
+ static constexpr char format = 'O';
+ static auto get(PyObject *value) { return value; }
+};
+
template <typename T>
struct PythonFormat<
T, typename std::enable_if<std::is_base_of<PythonObject, T>::value>::type> {
@@ -202,8 +219,14 @@ class PythonObject {
public:
PythonObject() : m_py_obj(nullptr) {}
- PythonObject(PyRefType type, PyObject *py_obj) : m_py_obj(nullptr) {
- Reset(type, py_obj);
+ PythonObject(PyRefType type, PyObject *py_obj) {
+ m_py_obj = py_obj;
+ // If this is a borrowed reference, we need to convert it to
+ // an owned reference by incrementing it. If it is an owned
+ // reference (for example the caller allocated it with PyDict_New()
+ // then we must *not* increment it.
+ if (m_py_obj && Py_IsInitialized() && type == PyRefType::Borrowed)
+ Py_XINCREF(m_py_obj);
}
PythonObject(const PythonObject &rhs)
@@ -222,23 +245,6 @@ public:
m_py_obj = nullptr;
}
- void Reset(PyRefType type, PyObject *py_obj) {
- if (py_obj == m_py_obj)
- return;
-
- if (Py_IsInitialized())
- Py_XDECREF(m_py_obj);
-
- m_py_obj = py_obj;
-
- // If this is a borrowed reference, we need to convert it to
- // an owned reference by incrementing it. If it is an owned
- // reference (for example the caller allocated it with PyDict_New()
- // then we must *not* increment it.
- if (m_py_obj && Py_IsInitialized() && type == PyRefType::Borrowed)
- Py_XINCREF(m_py_obj);
- }
-
void Dump() const {
if (m_py_obj)
_PyObject_Dump(m_py_obj);
@@ -304,17 +310,6 @@ public:
StructuredData::ObjectSP CreateStructuredObject() const;
protected:
- static llvm::Error nullDeref() {
- return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "A NULL PyObject* was dereferenced");
- }
- static llvm::Error exception(const char *s = nullptr) {
- return llvm::make_error<PythonException>(s);
- }
- static llvm::Error keyError() {
- return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "key not in dict");
- }
#if PY_MAJOR_VERSION < 3
// The python 2 API declares some arguments as char* that should
@@ -348,7 +343,6 @@ public:
}
llvm::Expected<PythonObject> GetAttribute(const llvm::Twine &name) const {
- using namespace python;
if (!m_py_obj)
return nullDeref();
PyObject *obj = PyObject_GetAttrString(m_py_obj, NullTerminated(name));
@@ -389,7 +383,6 @@ protected:
PyObject *m_py_obj;
};
-namespace python {
// This is why C++ needs monads.
template <typename T> llvm::Expected<T> As(llvm::Expected<PythonObject> &&obj) {
@@ -409,7 +402,6 @@ llvm::Expected<long long> As<long long>(llvm::Expected<PythonObject> &&obj);
template <>
llvm::Expected<std::string> As<std::string>(llvm::Expected<PythonObject> &&obj);
-} // namespace python
template <class T> class TypedPythonObject : public PythonObject {
public:
@@ -417,16 +409,12 @@ public:
// This can be eliminated once we drop python 2 support.
static void Convert(PyRefType &type, PyObject *&py_obj) {}
- void Reset() { PythonObject::Reset(); }
-
- void Reset(PyRefType type, PyObject *py_obj) = delete;
-
TypedPythonObject(PyRefType type, PyObject *py_obj) {
if (!py_obj)
return;
T::Convert(type, py_obj);
if (T::Check(py_obj))
- PythonObject::Reset(type, py_obj);
+ PythonObject::operator=(PythonObject(type, py_obj));
else if (type == PyRefType::Owned)
Py_DECREF(py_obj);
}
@@ -698,6 +686,8 @@ public:
~PythonException();
void log(llvm::raw_ostream &OS) const override;
std::error_code convertToErrorCode() const override;
+ bool Matches(PyObject *exc) const;
+ std::string ReadBacktrace() const;
};
// This extracts the underlying T out of an Expected<T> and returns it.
@@ -732,7 +722,6 @@ template <typename T> T unwrapOrSetPythonException(llvm::Expected<T> expected) {
return T();
}
-namespace python {
// This is only here to help incrementally migrate old, exception-unsafe
// code.
template <typename T> T unwrapIgnoringErrors(llvm::Expected<T> expected) {
@@ -741,8 +730,50 @@ template <typename T> T unwrapIgnoringErrors(llvm::Expected<T> expected) {
llvm::consumeError(expected.takeError());
return T();
}
-} // namespace python
+llvm::Expected<PythonObject> runStringOneLine(const llvm::Twine &string,
+ const PythonDictionary &globals,
+ const PythonDictionary &locals);
+
+llvm::Expected<PythonObject> runStringMultiLine(const llvm::Twine &string,
+ const PythonDictionary &globals,
+ const PythonDictionary &locals);
+
+// Sometimes the best way to interact with a python interpreter is
+// to run some python code. You construct a PythonScript with
+// script string. The script assigns some function to `_function_`
+// and you get a C++ callable object that calls the python function.
+//
+// Example:
+//
+// const char script[] = R"(
+// def main(x, y):
+// ....
+// )";
+//
+// Expected<PythonObject> cpp_foo_wrapper(PythonObject x, PythonObject y) {
+// // no need to synchronize access to this global, we already have the GIL
+// static PythonScript foo(script)
+// return foo(x, y);
+// }
+class PythonScript {
+ const char *script;
+ PythonCallable function;
+
+ llvm::Error Init();
+
+public:
+ PythonScript(const char *script) : script(script), function() {}
+
+ template <typename... Args>
+ llvm::Expected<PythonObject> operator()(Args &&... args) {
+ if (llvm::Error error = Init())
+ return std::move(error);
+ return function.Call(std::forward<Args>(args)...);
+ }
+};
+
+} // namespace python
} // namespace lldb_private
#endif
diff --git a/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.cpp b/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.cpp
deleted file mode 100644
index c9d834ce6..000000000
--- a/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.cpp
+++ /dev/null
@@ -1,169 +0,0 @@
-//===-- PythonExceptionState.cpp --------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLDB_DISABLE_PYTHON
-
-// LLDB Python header must be included first
-#include "lldb-python.h"
-
-#include "PythonExceptionState.h"
-
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/raw_ostream.h"
-
-using namespace lldb_private;
-
-PythonExceptionState::PythonExceptionState(bool restore_on_exit)
- : m_restore_on_exit(restore_on_exit) {
- Acquire(restore_on_exit);
-}
-
-PythonExceptionState::~PythonExceptionState() {
- if (m_restore_on_exit)
- Restore();
-}
-
-void PythonExceptionState::Acquire(bool restore_on_exit) {
- // If a state is already acquired, the user needs to decide whether they want
- // to discard or restore it. Don't allow the potential silent loss of a
- // valid state.
- assert(!IsError());
-
- if (!HasErrorOccurred())
- return;
-
- PyObject *py_type = nullptr;
- PyObject *py_value = nullptr;
- PyObject *py_traceback = nullptr;
- PyErr_Fetch(&py_type, &py_value, &py_traceback);
- // PyErr_Fetch clears the error flag.
- assert(!HasErrorOccurred());
-
- // Ownership of the objects returned by `PyErr_Fetch` is transferred to us.
- m_type.Reset(PyRefType::Owned, py_type);
- m_value.Reset(PyRefType::Owned, py_value);
- m_traceback.Reset(PyRefType::Owned, py_traceback);
- m_restore_on_exit = restore_on_exit;
-}
-
-void PythonExceptionState::Restore() {
- if (m_type.IsValid()) {
- // The documentation for PyErr_Restore says "Do not pass a null type and
- // non-null value or traceback. So only restore if type was non-null to
- // begin with. In this case we're passing ownership back to Python so
- // release them all.
- PyErr_Restore(m_type.release(), m_value.release(), m_traceback.release());
- }
-
- // After we restore, we should not hold onto the exception state. Demand
- // that it be re-acquired.
- Discard();
-}
-
-void PythonExceptionState::Discard() {
- m_type.Reset();
- m_value.Reset();
- m_traceback.Reset();
-}
-
-void PythonExceptionState::Reset() {
- if (m_restore_on_exit)
- Restore();
- else
- Discard();
-}
-
-bool PythonExceptionState::HasErrorOccurred() { return PyErr_Occurred(); }
-
-bool PythonExceptionState::IsError() const {
- return m_type.IsValid() || m_value.IsValid() || m_traceback.IsValid();
-}
-
-PythonObject PythonExceptionState::GetType() const { return m_type; }
-
-PythonObject PythonExceptionState::GetValue() const { return m_value; }
-
-PythonObject PythonExceptionState::GetTraceback() const { return m_traceback; }
-
-std::string PythonExceptionState::Format() const {
- // Don't allow this function to modify the error state.
- PythonExceptionState state(true);
-
- std::string backtrace = ReadBacktrace();
- if (!IsError())
- return std::string();
-
- // It's possible that ReadPythonBacktrace generated another exception. If
- // this happens we have to clear the exception, because otherwise
- // PyObject_Str() will assert below. That's why we needed to do the save /
- // restore at the beginning of this function.
- PythonExceptionState bt_error_state(false);
-
- std::string error_string;
- llvm::raw_string_ostream error_stream(error_string);
- error_stream << m_value.Str().GetString() << "\n";
-
- if (!bt_error_state.IsError()) {
- // If we were able to read the backtrace, just append it.
- error_stream << backtrace << "\n";
- } else {
- // Otherwise, append some information about why we were unable to obtain
- // the backtrace.
- PythonString bt_error = bt_error_state.GetValue().Str();
- error_stream << "An error occurred while retrieving the backtrace: "
- << bt_error.GetString() << "\n";
- }
- return error_stream.str();
-}
-
-std::string PythonExceptionState::ReadBacktrace() const {
- std::string retval("backtrace unavailable");
-
- auto traceback_module = PythonModule::ImportModule("traceback");
-#if PY_MAJOR_VERSION >= 3
- auto stringIO_module = PythonModule::ImportModule("io");
-#else
- auto stringIO_module = PythonModule::ImportModule("StringIO");
-#endif
- if (!m_traceback.IsAllocated())
- return retval;
-
- if (!traceback_module.IsAllocated() || !stringIO_module.IsAllocated())
- return retval;
-
- auto stringIO_builder =
- stringIO_module.ResolveName<PythonCallable>("StringIO");
- if (!stringIO_builder.IsAllocated())
- return retval;
-
- auto stringIO_buffer = stringIO_builder();
- if (!stringIO_buffer.IsAllocated())
- return retval;
-
- auto printTB = traceback_module.ResolveName<PythonCallable>("print_tb");
- if (!printTB.IsAllocated())
- return retval;
-
- auto printTB_result =
- printTB(m_traceback.get(), Py_None, stringIO_buffer.get());
- auto stringIO_getvalue =
- stringIO_buffer.ResolveName<PythonCallable>("getvalue");
- if (!stringIO_getvalue.IsAllocated())
- return retval;
-
- auto printTB_string = stringIO_getvalue().AsType<PythonString>();
- if (!printTB_string.IsAllocated())
- return retval;
-
- llvm::StringRef string_data(printTB_string.GetString());
- retval.assign(string_data.data(), string_data.size());
-
- return retval;
-}
-
-#endif
diff --git a/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.h b/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.h
deleted file mode 100644
index 3a88aa037..000000000
--- a/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.h
+++ /dev/null
@@ -1,56 +0,0 @@
-//===-- PythonExceptionState.h ----------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONEXCEPTIONSTATE_H
-#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONEXCEPTIONSTATE_H
-
-#ifndef LLDB_DISABLE_PYTHON
-
-#include "PythonDataObjects.h"
-
-namespace lldb_private {
-
-class PythonExceptionState {
-public:
- explicit PythonExceptionState(bool restore_on_exit);
- ~PythonExceptionState();
-
- void Acquire(bool restore_on_exit);
-
- void Restore();
-
- void Discard();
-
- void Reset();
-
- static bool HasErrorOccurred();
-
- bool IsError() const;
-
- PythonObject GetType() const;
-
- PythonObject GetValue() const;
-
- PythonObject GetTraceback() const;
-
- std::string Format() const;
-
-private:
- std::string ReadBacktrace() const;
-
- bool m_restore_on_exit;
-
- PythonObject m_type;
- PythonObject m_value;
- PythonObject m_traceback;
-};
-}
-
-#endif
-
-#endif
diff --git a/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
index 8f7133524..3eee52184 100644
--- a/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
+++ b/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
@@ -16,7 +16,6 @@
#include "lldb-python.h"
#include "PythonDataObjects.h"
-#include "PythonExceptionState.h"
#include "ScriptInterpreterPythonImpl.h"
#include "lldb/API/SBFrame.h"
@@ -56,6 +55,7 @@
using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::python;
+using llvm::Expected;
// Defined in the SWIG source file
#if PY_MAJOR_VERSION >= 3
@@ -747,9 +747,9 @@ bool ScriptInterpreterPythonImpl::EnterSession(uint16_t on_entry_flags,
return true;
}
-PythonObject &ScriptInterpreterPythonImpl::GetMainModule() {
+PythonModule &ScriptInterpreterPythonImpl::GetMainModule() {
if (!m_main_module.IsValid())
- m_main_module.Reset(PyRefType::Borrowed, PyImport_AddModule("__main__"));
+ m_main_module = unwrapIgnoringErrors(PythonModule::Import("__main__"));
return m_main_module;
}
@@ -1030,6 +1030,7 @@ bool ScriptInterpreterPythonImpl::Interrupt() {
"can't interrupt");
return false;
}
+
bool ScriptInterpreterPythonImpl::ExecuteOneLineWithReturn(
llvm::StringRef in_string, ScriptInterpreter::ScriptReturnType return_type,
void *ret_value, const ExecuteScriptOptions &options) {
@@ -1040,151 +1041,111 @@ bool ScriptInterpreterPythonImpl::ExecuteOneLineWithReturn(
Locker::NoSTDIN,
Locker::FreeAcquiredLock | Locker::TearDownSession);
- PythonObject py_return;
- PythonObject &main_module = GetMainModule();
- PythonDictionary globals(PyRefType::Borrowed,
- PyModule_GetDict(main_module.get()));
- PythonObject py_error;
- bool ret_success = false;
- int success;
+ PythonModule &main_module = GetMainModule();
+ PythonDictionary globals = main_module.GetDictionary();
PythonDictionary locals = GetSessionDictionary();
-
- if (!locals.IsValid()) {
+ if (!locals.IsValid())
locals = unwrapIgnoringErrors(
As<PythonDictionary>(globals.GetAttribute(m_dictionary_name)));
- }
-
if (!locals.IsValid())
locals = globals;
- py_error.Reset(PyRefType::Borrowed, PyErr_Occurred());
- if (py_error.IsValid())
- PyErr_Clear();
-
- std::string as_string = in_string.str();
- { // scope for PythonInputReaderManager
- // PythonInputReaderManager py_input(options.GetEnableIO() ? this : NULL);
- py_return.Reset(PyRefType::Owned,
- PyRun_String(as_string.c_str(), Py_eval_input,
- globals.get(), locals.get()));
- if (!py_return.IsValid()) {
- py_error.Reset(PyRefType::Borrowed, PyErr_Occurred());
- if (py_error.IsValid())
- PyErr_Clear();
-
- py_return.Reset(PyRefType::Owned,
- PyRun_String(as_string.c_str(), Py_single_input,
- globals.get(), locals.get()));
- }
+ Expected<PythonObject> maybe_py_return =
+ runStringOneLine(in_string, globals, locals);
+
+ if (!maybe_py_return) {
+ llvm::handleAllErrors(
+ maybe_py_return.takeError(),
+ [&](PythonException &E) {
+ E.Restore();
+ if (options.GetMaskoutErrors()) {
+ if (E.Matches(PyExc_SyntaxError)) {
+ PyErr_Print();
+ }
+ PyErr_Clear();
+ }
+ },
+ [](const llvm::ErrorInfoBase &E) {});
+ return false;
}
- if (py_return.IsValid()) {
- switch (return_type) {
- case eScriptReturnTypeCharPtr: // "char *"
- {
- const char format[3] = "s#";
- success = PyArg_Parse(py_return.get(), format, (char **)ret_value);
- break;
- }
- case eScriptReturnTypeCharStrOrNone: // char* or NULL if py_return ==
- // Py_None
- {
- const char format[3] = "z";
- success = PyArg_Parse(py_return.get(), format, (char **)ret_value);
- break;
- }
- case eScriptReturnTypeBool: {
- const char format[2] = "b";
- success = PyArg_Parse(py_return.get(), format, (bool *)ret_value);
- break;
- }
- case eScriptReturnTypeShortInt: {
- const char format[2] = "h";
- success = PyArg_Parse(py_return.get(), format, (short *)ret_value);
- break;
- }
- case eScriptReturnTypeShortIntUnsigned: {
- const char format[2] = "H";
- success =
- PyArg_Parse(py_return.get(), format, (unsigned short *)ret_value);
- break;
- }
- case eScriptReturnTypeInt: {
- const char format[2] = "i";
- success = PyArg_Parse(py_return.get(), format, (int *)ret_value);
- break;
- }
- case eScriptReturnTypeIntUnsigned: {
- const char format[2] = "I";
- success = PyArg_Parse(py_return.get(), format, (unsigned int *)ret_value);
- break;
- }
- case eScriptReturnTypeLongInt: {
- const char format[2] = "l";
- success = PyArg_Parse(py_return.get(), format, (long *)ret_value);
- break;
- }
- case eScriptReturnTypeLongIntUnsigned: {
- const char format[2] = "k";
- success =
- PyArg_Parse(py_return.get(), format, (unsigned long *)ret_value);
- break;
- }
- case eScriptReturnTypeLongLong: {
- const char format[2] = "L";
- success = PyArg_Parse(py_return.get(), format, (long long *)ret_value);
- break;
- }
- case eScriptReturnTypeLongLongUnsigned: {
- const char format[2] = "K";
- success =
- PyArg_Parse(py_return.get(), format, (unsigned long long *)ret_value);
- break;
- }
- case eScriptReturnTypeFloat: {
- const char format[2] = "f";
- success = PyArg_Parse(py_return.get(), format, (float *)ret_value);
- break;
- }
- case eScriptReturnTypeDouble: {
- const char format[2] = "d";
- success = PyArg_Parse(py_return.get(), format, (double *)ret_value);
- break;
- }
- case eScriptReturnTypeChar: {
- const char format[2] = "c";
- success = PyArg_Parse(py_return.get(), format, (char *)ret_value);
- break;
- }
- case eScriptReturnTypeOpaqueObject: {
- success = true;
- PyObject *saved_value = py_return.get();
- Py_XINCREF(saved_value);
- *((PyObject **)ret_value) = saved_value;
- break;
- }
- }
+ PythonObject py_return = std::move(maybe_py_return.get());
+ assert(py_return.IsValid());
- ret_success = success;
+ switch (return_type) {
+ case eScriptReturnTypeCharPtr: // "char *"
+ {
+ const char format[3] = "s#";
+ return PyArg_Parse(py_return.get(), format, (char **)ret_value);
+ }
+ case eScriptReturnTypeCharStrOrNone: // char* or NULL if py_return ==
+ // Py_None
+ {
+ const char format[3] = "z";
+ return PyArg_Parse(py_return.get(), format, (char **)ret_value);
+ }
+ case eScriptReturnTypeBool: {
+ const char format[2] = "b";
+ return PyArg_Parse(py_return.get(), format, (bool *)ret_value);
+ }
+ case eScriptReturnTypeShortInt: {
+ const char format[2] = "h";
+ return PyArg_Parse(py_return.get(), format, (short *)ret_value);
+ }
+ case eScriptReturnTypeShortIntUnsigned: {
+ const char format[2] = "H";
+ return PyArg_Parse(py_return.get(), format, (unsigned short *)ret_value);
+ }
+ case eScriptReturnTypeInt: {
+ const char format[2] = "i";
+ return PyArg_Parse(py_return.get(), format, (int *)ret_value);
+ }
+ case eScriptReturnTypeIntUnsigned: {
+ const char format[2] = "I";
+ return PyArg_Parse(py_return.get(), format, (unsigned int *)ret_value);
+ }
+ case eScriptReturnTypeLongInt: {
+ const char format[2] = "l";
+ return PyArg_Parse(py_return.get(), format, (long *)ret_value);
+ }
+ case eScriptReturnTypeLongIntUnsigned: {
+ const char format[2] = "k";
+ return PyArg_Parse(py_return.get(), format, (unsigned long *)ret_value);
+ }
+ case eScriptReturnTypeLongLong: {
+ const char format[2] = "L";
+ return PyArg_Parse(py_return.get(), format, (long long *)ret_value);
+ }
+ case eScriptReturnTypeLongLongUnsigned: {
+ const char format[2] = "K";
+ return PyArg_Parse(py_return.get(), format,
+ (unsigned long long *)ret_value);
+ }
+ case eScriptReturnTypeFloat: {
+ const char format[2] = "f";
+ return PyArg_Parse(py_return.get(), format, (float *)ret_value);
+ }
+ case eScriptReturnTypeDouble: {
+ const char format[2] = "d";
+ return PyArg_Parse(py_return.get(), format, (double *)ret_value);
+ }
+ case eScriptReturnTypeChar: {
+ const char format[2] = "c";
+ return PyArg_Parse(py_return.get(), format, (char *)ret_value);
+ }
+ case eScriptReturnTypeOpaqueObject: {
+ *((PyObject **)ret_value) = py_return.release();
+ return true;
}
-
- py_error.Reset(PyRefType::Borrowed, PyErr_Occurred());
- if (py_error.IsValid()) {
- ret_success = false;
- if (options.GetMaskoutErrors()) {
- if (PyErr_GivenExceptionMatches(py_error.get(), PyExc_SyntaxError))
- PyErr_Print();
- PyErr_Clear();
- }
}
-
- return ret_success;
}
Status ScriptInterpreterPythonImpl::ExecuteMultipleLines(
const char *in_string, const ExecuteScriptOptions &options) {
- Status error;
+
+ if (in_string == nullptr)
+ return Status();
Locker locker(this,
Locker::AcquireLock | Locker::InitSession |
@@ -1192,51 +1153,32 @@ Status ScriptInterpreterPythonImpl::ExecuteMultipleLines(
Locker::NoSTDIN,
Locker::FreeAcquiredLock | Locker::TearDownSession);
- PythonObject return_value;
- PythonObject &main_module = GetMainModule();
- PythonDictionary globals(PyRefType::Borrowed,
- PyModule_GetDict(main_module.get()));
- PythonObject py_error;
+ PythonModule &main_module = GetMainModule();
+ PythonDictionary globals = main_module.GetDictionary();
PythonDictionary locals = GetSessionDictionary();
-
if (!locals.IsValid())
locals = unwrapIgnoringErrors(
As<PythonDictionary>(globals.GetAttribute(m_dictionary_name)));
-
if (!locals.IsValid())
locals = globals;
- py_error.Reset(PyRefType::Borrowed, PyErr_Occurred());
- if (py_error.IsValid())
- PyErr_Clear();
-
- if (in_string != nullptr) {
- PythonObject code_object;
- code_object.Reset(PyRefType::Owned,
- Py_CompileString(in_string, "temp.py", Py_file_input));
+ Expected<PythonObject> return_value =
+ runStringMultiLine(in_string, globals, locals);
- if (code_object.IsValid()) {
-// In Python 2.x, PyEval_EvalCode takes a PyCodeObject, but in Python 3.x, it
-// takes a PyObject. They are convertible (hence the function
-// PyCode_Check(PyObject*), so we have to do the cast for Python 2.x
-#if PY_MAJOR_VERSION >= 3
- PyObject *py_code_obj = code_object.get();
-#else
- PyCodeObject *py_code_obj =
- reinterpret_cast<PyCodeObject *>(code_object.get());
-#endif
- return_value.Reset(
- PyRefType::Owned,
- PyEval_EvalCode(py_code_obj, globals.get(), locals.get()));
- }
+ if (!return_value) {
+ llvm::Error error =
+ llvm::handleErrors(return_value.takeError(), [&](PythonException &E) {
+ llvm::Error error = llvm::createStringError(
+ llvm::inconvertibleErrorCode(), E.ReadBacktrace());
+ if (!options.GetMaskoutErrors())
+ E.Restore();
+ return error;
+ });
+ return Status(std::move(error));
}
- PythonExceptionState exception_state(!options.GetMaskoutErrors());
- if (exception_state.IsError())
- error.SetErrorString(exception_state.Format().c_str());
-
- return error;
+ return Status();
}
void ScriptInterpreterPythonImpl::CollectDataForBreakpointCommandCallback(
@@ -2030,15 +1972,22 @@ StructuredData::DictionarySP ScriptInterpreterPythonImpl::GetDynamicSettings(
if (!generic)
return StructuredData::DictionarySP();
- PythonObject reply_pyobj;
Locker py_lock(this,
Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
TargetSP target_sp(target->shared_from_this());
- reply_pyobj.Reset(PyRefType::Owned,
- (PyObject *)LLDBSWIGPython_GetDynamicSetting(
- generic->GetValue(), setting_name, target_sp));
- PythonDictionary py_dict(PyRefType::Borrowed, reply_pyobj.get());
+ auto setting = (PyObject *)LLDBSWIGPython_GetDynamicSetting(
+ generic->GetValue(), setting_name, target_sp);
+
+ if (!setting)
+ return StructuredData::DictionarySP();
+
+ PythonDictionary py_dict =
+ unwrapIgnoringErrors(As<PythonDictionary>(Take<PythonObject>(setting)));
+
+ if (!py_dict)
+ return StructuredData::DictionarySP();
+
return py_dict.CreateStructuredDictionary();
}
diff --git a/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h b/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
index 373513f8e..929567e57 100644
--- a/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
+++ b/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
@@ -363,25 +363,25 @@ public:
eIOHandlerWatchpoint
};
- PythonObject &GetMainModule();
+ python::PythonModule &GetMainModule();
- PythonDictionary &GetSessionDictionary();
+ python::PythonDictionary &GetSessionDictionary();
- PythonDictionary &GetSysModuleDictionary();
+ python::PythonDictionary &GetSysModuleDictionary();
bool GetEmbeddedInterpreterModuleObjects();
bool SetStdHandle(lldb::FileSP file, const char *py_name,
- PythonObject &save_file, const char *mode);
-
- PythonObject m_saved_stdin;
- PythonObject m_saved_stdout;
- PythonObject m_saved_stderr;
- PythonObject m_main_module;
- PythonDictionary m_session_dict;
- PythonDictionary m_sys_module_dict;
- PythonObject m_run_one_line_function;
- PythonObject m_run_one_line_str_global;
+ python::PythonObject &save_file, const char *mode);
+
+ python::PythonObject m_saved_stdin;
+ python::PythonObject m_saved_stdout;
+ python::PythonObject m_saved_stderr;
+ python::PythonModule m_main_module;
+ python::PythonDictionary m_session_dict;
+ python::PythonDictionary m_sys_module_dict;
+ python::PythonObject m_run_one_line_function;
+ python::PythonObject m_run_one_line_str_global;
std::string m_dictionary_name;
ActiveIOHandler m_active_io_handler;
bool m_session_is_active;
diff --git a/unittests/ScriptInterpreter/Python/CMakeLists.txt b/unittests/ScriptInterpreter/Python/CMakeLists.txt
index 618767de9..471f4c6db 100644
--- a/unittests/ScriptInterpreter/Python/CMakeLists.txt
+++ b/unittests/ScriptInterpreter/Python/CMakeLists.txt
@@ -1,6 +1,5 @@
add_lldb_unittest(ScriptInterpreterPythonTests
PythonDataObjectsTests.cpp
- PythonExceptionStateTests.cpp
PythonTestSuite.cpp
LINK_LIBS
diff --git a/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp b/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp
index c01dade44..b676b42da 100644
--- a/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp
+++ b/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp
@@ -21,6 +21,8 @@
using namespace lldb_private;
using namespace lldb_private::python;
+using llvm::Error;
+using llvm::Expected;
class PythonDataObjectsTest : public PythonTestSuite {
public:
@@ -771,4 +773,86 @@ bar_unbound = Foo.bar
}
#endif
+}
+
+TEST_F(PythonDataObjectsTest, TestScript) {
+
+ static const char script[] = R"(
+def factorial(n):
+ if n > 1:
+ return n * factorial(n-1)
+ else:
+ return 1;
+main = factorial
+)";
+
+ PythonScript factorial(script);
+
+ EXPECT_THAT_EXPECTED(As<long long>(factorial(5ll)), llvm::HasValue(120));
+}
+
+TEST_F(PythonDataObjectsTest, TestExceptions) {
+
+ static const char script[] = R"(
+def foo():
+ return bar()
+def bar():
+ return baz()
+def baz():
+ return 1 / 0
+main = foo
+)";
+
+ PythonScript foo(script);
+
+ EXPECT_THAT_EXPECTED(foo(),
+ llvm::Failed<PythonException>(testing::Property(
+ &PythonException::ReadBacktrace,
+ testing::ContainsRegex("line 3, in foo..*"
+ "line 5, in bar.*"
+ "line 7, in baz.*"
+ "ZeroDivisionError"))));
+
+ static const char script2[] = R"(
+class MyError(Exception):
+ def __str__(self):
+ return self.my_message
+
+def main():
+ raise MyError("lol")
+
+)";
+
+ PythonScript lol(script2);
+
+ EXPECT_THAT_EXPECTED(lol(),
+ llvm::Failed<PythonException>(testing::Property(
+ &PythonException::ReadBacktrace,
+ testing::ContainsRegex("unprintable MyError"))));
+}
+
+TEST_F(PythonDataObjectsTest, TestRun) {
+
+ PythonDictionary globals(PyInitialValue::Empty);
+
+ auto x = As<long long>(runStringOneLine("40 + 2", globals, globals));
+ ASSERT_THAT_EXPECTED(x, llvm::Succeeded());
+ EXPECT_EQ(x.get(), 42l);
+
+ Expected<PythonObject> r = runStringOneLine("n = 42", globals, globals);
+ ASSERT_THAT_EXPECTED(r, llvm::Succeeded());
+ auto y = As<long long>(globals.GetItem("n"));
+ ASSERT_THAT_EXPECTED(y, llvm::Succeeded());
+ EXPECT_EQ(y.get(), 42l);
+
+ const char script[] = R"(
+def foobar():
+ return "foo" + "bar" + "baz"
+g = foobar()
+)";
+
+ r = runStringMultiLine(script, globals, globals);
+ ASSERT_THAT_EXPECTED(r, llvm::Succeeded());
+ auto g = As<std::string>(globals.GetItem("g"));
+ ASSERT_THAT_EXPECTED(g, llvm::HasValue("foobarbaz"));
} \ No newline at end of file
diff --git a/unittests/ScriptInterpreter/Python/PythonExceptionStateTests.cpp b/unittests/ScriptInterpreter/Python/PythonExceptionStateTests.cpp
deleted file mode 100644
index 8334e6473..000000000
--- a/unittests/ScriptInterpreter/Python/PythonExceptionStateTests.cpp
+++ /dev/null
@@ -1,164 +0,0 @@
-//===-- PythonExceptionStateTest.cpp ------------------------------*- C++
-//-*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "gtest/gtest.h"
-
-#include "Plugins/ScriptInterpreter/Python/PythonDataObjects.h"
-#include "Plugins/ScriptInterpreter/Python/PythonExceptionState.h"
-#include "Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h"
-#include "Plugins/ScriptInterpreter/Python/lldb-python.h"
-
-#include "PythonTestSuite.h"
-
-using namespace lldb_private;
-
-class PythonExceptionStateTest : public PythonTestSuite {
-public:
-protected:
- void RaiseException() {
- PyErr_SetString(PyExc_RuntimeError, "PythonExceptionStateTest test error");
- }
-};
-
-TEST_F(PythonExceptionStateTest, TestExceptionStateChecking) {
- PyErr_Clear();
- EXPECT_FALSE(PythonExceptionState::HasErrorOccurred());
-
- RaiseException();
- EXPECT_TRUE(PythonExceptionState::HasErrorOccurred());
-
- PyErr_Clear();
-}
-
-TEST_F(PythonExceptionStateTest, TestAcquisitionSemantics) {
- PyErr_Clear();
- PythonExceptionState no_error(false);
- EXPECT_FALSE(no_error.IsError());
- EXPECT_FALSE(PythonExceptionState::HasErrorOccurred());
-
- PyErr_Clear();
- RaiseException();
- PythonExceptionState error(false);
- EXPECT_TRUE(error.IsError());
- EXPECT_FALSE(PythonExceptionState::HasErrorOccurred());
- error.Discard();
-
- PyErr_Clear();
- RaiseException();
- error.Acquire(false);
- EXPECT_TRUE(error.IsError());
- EXPECT_FALSE(PythonExceptionState::HasErrorOccurred());
-
- PyErr_Clear();
-}
-
-TEST_F(PythonExceptionStateTest, TestDiscardSemantics) {
- PyErr_Clear();
-
- // Test that discarding an exception does not restore the exception
- // state even when auto-restore==true is set
- RaiseException();
- PythonExceptionState error(true);
- EXPECT_TRUE(error.IsError());
- EXPECT_FALSE(PythonExceptionState::HasErrorOccurred());
-
- error.Discard();
- EXPECT_FALSE(error.IsError());
- EXPECT_FALSE(PythonExceptionState::HasErrorOccurred());
-}
-
-TEST_F(PythonExceptionStateTest, TestResetSemantics) {
- PyErr_Clear();
-
- // Resetting when auto-restore is true should restore.
- RaiseException();
- PythonExceptionState error(true);
- EXPECT_TRUE(error.IsError());
- EXPECT_FALSE(PythonExceptionState::HasErrorOccurred());
- error.Reset();
- EXPECT_FALSE(error.IsError());
- EXPECT_TRUE(PythonExceptionState::HasErrorOccurred());
-
- PyErr_Clear();
-
- // Resetting when auto-restore is false should discard.
- RaiseException();
- PythonExceptionState error2(false);
- EXPECT_TRUE(error2.IsError());
- EXPECT_FALSE(PythonExceptionState::HasErrorOccurred());
- error2.Reset();
- EXPECT_FALSE(error2.IsError());
- EXPECT_FALSE(PythonExceptionState::HasErrorOccurred());
-
- PyErr_Clear();
-}
-
-TEST_F(PythonExceptionStateTest, TestManualRestoreSemantics) {
- PyErr_Clear();
- RaiseException();
- PythonExceptionState error(false);
- EXPECT_TRUE(error.IsError());
- EXPECT_FALSE(PythonExceptionState::HasErrorOccurred());
-
- error.Restore();
- EXPECT_FALSE(error.IsError());
- EXPECT_TRUE(PythonExceptionState::HasErrorOccurred());
-
- PyErr_Clear();
-}
-
-TEST_F(PythonExceptionStateTest, TestAutoRestoreSemantics) {
- PyErr_Clear();
- // Test that using the auto-restore flag correctly restores the exception
- // state on destruction, and not using the auto-restore flag correctly
- // does NOT restore the state on destruction.
- {
- RaiseException();
- PythonExceptionState error(false);
- EXPECT_TRUE(error.IsError());
- EXPECT_FALSE(PythonExceptionState::HasErrorOccurred());
- }
- EXPECT_FALSE(PythonExceptionState::HasErrorOccurred());
-
- PyErr_Clear();
- {
- RaiseException();
- PythonExceptionState error(true);
- EXPECT_TRUE(error.IsError());
- EXPECT_FALSE(PythonExceptionState::HasErrorOccurred());
- }
- EXPECT_TRUE(PythonExceptionState::HasErrorOccurred());
-
- PyErr_Clear();
-}
-
-TEST_F(PythonExceptionStateTest, TestAutoRestoreChanged) {
- // Test that if we re-acquire with different auto-restore semantics,
- // that the new semantics are respected.
- PyErr_Clear();
-
- RaiseException();
- PythonExceptionState error(false);
- EXPECT_TRUE(error.IsError());
-
- error.Reset();
- EXPECT_FALSE(error.IsError());
- EXPECT_FALSE(PythonExceptionState::HasErrorOccurred());
-
- RaiseException();
- error.Acquire(true);
- EXPECT_TRUE(error.IsError());
- EXPECT_FALSE(PythonExceptionState::HasErrorOccurred());
-
- error.Reset();
- EXPECT_FALSE(error.IsError());
- EXPECT_TRUE(PythonExceptionState::HasErrorOccurred());
-
- PyErr_Clear();
-}