Skip to content

Commit

Permalink
Port native Python-API to 3.x
Browse files Browse the repository at this point in the history
With this change, liblldb is 95% of the way towards being able
to work under both Python 2.x and Python 3.x.  This should
introduce no functional change for Python 2.x, but for Python
3.x there are some important changes.  Primarily, these are:

1) PyString doesn't exist in Python 3.  Everything is a PyUnicode.
   To account for this, PythonString now stores a PyBytes instead
   of a PyString.  In Python 2, this is equivalent to a PyUnicode,
   and in Python 3, we do a conversion from PyUnicode to PyBytes
   and store the PyBytes.
2) PyInt doesn't exist in Python 3.  Everything is a PyLong.  To
   account for this, PythonInteger stores a PyLong instead of a
   PyInt.  In Python 2.x, this requires doing a conversion to
   PyLong when creating a PythonInteger from a PyInt.  In 3.x,
   there is no PyInt anyway, so we can assume everything is a
   PyLong.
3) PyFile_FromFile doesn't exist in Python 3.  Instead there is a
   PyFile_FromFd.  This is not addressed in this patch because it
   will require quite a large change to plumb fd's all the way
   through the system into the ScriptInterpreter.  This is the only
   remaining piece of the puzzle to get LLDB supporting Python 3.x.

Being able to run the test suite is not addressed in this patch.
After the extension module can compile and you can enter an embedded
3.x interpreter, the test suite will be addressed in a followup.

llvm-svn: 249886
  • Loading branch information
Zachary Turner committed Oct 9, 2015
1 parent 3a1acdd commit 22c8efc
Show file tree
Hide file tree
Showing 7 changed files with 648 additions and 99 deletions.
201 changes: 147 additions & 54 deletions lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,18 @@ PythonObject::GetObjectType() const
return PyObjectType::List;
if (PyDict_Check(m_py_obj))
return PyObjectType::Dictionary;
if (PyUnicode_Check(m_py_obj))
return PyObjectType::String;
if (PyLong_Check(m_py_obj))
return PyObjectType::Integer;
#if PY_MAJOR_VERSION < 3
// These functions don't exist in Python 3.x. PyString is PyUnicode
// and PyInt is PyLong.
if (PyString_Check(m_py_obj))
return PyObjectType::String;
if (PyInt_Check(m_py_obj) || PyLong_Check(m_py_obj))
if (PyInt_Check(m_py_obj))
return PyObjectType::Integer;
#endif
return PyObjectType::Unknown;
}

Expand Down Expand Up @@ -142,14 +150,16 @@ PythonString::PythonString (const PythonObject &object) :
Reset(object.get()); // Use "Reset()" to ensure that py_obj is a string
}

PythonString::PythonString (llvm::StringRef string) :
PythonObject(PyString_FromStringAndSize(string.data(), string.size()))
PythonString::PythonString(llvm::StringRef string)
: PythonObject()
{
SetString(string);
}

PythonString::PythonString(const char *string) :
PythonObject(PyString_FromString(string))
PythonString::PythonString(const char *string)
: PythonObject()
{
SetString(llvm::StringRef(string));
}

PythonString::PythonString () :
Expand All @@ -162,35 +172,75 @@ PythonString::~PythonString ()
}

bool
PythonString::Reset (PyObject *py_obj)
PythonString::Check(PyObject *py_obj)
{
if (py_obj && PyString_Check(py_obj))
return PythonObject::Reset(py_obj);

PythonObject::Reset(nullptr);
return py_obj == nullptr;
if (!py_obj)
return false;
#if PY_MAJOR_VERSION >= 3
// Python 3 does not have PyString objects, only PyUnicode.
return PyUnicode_Check(py_obj);
#else
return PyUnicode_Check(py_obj) || PyString_Check(py_obj);
#endif
}

