diff --git a/swh/loader/cvs/rcsparse/py-rcsparse.c b/swh/loader/cvs/rcsparse/py-rcsparse.c
index bddde7c..2bc6309 100644
--- a/swh/loader/cvs/rcsparse/py-rcsparse.c
+++ b/swh/loader/cvs/rcsparse/py-rcsparse.c
@@ -1,786 +1,842 @@
/*
* This file is part of rcsparse.
*
* rcsparse is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* rcsparse is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with rcsparse. If not, see .
*/
#include
#include
#include
#include "queue.h"
#include "rcsparse.h"
+#if PY_MAJOR_VERSION >= 3
+#define PyString_AsStringAndSize _PyUnicode_AsUTF8AndSize
+#define PyString_CheckExact PyUnicode_CheckExact
+#define PyString_FromString PyUnicode_FromString
+#define PyString_FromStringAndSize PyUnicode_FromStringAndSize
+#endif
+
+static void
+_PyUnicode_AsUTF8AndSize(PyObject *obj, char **strp, Py_ssize_t *sizep)
+{
+ *strp = PyUnicode_AsUTF8AndSize(obj, sizep);
+}
+
static PyObject *
rcstoken2pystr(struct rcstoken *tok)
{
if (tok == NULL)
Py_RETURN_NONE;
return PyString_FromStringAndSize(tok->str, tok->len);
}
static PyObject *
rcstoklist2py(struct rcstoklist *head)
{
PyObject *list;
struct rcstoken *tok;
list = PyList_New(0);
if (list == NULL)
return NULL;
for (tok = SLIST_FIRST(head); tok != NULL; tok = SLIST_NEXT(tok, link)) {
PyObject *o;
o = rcstoken2pystr(tok);
if (PyList_Append(list, o) < 0) {
Py_XDECREF(o);
Py_XDECREF(list);
return NULL;
}
Py_XDECREF(o);
}
return list;
}
struct pyrcsrevtree {
PyObject_HEAD
struct pyrcsfile *pyrcs;
struct rcsrevtree *tree;
};
static int
pyrcsrevtree_find_internal(struct pyrcsrevtree *self, PyObject *key, struct rcsrev **frev)
{
struct rcsrev rev;
struct rcstoken tok;
Py_ssize_t l;
if (!PyString_CheckExact(key))
return -1;
PyString_AsStringAndSize(key, &tok.str, &l);
if (l < 0)
return -1;
tok.len = (unsigned)l;
rev.rev = &tok;
*frev = RB_FIND(rcsrevtree, self->tree, &rev);
return *frev != NULL;
}
static PyObject *
rcsrev2py(struct rcsrev *rev)
{
struct tm tm;
const char *month;
bzero(&tm, sizeof(struct tm));
#define readdate(str, dest, len) do { \
const char *pos; \
int scale; \
for (pos = str + len - 1, scale = 1; pos >= str; pos--, scale *= 10) \
if (*pos < '0' || *pos > '9') \
return PyErr_Format(PyExc_RuntimeError, "Invalid date format"); \
else \
dest += scale * (*pos - '0'); \
} while (0)
if (rev->date->len == 17) {
/* 2-digit year */
readdate(rev->date->str, tm.tm_year, 2);
month = rev->date->str + 3;
} else {
/* 4-digit year */
readdate(rev->date->str, tm.tm_year, 4);
tm.tm_year -= 1900;
month = rev->date->str + 5;
}
readdate(month, tm.tm_mon, 2);
tm.tm_mon--;
readdate(month + 3, tm.tm_mday, 2);
readdate(month + 6, tm.tm_hour, 2);
readdate(month + 9, tm.tm_min, 2);
readdate(month + 12, tm.tm_sec, 2);
#undef readdate
return Py_BuildValue("NNNNNNN",
rcstoken2pystr(rev->rev),
+#if PY_MAJOR_VERSION >= 3
+ PyLong_FromLong(timegm(&tm)),
+#else
PyInt_FromLong(timegm(&tm)),
+#endif
rcstoken2pystr(rev->author),
rcstoken2pystr(rev->state),
rcstoklist2py(&rev->branches),
rcstoken2pystr(rev->next),
rcstoken2pystr(rev->commitid));
}
static PyObject *
pyrcsrevtree_find(struct pyrcsrevtree *self, PyObject *key)
{
struct rcsrev *frev;
switch (pyrcsrevtree_find_internal(self, key, &frev))
{
case 1:
return rcsrev2py(frev);
case 0:
PyErr_SetObject(PyExc_KeyError, key);
return NULL;
case -1:
default:
return NULL;
}
}
static PyObject *
pyrcsrevtree_get(struct pyrcsrevtree *self, PyObject *args)
{
PyObject *key, *def = Py_None;
struct rcsrev *frev;
if (!PyArg_ParseTuple(args, "O|O", &key, &def))
return NULL;
switch (pyrcsrevtree_find_internal(self, key, &frev)) {
case 1:
return rcsrev2py(frev);
case 0:
return Py_INCREF(def), def;
case -1:
default:
return NULL;
}
}
static int
pyrcsrevtree_contains(struct pyrcsrevtree *self, PyObject *key)
{
struct rcsrev *rev;
return pyrcsrevtree_find_internal(self, key, &rev);
}
static PyObject *
pyrcsrevtree_has_key(struct pyrcsrevtree *self, PyObject *key)
{
switch (pyrcsrevtree_contains(self, key)) {
case 1:
Py_RETURN_TRUE;
case 0:
Py_RETURN_FALSE;
case -1:
default:
return NULL;
}
}
static PyObject *
pyrcsrevtree_items(struct pyrcsrevtree *self)
{
PyObject *list;
struct rcsrev *rev;
list = PyList_New(0);
if (list == NULL)
return NULL;
for (rev = RB_MIN(rcsrevtree, self->tree); rev != NULL; rev = RB_NEXT(rcsrevtree, self->tree, rev)) {
PyObject *f, *s, *p;
f = rcstoken2pystr(rev->rev);
s = rcsrev2py(rev);
p = PyTuple_Pack(2, f, s);
Py_XDECREF(f);
Py_XDECREF(s);
if (PyList_Append(list, p) < 0) {
Py_XDECREF(p);
Py_DECREF(list);
return NULL;
}
Py_XDECREF(p);
}
return list;
}
static PyObject *
pyrcsrevtree_keys(struct pyrcsrevtree *self)
{
PyObject *list;
struct rcsrev *rev;
list = PyList_New(0);
if (list == NULL)
return NULL;
for (rev = RB_MIN(rcsrevtree, self->tree); rev != NULL; rev = RB_NEXT(rcsrevtree, self->tree, rev)) {
PyObject *i;
i = rcstoken2pystr(rev->rev);
if (PyList_Append(list, i) < 0) {
Py_XDECREF(i);
Py_DECREF(list);
return NULL;
}
Py_XDECREF(i);
}
return list;
}
static PyObject *
pyrcsrevtree_values(struct pyrcsrevtree *self)
{
PyObject *list;
struct rcsrev *rev;
list = PyList_New(0);
if (list == NULL)
return NULL;
for (rev = RB_MIN(rcsrevtree, self->tree); rev != NULL; rev = RB_NEXT(rcsrevtree, self->tree, rev)) {
PyObject *i;
i = rcsrev2py(rev);
if (PyList_Append(list, i) < 0) {
Py_XDECREF(i);
Py_DECREF(list);
return NULL;
}
Py_XDECREF(i);
}
return list;
}
static void
pyrcsrevtree_dealloc(struct pyrcsrevtree *self)
{
Py_DECREF((PyObject *)self->pyrcs);
- self->ob_type->tp_free(self);
+ Py_TYPE(self)->tp_free(self);
}
static PyMappingMethods pyrcsrevtree_mapmethods = {
NULL,
(binaryfunc)pyrcsrevtree_find,
NULL
};
static PySequenceMethods pyrcsrevtree_seqmethods = {
.sq_contains= (objobjproc)pyrcsrevtree_contains
};
static PyMethodDef pyrcsrevtree_methods[] = {
{"__contains__",(PyCFunction)pyrcsrevtree_has_key, METH_O | METH_COEXIST, NULL},
{"__getitem__", (PyCFunction)pyrcsrevtree_find, METH_O | METH_COEXIST, NULL},
{"has_key", (PyCFunction)pyrcsrevtree_has_key, METH_O, NULL},
{"get", (PyCFunction)pyrcsrevtree_get, METH_VARARGS, NULL},
{"keys", (PyCFunction)pyrcsrevtree_keys, METH_NOARGS, NULL},
{"items", (PyCFunction)pyrcsrevtree_items, METH_NOARGS, NULL},
{"values", (PyCFunction)pyrcsrevtree_values, METH_NOARGS, NULL},
{NULL}
};
static PyTypeObject pyrcsrevtree_type = {
- PyObject_HEAD_INIT(&PyType_Type)
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
.tp_name= "rcsparse.rcsrevtree",
.tp_basicsize= sizeof(struct pyrcsrevtree),
.tp_dealloc= (destructor)pyrcsrevtree_dealloc,
.tp_as_mapping= &pyrcsrevtree_mapmethods,
.tp_as_sequence= &pyrcsrevtree_seqmethods,
.tp_flags= Py_TPFLAGS_DEFAULT,
.tp_doc= "RCS Revision Tree Map",
.tp_new= PyType_GenericNew,
.tp_methods= pyrcsrevtree_methods
};
static PyObject *
rcsrevtree2py(struct pyrcsfile *pyrcs, struct rcsrevtree *tree)
{
struct pyrcsrevtree *pytree;
if (tree == NULL)
Py_RETURN_NONE;
pytree = PyObject_New(struct pyrcsrevtree, &pyrcsrevtree_type);
pytree->pyrcs = pyrcs;
Py_INCREF((PyObject *)pyrcs);
pytree->tree = tree;
return (PyObject *)pytree;
}
struct pyrcstokmap {
PyObject_HEAD
struct pyrcsfile *pyrcs;
struct rcstokmap *map;
};
static int
pyrcstokmap_find_internal(struct pyrcstokmap *self, PyObject *key, struct rcstokpair **fpair)
{
struct rcstokpair pair;
struct rcstoken tok;
Py_ssize_t l;
if (!PyString_CheckExact(key))
return -1;
PyString_AsStringAndSize(key, &tok.str, &l);
if (l < 0)
return -1;
tok.len = (unsigned)l;
pair.first = &tok;
*fpair = RB_FIND(rcstokmap, self->map, &pair);
return *fpair != NULL;
}
static PyObject *
pyrcstokmap_find(struct pyrcstokmap *self, PyObject *key)
{
struct rcstokpair *fpair;
switch (pyrcstokmap_find_internal(self, key, &fpair))
{
case 1:
return rcstoken2pystr(fpair->second);
case 0:
PyErr_SetObject(PyExc_KeyError, key);
return NULL;
case -1:
default:
return NULL;
}
}
static PyObject *
pyrcstokmap_get(struct pyrcstokmap *self, PyObject *args)
{
PyObject *key, *def = Py_None;
struct rcstokpair *fpair;
if (!PyArg_ParseTuple(args, "O|O", &key, &def))
return NULL;
switch (pyrcstokmap_find_internal(self, key, &fpair)) {
case 1:
return rcstoken2pystr(fpair->second);
case 0:
return Py_INCREF(def), def;
case -1:
default:
return NULL;
}
}
static int
pyrcstokmap_contains(struct pyrcstokmap *self, PyObject *key)
{
struct rcstokpair *pair;
return pyrcstokmap_find_internal(self, key, &pair);
}
static PyObject *
pyrcstokmap_has_key(struct pyrcstokmap *self, PyObject *key)
{
switch (pyrcstokmap_contains(self, key)) {
case 1:
Py_RETURN_TRUE;
case 0:
Py_RETURN_FALSE;
case -1:
default:
return NULL;
}
}
static PyObject *
pyrcstokmap_items(struct pyrcstokmap *self)
{
PyObject *list;
struct rcstokpair *pair;
list = PyList_New(0);
if (list == NULL)
return NULL;
for (pair = RB_MIN(rcstokmap, self->map); pair != NULL; pair = RB_NEXT(rcstokmap, self->map, pair)) {
PyObject *f, *s, *p;
f = rcstoken2pystr(pair->first);
s = rcstoken2pystr(pair->second);
p = PyTuple_Pack(2, f, s);
Py_XDECREF(f);
Py_XDECREF(s);
if (PyList_Append(list, p) < 0) {
Py_XDECREF(p);
Py_DECREF(list);
return NULL;
}
Py_XDECREF(p);
}
return list;
}
static PyObject *
pyrcstokmap_keys(struct pyrcstokmap *self)
{
PyObject *list;
struct rcstokpair *pair;
list = PyList_New(0);
if (list == NULL)
return NULL;
for (pair = RB_MIN(rcstokmap, self->map); pair != NULL; pair = RB_NEXT(rcstokmap, self->map, pair)) {
PyObject *i;
i = rcstoken2pystr(pair->first);
if (PyList_Append(list, i) < 0) {
Py_XDECREF(i);
Py_DECREF(list);
return NULL;
}
Py_XDECREF(i);
}
return list;
}
static PyObject *
pyrcstokmap_values(struct pyrcstokmap *self)
{
PyObject *list;
struct rcstokpair *pair;
list = PyList_New(0);
if (list == NULL)
return NULL;
for (pair = RB_MIN(rcstokmap, self->map); pair != NULL; pair = RB_NEXT(rcstokmap, self->map, pair)) {
PyObject *i;
i = rcstoken2pystr(pair->second);
if (PyList_Append(list, i) < 0) {
Py_XDECREF(i);
Py_DECREF(list);
return NULL;
}
Py_XDECREF(i);
}
return list;
}
static void
pyrcstokmap_dealloc(struct pyrcstokmap *self)
{
Py_DECREF((PyObject *)self->pyrcs);
- self->ob_type->tp_free(self);
+ Py_TYPE(self)->tp_free(self);
}
static PyMappingMethods pyrcstokmap_mapmethods = {
NULL,
(binaryfunc)pyrcstokmap_find,
NULL
};
static PySequenceMethods pyrcstokmap_seqmethods = {
.sq_contains= (objobjproc)pyrcstokmap_contains
};
static PyMethodDef pyrcstokmap_methods[] = {
{"__contains__",(PyCFunction)pyrcstokmap_has_key, METH_O | METH_COEXIST, NULL},
{"__getitem__", (PyCFunction)pyrcstokmap_find, METH_O | METH_COEXIST, NULL},
{"has_key", (PyCFunction)pyrcstokmap_has_key, METH_O, NULL},
{"get", (PyCFunction)pyrcstokmap_get, METH_VARARGS, NULL},
{"keys", (PyCFunction)pyrcstokmap_keys, METH_NOARGS, NULL},
{"items", (PyCFunction)pyrcstokmap_items, METH_NOARGS, NULL},
{"values", (PyCFunction)pyrcstokmap_values, METH_NOARGS, NULL},
{NULL}
};
static PyTypeObject pyrcstokmap_type = {
- PyObject_HEAD_INIT(&PyType_Type)
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
.tp_name= "rcsparse.rcstokmap",
.tp_basicsize= sizeof(struct pyrcstokmap),
.tp_dealloc= (destructor)pyrcstokmap_dealloc,
.tp_as_mapping= &pyrcstokmap_mapmethods,
.tp_as_sequence= &pyrcstokmap_seqmethods,
.tp_flags= Py_TPFLAGS_DEFAULT,
.tp_doc= "RCS Token Map",
.tp_new= PyType_GenericNew,
.tp_methods= pyrcstokmap_methods
};
static PyObject *
rcstokmap2py(struct pyrcsfile *pyrcs, struct rcstokmap *map)
{
struct pyrcstokmap *pymap;
if (map == NULL)
Py_RETURN_NONE;
pymap = PyObject_New(struct pyrcstokmap, &pyrcstokmap_type);
pymap->pyrcs = pyrcs;
Py_INCREF((PyObject *)pyrcs);
pymap->map = map;
return (PyObject *)pymap;
}
struct pyrcsfile {
PyObject_HEAD
struct rcsfile *rcs;
};
enum {
PYRCSADM_HEAD,
PYRCSADM_BRANCH,
PYRCSADM_SYMBOLS,
PYRCSADM_LOCKS,
PYRCSADM_COMMENT,
PYRCSADM_EXPAND,
PYRCSADM_DESC,
};
static PyObject *
pyrcsfile_getstr(struct pyrcsfile *self, void *closure)
{
struct rcstoken *tok;
struct rcsadmin *adm;
if (rcsparseadmin(self->rcs) < 0)
return PyErr_Format(PyExc_RuntimeError, "Error parsing");
adm = &self->rcs->admin;
switch ((int)(uintptr_t)closure) {
case PYRCSADM_HEAD: tok = adm->head; break;
case PYRCSADM_BRANCH: tok = adm->branch; break;
case PYRCSADM_COMMENT: tok = adm->comment; break;
case PYRCSADM_EXPAND: tok = adm->expand; break;
case PYRCSADM_DESC: tok = adm->desc; break;
default:
return PyErr_Format(PyExc_RuntimeError, "Wrong closure");
}
return rcstoken2pystr(tok);
}
static PyObject *
pyrcsfile_gettokmap(struct pyrcsfile *self, void *closure)
{
struct rcstokmap *map;
struct rcsadmin *adm;
if (rcsparseadmin(self->rcs) < 0)
return PyErr_Format(PyExc_RuntimeError, "Error parsing");
adm = &self->rcs->admin;
switch ((int)(uintptr_t)closure) {
case PYRCSADM_SYMBOLS: map = &adm->symbols; break;
case PYRCSADM_LOCKS: map = &adm->locks; break;
default:
return PyErr_Format(PyExc_RuntimeError, "Wrong closure");
}
return rcstokmap2py(self, map);
}
static PyObject *
pyrcsfile_getaccess(struct pyrcsfile *self, void *closure)
{
if (rcsparseadmin(self->rcs) < 0)
return PyErr_Format(PyExc_RuntimeError, "Error parsing");
return rcstoklist2py(&self->rcs->admin.access);
}
static PyObject *
pyrcsfile_getstrict(struct pyrcsfile *self, void *closure)
{
if (rcsparseadmin(self->rcs) < 0)
return PyErr_Format(PyExc_RuntimeError, "Error parsing");
if (self->rcs->admin.strict)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
static PyObject *
pyrcsfile_checkout(struct pyrcsfile *self, PyObject *args)
{
PyObject *o;
const char *rev = "HEAD";
char *buf;
size_t len;
if (!PyArg_ParseTuple(args, "|s", &rev))
return NULL;
buf = rcscheckout(self->rcs, rev, &len);
if (buf == NULL)
return PyErr_Format(PyExc_RuntimeError, "Error parsing");
+#if PY_MAJOR_VERSION >= 3
+ o = PyBytes_FromStringAndSize(buf, len);
+#else
o = PyString_FromStringAndSize(buf, len);
+#endif
free(buf);
return o;
}
static PyObject *
pyrcsfile_getlog(struct pyrcsfile *self, PyObject *args)
{
PyObject *o;
const char *rev;
char *buf;
if (!PyArg_ParseTuple(args, "s", &rev))
return NULL;
buf = rcsgetlog(self->rcs, rev);
if (buf == NULL)
return PyErr_Format(PyExc_RuntimeError, "Error parsing");
+#if PY_MAJOR_VERSION >= 3
+ o = PyBytes_FromString(buf);
+#else
o = PyString_FromString(buf);
+#endif
free(buf);
return o;
}
static PyObject *
pyrcsfile_sym2rev(struct pyrcsfile *self, PyObject *args)
{
PyObject *o;
const char *rev = "HEAD";
char *buf;
if (!PyArg_ParseTuple(args, "|s", &rev))
return NULL;
buf = rcsrevfromsym(self->rcs, rev);
if (buf == NULL)
return PyErr_Format(PyExc_RuntimeError, "Error parsing");
o = PyString_FromString(buf);
free(buf);
return o;
}
static PyObject *
pyrcsfile_getrevs(struct pyrcsfile *self, void *closure)
{
if (rcsparsetree(self->rcs) < 0)
return PyErr_Format(PyExc_RuntimeError, "Error parsing");
return rcsrevtree2py(self, &self->rcs->admin.revs);
}
static int
pyrcsfile_init(struct pyrcsfile *pyrcs, PyObject *args)
{
const char *filename;
if (!PyArg_ParseTuple(args, "s", &filename))
return -1;
pyrcs->rcs = rcsopen(filename);
if (pyrcs->rcs == NULL) {
PyErr_SetFromErrnoWithFilename(PyExc_IOError, (char *)(long)filename);
return -1;
}
return 0;
}
static void
pyrcsfile_dealloc(struct pyrcsfile *self)
{
if (self->rcs != NULL)
rcsclose(self->rcs);
- self->ob_type->tp_free(self);
+ Py_TYPE(self)->tp_free(self);
}
static PyGetSetDef pyrcsfile_getseters[] = {
{"head", (getter)pyrcsfile_getstr, NULL, "rcsfile head data", (void *)PYRCSADM_HEAD},
{"branch", (getter)pyrcsfile_getstr, NULL, "rcsfile branch data", (void *)PYRCSADM_BRANCH},
{"access", (getter)pyrcsfile_getaccess, NULL, "rcsfile access data", NULL},
{"symbols", (getter)pyrcsfile_gettokmap, NULL, "rcsfile symbols data", (void *)PYRCSADM_SYMBOLS},
{"locks", (getter)pyrcsfile_gettokmap, NULL, "rcsfile locks data", (void *)PYRCSADM_LOCKS},
{"strict", (getter)pyrcsfile_getstrict, NULL, "rcsfile strict data", NULL},
{"comment", (getter)pyrcsfile_getstr, NULL, "rcsfile comment data", (void *)PYRCSADM_COMMENT},
{"expand", (getter)pyrcsfile_getstr, NULL, "rcsfile expand data", (void *)PYRCSADM_EXPAND},
{"revs", (getter)pyrcsfile_getrevs, NULL, "rcsfile revs data", NULL},
{"desc", (getter)pyrcsfile_getstr, NULL, "rcsfile desc data", (void *)PYRCSADM_DESC},
{NULL}
};
static PyMethodDef pyrcsfile_methods[] = {
{"checkout", (PyCFunction)pyrcsfile_checkout, METH_VARARGS, NULL},
{"getlog", (PyCFunction)pyrcsfile_getlog, METH_VARARGS, NULL},
{"sym2rev", (PyCFunction)pyrcsfile_sym2rev, METH_VARARGS, NULL},
{NULL}
};
static PyTypeObject pyrcsfile_type = {
PyObject_HEAD_INIT(&PyType_Type)
.tp_name= "rcsparse.rcsfile",
.tp_basicsize= sizeof(struct pyrcsfile),
.tp_dealloc= (destructor)pyrcsfile_dealloc,
.tp_flags= Py_TPFLAGS_DEFAULT,
.tp_doc= "RCS File",
.tp_getset= pyrcsfile_getseters,
.tp_init= (initproc)pyrcsfile_init,
.tp_new= PyType_GenericNew,
.tp_methods= pyrcsfile_methods,
};
static PyMethodDef pyrcsparse_methods[] = {
{NULL}
};
+#if PY_MAJOR_VERSION >= 3
+static struct PyModuleDef moduledef = {
+ PyModuleDef_HEAD_INIT,
+ "rcsparse", /* m_name */
+ "RCS file parser", /* m_doc */
+ -1, /* m_size */
+ pyrcsparse_methods, /* m_methods */
+ NULL, /* m_reload */
+ NULL, /* m_traverse */
+ NULL, /* m_clear */
+ NULL, /* m_free */
+};
+#endif
+
+#if PY_MAJOR_VERSION >= 3
+#define retnull return NULL
+
+PyMODINIT_FUNC
+PyInit_rcsparse(void)
+#else
+#define retnull return
+
PyMODINIT_FUNC
initrcsparse(void)
+#endif
{
PyObject *m;
if (PyType_Ready(&pyrcsfile_type) < 0)
- return;
+ retnull;
if (PyType_Ready(&pyrcstokmap_type) < 0)
- return;
+ retnull;
if (PyType_Ready(&pyrcsrevtree_type) < 0)
- return;
+ retnull;
+#if PY_MAJOR_VERSION >= 3
+ m = PyModule_Create(&moduledef);
+#else
m = Py_InitModule3("rcsparse", pyrcsparse_methods, "RCS file parser");
+#endif
if (m == NULL)
- return;
+ retnull;
Py_INCREF(&pyrcsfile_type);
PyModule_AddObject(m, "rcsfile", (PyObject *)&pyrcsfile_type);
Py_INCREF(&pyrcstokmap_type);
PyModule_AddObject(m, "rcstokmap", (PyObject *)&pyrcstokmap_type);
Py_INCREF(&pyrcsrevtree_type);
PyModule_AddObject(m, "rcsrevtree", (PyObject *)&pyrcsrevtree_type);
+
+#if PY_MAJOR_VERSION >= 3
+ return m;
+#endif
}
diff --git a/swh/loader/cvs/rcsparse/testmodule.py b/swh/loader/cvs/rcsparse/testmodule.py
index 2f0d388..ed9d0a8 100644
--- a/swh/loader/cvs/rcsparse/testmodule.py
+++ b/swh/loader/cvs/rcsparse/testmodule.py
@@ -1,13 +1,13 @@
import rcsparse
-import md5
f=rcsparse.rcsfile('test,v')
print f.head
print f.branch
s=f.symbols
print s['RELENG_4']
print s.items()
r=f.revs
i=r.items()
print i
-print f.getlog(f.sym2rev('RELENG_4'))
+print f.getlog(f.sym2rev('RELENG_4')).decode('ascii')
+print '1.1' in r