summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2010-02-02 19:33:24 -0500
committerDavid Malcolm <dmalcolm@redhat.com>2010-02-02 19:33:24 -0500
commit234a10d5bc133f9963db58fd4c08715fe43c2b94 (patch)
treeb0f25aa393b258c97370060e84e7a97402e9fea1
parent98f387056959d6ab8554a2fd616d1639739c4735 (diff)
download2to3c-234a10d5bc133f9963db58fd4c08715fe43c2b94.tar.gz
2to3c-234a10d5bc133f9963db58fd4c08715fe43c2b94.tar.xz
2to3c-234a10d5bc133f9963db58fd4c08715fe43c2b94.zip
introduce custom postprocessing code to (partly) deal with module initialization; add selftests for same
-rwxr-xr-x2to3c4
-rw-r--r--fixes/init-module.cocci76
-rw-r--r--fixes/initmodule.py132
3 files changed, 176 insertions, 36 deletions
diff --git a/2to3c b/2to3c
index ede6fb2..ae3233a 100755
--- a/2to3c
+++ b/2to3c
@@ -3,10 +3,12 @@
def get_fixers():
from fixes.typeobject import FixTypeobjectInitializers
from fixes import CocciFix
+ from fixes.initmodule import FixInitModule
fixes = [FixTypeobjectInitializers()]
for filename in ['RO.cocci', 'int-to-long.cocci', 'ob_type.cocci',
- 'repr.cocci', 'init-module.cocci']:
+ 'repr.cocci']:
fixes.append(CocciFix(filename))
+ fixes.append(FixInitModule())
return fixes
def fixup_content(content):
diff --git a/fixes/init-module.cocci b/fixes/init-module.cocci
index afeb89a..ca3bcc9 100644
--- a/fixes/init-module.cocci
+++ b/fixes/init-module.cocci
@@ -10,13 +10,43 @@ T FN(void) {
...
}
+
+
+@@
+identifier MOD_VAR;
+expression MODULE_NAME, MODULE_METHODS, MODULE_DOC;
+expression E;
+@@
+ if (E) {
+- return;
++ return MOD_ERROR_VAL;
+ }
+ ...
+ MOD_VAR = Py_InitModule3(MODULE_NAME, MODULE_METHODS, MODULE_DOC);
+
+
+@@
+identifier MOD_VAR;
+expression MODULE_NAME, MODULE_METHODS, MODULE_DOC;
+expression E;
+@@
+ MOD_VAR = Py_InitModule3(MODULE_NAME, MODULE_METHODS, MODULE_DOC);
+ ...
+ if (E) {
+- return;
++ return MOD_ERROR_VAL;
+ }
+
+
@@
type mod_init_fn.T;
identifier mod_init_fn.FN;
identifier mod_init_fn.MOD_VAR;
expression MODULE_NAME, MODULE_METHODS, MODULE_DOC;
+expression E;
+statement list SL;
@@
-+ #if PY_MAJOR_VERSION >= 3
++struct __HASH_IF_PY_MAJOR_VERSION_ge_3;
+static struct PyModuleDef moduledef = {
+ PyModuleDef_HEAD_INIT,
+ MODULE_NAME, /* m_name */
@@ -28,45 +58,21 @@ expression MODULE_NAME, MODULE_METHODS, MODULE_DOC;
+ NULL, /* m_clear */
+ NULL, /* m_free */
+};
-+#define MOD_ERROR_VAL NULL
-+#else
-+#endif
++struct __HASH_DEFINE__MOD_ERROR_VAL__NULL;
++struct __HASH_ELSE;
++struct __HASH_DEFINE__MOD_ERROR_VAL__;
++struct __HASH_ENDIF;
-T FN(void) {
+ T FN(void) {
...
-+ #if PY_MAJOR_VERSION >= 3
++__HASH_IF_PY_MAJOR_VERSION_ge_3;
+ MOD_VAR = PyModule_Create(&moduledef);
-+ #else
++__HASH_ELSE;
MOD_VAR = Py_InitModule3(MODULE_NAME, MODULE_METHODS, MODULE_DOC);
-+ #endif
-
- ...
-}
-
-
++__HASH_ENDIF;
-@@
-type mod_init_fn.T;
-identifier mod_init_fn.FN;
-expression E;
-@@
-T FN(void) {
...
-- if (E) return;
-+ if (E) return MOD_ERROR_VAL;
- ...
-}
+ }
+
-@@
-type mod_init_fn.T;
-identifier mod_init_fn.FN;
-identifier mod_init_fn.MOD_VAR;
-@@
-T FN(void) {
- ...
-- return;
-+ #if PY_MAJOR_VERSION >= 3
-+ return MOD_VAR;
-+ #endif
-}
diff --git a/fixes/initmodule.py b/fixes/initmodule.py
new file mode 100644
index 0000000..c106079
--- /dev/null
+++ b/fixes/initmodule.py
@@ -0,0 +1,132 @@
+from fixes import CocciFix, FixTest
+class FixInitModule(CocciFix):
+ def __init__(self):
+ CocciFix.__init__(self, 'init-module.cocci')
+
+ def preprocess(self, string):
+ # FIXME
+ return string
+
+ def postprocess(self, string):
+ for (before, after) in [('struct __HASH_IF_PY_MAJOR_VERSION_ge_3;',
+ '#if PY_MAJOR_VERSION > 3'),
+ ('struct __HASH_ELSE;',
+ '#else'),
+ ('struct __HASH_DEFINE__MOD_ERROR_VAL__NULL;',
+ '#define MOD_ERROR_VAL NULL'),
+ ('struct __HASH_DEFINE__MOD_ERROR_VAL__;',
+ '#define MOD_ERROR_VAL'),
+ ('struct __HASH_ENDIF;',
+ '#endif'),
+ ('__HASH_IF_PY_MAJOR_VERSION_ge_3;',
+ '#if PY_MAJOR_VERSION > 3'),
+ ('__HASH_ELSE;',
+ '#else'),
+ ('__HASH_ENDIF;',
+ '#endif'),
+ ]:
+ string = string.replace(before, after)
+
+ # etc
+ return string
+
+ def transform(self, string):
+ # FIXME: preprocess
+ string = self.preprocess(string)
+ #print 'input:', repr(string)
+ string = CocciFix.transform(self, string)
+ #print 'output:', repr(string)
+ string = self.postprocess(string)
+ return string
+
+#import unittest
+class TestFixups(FixTest):
+ def setUp(self):
+ self.fixer = FixInitModule()
+
+ def test_fixups(self):
+ self.assertTransformsTo(self.fixer,
+ '''
+PyMODINIT_FUNC
+initxx(void)
+{
+ PyObject *m;
+
+ if (something_that_can_fail() < 0)
+ return;
+
+ m = Py_InitModule3("xx", xx_methods, module_doc);
+ if (m == NULL)
+ return;
+
+ PyModule_AddObject(m, "Null", (PyObject *)&Null_Type);
+}
+''',
+ '''
+#if PY_MAJOR_VERSION > 3
+static struct PyModuleDef moduledef = {
+ PyModuleDef_HEAD_INIT,
+ "xx",/* m_name */
+ module_doc,/* m_doc */
+ 0,/* m_size */
+ xx_methods,/* m_methods */
+ NULL,/* m_reload */
+ NULL,/* m_traverse */
+ NULL,/* m_clear */
+ NULL,/* m_free */
+};
+#define MOD_ERROR_VAL NULL
+#else
+#define MOD_ERROR_VAL
+#endif
+PyMODINIT_FUNC
+initxx(void)
+{
+ PyObject *m;
+
+ if (something_that_can_fail() < 0)
+ return MOD_ERROR_VAL;
+
+ #if PY_MAJOR_VERSION > 3
+ m = PyModule_Create(&moduledef);
+ #else
+ m = Py_InitModule3("xx", xx_methods, module_doc);
+ #endif
+ if (m == NULL)
+ return MOD_ERROR_VAL;
+
+ PyModule_AddObject(m, "Null", (PyObject *)&Null_Type);
+}
+''')
+# FIXME: this should have a trailing:
+'''
+ #if PY_MAJOR_VERSION > 3
+ return m;
+ #endif
+'''
+# but I haven't figured out how to get spatch to add that whilst correctly
+# handling error paths
+
+# Some code that isn't handled yet:
+# Multiple error-handling paths:
+'''
+PyMODINIT_FUNC
+initxx(void)
+{
+ PyObject *m;
+
+ if (something_that_can_fail() < 0)
+ return;
+
+ m = Py_InitModule3("xx", xx_methods, module_doc);
+ if (m == NULL)
+ return;
+
+ if (PyType_Ready(&Null_Type) < 0)
+ return;
+ PyModule_AddObject(m, "Null", (PyObject *)&Null_Type);
+}
+'''
+
+if __name__ == '__main__':
+ unittest.main()