JDevlieghere created this revision.
JDevlieghere added reviewers: labath, clayborg, lanza.
Herald added a project: All.
JDevlieghere requested review of this revision.

We dropped downstream support for Python 2 in the previous release. Now that we 
have branched for the next release the window where this kind of change could 
introduce conflicts is closing too. Start by getting rid of Python 2 support in 
the Script Interpreter plugin.


https://reviews.llvm.org/D124429

Files:
  lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
  lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
  lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp
  lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
  lldb/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp
  lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp

Index: lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp
===================================================================
--- lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp
+++ lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp
@@ -51,11 +51,7 @@
 // callbacks. Because they're defined in libLLDB which we cannot link for the
 // unit test, we have a 'default' implementation here.
 
-#if PY_MAJOR_VERSION >= 3
 extern "C" PyObject *PyInit__lldb(void) { return nullptr; }
-#else
-extern "C" void init_lldb(void) {}
-#endif
 
 llvm::Expected<bool> lldb_private::LLDBSwigPythonBreakpointCallbackFunction(
     const char *python_function_name, const char *session_dictionary_name,
Index: lldb/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp
===================================================================
--- lldb/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp
+++ lldb/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp
@@ -164,18 +164,6 @@
 TEST_F(PythonDataObjectsTest, TestPythonInteger) {
   // Test that integers behave correctly when wrapped by a PythonInteger.
 
-#if PY_MAJOR_VERSION < 3
-  // Verify that `PythonInt` works correctly when given a PyInt object.
-  // Note that PyInt doesn't exist in Python 3.x, so this is only for 2.x
-  PyObject *py_int = PyInt_FromLong(12);
-  EXPECT_TRUE(PythonInteger::Check(py_int));
-  PythonInteger python_int(PyRefType::Owned, py_int);
-
-  EXPECT_EQ(PyObjectType::Integer, python_int.GetObjectType());
-  auto python_int_value = As<long long>(python_int);
-  EXPECT_THAT_EXPECTED(python_int_value, llvm::HasValue(12));
-#endif
-
   // Verify that `PythonInteger` works correctly when given a PyLong object.
   PyObject *py_long = PyLong_FromLong(12);
   EXPECT_TRUE(PythonInteger::Check(py_long));
@@ -225,13 +213,8 @@
   EXPECT_TRUE(PythonBytes::Check(py_bytes));
   PythonBytes python_bytes(PyRefType::Owned, py_bytes);
 
-#if PY_MAJOR_VERSION < 3
-  EXPECT_TRUE(PythonString::Check(py_bytes));
-  EXPECT_EQ(PyObjectType::String, python_bytes.GetObjectType());
-#else
   EXPECT_FALSE(PythonString::Check(py_bytes));
   EXPECT_EQ(PyObjectType::Bytes, python_bytes.GetObjectType());
-#endif
 
   llvm::ArrayRef<uint8_t> bytes = python_bytes.GetBytes();
   EXPECT_EQ(bytes.size(), strlen(test_bytes));
@@ -258,23 +241,12 @@
   static const char *test_string = "PythonDataObjectsTest::TestPythonString1";
   static const char *test_string2 = "PythonDataObjectsTest::TestPythonString2";
 
-#if PY_MAJOR_VERSION < 3
-  // Verify that `PythonString` works correctly when given a PyString object.
-  // Note that PyString doesn't exist in Python 3.x, so this is only for 2.x
-  PyObject *py_string = PyString_FromString(test_string);
-  EXPECT_TRUE(PythonString::Check(py_string));
-  PythonString python_string(PyRefType::Owned, py_string);
-
-  EXPECT_EQ(PyObjectType::String, python_string.GetObjectType());
-  EXPECT_STREQ(test_string, python_string.GetString().data());
-#else
   // Verify that `PythonString` works correctly when given a PyUnicode object.
   PyObject *py_unicode = PyUnicode_FromString(test_string);
   EXPECT_TRUE(PythonString::Check(py_unicode));
   PythonString python_unicode(PyRefType::Owned, py_unicode);
   EXPECT_EQ(PyObjectType::String, python_unicode.GetObjectType());
   EXPECT_STREQ(test_string, python_unicode.GetString().data());
-#endif
 
   // Test that creating a `PythonString` object works correctly with the
   // string constructor
Index: lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
===================================================================
--- lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
+++ lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
@@ -60,17 +60,10 @@
 LLDB_PLUGIN_DEFINE(ScriptInterpreterPython)
 
 // Defined in the SWIG source file
-#if PY_MAJOR_VERSION >= 3
 extern "C" PyObject *PyInit__lldb(void);
 
 #define LLDBSwigPyInit PyInit__lldb
 
-#else
-extern "C" void init_lldb(void);
-
-#define LLDBSwigPyInit init_lldb
-#endif
-
 #if defined(_WIN32)
 // Don't mess with the signal handlers on Windows.
 #define LLDB_USE_PYTHON_SET_INTERRUPT 0
@@ -145,11 +138,7 @@
 private:
   void InitializePythonHome() {
 #if LLDB_EMBED_PYTHON_HOME
-#if PY_MAJOR_VERSION >= 3
-    typedef wchar_t* str_type;
-#else
-    typedef char* str_type;
-#endif
+    typedef wchar_t *str_type;
     static str_type g_python_home = []() -> str_type {
       const char *lldb_python_home = LLDB_PYTHON_HOME;
       const char *absolute_python_home = nullptr;
@@ -164,27 +153,12 @@
         llvm::sys::path::append(path, lldb_python_home);
         absolute_python_home = path.c_str();
       }
-#if PY_MAJOR_VERSION >= 3
       size_t size = 0;
       return Py_DecodeLocale(absolute_python_home, &size);
-#else
-      return strdup(absolute_python_home);
-#endif
     }();
     if (g_python_home != nullptr) {
       Py_SetPythonHome(g_python_home);
     }
-#else
-#if defined(__APPLE__) && PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION == 7
-    // For Darwin, the only Python version supported is the one shipped in the
-    // OS OS and linked with lldb. Other installation of Python may have higher
-    // priorities in the path, overriding PYTHONHOME and causing
-    // problems/incompatibilities. In order to avoid confusion, always hardcode
-    // the PythonHome to be right, as it's not going to change.
-    static char path[] =
-        "/System/Library/Frameworks/Python.framework/Versions/2.7";
-    Py_SetPythonHome(path);
-#endif
 #endif
   }
 
Index: lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp
===================================================================
--- lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp
+++ lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp
@@ -22,7 +22,6 @@
 PyDoc_STRVAR(moduleDocumentation,
              "Simple readline module implementation based on libedit.");
 
-#if PY_MAJOR_VERSION >= 3
 static struct PyModuleDef readline_module = {
     PyModuleDef_HEAD_INIT, // m_base
     "lldb_editline",       // m_name
@@ -34,26 +33,13 @@
     nullptr,               // m_clear
     nullptr,               // m_free
 };
-#else
-static struct PyMethodDef moduleMethods[] = {{nullptr, nullptr, 0, nullptr}};
-#endif
 
-static char *
-#if PY_MAJOR_VERSION >= 3
-simple_readline(FILE *stdin, FILE *stdout, const char *prompt)
-#else
-simple_readline(FILE *stdin, FILE *stdout, char *prompt)
-#endif
-{
+static char *simple_readline(FILE *stdin, FILE *stdout, const char *prompt) {
   rl_instream = stdin;
   rl_outstream = stdout;
   char *line = readline(prompt);
   if (!line) {
-#if PY_MAJOR_VERSION >= 3
     char *ret = (char *)PyMem_RawMalloc(1);
-#else
-    char *ret = (char *)PyMem_Malloc(1);
-#endif
     if (ret != NULL)
       *ret = '\0';
     return ret;
@@ -61,11 +47,7 @@
   if (*line)
     add_history(line);
   int n = strlen(line);
-#if PY_MAJOR_VERSION >= 3
   char *ret = (char *)PyMem_RawMalloc(n + 2);
-#else
-  char *ret = (char *)PyMem_Malloc(n + 2);
-#endif
   if (ret) {
     memcpy(ret, line, n);
     free(line);
@@ -78,11 +60,6 @@
 PyMODINIT_FUNC initlldb_readline(void) {
   PyOS_ReadlineFunctionPointer = simple_readline;
 
-#if PY_MAJOR_VERSION >= 3
   return PyModule_Create(&readline_module);
-#else
-  Py_InitModule4("readline", moduleMethods, moduleDocumentation,
-                 static_cast<PyObject *>(NULL), PYTHON_API_VERSION);
-#endif
 }
 #endif
Index: lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
===================================================================
--- lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
+++ lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
@@ -181,13 +181,7 @@
                                  "key not in dict");
 }
 
-#if PY_MAJOR_VERSION < 3
-// The python 2 API declares some arguments as char* that should
-// be const char *, but it doesn't actually modify them.
-inline char *py2_const_cast(const char *s) { return const_cast<char *>(s); }
-#else
 inline const char *py2_const_cast(const char *s) { return s; }
-#endif
 
 enum class PyInitialValue { Invalid, Empty };
 
@@ -391,14 +385,9 @@
 
 template <class T> class TypedPythonObject : public PythonObject {
 public:
-  // override to perform implicit type conversions on Reset
-  // This can be eliminated once we drop python 2 support.
-  static void Convert(PyRefType &type, PyObject *&py_obj) {}
-
   TypedPythonObject(PyRefType type, PyObject *py_obj) {
     if (!py_obj)
       return;
-    T::Convert(type, py_obj);
     if (T::Check(py_obj))
       PythonObject::operator=(PythonObject(type, py_obj));
     else if (type == PyRefType::Owned)
@@ -453,7 +442,6 @@
   explicit PythonString(llvm::StringRef string); // safe, null on error
 
   static bool Check(PyObject *py_obj);
-  static void Convert(PyRefType &type, PyObject *&py_obj);
 
   llvm::StringRef GetString() const; // safe, empty string on error
 
@@ -475,7 +463,6 @@
   explicit PythonInteger(int64_t value);
 
   static bool Check(PyObject *py_obj);
-  static void Convert(PyRefType &type, PyObject *&py_obj);
 
   void SetInteger(int64_t value);
 
Index: lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
===================================================================
--- lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
+++ lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
@@ -71,9 +71,7 @@
 }
 
 static bool python_is_finalizing() {
-#if PY_MAJOR_VERSION == 2
-  return false;
-#elif PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 7
+#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 7
   return _Py_Finalizing != nullptr;
 #else
   return _Py_IsFinalizing();
@@ -97,12 +95,6 @@
 Expected<long long> PythonObject::AsLongLong() const {
   if (!m_py_obj)
     return nullDeref();
-#if PY_MAJOR_VERSION < 3
-  if (!PyLong_Check(m_py_obj)) {
-    PythonInteger i(PyRefType::Borrowed, m_py_obj);
-    return i.AsLongLong();
-  }
-#endif
   assert(!PyErr_Occurred());
   long long r = PyLong_AsLongLong(m_py_obj);
   if (PyErr_Occurred())
@@ -113,12 +105,6 @@
 Expected<long long> PythonObject::AsUnsignedLongLong() const {
   if (!m_py_obj)
     return nullDeref();
-#if PY_MAJOR_VERSION < 3
-  if (!PyLong_Check(m_py_obj)) {
-    PythonInteger i(PyRefType::Borrowed, m_py_obj);
-    return i.AsUnsignedLongLong();
-  }
-#endif
   assert(!PyErr_Occurred());
   long long r = PyLong_AsUnsignedLongLong(m_py_obj);
   if (PyErr_Occurred())
@@ -130,12 +116,6 @@
 Expected<unsigned long long> PythonObject::AsModuloUnsignedLongLong() const {
   if (!m_py_obj)
     return nullDeref();
-#if PY_MAJOR_VERSION < 3
-  if (!PyLong_Check(m_py_obj)) {
-    PythonInteger i(PyRefType::Borrowed, m_py_obj);
-    return i.AsModuloUnsignedLongLong();
-  }
-#endif
   assert(!PyErr_Occurred());
   unsigned long long r = PyLong_AsUnsignedLongLongMask(m_py_obj);
   if (PyErr_Occurred())
@@ -183,10 +163,8 @@
     return PyObjectType::Dictionary;
   if (PythonString::Check(m_py_obj))
     return PyObjectType::String;
-#if PY_MAJOR_VERSION >= 3
   if (PythonBytes::Check(m_py_obj))
     return PyObjectType::Bytes;
-#endif
   if (PythonByteArray::Check(m_py_obj))
     return PyObjectType::ByteArray;
   if (PythonBoolean::Check(m_py_obj))
@@ -282,9 +260,7 @@
 }
 
 StructuredData::ObjectSP PythonObject::CreateStructuredObject() const {
-#if PY_MAJOR_VERSION >= 3
   assert(PyGILState_Check());
-#endif
   switch (GetObjectType()) {
   case PyObjectType::Dictionary:
     return PythonDictionary(PyRefType::Borrowed, m_py_obj)
@@ -398,11 +374,7 @@
 // PythonString
 
 Expected<PythonString> PythonString::FromUTF8(llvm::StringRef string) {
-#if PY_MAJOR_VERSION >= 3
   PyObject *str = PyUnicode_FromStringAndSize(string.data(), string.size());
-#else
-  PyObject *str = PyString_FromStringAndSize(string.data(), string.size());
-#endif
   if (!str)
     return llvm::make_error<PythonException>();
   return Take<PythonString>(str);
@@ -416,35 +388,9 @@
 
   if (PyUnicode_Check(py_obj))
     return true;
-#if PY_MAJOR_VERSION < 3
-  if (PyString_Check(py_obj))
-    return true;
-#endif
   return false;
 }
 
-void PythonString::Convert(PyRefType &type, PyObject *&py_obj) {
-#if PY_MAJOR_VERSION < 3
-  // In Python 2, Don't store PyUnicode objects directly, because we need
-  // access to their underlying character buffers which Python 2 doesn't
-  // provide.
-  if (PyUnicode_Check(py_obj)) {
-    PyObject *s = PyUnicode_AsUTF8String(py_obj);
-    if (s == nullptr) {
-      PyErr_Clear();
-      if (type == PyRefType::Owned)
-        Py_DECREF(py_obj);
-      return;
-    }
-    if (type == PyRefType::Owned)
-      Py_DECREF(py_obj);
-    else
-      type = PyRefType::Owned;
-    py_obj = s;
-  }
-#endif
-}
-
 llvm::StringRef PythonString::GetString() const {
   auto s = AsUTF8();
   if (!s) {
@@ -461,15 +407,7 @@
   Py_ssize_t size;
   const char *data;
 
-#if PY_MAJOR_VERSION >= 3
   data = PyUnicode_AsUTF8AndSize(m_py_obj, &size);
-#else
-  char *c = NULL;
-  int r = PyString_AsStringAndSize(m_py_obj, &c, &size);
-  if (r < 0)
-    c = NULL;
-  data = c;
-#endif
 
   if (!data)
     return exception();
@@ -479,14 +417,10 @@
 
 size_t PythonString::GetSize() const {
   if (IsValid()) {
-#if PY_MAJOR_VERSION >= 3
 #if PY_MINOR_VERSION >= 3
     return PyUnicode_GetLength(m_py_obj);
 #else
     return PyUnicode_GetSize(m_py_obj);
-#endif
-#else
-    return PyString_Size(m_py_obj);
 #endif
   }
   return 0;
@@ -516,41 +450,9 @@
   if (!py_obj)
     return false;
 
-#if PY_MAJOR_VERSION >= 3
   // Python 3 does not have PyInt_Check.  There is only one type of integral
   // value, long.
   return PyLong_Check(py_obj);
-#else
-  return PyLong_Check(py_obj) || PyInt_Check(py_obj);
-#endif
-}
-
-void PythonInteger::Convert(PyRefType &type, PyObject *&py_obj) {
-#if PY_MAJOR_VERSION < 3
-  // Always store this as a PyLong, which makes interoperability between Python
-  // 2.x and Python 3.x easier.  This is only necessary in 2.x, since 3.x
-  // doesn't even have a PyInt.
-  if (PyInt_Check(py_obj)) {
-    // Since we converted the original object to a different type, the new
-    // object is an owned object regardless of the ownership semantics
-    // requested by the user.
-    long long value = PyInt_AsLong(py_obj);
-    PyObject *l = nullptr;
-    if (!PyErr_Occurred())
-      l = PyLong_FromLongLong(value);
-    if (l == nullptr) {
-      PyErr_Clear();
-      if (type == PyRefType::Owned)
-        Py_DECREF(py_obj);
-      return;
-    }
-    if (type == PyRefType::Owned)
-      Py_DECREF(py_obj);
-    else
-      type = PyRefType::Owned;
-    py_obj = l;
-  }
-#endif
 }
 
 void PythonInteger::SetInteger(int64_t value) {
@@ -762,13 +664,9 @@
 PythonDictionary::GetItem(const PythonObject &key) const {
   if (!IsValid())
     return nullDeref();
-#if PY_MAJOR_VERSION >= 3
   PyObject *o = PyDict_GetItemWithError(m_py_obj, key.get());
   if (PyErr_Occurred())
     return exception();
-#else
-  PyObject *o = PyDict_GetItem(m_py_obj, key.get());
-#endif
   if (!o)
     return keyError();
   return Retain<PythonObject>(o);
@@ -826,13 +724,7 @@
   return result;
 }
 
-PythonModule PythonModule::BuiltinsModule() {
-#if PY_MAJOR_VERSION >= 3
-  return AddModule("builtins");
-#else
-  return AddModule("__builtin__");
-#endif
-}
+PythonModule PythonModule::BuiltinsModule() { return AddModule("builtins"); }
 
 PythonModule PythonModule::MainModule() { return AddModule("__main__"); }
 
@@ -1000,9 +892,6 @@
 bool PythonFile::Check(PyObject *py_obj) {
   if (!py_obj)
     return false;
-#if PY_MAJOR_VERSION < 3
-  return PyFile_Check(py_obj);
-#else
   // In Python 3, there is no `PyFile_Check`, and in fact PyFile is not even a
   // first-class object type anymore.  `PyFile_FromFd` is just a thin wrapper
   // over `io.open()`, which returns some object derived from `io.IOBase`. As a
@@ -1024,7 +913,6 @@
     return false;
   }
   return !!r;
-#endif
 }
 
 const char *PythonException::toCString() const {
@@ -1121,7 +1009,6 @@
 
 llvm::Expected<File::OpenOptions>
 GetOptionsForPyObject(const PythonObject &obj) {
-#if PY_MAJOR_VERSION >= 3
   auto options = File::OpenOptions(0);
   auto readable = As<bool>(obj.CallMethod("readable"));
   if (!readable)
@@ -1136,10 +1023,6 @@
   else if (readable.get())
     options |= File::eOpenOptionReadOnly;
   return options;
-#else
-  PythonString py_mode = obj.GetAttributeValue("mode").AsType<PythonString>();
-  return File::GetOptionsFromMode(py_mode.GetString());
-#endif
 }
 
 // Base class template for python files.   All it knows how to do
@@ -1223,8 +1106,6 @@
 char SimplePythonFile::ID = 0;
 } // namespace
 
-#if PY_MAJOR_VERSION >= 3
-
 namespace {
 class PythonBuffer {
 public:
@@ -1414,8 +1295,6 @@
 };
 } // namespace
 
-#endif
-
 llvm::Expected<FileSP> PythonFile::ConvertToFile(bool borrowed) {
   if (!IsValid())
     return llvm::createStringError(llvm::inconvertibleErrorCode(),
@@ -1466,13 +1345,6 @@
     return llvm::createStringError(llvm::inconvertibleErrorCode(),
                                    "invalid PythonFile");
 
-#if PY_MAJOR_VERSION < 3
-
-  return llvm::createStringError(llvm::inconvertibleErrorCode(),
-                                 "not supported on python 2");
-
-#else
-
   int fd = PyObject_AsFileDescriptor(m_py_obj);
   if (fd < 0) {
     PyErr_Clear();
@@ -1522,8 +1394,6 @@
                                    "invalid File");
 
   return file_sp;
-
-#endif
 }
 
 Expected<PythonFile> PythonFile::FromFile(File &file, const char *mode) {
@@ -1533,10 +1403,8 @@
 
   if (auto *simple = llvm::dyn_cast<SimplePythonFile>(&file))
     return Retain<PythonFile>(simple->GetPythonObject());
-#if PY_MAJOR_VERSION >= 3
   if (auto *pythonio = llvm::dyn_cast<PythonIOFile>(&file))
     return Retain<PythonFile>(pythonio->GetPythonObject());
-#endif
 
   if (!mode) {
     auto m = file.GetOpenMode();
@@ -1546,26 +1414,8 @@
   }
 
   PyObject *file_obj;
-#if PY_MAJOR_VERSION >= 3
   file_obj = PyFile_FromFd(file.GetDescriptor(), nullptr, mode, -1, nullptr,
                            "ignore", nullptr, /*closefd=*/0);
-#else
-  // I'd like to pass ::fflush here if the file is writable,  so that
-  // when the python side destructs the file object it will be flushed.
-  // However, this would be dangerous.    It can cause fflush to be called
-  // after fclose if the python program keeps a reference to the file after
-  // the original lldb_private::File has been destructed.
-  //
-  // It's all well and good to ask a python program not to use a closed file
-  // but asking a python program to make sure objects get released in a
-  // particular order is not safe.
-  //
-  // The tradeoff here is that if a python 2 program wants to make sure this
-  // file gets flushed, they'll have to do it explicitly or wait untill the
-  // original lldb File itself gets flushed.
-  file_obj = PyFile_FromFile(file.GetStream(), py2_const_cast(""),
-                             py2_const_cast(mode), [](FILE *) { return 0; });
-#endif
 
   if (!file_obj)
     return exception();
@@ -1612,12 +1462,7 @@
     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();
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to