[Checkins] SVN: zope.i18nmessageid/trunk/ Merge svn+ssh://svn.zope.org/repos/main/zope.i18nmessageid/branches/jython-compat to trunk.

Chris McDonough chrism at plope.com
Tue Aug 10 01:05:24 EDT 2010


Log message for revision 115603:
  Merge svn+ssh://svn.zope.org/repos/main/zope.i18nmessageid/branches/jython-compat to trunk.
  

Changed:
  _U  zope.i18nmessageid/trunk/
  U   zope.i18nmessageid/trunk/CHANGES.txt
  U   zope.i18nmessageid/trunk/setup.py
  U   zope.i18nmessageid/trunk/src/zope/i18nmessageid/message.py
  U   zope.i18nmessageid/trunk/src/zope/i18nmessageid/tests.py

-=-

Property changes on: zope.i18nmessageid/trunk
___________________________________________________________________
Modified: svn:ignore
   - bin
build
dist
lib
develop-eggs
eggs
parts
.installed.cfg

   + bin
build
dist
lib
develop-eggs
eggs
parts
.installed.cfg
.coverage


Modified: zope.i18nmessageid/trunk/CHANGES.txt
===================================================================
--- zope.i18nmessageid/trunk/CHANGES.txt	2010-08-10 05:00:00 UTC (rev 115602)
+++ zope.i18nmessageid/trunk/CHANGES.txt	2010-08-10 05:05:24 UTC (rev 115603)
@@ -5,7 +5,17 @@
 3.5.3 (unreleased)
 ------------------
 
+- Made compilation of C extension optional again; 3.5.1 broke this
+  inasmuch as this package become unusable on non-CPython platforms.
+  Making the compilation of the C extension optional again implied
+  removing ``setup.py`` code added in 3.5.1 which made the C extension
+  a setuptools "Feature" and readding code from 3.5.0 which overrides
+  the distutils ``build_ext`` command.
 
+- Move pickle equality tests into a unittest.TestCase test to make it
+  easier to condition the tests on whether the C extension has been
+  compiled.  This also makes the tests pass on Jython.
+
 3.5.2 (2010-04-30)
 ------------------
 