bool
PythonString::Reset(PyObject *py_obj)
{
if (!PythonString::Check(py_obj))
{
PythonObject::Reset(nullptr);
return false;
}

// Convert this to a PyBytes object, and only store the PyBytes. Note that in
// Python 2.x, PyString and PyUnicode are interchangeable, and PyBytes is an alias
// of PyString. So on 2.x, if we get into this branch, we already have a PyBytes.
//#if PY_MAJOR_VERSION >= 3
if (PyUnicode_Check(py_obj))
{
PyObject *unicode = py_obj;
py_obj = PyUnicode_AsUTF8String(py_obj);
Py_XDECREF(unicode);
}
//#endif

assert(PyBytes_Check(py_obj) && "PythonString::Reset received a non-string");
return PythonObject::Reset(py_obj);
}

llvm::StringRef
PythonString::GetString() const
{
if (m_py_obj)
return llvm::StringRef(PyString_AsString(m_py_obj), GetSize());
{
Py_ssize_t size;
char *c;
PyBytes_AsStringAndSize(m_py_obj, &c, &size);
return llvm::StringRef(c, size);
}
return llvm::StringRef();
}

size_t
PythonString::GetSize() const
{
if (m_py_obj)
return PyString_Size(m_py_obj);
return PyBytes_Size(m_py_obj);
return 0;
}

void
PythonString::SetString (llvm::StringRef string)
{
#if PY_MAJOR_VERSION >= 3
PyObject *unicode = PyUnicode_FromStringAndSize(string.data(), string.size());
PyObject *bytes = PyUnicode_AsUTF8String(unicode);
PythonObject::Reset(bytes);
Py_XDECREF(unicode);
#else
PythonObject::Reset(PyString_FromStringAndSize(string.data(), string.size()));
#endif
}

StructuredData::StringSP
Expand Down Expand Up @@ -229,27 +279,54 @@ PythonInteger::~PythonInteger ()
}

bool
PythonInteger::Reset (PyObject *py_obj)
PythonInteger::Check(PyObject *py_obj)
{
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
}

bool
PythonInteger::Reset(PyObject *py_obj)
{
if (py_obj)
if (!PythonInteger::Check(py_obj))
{
if (PyInt_Check (py_obj) || PyLong_Check(py_obj))
return PythonObject::Reset(py_obj);
PythonObject::Reset(nullptr);
return false;
}

PythonObject::Reset(nullptr);
return py_obj == nullptr;

#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))
{
PyObject *py_long = PyLong_FromLongLong(PyInt_AsLong(py_obj));
Py_XDECREF(py_obj);
py_obj = py_long;
}
#endif

assert(PyLong_Check(py_obj) && "Couldn't get a PyLong from this PyObject");

return PythonObject::Reset(py_obj);
}

int64_t
PythonInteger::GetInteger() const
{
if (m_py_obj)
{
if (PyInt_Check(m_py_obj))
return PyInt_AsLong(m_py_obj);
else if (PyLong_Check(m_py_obj))
return PyLong_AsLongLong(m_py_obj);
assert(PyLong_Check(m_py_obj) && "PythonInteger::GetInteger has a PyObject that isn't a PyLong");

return PyLong_AsLongLong(m_py_obj);
}
return UINT64_MAX;
}
Expand All @@ -272,13 +349,8 @@ PythonInteger::CreateStructuredInteger() const
// PythonList
//----------------------------------------------------------------------

PythonList::PythonList (bool create_empty) :
PythonObject(create_empty ? PyList_New(0) : nullptr)
{
}

PythonList::PythonList (uint32_t count) :
PythonObject(PyList_New(count))
PythonList::PythonList()
: PythonObject(PyList_New(0))
{
}

Expand All @@ -300,13 +372,23 @@ PythonList::~PythonList ()
}

bool
PythonList::Reset (PyObject *py_obj)
PythonList::Check(PyObject *py_obj)
{
if (py_obj && PyList_Check(py_obj))
return PythonObject::Reset(py_obj);

PythonObject::Reset(nullptr);
return py_obj == nullptr;
if (!py_obj)
return false;
return PyList_Check(py_obj);
}

bool
PythonList::Reset(PyObject *py_obj)
{
if (!PythonList::Check(py_obj))
{
PythonObject::Reset(nullptr);
return false;
}

return PythonObject::Reset(py_obj);
}

uint32_t
Expand Down Expand Up @@ -356,8 +438,8 @@ PythonList::CreateStructuredArray() const
// PythonDictionary
//----------------------------------------------------------------------

