From ee10f2610c4a51c37ca00d31fd6e11a08351d4f1 Mon Sep 17 00:00:00 2001
From: Alberto Bertogli <albertito@blitiri.com.ar>
Date: Thu, 26 Mar 2009 21:34:19 -0300
Subject: [PATCH 17/32] Add Python 3 bindings

This patch adds Python 3 bindings, based on Python 2 bindings.

Signed-off-by: Alberto Bertogli <albertito@blitiri.com.ar>
---
 INSTALL                                |   11 ++--
 Makefile                               |   12 ++++-
 bindings/{python2 => python3}/libjio.c |  102 +++++++++++++++-----------------
 bindings/{python2 => python3}/setup.py |    0
 4 files changed, 64 insertions(+), 61 deletions(-)
 copy bindings/{python2 => python3}/libjio.c (89%)
 copy bindings/{python2 => python3}/setup.py (100%)

diff --git a/INSTALL b/INSTALL
index f9b2794..ff96287 100644
--- a/INSTALL
+++ b/INSTALL
@@ -28,10 +28,11 @@ Special builds
 Python bindings
 ---------------
 
-In order to build the Python bindings, you should have libjio already
-installed.
-
-To build the bindings, run "make python2". To install them, run
-"make python2_install".
+The library comes with bindings for Python 2 and Python 3. In order to build
+them, you should have libjio already installed.
 
+ - To build the Python 2 bindings, run "make python2". To install them, run
+   "make python2_install".
+ - To build the Python 3 bindings, run "make python3". To install them, run
+   "make python3_install".
 
diff --git a/Makefile b/Makefile
index ea60e21..8128284 100644
--- a/Makefile
+++ b/Makefile
@@ -89,6 +89,13 @@ python2:
 python2_install: python2
 	cd bindings/python2 && python setup.py install
 
+python3:
+	cd bindings/python3 && python3 setup.py build
+
+python3_install: python3
+	cd bindings/python3 && python3 setup.py install
+
+
 
 preload: all
 	install -d bindings/preload/build/
@@ -107,9 +114,12 @@ clean:
 	rm -f $(OBJS) libjio.a libjio.so libjio.pc jiofsck.o jiofsck
 	rm -f *.bb *.bbg *.da *.gcov *.gcno *.gcda gmon.out
 	rm -rf bindings/python2/build/
+	rm -rf bindings/python3/build/
 	rm -rf bindings/preload/build/
 
 
-.PHONY: default all install python2 python2_install preload preload_install \
+.PHONY: default all install \
+	python2 python2_install python3 python3_install \
+	preload preload_install \
 	clean
 
diff --git a/bindings/python2/libjio.c b/bindings/python3/libjio.c
similarity index 89%
copy from bindings/python2/libjio.c
copy to bindings/python3/libjio.c
index 1edfc47..0b119a6 100644
--- a/bindings/python2/libjio.c
+++ b/bindings/python3/libjio.c
@@ -1,6 +1,6 @@
 
 /*
- * Python bindings for libjio
+ * Python 3 bindings for libjio
  * Alberto Bertogli (albertito@blitiri.com.ar)
  */
 
