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