Skip to content

Commit e98989b

Browse files
authored
Merge pull request #8802 from apple/jdevlieghere/5.10/python-3.12-fixes-pt-1
Python 3.12 Support (Part 1)
2 parents db24e22 + 681e413 commit e98989b

File tree

3 files changed

+47
-49
lines changed

3 files changed

+47
-49
lines changed

lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp

+18-14
Original file line numberDiff line numberDiff line change
@@ -93,24 +93,28 @@ struct InitializePythonRAII {
9393
InitializePythonRAII() {
9494
InitializePythonHome();
9595

96+
// The table of built-in modules can only be extended before Python is
97+
// initialized.
98+
if (!Py_IsInitialized()) {
9699
#ifdef LLDB_USE_LIBEDIT_READLINE_COMPAT_MODULE
97-
// Python's readline is incompatible with libedit being linked into lldb.
98-
// Provide a patched version local to the embedded interpreter.
99-
bool ReadlinePatched = false;
100-
for (auto *p = PyImport_Inittab; p->name != nullptr; p++) {
101-
if (strcmp(p->name, "readline") == 0) {
102-
p->initfunc = initlldb_readline;
103-
break;
100+
// Python's readline is incompatible with libedit being linked into lldb.
101+
// Provide a patched version local to the embedded interpreter.
102+
bool ReadlinePatched = false;
103+
for (auto *p = PyImport_Inittab; p->name != nullptr; p++) {
104+
if (strcmp(p->name, "readline") == 0) {
105+
p->initfunc = initlldb_readline;
106+
break;
107+
}
108+
}
109+
if (!ReadlinePatched) {
110+
PyImport_AppendInittab("readline", initlldb_readline);
111+
ReadlinePatched = true;
104112
}
105-
}
106-
if (!ReadlinePatched) {
107-
PyImport_AppendInittab("readline", initlldb_readline);
108-
ReadlinePatched = true;
109-
}
110113
#endif
111114

112-
// Register _lldb as a built-in module.
113-
PyImport_AppendInittab("_lldb", LLDBSwigPyInit);
115+
// Register _lldb as a built-in module.
116+
PyImport_AppendInittab("_lldb", LLDBSwigPyInit);
117+
}
114118

115119
// Python < 3.2 and Python >= 3.2 reversed the ordering requirements for
116120
// calling `Py_Initialize` and `PyEval_InitThreads`. < 3.2 requires that you

lldb/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp

+25-15
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
#include "Plugins/ScriptInterpreter/Python/PythonDataObjects.h"
1313
#include "Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h"
14+
#include "TestingSupport/SubsystemRAII.h"
1415
#include "lldb/Host/File.h"
1516
#include "lldb/Host/FileSystem.h"
1617
#include "lldb/Host/HostInfo.h"
@@ -27,6 +28,8 @@ using llvm::Error;
2728
using llvm::Expected;
2829

2930
class PythonDataObjectsTest : public PythonTestSuite {
31+
SubsystemRAII<FileSystem> subsystems;
32+
3033
public:
3134
void SetUp() override {
3235
PythonTestSuite::SetUp();
@@ -52,21 +55,24 @@ class PythonDataObjectsTest : public PythonTestSuite {
5255

5356
TEST_F(PythonDataObjectsTest, TestOwnedReferences) {
5457
// After creating a new object, the refcount should be >= 1
55-
PyObject *obj = PyLong_FromLong(3);
56-
Py_ssize_t original_refcnt = obj->ob_refcnt;
58+
PyObject *obj = PyBytes_FromString("foo");
59+
Py_ssize_t original_refcnt = Py_REFCNT(obj);
5760
EXPECT_LE(1, original_refcnt);
5861

5962
// If we take an owned reference, the refcount should be the same
60-
PythonObject owned_long(PyRefType::Owned, obj);
61-
EXPECT_EQ(original_refcnt, owned_long.get()->ob_refcnt);
63+
PythonObject owned(PyRefType::Owned, obj);
64+
Py_ssize_t owned_refcnt = Py_REFCNT(owned.get());
65+
EXPECT_EQ(original_refcnt, owned_refcnt);
6266

6367
// Take another reference and verify that the refcount increases by 1
64-
PythonObject strong_ref(owned_long);
65-
EXPECT_EQ(original_refcnt + 1, strong_ref.get()->ob_refcnt);
68+
PythonObject strong_ref(owned);
69+
Py_ssize_t strong_refcnt = Py_REFCNT(strong_ref.get());
70+
EXPECT_EQ(original_refcnt + 1, strong_refcnt);
6671

6772
// If we reset the first one, the refcount should be the original value.
68-
owned_long.Reset();
69-
EXPECT_EQ(original_refcnt, strong_ref.get()->ob_refcnt);
73+
owned.Reset();
74+
strong_refcnt = Py_REFCNT(strong_ref.get());
75+
EXPECT_EQ(original_refcnt, strong_refcnt);
7076
}
7177

7278
TEST_F(PythonDataObjectsTest, TestResetting) {
@@ -83,12 +89,15 @@ TEST_F(PythonDataObjectsTest, TestResetting) {
8389
}
8490

8591
TEST_F(PythonDataObjectsTest, TestBorrowedReferences) {
86-
PythonInteger long_value(PyRefType::Owned, PyLong_FromLong(3));
87-
Py_ssize_t original_refcnt = long_value.get()->ob_refcnt;
92+
PythonByteArray byte_value(PyRefType::Owned,
93+
PyByteArray_FromStringAndSize("foo", 3));
94+
Py_ssize_t original_refcnt = Py_REFCNT(byte_value.get());
8895
EXPECT_LE(1, original_refcnt);
8996

90-
PythonInteger borrowed_long(PyRefType::Borrowed, long_value.get());
91-
EXPECT_EQ(original_refcnt + 1, borrowed_long.get()->ob_refcnt);
97+
PythonByteArray borrowed_byte(PyRefType::Borrowed, byte_value.get());
98+
Py_ssize_t borrowed_refcnt = Py_REFCNT(borrowed_byte.get());
99+
100+
EXPECT_EQ(original_refcnt + 1, borrowed_refcnt);
92101
}
93102

94103
TEST_F(PythonDataObjectsTest, TestGlobalNameResolutionNoDot) {
@@ -204,8 +213,8 @@ TEST_F(PythonDataObjectsTest, TestPythonBoolean) {
204213
};
205214

206215
// Test PythonBoolean constructed from long integer values.
207-
test_from_long(0); // Test 'false' value.
208-
test_from_long(1); // Test 'true' value.
216+
test_from_long(0); // Test 'false' value.
217+
test_from_long(1); // Test 'true' value.
209218
test_from_long(~0); // Any value != 0 is 'true'.
210219
}
211220

@@ -803,7 +812,8 @@ main = foo
803812
testing::ContainsRegex("line 7, in baz"),
804813
testing::ContainsRegex("ZeroDivisionError")))));
805814

806-
#if !((defined(_WIN32) || defined(_WIN64)) && (defined(__aarch64__) || defined(_M_ARM64)))
815+
#if !((defined(_WIN32) || defined(_WIN64)) && \
816+
(defined(__aarch64__) || defined(_M_ARM64)))
807817

808818
static const char script2[] = R"(
809819
class MyError(Exception):

lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp

+4-20
Original file line numberDiff line numberDiff line change
@@ -9,42 +9,26 @@
99
#include "gtest/gtest.h"
1010

1111
#include "Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h"
12-
#include "Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h"
13-
#include "Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h"
1412
#include "Plugins/ScriptInterpreter/Python/lldb-python.h"
1513

16-
#include "lldb/Host/FileSystem.h"
17-
#include "lldb/Host/HostInfo.h"
18-
1914
#include "PythonTestSuite.h"
2015

21-
using namespace lldb_private;
22-
class TestScriptInterpreterPython : public ScriptInterpreterPythonImpl {
23-
public:
24-
using ScriptInterpreterPythonImpl::Initialize;
25-
};
26-
2716
void PythonTestSuite::SetUp() {
28-
FileSystem::Initialize();
29-
HostInfoBase::Initialize();
30-
// ScriptInterpreterPython::Initialize() depends on HostInfo being
31-
// initializedso it can compute the python directory etc.
32-
TestScriptInterpreterPython::Initialize();
33-
3417
// Although we don't care about concurrency for the purposes of running
3518
// this test suite, Python requires the GIL to be locked even for
3619
// deallocating memory, which can happen when you call Py_DECREF or
3720
// Py_INCREF. So acquire the GIL for the entire duration of this
3821
// test suite.
22+
Py_InitializeEx(0);
3923
m_gil_state = PyGILState_Ensure();
24+
PyRun_SimpleString("import sys");
4025
}
4126

4227
void PythonTestSuite::TearDown() {
4328
PyGILState_Release(m_gil_state);
4429

45-
TestScriptInterpreterPython::Terminate();
46-
HostInfoBase::Terminate();
47-
FileSystem::Terminate();
30+
// We could call Py_FinalizeEx here, but initializing and finalizing Python is
31+
// pretty slow, so just keep Python initialized across tests.
4832
}
4933

5034
// The following functions are the Pythonic implementations of the required

0 commit comments

Comments
 (0)