--- a/PAMmodule.c.python3 2014-06-24 11:29:10.958299393 +0200 +++ b/PAMmodule.c 2014-06-24 15:20:02.728118493 +0200 @@ -15,6 +15,14 @@ #include #include +#if PY_MAJOR_VERSION >= 3 +#define IS_PY3K +#else +// include bytesobject.h to map PyBytes_* to PyString_* +#include +#endif + + static PyObject *PyPAM_Error; typedef struct { @@ -28,7 +36,11 @@ void *dlh1, *dlh2; } PyPAMObject; +#ifdef IS_PY3K +static PyTypeObject PyPAMObject_Type; +#else staticforward PyTypeObject PyPAMObject_Type; +#endif static void PyPAM_Err(PyPAMObject *self, int result) { @@ -139,7 +151,6 @@ return NULL; } - PyPAMObject_Type.ob_type = &PyType_Type; p = (PyPAMObject *) PyObject_NEW(PyPAMObject, &PyPAMObject_Type); if (p == NULL) @@ -562,35 +573,44 @@ PyObject_Del(self); } -static PyObject * PyPAM_getattr(PyPAMObject *self, char *name) -{ - return Py_FindMethod(PyPAMObject_Methods, (PyObject *) self, name); -} - static PyObject * PyPAM_repr(PyPAMObject *self) { char buf[1024]; snprintf(buf, 1024, "", self->service, self->user, self->conv, self->pamh); - return PyString_FromString(buf); + return PyBytes_FromString(buf); } static PyTypeObject PyPAMObject_Type = { - PyObject_HEAD_INIT(0) /* Must fill in type value later */ - 0, - "pam", - sizeof(PyPAMObject), - 0, - (destructor)PyPAM_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - (getattrfunc)PyPAM_getattr, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - (reprfunc)PyPAM_repr, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ + PyVarObject_HEAD_INIT(NULL, 0) /* Must fill in type value later */ + "pam", /* tp_name */ + sizeof(PyPAMObject), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)PyPAM_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + (reprfunc)PyPAM_repr, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + "PyPAM", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + PyPAMObject_Methods, /* tp_methods */ }; static PyMethodDef PyPAM_Methods[] = { @@ -607,7 +627,12 @@ */ static void insint(PyObject *d, char *name, int value) { - PyObject* v = PyInt_FromLong((long) value); + PyObject* v; +#ifdef IS_PY3K + v = PyLong_FromLong((long) value); +#else + v = PyInt_FromLong((long) value); +#endif if (!v || PyDict_SetItemString(d, name, v)) PyErr_Clear(); @@ -615,19 +640,42 @@ Py_XDECREF(v); } +#ifdef IS_PY3K +static struct PyModuleDef pamdef = { + PyModuleDef_HEAD_INIT, + "PAM", + NULL, + -1, + PyPAM_Methods, + NULL, + NULL, + NULL, + NULL +}; + +#define INITERROR return NULL +PyObject *PyInit_PAM(void) + +#else +#define INITERROR return void initPAM(void) +#endif { PyObject *m, *d; +#ifdef IS_PY3K + m = PyModule_Create(&pamdef); +#else m = Py_InitModule("PAM", PyPAM_Methods); +#endif d = PyModule_GetDict(m); PyPAM_Error = PyErr_NewException("PAM.error", NULL, NULL); if (PyPAM_Error == NULL) - return; + INITERROR; PyDict_SetItemString(d, "error", PyPAM_Error); - PyPAMObject_Type.ob_type = &PyType_Type; + Py_TYPE(&PyPAMObject_Type) = &PyType_Type; PyPAMObject_Type.tp_doc = PyPAMObject_doc; Py_INCREF(&PyPAMObject_Type); @@ -692,4 +740,7 @@ insint(d, "PAM_BINARY_PROMPT", PAM_BINARY_PROMPT); #endif +#ifdef IS_PY3K + return m; +#endif } --- a/setup.py.python3 2014-06-24 15:58:07.792172439 +0200 +++ b/setup.py 2014-06-24 15:58:13.714909021 +0200 @@ -12,7 +12,7 @@ license='LGPL', ext_modules=[ Extension( - 'PAMmodule', + 'PAM', ['PAMmodule.c'], libraries=['pam', 'pam_misc'], extra_compile_args = ['-std=c99'], --- a/tests/PamTest.py.python3 2014-06-24 16:54:28.902998249 +0200 +++ b/tests/PamTest.py 2014-06-24 17:07:11.392094775 +0200 @@ -41,13 +41,13 @@ def test_userdata_default(self): """The default value for userdata is None.""" - self.failUnless(self.pam.get_userdata() is None) + self.assertTrue(self.pam.get_userdata() is None) def test_userdata(self): """The userdata getter and setter will store and return any data.""" self.pam.set_userdata(1) - self.failUnless(self.pam.get_userdata() == 1) + self.assertTrue(self.pam.get_userdata() == 1) def test_start(self): """pam.start() works as expected."""