Modified: zope.i18nmessageid/trunk/setup.py
===================================================================
--- zope.i18nmessageid/trunk/setup.py	2010-08-10 05:00:00 UTC (rev 115602)
+++ zope.i18nmessageid/trunk/setup.py	2010-08-10 05:05:24 UTC (rev 115603)
@@ -20,22 +20,47 @@
 """
 
 import os
+import sys
 
-from setuptools import setup, find_packages, Extension, Feature
+from setuptools import setup, find_packages, Extension
+from distutils.command.build_ext import build_ext
+from distutils.errors import CCompilerError
+from distutils.errors import DistutilsExecError
+from distutils.errors import DistutilsPlatformError
 
 def read(*rnames):
     return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
 
-codeoptimization = Feature("Optional code optimizations",
-    standard=True,
-    ext_modules=[
-        Extension("zope.i18nmessageid._zope_i18nmessageid_message", [
-            os.path.join('src', 'zope', 'i18nmessageid',
-                "_zope_i18nmessageid_message.c")
-        ]),
-    ],
-)
+class optional_build_ext(build_ext):
+    """This class subclasses build_ext and allows
+       the building of C extensions to fail.
+    """
+    def run(self):
+        try:
+            build_ext.run(self)
+        
+        except DistutilsPlatformError, e:
+            self._unavailable(e)
 
+    def build_extension(self, ext):
+       try:
+           build_ext.build_extension(self, ext)
+        
+       except (CCompilerError, DistutilsExecError), e:
+           self._unavailable(e)
+
+    def _unavailable(self, e):
+        print >> sys.stderr, '*' * 80
+        print >> sys.stderr, """WARNING:
+
+        An optional code optimization (C extension) could not be compiled.
+
+        Optimizations for this package will not be available!"""
+        print >> sys.stderr
+        print >> sys.stderr, e
+        print >> sys.stderr, '*' * 80
+
+
 setup(name='zope.i18nmessageid',
     version = '3.5.3dev',
     author='Zope Foundation and Contributors',
@@ -63,9 +88,16 @@
     url='http://pypi.python.org/pypi/zope.i18nmessageid',
     packages=find_packages('src'),
     package_dir = {'': 'src'},
-    features = {'codeoptimization': codeoptimization},
+    ext_modules=[
+        Extension("zope.i18nmessageid._zope_i18nmessageid_message",
+                  [os.path.join('src', 'zope', 'i18nmessageid',
+                                "_zope_i18nmessageid_message.c") ]),
+        ],
     namespace_packages=['zope',],
     install_requires=['setuptools'],
     include_package_data = True,
+    test_suite='zope.i18nmessageid.tests.test_suite',
     zip_safe = False,
-)
+    cmdclass = {'build_ext':optional_build_ext},
+    )
+

Modified: zope.i18nmessageid/trunk/src/zope/i18nmessageid/message.py
===================================================================
--- zope.i18nmessageid/trunk/src/zope/i18nmessageid/message.py	2010-08-10 05:00:00 UTC (rev 115602)
+++ zope.i18nmessageid/trunk/src/zope/i18nmessageid/message.py	2010-08-10 05:05:24 UTC (rev 115603)
@@ -27,7 +27,7 @@
     These are the doc tests from message.txt. Note that we have to create the
     message manually since MessageFactory would return the C implementation.
 
-    >>> from zope.i18nmessageid.message import pyMessage as Message
+    >>> from zope.i18nmessageid.message import Message
     >>> robot = Message(u"robot-message", 'futurama', u"${name} is a robot.")
 
     >>> robot
@@ -39,10 +39,6 @@
     u'${name} is a robot.'
     >>> robot.mapping
 
-    Only the python implementation has a _readonly attribute
-    >>> robot._readonly
-    True
-
     >>> robot.domain = "planetexpress"
     Traceback (most recent call last):
     ...
@@ -81,56 +77,14 @@
     >>> args
     (u'fembot', None, None, None)
 
-    Change classes for pickle tests
-    >>> import zope.i18nmessageid.message
-    >>> oldMessage = zope.i18nmessageid.message.Message
-    >>> zope.i18nmessageid.message.Message = Message
-
-    At first check if pickling and unpicklung from pyMessage to pyMessage works
+    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._readonly
+    >>> pickle_bot.__reduce__()[0] is Message
     True
-    >>> from zope.i18nmessageid.message import pyMessage
-    >>> pickle_bot.__reduce__()[0] is pyMessage
-    True
-    >>> del pickle_bot
-
-    At second check if cMessage is able to load the state of a pyMessage
-    >>> from _zope_i18nmessageid_message import Message
-    >>> zope.i18nmessageid.message.Message = Message
-    >>> c_bot = loads(pystate)
-    >>> c_bot, c_bot.domain, c_bot.default, c_bot.mapping
-    (u'robot-message', 'futurama', u'${name} is a robot.', {u'name': u'Bender'})
-    >>> c_bot._readonly
-    Traceback (most recent call last):
-    AttributeError: 'zope.i18nmessageid.message.Message' object has no attribute '_readonly'
-    >>> from _zope_i18nmessageid_message import Message as cMessage
-    >>> c_bot.__reduce__()[0] is cMessage
-    True
-
-    At last check if pyMessage can load a state of cMessage
-    >>> cstate = dumps(c_bot)
-    >>> del c_bot
-    >>> from zope.i18nmessageid.message import pyMessage as Message
-    >>> zope.i18nmessageid.message.Message = Message
-    >>> py_bot = loads(cstate)
-    >>> py_bot, py_bot.domain, py_bot.default, py_bot.mapping
-    (u'robot-message', 'futurama', u'${name} is a robot.', {u'name': u'Bender'})
-    >>> py_bot._readonly
-    True
-    >>> py_bot.__reduce__()[0] is pyMessage
-    True
-
-    Both pickle states should be equal
-    >>> pystate == cstate
-    True
-
-    Finally restore classes for other unit tests
-    >>> zope.i18nmessageid.message.Message = oldMessage
     """
 
     __slots__ = ('domain', 'default', 'mapping', '_readonly')
@@ -173,7 +127,7 @@
 
 try:
     from _zope_i18nmessageid_message import Message
-except ImportError:
+except ImportError: # pragma: no cover
     pass
 
 class MessageFactory(object):

Modified: zope.i18nmessageid/trunk/src/zope/i18nmessageid/tests.py
===================================================================
--- zope.i18nmessageid/trunk/src/zope/i18nmessageid/tests.py	2010-08-10 05:00:00 UTC (rev 115602)
+++ zope.i18nmessageid/trunk/src/zope/i18nmessageid/tests.py	2010-08-10 05:05:24 UTC (rev 115603)
@@ -17,11 +17,115 @@
 from doctest import DocFileSuite
 from doctest import DocTestSuite
 