@@ -44,6 +44,7 @@ typedef struct {
 
 static PyTypeObject jfile_type;
 
+
 /* jtrans */
 typedef struct {
 	PyObject_HEAD
@@ -79,7 +80,7 @@ static PyObject *jf_fileno(jfile_object *fp, PyObject *args)
 	if (!PyArg_ParseTuple(args, ":fileno"))
 		return NULL;
 
-	return PyInt_FromLong(fp->fs->fd);
+	return PyLong_FromLong(fp->fs->fd);
 }
 
 /* read */
@@ -111,7 +112,7 @@ static PyObject *jf_read(jfile_object *fp, PyObject *args)
 	if (rv < 0) {
 		r = PyErr_SetFromErrno(PyExc_IOError);
 	} else {
-		r = PyString_FromStringAndSize((char *) buf, rv);
+		r = PyBytes_FromStringAndSize((char *) buf, rv);
 	}
 
 	free(buf);
@@ -148,7 +149,7 @@ static PyObject *jf_pread(jfile_object *fp, PyObject *args)
 	if (rv < 0) {
 		r = PyErr_SetFromErrno(PyExc_IOError);
 	} else {
-		r = PyString_FromStringAndSize((char *) buf, rv);
+		r = PyBytes_FromStringAndSize((char *) buf, rv);
 	}
 
 	free(buf);
@@ -333,7 +334,7 @@ static PyObject *jf_new_trans(jfile_object *fp, PyObject *args)
 	if (!PyArg_ParseTuple(args, ":new_trans"))
 		return NULL;
 
-	tp = PyObject_New(jtrans_object, &jtrans_type);
+	tp = (jtrans_object *) jtrans_type.tp_alloc(&jtrans_type, 0);
 	if (tp == NULL)
 		return NULL;
 
@@ -351,7 +352,6 @@ static PyObject *jf_new_trans(jfile_object *fp, PyObject *args)
 	return (PyObject *) tp;
 }
 
-
 /* method table */
 static PyMethodDef jfile_methods[] = {
 	{ "fileno", (PyCFunction) jf_fileno, METH_VARARGS, jf_fileno__doc },
@@ -370,20 +370,12 @@ static PyMethodDef jfile_methods[] = {
 	{ NULL }
 };
 
-static PyObject *jf_getattr(jfile_object *fp, char *name)
-{
-	return Py_FindMethod(jfile_methods, (PyObject *)fp, name);
-}
-
 static PyTypeObject jfile_type = {
 	PyObject_HEAD_INIT(NULL)
-	0,
-	"libjio.jfile",
-	sizeof(jfile_object),
-	0,
-	(destructor)jf_dealloc,
-	0,
-	(getattrfunc)jf_getattr,
+	.tp_name = "libjio.jfile",
+	.tp_itemsize = sizeof(jfile_object),
+	.tp_dealloc = (destructor) jf_dealloc,
+	.tp_methods = jfile_methods,
 };
 
 
@@ -479,29 +471,19 @@ static PyObject *jt_rollback(jtrans_object *tp, PyObject *args)
 static PyMethodDef jtrans_methods[] = {
 	{ "add", (PyCFunction) jt_add, METH_VARARGS, jt_add__doc },
 	{ "commit", (PyCFunction) jt_commit, METH_VARARGS, jt_commit__doc },
-	{ "rollback", (PyCFunction) jt_rollback, METH_VARARGS,
-		jt_rollback__doc },
+	{ "rollback", (PyCFunction) jt_rollback, METH_VARARGS, jt_rollback__doc },
 	{ NULL }
 };
 
-static PyObject *jt_getattr(jtrans_object *tp, char *name)
-{
-	return Py_FindMethod(jtrans_methods, (PyObject *)tp, name);
-}
-
 static PyTypeObject jtrans_type = {
 	PyObject_HEAD_INIT(NULL)
-	0,
-	"libjio.jtrans",
-	sizeof(jtrans_object),
-	0,
-	(destructor)jt_dealloc,
-	0,
-	(getattrfunc)jt_getattr,
+	.tp_name = "libjio.jtrans",
+	.tp_itemsize = sizeof(jtrans_object),
+	.tp_dealloc = (destructor) jt_dealloc,
+	.tp_methods = jtrans_methods,
 };
 
 
-
 /*
  * The module
  */
@@ -530,7 +512,7 @@ static PyObject *jf_open(PyObject *self, PyObject *args)
 				&jflags))
 		return NULL;
 
-	fp = PyObject_New(jfile_object, &jfile_type);
+	fp = (jfile_object *) jfile_type.tp_alloc(&jfile_type, 0);
 	if (fp == NULL)
 		return NULL;
 
