Skip to content

Commit

Permalink
Make the C accelerator modules compatible with Python 3
Browse files Browse the repository at this point in the history
This is just the first step toward full compatibility with Python 3: it
discloses some problems related to bytes-vs-str stricter rules that
needs to be sorted out.
  • Loading branch information
lelit committed Dec 3, 2015
1 parent e02f902 commit 109fe00
Show file tree
Hide file tree
Showing 3 changed files with 169 additions and 43 deletions.
85 changes: 73 additions & 12 deletions dulwich/_diff_tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,22 @@ typedef int Py_ssize_t;
#define Py_SIZE(ob) (((PyVarObject*)(ob))->ob_size)
#endif

#if PY_MAJOR_VERSION >= 3
#define PyInt_FromLong PyLong_FromLong
#define PyInt_AsLong PyLong_AsLong
#define PyInt_AS_LONG PyLong_AS_LONG
#define PyString_AS_STRING PyBytes_AS_STRING
#define PyString_AsString PyBytes_AsString
#define PyString_AsStringAndSize PyBytes_AsStringAndSize
#define PyString_Check PyBytes_Check
#define PyString_CheckExact PyBytes_CheckExact
#define PyString_FromStringAndSize PyBytes_FromStringAndSize
#define PyString_FromString PyBytes_FromString
#define PyString_GET_SIZE PyBytes_GET_SIZE
#define PyString_Size PyBytes_Size
#define _PyString_Join _PyBytes_Join
#endif

static PyObject *tree_entry_cls = NULL, *null_entry = NULL,
*defaultdict_cls = NULL, *int_cls = NULL;
static int block_size;
Expand Down Expand Up @@ -152,6 +168,17 @@ static int entry_path_cmp(PyObject *entry1, PyObject *entry2)
path1 = PyObject_GetAttrString(entry1, "path");
if (!path1)
goto done;

#if PY_MAJOR_VERSION >= 3
/* XXX: Is FSConverter desiderable here? */
if (PyUnicode_Check(path1)) {
PyObject *bytes;
if (!PyUnicode_FSConverter(path1, &bytes))
goto done;
Py_DECREF(path1);
path1 = bytes;
}
#endif
if (!PyString_Check(path1)) {
PyErr_SetString(PyExc_TypeError, "path is not a string");
goto done;
Expand All @@ -160,6 +187,17 @@ static int entry_path_cmp(PyObject *entry1, PyObject *entry2)
path2 = PyObject_GetAttrString(entry2, "path");
if (!path2)
goto done;

#if PY_MAJOR_VERSION >= 3
/* XXX: Is FSConverter desiderable here? */
if (PyUnicode_Check(path2)) {
PyObject *bytes;
if (!PyUnicode_FSConverter(path2, &bytes))
goto done;
Py_DECREF(path2);
path2 = bytes;
}
#endif
if (!PyString_Check(path2)) {
PyErr_SetString(PyExc_TypeError, "path is not a string");
goto done;
Expand Down Expand Up @@ -390,12 +428,28 @@ static PyMethodDef py_diff_tree_methods[] = {
{ NULL, NULL, 0, NULL }
};

PyMODINIT_FUNC
init_diff_tree(void)
static PyObject *
moduleinit(void)
{
PyObject *m, *objects_mod = NULL, *diff_tree_mod = NULL;
PyObject *block_size_obj = NULL;
PyObject *block_size_obj = NULL;

#if PY_MAJOR_VERSION >= 3
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
"_diff_tree", /* m_name */
NULL, /* m_doc */
-1, /* m_size */
py_diff_tree_methods, /* m_methods */
NULL, /* m_reload */
NULL, /* m_traverse */
NULL, /* m_clear*/
NULL, /* m_free */
};
m = PyModule_Create(&moduledef);
#else
m = Py_InitModule("_diff_tree", py_diff_tree_methods);
#endif
if (!m)
goto error;

Expand Down Expand Up @@ -437,11 +491,8 @@ init_diff_tree(void)
}

Py_DECREF(diff_tree_mod);
#if PY_MAJOR_VERSION < 3
return;
#else
return NULL;
#endif

return m;

error:
Py_XDECREF(objects_mod);
Expand All @@ -450,9 +501,19 @@ init_diff_tree(void)
Py_XDECREF(block_size_obj);
Py_XDECREF(defaultdict_cls);
Py_XDECREF(int_cls);
#if PY_MAJOR_VERSION < 3
return;
#else
return NULL;
#endif
}

#if PY_MAJOR_VERSION >= 3
PyMODINIT_FUNC
PyInit__diff_tree(void)
{
return moduleinit();
}
#else
PyMODINIT_FUNC
init_diff_tree(void)
{
moduleinit();
}
#endif
74 changes: 47 additions & 27 deletions dulwich/_objects.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,15 @@
typedef int Py_ssize_t;
#endif

