diff options
| author | Lennart Regebro <regebro@gmail.com> | 2011-03-14 16:01:54 +0000 |
|---|---|---|
| committer | Lennart Regebro <regebro@gmail.com> | 2011-03-14 16:01:54 +0000 |
| commit | 41a51e780d7e09c82b48ebfba698c9ec0a0b85aa (patch) | |
| tree | 35910eb14d8fe5c6929a9434937c0179a65a609a /src | |
| parent | 2c369563f794888732d769b373bd2d050d379427 (diff) | |
| download | zope-i18nmessageid-41a51e780d7e09c82b48ebfba698c9ec0a0b85aa.tar.gz | |
Python 3 support.
Diffstat (limited to 'src')
| -rw-r--r-- | src/zope/i18nmessageid/_zope_i18nmessageid_message.c | 82 | ||||
| -rw-r--r-- | src/zope/i18nmessageid/message.py | 36 | ||||
| -rw-r--r-- | src/zope/i18nmessageid/messages.txt | 29 | ||||
| -rw-r--r-- | src/zope/i18nmessageid/tests.py | 13 |
4 files changed, 103 insertions, 57 deletions
diff --git a/src/zope/i18nmessageid/_zope_i18nmessageid_message.c b/src/zope/i18nmessageid/_zope_i18nmessageid_message.c index 98e2d06..3a45750 100644 --- a/src/zope/i18nmessageid/_zope_i18nmessageid_message.c +++ b/src/zope/i18nmessageid/_zope_i18nmessageid_message.c @@ -14,6 +14,23 @@ #include "Python.h" +/* Support for Python < 2.6: */ + +#ifndef Py_TYPE + #define Py_TYPE(ob) (((PyObject*)(ob))->ob_type) +#endif + +#ifndef PyVarObject_HEAD_INIT + #define PyVarObject_HEAD_INIT(type, size) \ + PyObject_HEAD_INIT(type) size, +#endif + +#if PY_MAJOR_VERSION >= 3 + #define MOD_ERROR_VAL NULL +#else + #define MOD_ERROR_VAL +#endif + /* these macros make gc support easier; they are only available in Python 2.4 and borrowed from there */ @@ -112,9 +129,9 @@ Message_new(PyTypeObject *type, PyObject *args, PyObject *kwds) #include "structmember.h" static PyMemberDef Message_members[] = { - { "domain", T_OBJECT, offsetof(Message, domain), RO }, - { "default", T_OBJECT, offsetof(Message, default_), RO }, - { "mapping", T_OBJECT, offsetof(Message, mapping), RO }, + { "domain", T_OBJECT, offsetof(Message, domain), READONLY }, + { "default", T_OBJECT, offsetof(Message, default_), READONLY }, + { "mapping", T_OBJECT, offsetof(Message, mapping), READONLY }, {NULL} /* Sentinel */ }; @@ -150,7 +167,7 @@ Message_reduce(Message *self) value = PyObject_CallFunctionObjArgs((PyObject *)&PyUnicode_Type, self, NULL); if (value == NULL) return NULL; - result = Py_BuildValue("(O(OOOO))", self->base.ob_type, + result = Py_BuildValue("(O(OOOO))", Py_TYPE(&(self->base)), value, self->domain ? self->domain : Py_None, self->default_ ? self->default_ : Py_None, @@ -175,10 +192,9 @@ static char MessageType__doc__[] = "no translation domain. default may also be None, in which case the\n" "message id itself implicitly serves as the default text.\n"; -statichere PyTypeObject +static PyTypeObject MessageType = { - PyObject_HEAD_INIT(NULL) - /* ob_size */ 0, + PyVarObject_HEAD_INIT(NULL, 0) /* tp_name */ "zope.i18nmessageid.message." "Message", /* tp_basicsize */ sizeof(Message), @@ -187,7 +203,7 @@ MessageType = { /* tp_print */ (printfunc)0, /* tp_getattr */ (getattrfunc)0, /* tp_setattr */ (setattrfunc)0, - /* tp_compare */ (cmpfunc)0, + /* tp_compare */ 0, /* tp_repr */ (reprfunc)0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, @@ -228,37 +244,65 @@ MessageType = { /* List of methods defined in the module */ - static struct PyMethodDef _zope_i18nmessageid_message_methods[] = { - {NULL, (PyCFunction)NULL, 0, NULL} /* sentinel */ + {NULL, (PyCFunction)NULL, 0, NULL}, /* sentinel */ }; +static char _zope_i18nmessageid_message_module_name[] = +"_zope_i18nmessageid_message"; static char _zope_i18nmessageid_message_module_documentation[] = -"I18n Messages" -; +"I18n Messages"; + +#if PY_MAJOR_VERSION >= 3 + static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + _zope_i18nmessageid_message_module_name,/* m_name */ + _zope_i18nmessageid_message_module_documentation,/* m_doc */ + -1,/* m_size */ + _zope_i18nmessageid_message_methods,/* m_methods */ + NULL,/* m_reload */ + NULL,/* m_traverse */ + NULL,/* m_clear */ + NULL,/* m_free */ + }; +#endif #ifndef PyMODINIT_FUNC /* declarations for DLL import/export */ -#define PyMODINIT_FUNC void + #define PyMODINIT_FUNC void #endif + PyMODINIT_FUNC -init_zope_i18nmessageid_message(void) +#if PY_MAJOR_VERSION >= 3 + PyInit__zope_i18nmessageid_message(void) +#else + init_zope_i18nmessageid_message(void) +#endif { PyObject *m; /* Initialize types: */ MessageType.tp_base = &PyUnicode_Type; if (PyType_Ready(&MessageType) < 0) - return; + return MOD_ERROR_VAL; /* Create the module and add the functions */ - m = Py_InitModule3("_zope_i18nmessageid_message", +#if PY_MAJOR_VERSION >= 3 + m = PyModule_Create(&moduledef); +#else + m = Py_InitModule3(_zope_i18nmessageid_message_module_name, _zope_i18nmessageid_message_methods, _zope_i18nmessageid_message_module_documentation); - +#endif + if (m == NULL) - return; + return MOD_ERROR_VAL; /* Add types: */ if (PyModule_AddObject(m, "Message", (PyObject *)&MessageType) < 0) - return; + return MOD_ERROR_VAL; + +#if PY_MAJOR_VERSION >= 3 + return m; +#endif + } diff --git a/src/zope/i18nmessageid/message.py b/src/zope/i18nmessageid/message.py index cd24544..2bc74a0 100644 --- a/src/zope/i18nmessageid/message.py +++ b/src/zope/i18nmessageid/message.py @@ -30,13 +30,13 @@ class Message(unicode): >>> from zope.i18nmessageid.message import Message >>> robot = Message(u"robot-message", 'futurama', u"${name} is a robot.") - >>> robot - u'robot-message' + >>> robot == u'robot-message' + True >>> isinstance(robot, unicode) True - >>> robot.default - u'${name} is a robot.' + >>> robot.default == u'${name} is a robot.' + True >>> robot.mapping >>> robot.domain = "planetexpress" @@ -55,34 +55,34 @@ class Message(unicode): TypeError: readonly attribute >>> new_robot = Message(robot, mapping={u'name': u'Bender'}) - >>> new_robot - u'robot-message' - >>> new_robot.domain - 'futurama' - >>> new_robot.default - u'${name} is a robot.' - >>> new_robot.mapping - {u'name': u'Bender'} + >>> new_robot == u'robot-message' + True + >>> new_robot.domain == 'futurama' + True + >>> new_robot.default == u'${name} is a robot.' + True + >>> new_robot.mapping == {u'name': u'Bender'} + True >>> callable, args = new_robot.__reduce__() >>> callable is Message True - >>> args - (u'robot-message', 'futurama', u'${name} is a robot.', {u'name': u'Bender'}) + >>> args == (u'robot-message', 'futurama', u'${name} is a robot.', {u'name': u'Bender'}) + True >>> fembot = Message(u'fembot') >>> callable, args = fembot.__reduce__() >>> callable is Message True - >>> args - (u'fembot', None, None, None) + >>> args == (u'fembot', None, None, None) + True Check if pickling and unpickling works >>> from pickle import dumps, loads >>> pystate = dumps(new_robot) >>> pickle_bot = loads(pystate) - >>> pickle_bot, pickle_bot.domain, pickle_bot.default, pickle_bot.mapping - (u'robot-message', 'futurama', u'${name} is a robot.', {u'name': u'Bender'}) + >>> (pickle_bot, pickle_bot.domain, pickle_bot.default, pickle_bot.mapping) == (u'robot-message', 'futurama', u'${name} is a robot.', {u'name': u'Bender'}) + True >>> pickle_bot.__reduce__()[0] is Message True """ diff --git a/src/zope/i18nmessageid/messages.txt b/src/zope/i18nmessageid/messages.txt index 3dbc687..4bf52a5 100644 --- a/src/zope/i18nmessageid/messages.txt +++ b/src/zope/i18nmessageid/messages.txt @@ -48,16 +48,16 @@ with a string that needs to be translatable: Messages at first seem like they are unicode strings: - >>> robot - u'robot-message' + >>> robot == u'robot-message' + True >>> isinstance(robot, unicode) True The additional domain, default and mapping information is available through attributes: - >>> robot.default - u'${name} is a robot.' + >>> robot.default == u'${name} is a robot.' + True >>> robot.mapping >>> robot.domain 'futurama' @@ -84,30 +84,29 @@ If you need to change their information, you'll have to make a new message id object: >>> new_robot = Message(robot, mapping={u'name': u'Bender'}) - >>> new_robot - u'robot-message' + >>> new_robot == u'robot-message' + True >>> new_robot.domain 'futurama' - >>> new_robot.default - u'${name} is a robot.' - >>> new_robot.mapping - {u'name': u'Bender'} + >>> new_robot.default == u'${name} is a robot.' + True + >>> new_robot.mapping == {u'name': u'Bender'} + True Last but not least, messages are reduceable for pickling: >>> callable, args = new_robot.__reduce__() >>> callable is Message True - >>> args - (u'robot-message', 'futurama', u'${name} is a robot.', {u'name': u'Bender'}) + >>> args == (u'robot-message', 'futurama', u'${name} is a robot.', {u'name': u'Bender'}) + True >>> fembot = Message(u'fembot') >>> callable, args = fembot.__reduce__() >>> callable is Message True - >>> args - (u'fembot', None, None, None) - + >>> args == (u'fembot', None, None, None) + True Message IDs and backward compatability -------------------------------------- diff --git a/src/zope/i18nmessageid/tests.py b/src/zope/i18nmessageid/tests.py index 46d41ec..d9ff029 100644 --- a/src/zope/i18nmessageid/tests.py +++ b/src/zope/i18nmessageid/tests.py @@ -86,7 +86,7 @@ class PickleEqualityTests(unittest.TestCase): del pickle_bot # Second check if cMessage is able to load the state of a pyMessage - from _zope_i18nmessageid_message import Message + from zope.i18nmessageid._zope_i18nmessageid_message import Message zope.i18nmessageid.message.Message = Message c_bot = loads(pystate) self.assertEqual(c_bot, u'robot-message') @@ -94,7 +94,7 @@ class PickleEqualityTests(unittest.TestCase): self.assertEqual(c_bot.default, u'${name} is a robot.') self.assertEqual(c_bot.mapping, {u'name': u'Bender'}) self.failIf(hasattr(c_bot, '_readonly')) - from _zope_i18nmessageid_message import Message as cMessage + from zope.i18nmessageid._zope_i18nmessageid_message import Message as cMessage self.failUnless(c_bot.__reduce__()[0] is cMessage) # Last check if pyMessage can load a state of cMessage @@ -114,15 +114,18 @@ class PickleEqualityTests(unittest.TestCase): self.assertEqual(pystate, cstate) try: - from _zope_i18nmessageid_message import Message as import_test + from zope.i18nmessageid._zope_i18nmessageid_message import Message as import_test def test_suite(): return unittest.TestSuite(( DocTestSuite('zope.i18nmessageid.message'), DocFileSuite('messages.txt', package='zope.i18nmessageid'), unittest.makeSuite(PickleEqualityTests), )) -except ImportError: # pragma: no cover - # couldnt import C version +except ImportError, e: # pragma: no cover + print '=' * 80 + print "Could not import C version:" + print e + print '=' * 80 def test_suite(): return unittest.TestSuite(( DocTestSuite('zope.i18nmessageid.message'), |
