[Rpm-maint] [PATCH 06/15] Update module initialization to work with both Python 2.* and Python 3.*

David Malcolm dmalcolm at redhat.com
Thu Oct 15 19:15:00 UTC 2009


Introduce macros and conditional compilation to deal with the major changes to the way
that Python extension modules are initialized between Python 2 and 3 (PEP 3121).
---
 python/header-py.h  |    7 +++++
 python/rpmbmodule.c |   37 ++++++++++++++++++++++++--
 python/rpmmodule.c  |   72 ++++++++++++++++++++++++++++++++++++++++----------
 3 files changed, 98 insertions(+), 18 deletions(-)

diff --git a/python/header-py.h b/python/header-py.h
index 8c9dd68..277ef96 100644
--- a/python/header-py.h
+++ b/python/header-py.h
@@ -12,6 +12,13 @@ extern PyTypeObject hdr_Type;
 #define DEPRECATED_METHOD(_msg) \
     PyErr_WarnEx(PyExc_PendingDeprecationWarning, (_msg), 2);
 
+/*
+  FIXME: this is "global" module state and for Python 3 this ought to be split
+  out into a module state struct as per PEP 3121
+
+  Unfortunately we don't have convenient module ptrs available at each point
+  of use, so I've punted it for now.  
+*/
 extern PyObject * pyrpmError;
 
 PyObject * hdr_Wrap(PyTypeObject *subtype, Header h);
diff --git a/python/rpmbmodule.c b/python/rpmbmodule.c
index 2332590..8a7c8fd 100644
--- a/python/rpmbmodule.c
+++ b/python/rpmbmodule.c
@@ -7,22 +7,53 @@
 static char rpmb__doc__[] =
 "";
 
-void init_rpmb(void);	/* XXX eliminate gcc warning */
+#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 */
+};
+
+#define INITERROR return NULL
+
+PyObject *
+PyInit__rpmb(void);
+
+PyObject *
+PyInit__rpmb(void)
+#else
+#define INITERROR return
 
+void init_rpmb(void);	/* XXX eliminate gcc warning */
 void init_rpmb(void)
+#endif
 {
     PyObject * d, *m;
 
-    if (PyType_Ready(&spec_Type) < 0) return;
+    if (PyType_Ready(&spec_Type) < 0) INITERROR;
 
+    /* FIXME: need to port this, as per PEP 3121 */
+#if PY_MAJOR_VERSION >= 3
+    m = PyModule_Create(&moduledef);
+#else
     m = Py_InitModule3("_rpmb", NULL, rpmb__doc__);
+#endif
     if (m == NULL)
-	return;
+	INITERROR;
 
     d = PyModule_GetDict(m);
 
     Py_INCREF(&spec_Type);
     PyModule_AddObject(m, "spec", (PyObject *) &spec_Type);
 
+#if PY_MAJOR_VERSION >= 3
+    return m;
+#endif
 }
 
diff --git a/python/rpmmodule.c b/python/rpmmodule.c
index 2d903fc..6a3f98a 100644
--- a/python/rpmmodule.c
+++ b/python/rpmmodule.c
@@ -201,35 +201,73 @@ static void addRpmTags(PyObject *module)
     rpmtdFree(names);
 }
 
+#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 */
+};
+
+#define INITERROR return NULL
+
+PyObject *
+PyInit__rpm(void);
+
+PyObject *
+PyInit__rpm(void)
+#else
 void init_rpm(void);	/* XXX eliminate gcc warning */
+#define INITERROR return
 
 void init_rpm(void)
+#endif
 {
     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;
-
+    if (PyType_Ready(&hdr_Type) < 0) INITERROR;
+    if (PyType_Ready(&rpmds_Type) < 0) INITERROR;
+    if (PyType_Ready(&rpmfd_Type) < 0) INITERROR;
+    if (PyType_Ready(&rpmfi_Type) < 0) INITERROR;
+    if (PyType_Ready(&rpmKeyring_Type) < 0) INITERROR;
+    if (PyType_Ready(&rpmmi_Type) < 0) INITERROR;
+    if (PyType_Ready(&rpmProblem_Type) < 0) INITERROR;
+    if (PyType_Ready(&rpmps_Type) < 0) INITERROR;
+    if (PyType_Ready(&rpmPubkey_Type) < 0) INITERROR;
+    if (PyType_Ready(&rpmtd_Type) < 0) INITERROR;
+    if (PyType_Ready(&rpmte_Type) < 0) INITERROR;
+    if (PyType_Ready(&rpmts_Type) < 0) INITERROR;
+
+#if PY_MAJOR_VERSION >= 3
+    m = PyModule_Create(&moduledef);
+#else
     m = Py_InitModule3("_rpm", rpmModuleMethods, rpm__doc__);
+#endif
     if (m == NULL)
-	return;
+	INITERROR;
 
     /* 
      * 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;
+	INITERROR;
 
     rpmReadConfigFiles(NULL, NULL);
 
@@ -439,5 +477,9 @@ void init_rpm(void)
     REGISTER_ENUM(HEADERCONV_EXPANDFILELIST);
     REGISTER_ENUM(HEADERCONV_COMPRESSFILELIST);
     REGISTER_ENUM(HEADERCONV_RETROFIT_V3);
+
+#if PY_MAJOR_VERSION >= 3
+    return m;
+#endif
 }
 
-- 
1.6.2.5



More information about the Rpm-maint mailing list