I don't have a good way to test it without also converting cvs2gitdump (which is beyond my pythons skills) but leaving this here before it rots in my local tree ;)
Index: Makefile =================================================================== RCS file: /cvs/ports/devel/py-rcsparse/Makefile,v retrieving revision 1.20 diff -u -p -r1.20 Makefile --- Makefile 12 Jul 2019 20:45:52 -0000 1.20 +++ Makefile 26 Apr 2020 16:13:12 -0000 @@ -8,15 +8,22 @@ GH_COMMIT= 206bca0b90f5780815c0b6c6cbcc DISTNAME= rcsparse-20151027 PKGNAME= py-${DISTNAME} +REVISION= 0 -CATEGORIES= devel +CATEGORIES= devel # AGPLv3+ PERMIT_PACKAGE= Yes WANTLIB += ${MODPY_WANTLIB} pthread +FLAVORS= python3 +FLAVOR?= + MODULES= lang/python -NO_TEST= Yes +TEST_DEPENDS= ${BUILD_PKGPATH} + +do-test: + cd ${WRKSRC}; ${MODPY_BIN} testmodule.py .include <bsd.port.mk> Index: patches/patch-py-rcsparse_c =================================================================== RCS file: patches/patch-py-rcsparse_c diff -N patches/patch-py-rcsparse_c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-py-rcsparse_c 26 Apr 2020 16:13:12 -0000 @@ -0,0 +1,138 @@ +$OpenBSD$ + +Index: py-rcsparse.c +--- py-rcsparse.c.orig ++++ py-rcsparse.c +@@ -25,6 +25,13 @@ + #include "rcsparse.h" + + ++#if PY_MAJOR_VERSION >= 3 ++#define PyString_AsStringAndSize(a,b,c) PyUnicode_AsUTF8AndSize(a,c) ++#define PyString_CheckExact PyUnicode_CheckExact ++#define PyString_FromString PyUnicode_FromString ++#define PyString_FromStringAndSize PyUnicode_FromStringAndSize ++#endif ++ + static PyObject * + rcstoken2pystr(struct rcstoken *tok) + { +@@ -124,7 +131,11 @@ rcsrev2py(struct rcsrev *rev) + + 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), +@@ -275,7 +286,7 @@ 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 = { +@@ -300,7 +311,7 @@ static PyMethodDef pyrcsrevtree_methods[] = { + }; + + 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, +@@ -496,7 +507,7 @@ 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 = { +@@ -521,7 +532,7 @@ static PyMethodDef pyrcstokmap_methods[] = { + }; + + 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, +@@ -720,7 +731,7 @@ 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[] = { +@@ -761,21 +772,48 @@ 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); +@@ -783,4 +821,8 @@ initrcsparse(void) + 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 + } Index: patches/patch-testmodule_py =================================================================== RCS file: patches/patch-testmodule_py diff -N patches/patch-testmodule_py --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-testmodule_py 26 Apr 2020 16:13:12 -0000 @@ -0,0 +1,25 @@ +$OpenBSD$ + +Index: testmodule.py +--- testmodule.py.orig ++++ testmodule.py +@@ -1,13 +1,12 @@ + import rcsparse +-import md5 + + f=rcsparse.rcsfile('test,v') +-print f.head +-print f.branch ++print (f.head) ++print (f.branch) + s=f.symbols +-print s['RELENG_4'] +-print s.items() ++print (s['RELENG_4']) ++print (s.items()) + r=f.revs + i=r.items() +-print i +-print f.getlog(f.sym2rev('RELENG_4')) ++print (i) ++print (f.getlog(f.sym2rev('RELENG_4'))) Index: pkg/PLIST =================================================================== RCS file: /cvs/ports/devel/py-rcsparse/pkg/PLIST,v retrieving revision 1.3 diff -u -p -r1.3 PLIST --- pkg/PLIST 31 Oct 2015 16:30:18 -0000 1.3 +++ pkg/PLIST 26 Apr 2020 16:13:12 -0000 @@ -1,4 +1,4 @@ @comment $OpenBSD: PLIST,v 1.3 2015/10/31 16:30:18 sthen Exp $ @conflict rcsparse-* lib/python${MODPY_VERSION}/site-packages/rcsparse-0.1-py${MODPY_VERSION}.egg-info -lib/python${MODPY_VERSION}/site-packages/rcsparse.so +@so lib/python${MODPY_VERSION}/site-packages/rcsparse.so