PythonDictionary::PythonDictionary (bool create_empty) :
PythonObject(create_empty ? PyDict_New() : nullptr)
PythonDictionary::PythonDictionary()
: PythonObject(PyDict_New())
{
}

Expand All @@ -379,13 +461,24 @@ PythonDictionary::~PythonDictionary ()
}

bool
PythonDictionary::Reset (PyObject *py_obj)
PythonDictionary::Check(PyObject *py_obj)
{
if (py_obj && PyDict_Check(py_obj))
return PythonObject::Reset(py_obj);

PythonObject::Reset(nullptr);
return py_obj == nullptr;
if (!py_obj)
return false;

return PyDict_Check(py_obj);
}

bool
PythonDictionary::Reset(PyObject *py_obj)
{
if (!PythonDictionary::Check(py_obj))
{
PythonObject::Reset(nullptr);
return false;
}

return PythonObject::Reset(py_obj);
}

uint32_t
Expand Down Expand Up @@ -423,8 +516,11 @@ PythonDictionary::GetItemForKeyAsString (const PythonString &key, const char *fa
if (m_py_obj && key)
{
PyObject *py_obj = PyDict_GetItem(m_py_obj, key.get());
if (py_obj && PyString_Check(py_obj))
return PyString_AsString(py_obj);
if (py_obj && PythonString::Check(py_obj))
{
PythonString str(py_obj);
return str.GetString().data();
}
}
return fail_value;
}
Expand All @@ -435,13 +531,10 @@ PythonDictionary::GetItemForKeyAsInteger (const PythonString &key, int64_t fail_
if (m_py_obj && key)
{
PyObject *py_obj = PyDict_GetItem(m_py_obj, key.get());
if (py_obj)
if (PythonInteger::Check(py_obj))
{
if (PyInt_Check(py_obj))
return PyInt_AsLong(py_obj);

if (PyLong_Check(py_obj))
return PyLong_AsLong(py_obj);
PythonInteger int_obj(py_obj);
return int_obj.GetInteger();
}
}
return fail_value;
Expand All @@ -452,7 +545,7 @@ PythonDictionary::GetKeys () const
{
if (m_py_obj)
return PythonList(PyDict_Keys(m_py_obj));
return PythonList(true);
return PythonList();
}

PythonString
Expand Down
25 changes: 15 additions & 10 deletions lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ enum class PyObjectType
protected:
PyObject* m_py_obj;
};

class PythonString: public PythonObject
{
public:
Expand All @@ -167,6 +167,8 @@ enum class PyObjectType
PythonString (const char *string);
virtual ~PythonString ();

static bool Check(PyObject *py_obj);

virtual bool
Reset (PyObject* py_obj = NULL);

Expand All @@ -180,7 +182,7 @@ enum class PyObjectType

StructuredData::StringSP CreateStructuredString() const;
};

class PythonInteger: public PythonObject
{
public:
Expand All @@ -190,7 +192,9 @@ enum class PyObjectType
PythonInteger (const PythonObject &object);
PythonInteger (int64_t value);
virtual ~PythonInteger ();


static bool Check(PyObject *py_obj);

virtual bool
Reset (PyObject* py_obj = NULL);

Expand All @@ -205,13 +209,13 @@ enum class PyObjectType
class PythonList: public PythonObject
{
public:

PythonList (bool create_empty);
PythonList();
PythonList (PyObject* py_obj);
PythonList (const PythonObject &object);
PythonList (uint32_t count);
virtual ~PythonList ();


static bool Check(PyObject *py_obj);

virtual bool
Reset (PyObject* py_obj = NULL);

Expand All @@ -231,12 +235,13 @@ enum class PyObjectType
class PythonDictionary: public PythonObject
{
public:

explicit PythonDictionary (bool create_empty);
PythonDictionary();
PythonDictionary (PyObject* object);
PythonDictionary (const PythonObject &object);
virtual ~PythonDictionary ();


static bool Check(PyObject *py_obj);

virtual bool
Reset (PyObject* object = NULL);

Expand Down
Loading

0 comments on commit 22c8efc

Please sign in to comment.