Skip to content

Commit

Permalink
Merge pull request #8802 from apple/jdevlieghere/5.10/python-3.12-fix…
Browse files Browse the repository at this point in the history
…es-pt-1

Python 3.12 Support (Part 1)
  • Loading branch information
JDevlieghere authored May 24, 2024
2 parents db24e22 + 681e413 commit e98989b
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -93,24 +93,28 @@ struct InitializePythonRAII {
InitializePythonRAII() {
InitializePythonHome();

// The table of built-in modules can only be extended before Python is
// initialized.
if (!Py_IsInitialized()) {
#ifdef LLDB_USE_LIBEDIT_READLINE_COMPAT_MODULE
// Python's readline is incompatible with libedit being linked into lldb.
// Provide a patched version local to the embedded interpreter.
bool ReadlinePatched = false;
for (auto *p = PyImport_Inittab; p->name != nullptr; p++) {
if (strcmp(p->name, "readline") == 0) {
p->initfunc = initlldb_readline;
break;
// Python's readline is incompatible with libedit being linked into lldb.
// Provide a patched version local to the embedded interpreter.
bool ReadlinePatched = false;
for (auto *p = PyImport_Inittab; p->name != nullptr; p++) {
if (strcmp(p->name, "readline") == 0) {
p->initfunc = initlldb_readline;
break;
}
}
if (!ReadlinePatched) {
PyImport_AppendInittab("readline", initlldb_readline);
ReadlinePatched = true;
}
}
if (!ReadlinePatched) {
PyImport_AppendInittab("readline", initlldb_readline);
ReadlinePatched = true;
}
#endif

// Register _lldb as a built-in module.
PyImport_AppendInittab("_lldb", LLDBSwigPyInit);
// Register _lldb as a built-in module.
PyImport_AppendInittab("_lldb", LLDBSwigPyInit);
}

// Python < 3.2 and Python >= 3.2 reversed the ordering requirements for
// calling `Py_Initialize` and `PyEval_InitThreads`. < 3.2 requires that you
Expand Down
40 changes: 25 additions & 15 deletions lldb/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#include "Plugins/ScriptInterpreter/Python/PythonDataObjects.h"
#include "Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h"
#include "TestingSupport/SubsystemRAII.h"
#include "lldb/Host/File.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostInfo.h"
Expand All @@ -27,6 +28,8 @@ using llvm::Error;
using llvm::Expected;

class PythonDataObjectsTest : public PythonTestSuite {
SubsystemRAII<FileSystem> subsystems;

public:
void SetUp() override {
PythonTestSuite::SetUp();
Expand All @@ -52,21 +55,24 @@ class PythonDataObjectsTest : public PythonTestSuite {

TEST_F(PythonDataObjectsTest, TestOwnedReferences) {
// After creating a new object, the refcount should be >= 1
PyObject *obj = PyLong_FromLong(3);
Py_ssize_t original_refcnt = obj->ob_refcnt;
PyObject *obj = PyBytes_FromString("foo");
Py_ssize_t original_refcnt = Py_REFCNT(obj);
EXPECT_LE(1, original_refcnt);

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

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

// If we reset the first one, the refcount should be the original value.
owned_long.Reset();
EXPECT_EQ(original_refcnt, strong_ref.get()->ob_refcnt);
owned.Reset();
strong_refcnt = Py_REFCNT(strong_ref.get());
EXPECT_EQ(original_refcnt, strong_refcnt);
}

TEST_F(PythonDataObjectsTest, TestResetting) {
Expand All @@ -83,12 +89,15 @@ TEST_F(PythonDataObjectsTest, TestResetting) {
}

TEST_F(PythonDataObjectsTest, TestBorrowedReferences) {
PythonInteger long_value(PyRefType::Owned, PyLong_FromLong(3));
Py_ssize_t original_refcnt = long_value.get()->ob_refcnt;
PythonByteArray byte_value(PyRefType::Owned,
PyByteArray_FromStringAndSize("foo", 3));
Py_ssize_t original_refcnt = Py_REFCNT(byte_value.get());
EXPECT_LE(1, original_refcnt);

PythonInteger borrowed_long(PyRefType::Borrowed, long_value.get());
EXPECT_EQ(original_refcnt + 1, borrowed_long.get()->ob_refcnt);
PythonByteArray borrowed_byte(PyRefType::Borrowed, byte_value.get());
Py_ssize_t borrowed_refcnt = Py_REFCNT(borrowed_byte.get());

EXPECT_EQ(original_refcnt + 1, borrowed_refcnt);
}

TEST_F(PythonDataObjectsTest, TestGlobalNameResolutionNoDot) {
Expand Down Expand Up @@ -204,8 +213,8 @@ TEST_F(PythonDataObjectsTest, TestPythonBoolean) {
};

// Test PythonBoolean constructed from long integer values.
test_from_long(0); // Test 'false' value.
test_from_long(1); // Test 'true' value.
test_from_long(0); // Test 'false' value.
test_from_long(1); // Test 'true' value.
test_from_long(~0); // Any value != 0 is 'true'.
}

Expand Down Expand Up @@ -803,7 +812,8 @@ main = foo
testing::ContainsRegex("line 7, in baz"),
testing::ContainsRegex("ZeroDivisionError")))));

#if !((defined(_WIN32) || defined(_WIN64)) && (defined(__aarch64__) || defined(_M_ARM64)))
#if !((defined(_WIN32) || defined(_WIN64)) && \
(defined(__aarch64__) || defined(_M_ARM64)))

static const char script2[] = R"(
class MyError(Exception):
Expand Down
24 changes: 4 additions & 20 deletions lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,42 +9,26 @@
#include "gtest/gtest.h"

#include "Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h"
#include "Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h"
#include "Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h"
#include "Plugins/ScriptInterpreter/Python/lldb-python.h"

#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostInfo.h"

#include "PythonTestSuite.h"

using namespace lldb_private;
class TestScriptInterpreterPython : public ScriptInterpreterPythonImpl {
public:
using ScriptInterpreterPythonImpl::Initialize;
};

void PythonTestSuite::SetUp() {
FileSystem::Initialize();
HostInfoBase::Initialize();
// ScriptInterpreterPython::Initialize() depends on HostInfo being
// initializedso it can compute the python directory etc.
TestScriptInterpreterPython::Initialize();

// Although we don't care about concurrency for the purposes of running
// this test suite, Python requires the GIL to be locked even for
// deallocating memory, which can happen when you call Py_DECREF or
// Py_INCREF. So acquire the GIL for the entire duration of this
// test suite.
Py_InitializeEx(0);
m_gil_state = PyGILState_Ensure();
PyRun_SimpleString("import sys");
}

void PythonTestSuite::TearDown() {
PyGILState_Release(m_gil_state);

TestScriptInterpreterPython::Terminate();
HostInfoBase::Terminate();
FileSystem::Terminate();
// We could call Py_FinalizeEx here, but initializing and finalizing Python is
// pretty slow, so just keep Python initialized across tests.
}

// The following functions are the Pythonic implementations of the required
Expand Down

0 comments on commit e98989b

Please sign in to comment.