#if PY_MAJOR_VERSION >= 3
#define PyInt_Check(obj) 0
#define PyInt_CheckExact(obj) 0
#define PyInt_AsLong PyLong_AsLong
#define PyString_AS_STRING PyBytes_AS_STRING
#define PyString_Check PyBytes_Check
#define PyString_FromStringAndSize PyBytes_FromStringAndSize
#endif

#if defined(__MINGW32_VERSION) || defined(__APPLE__)
size_t rep_strnlen(char *text, size_t maxlen);
size_t rep_strnlen(char *text, size_t maxlen)
Expand Down Expand Up @@ -248,58 +257,69 @@ static PyMethodDef py_objects_methods[] = {
{ NULL, NULL, 0, NULL }
};

PyMODINIT_FUNC
init_objects(void)
static PyObject *
moduleinit(void)
{
PyObject *m, *objects_mod, *errors_mod;

m = Py_InitModule3("_objects", py_objects_methods, NULL);
if (m == NULL) {
#if PY_MAJOR_VERSION < 3
return;
#if PY_MAJOR_VERSION >= 3
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
"_objects", /* m_name */
NULL, /* m_doc */
-1, /* m_size */
py_objects_methods, /* m_methods */
NULL, /* m_reload */
NULL, /* m_traverse */
NULL, /* m_clear*/
NULL, /* m_free */
};
m = PyModule_Create(&moduledef);
#else
return NULL;
m = Py_InitModule3("_objects", py_objects_methods, NULL);
#endif
if (m == NULL) {
return NULL;
}

errors_mod = PyImport_ImportModule("dulwich.errors");
if (errors_mod == NULL) {
#if PY_MAJOR_VERSION < 3
return;
#else
return NULL;
#endif
return NULL;
}

object_format_exception_cls = PyObject_GetAttrString(
errors_mod, "ObjectFormatException");
Py_DECREF(errors_mod);
if (object_format_exception_cls == NULL) {
#if PY_MAJOR_VERSION < 3
return;
#else
return NULL;
#endif
return NULL;
}

/* This is a circular import but should be safe since this module is
* imported at at the very bottom of objects.py. */
objects_mod = PyImport_ImportModule("dulwich.objects");
if (objects_mod == NULL) {
#if PY_MAJOR_VERSION < 3
return;
#else
return NULL;
#endif
return NULL;
}

tree_entry_cls = PyObject_GetAttrString(objects_mod, "TreeEntry");
Py_DECREF(objects_mod);
if (tree_entry_cls == NULL) {
#if PY_MAJOR_VERSION < 3
return;
#else
return NULL;
#endif
return NULL;
}

return m;
}

#if PY_MAJOR_VERSION >= 3
PyMODINIT_FUNC
PyInit__objects(void)
{
return moduleinit();
}
#else
PyMODINIT_FUNC
init_objects(void)
{
moduleinit();
}
#endif
53 changes: 49 additions & 4 deletions dulwich/_pack.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,19 @@
#include <Python.h>
#include <stdint.h>

#if PY_MAJOR_VERSION >= 3
#define PyInt_FromLong PyLong_FromLong
#define PyString_AS_STRING PyBytes_AS_STRING
#define PyString_AsString PyBytes_AsString
#define PyString_Check PyBytes_Check
#define PyString_CheckExact PyBytes_CheckExact
#define PyString_FromStringAndSize PyBytes_FromStringAndSize
#define PyString_FromString PyBytes_FromString
#define PyString_GET_SIZE PyBytes_GET_SIZE
#define PyString_Size PyBytes_Size
#define _PyString_Join _PyBytes_Join
#endif

static PyObject *PyExc_ApplyDeltaError = NULL;

static int py_is_sha(PyObject *sha)
Expand Down Expand Up @@ -239,21 +252,53 @@ static PyMethodDef py_pack_methods[] = {
{ NULL, NULL, 0, NULL }
};

void init_pack(void)
static PyObject *
moduleinit(void)
{
PyObject *m;
PyObject *errors_module;

errors_module = PyImport_ImportModule("dulwich.errors");
if (errors_module == NULL)
return;
return NULL;

PyExc_ApplyDeltaError = PyObject_GetAttrString(errors_module, "ApplyDeltaError");
Py_DECREF(errors_module);
if (PyExc_ApplyDeltaError == NULL)
return;
return NULL;

#if PY_MAJOR_VERSION >= 3
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
"_pack", /* m_name */
NULL, /* m_doc */
-1, /* m_size */
py_pack_methods, /* m_methods */
NULL, /* m_reload */
NULL, /* m_traverse */
NULL, /* m_clear*/
NULL, /* m_free */
};
m = PyModule_Create(&moduledef);
#else
m = Py_InitModule3("_pack", py_pack_methods, NULL);
#endif
if (m == NULL)
return;
return NULL;

return m;
}

#if PY_MAJOR_VERSION >= 3
PyMODINIT_FUNC
PyInit__pack(void)
{
return moduleinit();
}
#else
PyMODINIT_FUNC
init_pack(void)
{
moduleinit();
}
#endif

0 comments on commit 109fe00

Please sign in to comment.