Update module initialization to work with both Python 2.x and 3.x
authorPanu Matilainen <pmatilai@redhat.com>
Thu, 29 Oct 2009 10:56:18 +0000 (12:56 +0200)
committerPanu Matilainen <pmatilai@redhat.com>
Thu, 29 Oct 2009 10:56:18 +0000 (12:56 +0200)
- split common initialization tasks to separate functions, so that only the
  details of initializing a python module object differ
- patch from David Malcolm

python/rpmbmodule.c
python/rpmmodule.c

index 2332590..2a32a95 100644 (file)
@@ -7,22 +7,61 @@
 static char rpmb__doc__[] =
 "";
 
-void init_rpmb(void);  /* XXX eliminate gcc warning */
-
-void init_rpmb(void)
+/*
+  Do any common preliminary work before python 2 vs python 3 module creation:
+*/
+static int prepareInitModule(void)
 {
-    PyObject * d, *m;
+    if (PyType_Ready(&spec_Type) < 0) return 0;
 
-    if (PyType_Ready(&spec_Type) < 0) return;
-
-    m = Py_InitModule3("_rpmb", NULL, rpmb__doc__);
-    if (m == NULL)
-       return;
-
-    d = PyModule_GetDict(m);
+    return 1;
+}
 
+static int initModule(PyObject *m)
+{
     Py_INCREF(&spec_Type);
     PyModule_AddObject(m, "spec", (PyObject *) &spec_Type);
 
+    return 1;
+}
+
+#if PY_MAJOR_VERSION >= 3
+static struct PyModuleDef moduledef = {
+    PyModuleDef_HEAD_INIT,
+    "_rpmb",     /* m_name */
+    rpmb__doc__, /* m_doc */
+    0,           /* m_size */
+    NULL,        /* m_methods */
+    NULL,        /* m_reload */
+    NULL,        /* m_traverse */
+    NULL,        /* m_clear */
+    NULL         /* m_free */
+};
+
+PyObject * PyInit__rpm(void);  /* XXX eliminate gcc warning */
+PyObject * PyInit__rpm(void)
+{
+    PyObject *m;
+
+    if (!prepareInitModule())
+        return NULL;
+    m = PyModule_Create(&moduledef);
+    if (m == NULL || !initModule(m)) {
+        Py_XDECREF(m);
+        m = NULL;
+    }
+    return m;
 }
+#else
+void init_rpmb(void);  /* XXX eliminate gcc warning */
+void init_rpmb(void)
+{
+    PyObject *m;
+  
+    if (!prepareInitModule())
+        return;
 
+    m = Py_InitModule3("_rpmb", NULL, rpmb__doc__);
+    if (m) initModule(m);
+}
+#endif
index 30572f7..5237643 100644 (file)
@@ -201,35 +201,88 @@ static void addRpmTags(PyObject *module)
     rpmtdFree(names);
 }
 
-void init_rpm(void);   /* XXX eliminate gcc warning */
+/*
+  Do any common preliminary work before python 2 vs python 3 module creation:
+*/
+static int prepareInitModule(void)
+{
+    if (PyType_Ready(&hdr_Type) < 0) return 0;
+    if (PyType_Ready(&rpmds_Type) < 0) return 0;
+    if (PyType_Ready(&rpmfd_Type) < 0) return 0;
+    if (PyType_Ready(&rpmfi_Type) < 0) return 0;
+    if (PyType_Ready(&rpmKeyring_Type) < 0) return 0;
+    if (PyType_Ready(&rpmmi_Type) < 0) return 0;
+    if (PyType_Ready(&rpmProblem_Type) < 0) return 0;
+    if (PyType_Ready(&rpmps_Type) < 0) return 0;
+    if (PyType_Ready(&rpmPubkey_Type) < 0) return 0;
+    if (PyType_Ready(&rpmtd_Type) < 0) return 0;
+    if (PyType_Ready(&rpmte_Type) < 0) return 0;
+    if (PyType_Ready(&rpmts_Type) < 0) return 0;
+
+    return 1;
+}
+static int initModule(PyObject *m);
+
+#if PY_MAJOR_VERSION >= 3
+static int rpmModuleTraverse(PyObject *m, visitproc visit, void *arg) {
+    Py_VISIT(pyrpmError);
+    return 0;
+}
+
+static int rpmModuleClear(PyObject *m) {
+    Py_CLEAR(pyrpmError);
+    return 0;
+}
 
+static struct PyModuleDef moduledef = {
+    PyModuleDef_HEAD_INIT,
+    "_rpm",            /* m_name */
+    rpm__doc__,        /* m_doc */
+    0,                 /* m_size */
+    rpmModuleMethods,
+    NULL,              /* m_reload */
+    rpmModuleTraverse,
+    rpmModuleClear,
+    NULL               /* m_free */
+};
+
+PyObject *
+PyInit__rpm(void);
+
+PyObject *
+PyInit__rpm(void)
+{
+    PyObject * m;
+    if (!prepareInitModule()) return NULL;
+    m = PyModule_Create(&moduledef);
+    initModule(m);
+    return m;
+}
+#else
+void init_rpm(void);   /* XXX eliminate gcc warning */
 void init_rpm(void)
 {
-    PyObject * d, *m;
-
-    if (PyType_Ready(&hdr_Type) < 0) return;
-    if (PyType_Ready(&rpmds_Type) < 0) return;
-    if (PyType_Ready(&rpmfd_Type) < 0) return;
-    if (PyType_Ready(&rpmfi_Type) < 0) return;
-    if (PyType_Ready(&rpmKeyring_Type) < 0) return;
-    if (PyType_Ready(&rpmmi_Type) < 0) return;
-    if (PyType_Ready(&rpmProblem_Type) < 0) return;
-    if (PyType_Ready(&rpmps_Type) < 0) return;
-    if (PyType_Ready(&rpmPubkey_Type) < 0) return;
-    if (PyType_Ready(&rpmtd_Type) < 0) return;
-    if (PyType_Ready(&rpmte_Type) < 0) return;
-    if (PyType_Ready(&rpmts_Type) < 0) return;
+    PyObject * m;
 
+    if (!prepareInitModule()) return;
     m = Py_InitModule3("_rpm", rpmModuleMethods, rpm__doc__);
     if (m == NULL)
        return;
+    initModule(m);
+}
+#endif
+
+/* Shared python2/3 module initialization: */
+static int initModule(PyObject *m)
+{
+    PyObject * d;
 
     /* 
      * treat error to register rpm cleanup hook as fatal, tracebacks
      * can and will leave stale locks around if we can't clean up
      */
     if (Py_AtExit(rpm_exithook) == -1)
-       return;
+        return 0;
 
     rpmReadConfigFiles(NULL, NULL);
 
@@ -439,5 +492,7 @@ void init_rpm(void)
     REGISTER_ENUM(HEADERCONV_EXPANDFILELIST);
     REGISTER_ENUM(HEADERCONV_COMPRESSFILELIST);
     REGISTER_ENUM(HEADERCONV_RETROFIT_V3);
+
+    return 1;
 }