@@ -587,7 +569,7 @@ static PyObject *jf_jfsck(PyObject *self, PyObject *args)
 		return PyErr_NoMemory();
 	} else if (rv != 0) {
 		Py_XDECREF(dict);
-		PyErr_SetObject(PyExc_IOError, PyInt_FromLong(rv));
+		PyErr_SetObject(PyExc_IOError, PyLong_FromLong(rv));
 		return NULL;
 	}
 
@@ -623,38 +605,46 @@ static PyObject *jf_jfsck_cleanup(PyObject *self, PyObject *args)
 	Py_END_ALLOW_THREADS
 
 	if (rv != 1) {
-		PyErr_SetObject(PyExc_IOError, PyInt_FromLong(rv));
+		PyErr_SetObject(PyExc_IOError, PyLong_FromLong(rv));
 		return NULL;
 	}
 
-	return PyInt_FromLong(rv);
+	return PyLong_FromLong(rv);
 }
 
-/* function table */
-static PyMethodDef libjio_functions[] = {
-	{ "open", (PyCFunction) jf_open, METH_VARARGS, jf_open__doc },
-	{ "jfsck", (PyCFunction) jf_jfsck, METH_VARARGS, jf_jfsck__doc },
-	{ "jfsck_cleanup", (PyCFunction) jf_jfsck_cleanup, METH_VARARGS,
+
+static PyMethodDef module_methods[] = {
+	{ "open", jf_open, METH_VARARGS, jf_open__doc },
+	{ "jfsck", jf_jfsck, METH_VARARGS, jf_jfsck__doc },
+	{ "jfsck_cleanup", jf_jfsck_cleanup, METH_VARARGS,
 		jf_jfsck_cleanup__doc },
-	{ NULL, },
+	{ NULL, NULL, 0, NULL },
 };
 
-/* module initialization */
-PyDoc_STRVAR(libjio__doc,
-"libjio is a library to do transactional, journaled I/O\n\
-You can find it at http://blitiri.com.ar/p/libjio/\n\
-\n\
-Use the open() method to create a file object, and then operate on it.\n\
-Please read the documentation for more information.\n");
+#define module_doc "libjio is a library to do transactional, journaled I/O\n" \
+	"You can find it at http://blitiri.com.ar/p/libjio/\n" \
+	"\n" \
+	"Use the open() method to create a file object, and then operate " \
+	"on it.\n" \
+	"Please read the documentation for more information.\n"
+
+static PyModuleDef libjio_module = {
+	PyModuleDef_HEAD_INIT,
+	.m_name = "libjio",
+	.m_doc = module_doc,
+	.m_size = -1,
+	.m_methods = module_methods,
+};
 
-PyMODINIT_FUNC initlibjio(void)
+PyMODINIT_FUNC PyInit_libjio(void)
 {
-	PyObject* m;
+	PyObject *m;
 
-	jfile_type.ob_type = &PyType_Type;
-	jtrans_type.ob_type = &PyType_Type;
+	if (PyType_Ready(&jfile_type) < 0 ||
+			PyType_Ready(&jtrans_type) < 0)
+		return NULL;
 
-	m = Py_InitModule3("libjio", libjio_functions, libjio__doc);
+	m = PyModule_Create(&libjio_module);
 
 	Py_INCREF(&jfile_type);
 	PyModule_AddObject(m, "jfile", (PyObject *) &jfile_type);
@@ -692,5 +682,7 @@ PyMODINIT_FUNC initlibjio(void)
 	PyModule_AddIntConstant(m, "SEEK_SET", SEEK_SET);
 	PyModule_AddIntConstant(m, "SEEK_CUR", SEEK_CUR);
 	PyModule_AddIntConstant(m, "SEEK_END", SEEK_END);
+
+	return m;
 }
 
diff --git a/bindings/python2/setup.py b/bindings/python3/setup.py
similarity index 100%
copy from bindings/python2/setup.py
copy to bindings/python3/setup.py
-- 
1.6.2.rc0.226.gf08f


