From e4c495a8b6d9727de99b35bddf70f2c942e7f8b9 Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Fri, 5 Mar 2010 19:06:29 -0500 Subject: Rename "fixes" -> "lib2to3c"; start writing a setup.py --- 2to3c | 6 +-- fixes/RO.cocci | 5 -- fixes/__init__.py | 71 ------------------------ fixes/init-module.cocci | 78 --------------------------- fixes/initmodule.py | 132 --------------------------------------------- fixes/int-to-long.cocci | 82 ---------------------------- fixes/ob_type.cocci | 27 ---------- fixes/repr.cocci | 27 ---------- fixes/typeobject.py | 77 -------------------------- lib2to3c/RO.cocci | 5 ++ lib2to3c/__init__.py | 71 ++++++++++++++++++++++++ lib2to3c/init-module.cocci | 78 +++++++++++++++++++++++++++ lib2to3c/initmodule.py | 132 +++++++++++++++++++++++++++++++++++++++++++++ lib2to3c/int-to-long.cocci | 82 ++++++++++++++++++++++++++++ lib2to3c/ob_type.cocci | 27 ++++++++++ lib2to3c/repr.cocci | 27 ++++++++++ lib2to3c/typeobject.py | 77 ++++++++++++++++++++++++++ setup.py | 12 +++++ 18 files changed, 514 insertions(+), 502 deletions(-) delete mode 100644 fixes/RO.cocci delete mode 100644 fixes/__init__.py delete mode 100644 fixes/init-module.cocci delete mode 100644 fixes/initmodule.py delete mode 100644 fixes/int-to-long.cocci delete mode 100644 fixes/ob_type.cocci delete mode 100644 fixes/repr.cocci delete mode 100644 fixes/typeobject.py create mode 100644 lib2to3c/RO.cocci create mode 100644 lib2to3c/__init__.py create mode 100644 lib2to3c/init-module.cocci create mode 100644 lib2to3c/initmodule.py create mode 100644 lib2to3c/int-to-long.cocci create mode 100644 lib2to3c/ob_type.cocci create mode 100644 lib2to3c/repr.cocci create mode 100644 lib2to3c/typeobject.py create mode 100644 setup.py diff --git a/2to3c b/2to3c index ae3233a..2587a99 100755 --- a/2to3c +++ b/2to3c @@ -1,9 +1,9 @@ #!/usr/bin/env python def get_fixers(): - from fixes.typeobject import FixTypeobjectInitializers - from fixes import CocciFix - from fixes.initmodule import FixInitModule + from lib2to3c.typeobject import FixTypeobjectInitializers + from lib2to3c import CocciFix + from lib2to3c.initmodule import FixInitModule fixes = [FixTypeobjectInitializers()] for filename in ['RO.cocci', 'int-to-long.cocci', 'ob_type.cocci', 'repr.cocci']: diff --git a/fixes/RO.cocci b/fixes/RO.cocci deleted file mode 100644 index 14e0229..0000000 --- a/fixes/RO.cocci +++ /dev/null @@ -1,5 +0,0 @@ -// structmember.h lost the #define alias RO for READONLY; replace accordingly: -@@ -@@ --RO -+READONLY \ No newline at end of file diff --git a/fixes/__init__.py b/fixes/__init__.py deleted file mode 100644 index afc578b..0000000 --- a/fixes/__init__.py +++ /dev/null @@ -1,71 +0,0 @@ -import os -import tempfile -from subprocess import Popen, PIPE - -class Fix(object): - def transform(self, string): - raise NotImplementedError - -class CoccinelleError(RuntimeError): - def __init__(self, p, args, stderr): - self.p = p - self.args = args - self.stderr = stderr - - def __str__(self): - return ('Return code: %s (args: %s)\n --- start of captured stderr ---\n%s--- enf of captured stderr ---\n' - % (self.p.returncode, repr(self.args), self.stderr)) - -class CocciFix(Fix): - def __init__(self, filename): - self.filename = filename - - def get_script_path(self): - return os.path.join('fixes', self.filename) - - def transform(self, string): - # spatch seems to require the input and output to be actual files, - # rather than stdin/stdout. - - (src_hn, src_path) = tempfile.mkstemp(suffix="-%s.in.c" % self.filename) - #print (src_hn, src_path) - (dst_hn, dst_path) = tempfile.mkstemp(suffix="-%s.out.c" % self.filename) - #print (dst_hn, dst_path) - os.write(src_hn, string) - - args = ['spatch', '-sp_file', self.get_script_path(), src_path, '-o', dst_path] - p = Popen(args, stdout=PIPE, stderr=PIPE) - (stdout, stderr) = p.communicate() - if p.returncode != 0: - raise CoccinelleError(p, args, stderr) - - string = open(dst_path, 'r').read() - os.close(src_hn) - os.close(dst_hn) - - return string - -import unittest -class NonequalStrings(Exception): - def __init__(self, actual_result, exp_result): - self.actual_result = actual_result - self.exp_result = exp_result - - def __str__(self): - from difflib import unified_diff - result = '\n' - for line in unified_diff(self.exp_result.splitlines(), - self.actual_result.splitlines(), - fromfile = 'Expected result', - tofile = 'Actual result', - lineterm=''): - result += line + '\n' - return result - -class FixTest(unittest.TestCase): - '''Subclass of TestCase for verifying that a Fix is working as expected''' - def assertTransformsTo(self, fixer, src, exp_result): - actual_result = fixer.transform(src) - if actual_result != exp_result: - raise NonequalStrings(actual_result, exp_result) - diff --git a/fixes/init-module.cocci b/fixes/init-module.cocci deleted file mode 100644 index ca3bcc9..0000000 --- a/fixes/init-module.cocci +++ /dev/null @@ -1,78 +0,0 @@ -@ mod_init_fn @ -type T; -identifier FN; -identifier MOD_VAR; -expression MODULE_NAME, MODULE_METHODS, MODULE_DOC; -@@ -T FN(void) { - ... - MOD_VAR = Py_InitModule3(MODULE_NAME, MODULE_METHODS, MODULE_DOC); - ... -} - - - -@@ -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; -@@ -+struct __HASH_IF_PY_MAJOR_VERSION_ge_3; -+static struct PyModuleDef moduledef = { -+ PyModuleDef_HEAD_INIT, -+ MODULE_NAME, /* m_name */ -+ MODULE_DOC, /* m_doc */ -+ 0, /* m_size */ -+ MODULE_METHODS, /* m_methods */ -+ NULL, /* m_reload */ -+ NULL, /* m_traverse */ -+ NULL, /* m_clear */ -+ NULL, /* m_free */ -+}; -+struct __HASH_DEFINE__MOD_ERROR_VAL__NULL; -+struct __HASH_ELSE; -+struct __HASH_DEFINE__MOD_ERROR_VAL__; -+struct __HASH_ENDIF; - - T FN(void) { - ... - -+__HASH_IF_PY_MAJOR_VERSION_ge_3; -+ MOD_VAR = PyModule_Create(&moduledef); -+__HASH_ELSE; - MOD_VAR = Py_InitModule3(MODULE_NAME, MODULE_METHODS, MODULE_DOC); -+__HASH_ENDIF; - - ... - } - - diff --git a/fixes/initmodule.py b/fixes/initmodule.py deleted file mode 100644 index c106079..0000000 --- a/fixes/initmodule.py +++ /dev/null @@ -1,132 +0,0 @@ -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() diff --git a/fixes/int-to-long.cocci b/fixes/int-to-long.cocci deleted file mode 100644 index 110d97d..0000000 --- a/fixes/int-to-long.cocci +++ /dev/null @@ -1,82 +0,0 @@ -@@ -expression E1; -@@ --PyInt_AsLong(E1) -+PyLong_AsLong(E1) - -@@ -expression E1; -@@ --PyInt_Check(E1) -+PyLong_Check(E1) - -@@ -expression E1, E2, E3; -@@ --PyInt_FromString(E1, E2, E3) -+PyLong_FromString(E1, E2, E3) - -@@ -expression E1, E2, E3; -@@ --PyInt_FromUnicode(E1, E2, E3) -+PyLong_FromUnicode(E1, E2, E3) - -@@ -expression E1; -@@ --PyInt_FromLong(E1) -+PyLong_FromLong(E1) - -@@ -expression E1; -@@ --PyInt_FromSize_t(E1) -+PyLong_FromSize_t(E1) - -@@ -expression E1; -@@ --PyInt_FromSsize_t(E1) -+PyLong_FromSsize_t(E1) - -@@ -expression E1; -@@ --PyInt_AsLong(E1) -+PyLong_AsLong(E1) - -@@ -expression E1; -@@ --PyInt_AsSsize_t(E1) -+PyLong_AsSsize_t(E1) - -@@ -expression E1; -@@ --PyInt_AsUnsignedLongMask(E1) -+PyLong_AsUnsignedLongMask(E1) - -@@ -expression E1; -@@ --PyInt_AsUnsignedLongLongMask(E1) -+PyLong_AsUnsignedLongLongMask(E1) - -@@ -expression E1; -@@ --PyInt_AS_LONG(E1) -+PyLong_AS_LONG(E1) - -@@ -expression E1; -@@ --PyNumber_Int(E1) -+PyNumber_Long(E1) - -@@ -@@ --PyInt_Type -+PyLong_Type \ No newline at end of file diff --git a/fixes/ob_type.cocci b/fixes/ob_type.cocci deleted file mode 100644 index daf6d96..0000000 --- a/fixes/ob_type.cocci +++ /dev/null @@ -1,27 +0,0 @@ -// Convert non-PyObject* deferences of "ob_type" to use Py_TYPE macro instead -@@ -PyObject *py_obj_ptr; -type T; -T non_py_obj_ptr; -@@ -( - py_obj_ptr->ob_type -| -- non_py_obj_ptr->ob_type -+ Py_TYPE(non_py_obj_ptr) -) - -@@ -identifier F; // FIXME: must be an initial field of a struct -type T; -T non_py_obj_ptr; -@@ -- non_py_obj_ptr->F.ob_type -+ Py_TYPE(non_py_obj_ptr) - -@@ -PyTypeObject typeobj; -@@ -- typeobj.ob_type -+ Py_TYPE(&typeobj) - diff --git a/fixes/repr.cocci b/fixes/repr.cocci deleted file mode 100644 index dfa1ef4..0000000 --- a/fixes/repr.cocci +++ /dev/null @@ -1,27 +0,0 @@ -// tp_repr functions should return unicode in py3k -// FIXME: need to restrict to just tp_repr functions: -@@ -type T; -function FN_repr; -expression E; -@@ -PyObject * -FN_repr(T *self) -{ - ... -- return PyString_FromString(E); -+ return PyUnicode_FromString(E); -} - -@@ -type T; -function FN_repr; -expression E1, E2; -@@ -PyObject * -FN_repr(T *self) -{ - ... -- return PyString_FromFormat(E1, E2); -+ return PyUnicode_FromFormat(E1, E2); -} diff --git a/fixes/typeobject.py b/fixes/typeobject.py deleted file mode 100644 index dde1f74..0000000 --- a/fixes/typeobject.py +++ /dev/null @@ -1,77 +0,0 @@ -import sys -import re - -# I wasn't able to express this refactoring in SmPLs; the implied comma embedded -# in the _HEAD_INIT macros seems to be too much for spatch to reasonably deal -# with. - -# So I expressed this one as a regex. - -# Whitespace patterns: -req_ws = r'\s+' -opt_ws = r'\s*' -c_identifier = r'([_A-Za-z][_0-9A-Za-z]*)' - -pat = ('.*' + r'PyTypeObject' + req_ws - + c_identifier + opt_ws - + r'=' + opt_ws + r'\{' + opt_ws - + r'(PyObject_HEAD_INIT\((.*)\)' + opt_ws - + r'([0-9]+)' + opt_ws + r',).*' - ) - -def fixup_typeobject_initializers(content): - while True: - m = re.match(pat, content, re.DOTALL) - if m: - if False: - print m.groups() - print m.group(2) - print m.group(3) - print m.group(4) - print m.span(2) - content = (content[:m.start(2)] - + 'PyVarObject_HEAD_INIT(%s, %s)' % (m.group(3),m.group(4)) - + content[m.end(2):]) - else: - return content - -from fixes import Fix, FixTest -class FixTypeobjectInitializers(Fix): - def transform(self, string): - return fixup_typeobject_initializers(string) - -import unittest -class TestFixups(FixTest): - def setUp(self): - self.fixer = FixTypeobjectInitializers() - - def test_fixups(self): - self.assertTransformsTo(self.fixer, - ''' -PyTypeObject DBusPyIntBase_Type = { - PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type)) - 0, - "_dbus_bindings._IntBase", -''', - ''' -PyTypeObject DBusPyIntBase_Type = { - PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0) - "_dbus_bindings._IntBase", -''') - - def test_fixup_with_comment(self): - self.assertTransformsTo(self.fixer, - ''' -PyTypeObject PyFortran_Type = { - PyObject_HEAD_INIT(0) - 0, /*ob_size*/ - "fortran", /*tp_name*/ -''', - ''' -PyTypeObject PyFortran_Type = { - PyVarObject_HEAD_INIT(0, 0) /*ob_size*/ - "fortran", /*tp_name*/ -''') - -if __name__ == '__main__': - unittest.main() diff --git a/lib2to3c/RO.cocci b/lib2to3c/RO.cocci new file mode 100644 index 0000000..14e0229 --- /dev/null +++ b/lib2to3c/RO.cocci @@ -0,0 +1,5 @@ +// structmember.h lost the #define alias RO for READONLY; replace accordingly: +@@ +@@ +-RO ++READONLY \ No newline at end of file diff --git a/lib2to3c/__init__.py b/lib2to3c/__init__.py new file mode 100644 index 0000000..8d545ae --- /dev/null +++ b/lib2to3c/__init__.py @@ -0,0 +1,71 @@ +import os +import tempfile +from subprocess import Popen, PIPE + +class Fix(object): + def transform(self, string): + raise NotImplementedError + +class CoccinelleError(RuntimeError): + def __init__(self, p, args, stderr): + self.p = p + self.args = args + self.stderr = stderr + + def __str__(self): + return ('Return code: %s (args: %s)\n --- start of captured stderr ---\n%s--- enf of captured stderr ---\n' + % (self.p.returncode, repr(self.args), self.stderr)) + +class CocciFix(Fix): + def __init__(self, filename): + self.filename = filename + + def get_script_path(self): + return os.path.join('lib2to3c', self.filename) + + def transform(self, string): + # spatch seems to require the input and output to be actual files, + # rather than stdin/stdout. + + (src_hn, src_path) = tempfile.mkstemp(suffix="-%s.in.c" % self.filename) + #print (src_hn, src_path) + (dst_hn, dst_path) = tempfile.mkstemp(suffix="-%s.out.c" % self.filename) + #print (dst_hn, dst_path) + os.write(src_hn, string) + + args = ['spatch', '-sp_file', self.get_script_path(), src_path, '-o', dst_path] + p = Popen(args, stdout=PIPE, stderr=PIPE) + (stdout, stderr) = p.communicate() + if p.returncode != 0: + raise CoccinelleError(p, args, stderr) + + string = open(dst_path, 'r').read() + os.close(src_hn) + os.close(dst_hn) + + return string + +import unittest +class NonequalStrings(Exception): + def __init__(self, actual_result, exp_result): + self.actual_result = actual_result + self.exp_result = exp_result + + def __str__(self): + from difflib import unified_diff + result = '\n' + for line in unified_diff(self.exp_result.splitlines(), + self.actual_result.splitlines(), + fromfile = 'Expected result', + tofile = 'Actual result', + lineterm=''): + result += line + '\n' + return result + +class FixTest(unittest.TestCase): + '''Subclass of TestCase for verifying that a Fix is working as expected''' + def assertTransformsTo(self, fixer, src, exp_result): + actual_result = fixer.transform(src) + if actual_result != exp_result: + raise NonequalStrings(actual_result, exp_result) + diff --git a/lib2to3c/init-module.cocci b/lib2to3c/init-module.cocci new file mode 100644 index 0000000..ca3bcc9 --- /dev/null +++ b/lib2to3c/init-module.cocci @@ -0,0 +1,78 @@ +@ mod_init_fn @ +type T; +identifier FN; +identifier MOD_VAR; +expression MODULE_NAME, MODULE_METHODS, MODULE_DOC; +@@ +T FN(void) { + ... + MOD_VAR = Py_InitModule3(MODULE_NAME, MODULE_METHODS, MODULE_DOC); + ... +} + + + +@@ +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; +@@ ++struct __HASH_IF_PY_MAJOR_VERSION_ge_3; ++static struct PyModuleDef moduledef = { ++ PyModuleDef_HEAD_INIT, ++ MODULE_NAME, /* m_name */ ++ MODULE_DOC, /* m_doc */ ++ 0, /* m_size */ ++ MODULE_METHODS, /* m_methods */ ++ NULL, /* m_reload */ ++ NULL, /* m_traverse */ ++ NULL, /* m_clear */ ++ NULL, /* m_free */ ++}; ++struct __HASH_DEFINE__MOD_ERROR_VAL__NULL; ++struct __HASH_ELSE; ++struct __HASH_DEFINE__MOD_ERROR_VAL__; ++struct __HASH_ENDIF; + + T FN(void) { + ... + ++__HASH_IF_PY_MAJOR_VERSION_ge_3; ++ MOD_VAR = PyModule_Create(&moduledef); ++__HASH_ELSE; + MOD_VAR = Py_InitModule3(MODULE_NAME, MODULE_METHODS, MODULE_DOC); ++__HASH_ENDIF; + + ... + } + + diff --git a/lib2to3c/initmodule.py b/lib2to3c/initmodule.py new file mode 100644 index 0000000..c890a9e --- /dev/null +++ b/lib2to3c/initmodule.py @@ -0,0 +1,132 @@ +from lib2to3c 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() diff --git a/lib2to3c/int-to-long.cocci b/lib2to3c/int-to-long.cocci new file mode 100644 index 0000000..110d97d --- /dev/null +++ b/lib2to3c/int-to-long.cocci @@ -0,0 +1,82 @@ +@@ +expression E1; +@@ +-PyInt_AsLong(E1) ++PyLong_AsLong(E1) + +@@ +expression E1; +@@ +-PyInt_Check(E1) ++PyLong_Check(E1) + +@@ +expression E1, E2, E3; +@@ +-PyInt_FromString(E1, E2, E3) ++PyLong_FromString(E1, E2, E3) + +@@ +expression E1, E2, E3; +@@ +-PyInt_FromUnicode(E1, E2, E3) ++PyLong_FromUnicode(E1, E2, E3) + +@@ +expression E1; +@@ +-PyInt_FromLong(E1) ++PyLong_FromLong(E1) + +@@ +expression E1; +@@ +-PyInt_FromSize_t(E1) ++PyLong_FromSize_t(E1) + +@@ +expression E1; +@@ +-PyInt_FromSsize_t(E1) ++PyLong_FromSsize_t(E1) + +@@ +expression E1; +@@ +-PyInt_AsLong(E1) ++PyLong_AsLong(E1) + +@@ +expression E1; +@@ +-PyInt_AsSsize_t(E1) ++PyLong_AsSsize_t(E1) + +@@ +expression E1; +@@ +-PyInt_AsUnsignedLongMask(E1) ++PyLong_AsUnsignedLongMask(E1) + +@@ +expression E1; +@@ +-PyInt_AsUnsignedLongLongMask(E1) ++PyLong_AsUnsignedLongLongMask(E1) + +@@ +expression E1; +@@ +-PyInt_AS_LONG(E1) ++PyLong_AS_LONG(E1) + +@@ +expression E1; +@@ +-PyNumber_Int(E1) ++PyNumber_Long(E1) + +@@ +@@ +-PyInt_Type ++PyLong_Type \ No newline at end of file diff --git a/lib2to3c/ob_type.cocci b/lib2to3c/ob_type.cocci new file mode 100644 index 0000000..daf6d96 --- /dev/null +++ b/lib2to3c/ob_type.cocci @@ -0,0 +1,27 @@ +// Convert non-PyObject* deferences of "ob_type" to use Py_TYPE macro instead +@@ +PyObject *py_obj_ptr; +type T; +T non_py_obj_ptr; +@@ +( + py_obj_ptr->ob_type +| +- non_py_obj_ptr->ob_type ++ Py_TYPE(non_py_obj_ptr) +) + +@@ +identifier F; // FIXME: must be an initial field of a struct +type T; +T non_py_obj_ptr; +@@ +- non_py_obj_ptr->F.ob_type ++ Py_TYPE(non_py_obj_ptr) + +@@ +PyTypeObject typeobj; +@@ +- typeobj.ob_type ++ Py_TYPE(&typeobj) + diff --git a/lib2to3c/repr.cocci b/lib2to3c/repr.cocci new file mode 100644 index 0000000..dfa1ef4 --- /dev/null +++ b/lib2to3c/repr.cocci @@ -0,0 +1,27 @@ +// tp_repr functions should return unicode in py3k +// FIXME: need to restrict to just tp_repr functions: +@@ +type T; +function FN_repr; +expression E; +@@ +PyObject * +FN_repr(T *self) +{ + ... +- return PyString_FromString(E); ++ return PyUnicode_FromString(E); +} + +@@ +type T; +function FN_repr; +expression E1, E2; +@@ +PyObject * +FN_repr(T *self) +{ + ... +- return PyString_FromFormat(E1, E2); ++ return PyUnicode_FromFormat(E1, E2); +} diff --git a/lib2to3c/typeobject.py b/lib2to3c/typeobject.py new file mode 100644 index 0000000..56a9744 --- /dev/null +++ b/lib2to3c/typeobject.py @@ -0,0 +1,77 @@ +import sys +import re + +# I wasn't able to express this refactoring in SmPLs; the implied comma embedded +# in the _HEAD_INIT macros seems to be too much for spatch to reasonably deal +# with. + +# So I expressed this one as a regex. + +# Whitespace patterns: +req_ws = r'\s+' +opt_ws = r'\s*' +c_identifier = r'([_A-Za-z][_0-9A-Za-z]*)' + +pat = ('.*' + r'PyTypeObject' + req_ws + + c_identifier + opt_ws + + r'=' + opt_ws + r'\{' + opt_ws + + r'(PyObject_HEAD_INIT\((.*)\)' + opt_ws + + r'([0-9]+)' + opt_ws + r',).*' + ) + +def fixup_typeobject_initializers(content): + while True: + m = re.match(pat, content, re.DOTALL) + if m: + if False: + print m.groups() + print m.group(2) + print m.group(3) + print m.group(4) + print m.span(2) + content = (content[:m.start(2)] + + 'PyVarObject_HEAD_INIT(%s, %s)' % (m.group(3),m.group(4)) + + content[m.end(2):]) + else: + return content + +from lib2to3c import Fix, FixTest +class FixTypeobjectInitializers(Fix): + def transform(self, string): + return fixup_typeobject_initializers(string) + +import unittest +class TestFixups(FixTest): + def setUp(self): + self.fixer = FixTypeobjectInitializers() + + def test_fixups(self): + self.assertTransformsTo(self.fixer, + ''' +PyTypeObject DBusPyIntBase_Type = { + PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type)) + 0, + "_dbus_bindings._IntBase", +''', + ''' +PyTypeObject DBusPyIntBase_Type = { + PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0) + "_dbus_bindings._IntBase", +''') + + def test_fixup_with_comment(self): + self.assertTransformsTo(self.fixer, + ''' +PyTypeObject PyFortran_Type = { + PyObject_HEAD_INIT(0) + 0, /*ob_size*/ + "fortran", /*tp_name*/ +''', + ''' +PyTypeObject PyFortran_Type = { + PyVarObject_HEAD_INIT(0, 0) /*ob_size*/ + "fortran", /*tp_name*/ +''') + +if __name__ == '__main__': + unittest.main() diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..4e0a3e3 --- /dev/null +++ b/setup.py @@ -0,0 +1,12 @@ +from setuptools import setup, find_packages + +setup(name="2to3c", + version="0.1", + description="", + author="David Malcolm", + author_email="dmalcolm@redhat.com", + packages=find_packages(exclude='tests'), + url="http://fedorahosted.org/2to3c/", + scripts=['2to3c'] + ) + -- cgit