-def test_suite():
-    return unittest.TestSuite((
+class PickleEqualityTests(unittest.TestCase):
+    def setUp(self):
+        # set the C version up as the used version
+        import zope.i18nmessageid.message
+        self.oldMessage = zope.i18nmessageid.message.Message
+
+    def tearDown(self):
+        # set the original version back up as the used version
+        import zope.i18nmessageid.message
+        zope.i18nmessageid.message.Message = self.oldMessage
+
+    def test_message_pickling(self):
+        from zope.i18nmessageid.message import pyMessage as Message
+        robot = Message(u"robot-message", 'futurama', u"${name} is a robot.")
+
+        self.assertEqual(robot, u'robot-message')
+        self.failUnless(isinstance(robot, unicode))
+        self.assertEqual(robot.default, u'${name} is a robot.')
+        self.assertEqual(robot.mapping, None)
+
+        # Only the python implementation has a _readonly attribute
+        self.assertEqual(robot._readonly, True)
+        self.assertRaises(
+            TypeError,
+            robot.__setattr__, 'domain', "planetexpress")
+        self.assertRaises(
+            TypeError,
+            robot.__setattr__, 'default', u"${name} is not a robot.")
+        self.assertRaises(
+            TypeError,
+            robot.__setattr__, 'mapping', {u'name': u'Bender'})
+        
+        new_robot = Message(robot, mapping={u'name': u'Bender'})
+        self.assertEqual(new_robot, u'robot-message')
+        self.assertEqual(new_robot.domain, 'futurama')
+        self.assertEqual(new_robot.default, u'${name} is a robot.')
+        self.assertEqual(new_robot.mapping, {u'name': u'Bender'})
+
+        callable, args = new_robot.__reduce__()
+        self.failUnless(callable is Message)
+        self.assertEqual(
+            args,
+            (u'robot-message', 'futurama', u'${name} is a robot.',
+             {u'name': u'Bender'}))
+
+        fembot = Message(u'fembot')
+        callable, args = fembot.__reduce__()
+        self.failUnless(callable is Message)
+        self.assertEqual(args, (u'fembot', None, None, None))
+
+        import zope.i18nmessageid.message
+        zope.i18nmessageid.message.Message = Message
+
+        # First check if pickling and unpickling from pyMessage to
+        # pyMessage works
+        from pickle import dumps, loads
+        pystate = dumps(new_robot)
+        pickle_bot = loads(pystate)
+        self.assertEqual(pickle_bot, u'robot-message')
+        self.assertEqual(pickle_bot.domain, 'futurama')
+        self.assertEqual(pickle_bot.default, u'${name} is a robot.')
+        self.assertEqual(pickle_bot.mapping, {u'name': u'Bender'})
+        self.assertEqual(pickle_bot._readonly, True)
+
+        from zope.i18nmessageid.message import pyMessage
+        self.failUnless(pickle_bot.__reduce__()[0] is pyMessage)
+        del pickle_bot
+
+        # Second check if cMessage is able to load the state of a pyMessage
+        from _zope_i18nmessageid_message import Message
+        zope.i18nmessageid.message.Message = Message
+        c_bot = loads(pystate) 
+        self.assertEqual(c_bot, u'robot-message')
+        self.assertEqual(c_bot.domain, 'futurama')
+        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
+        self.failUnless(c_bot.__reduce__()[0] is cMessage)
+
+        # Last check if pyMessage can load a state of cMessage
+        cstate = dumps(c_bot)
+        del c_bot
+        from zope.i18nmessageid.message import pyMessage as Message
+        zope.i18nmessageid.message.Message = Message
+        py_bot = loads(cstate)
+        self.assertEqual(py_bot, u'robot-message')
+        self.assertEqual(py_bot.domain, 'futurama')
+        self.assertEqual(py_bot.default, u'${name} is a robot.')
+        self.assertEqual(py_bot.mapping, {u'name': u'Bender'})
+        self.assertEqual(py_bot._readonly, True)
+        self.failUnless(py_bot.__reduce__()[0] is pyMessage)
+
+        # Both pickle states should be equal
+        self.assertEqual(pystate, cstate)
+
+try:
+    from _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),
 	    ))
-
-if __name__ == '__main__':
-    unittest.main(defaultTest="test_suite")
+except ImportError: # pragma: no cover
+    # couldnt import C version
+    def test_suite():
+        return unittest.TestSuite((
+	    DocTestSuite('zope.i18nmessageid.message'),
+	    DocFileSuite('messages.txt', package='zope.i18nmessageid'),
+	    ))
+    



More information about the checkins mailing list