[Checkins] SVN: zope.component/branches/tseaver-wo_zope_deferred/ Added a pure-Python 'hookable' implementation, for use when 'zope.hookable'

Tres Seaver tseaver at palladion.com
Wed Mar 4 18:29:00 EST 2009


Log message for revision 97498:
  Added a pure-Python 'hookable' implementation, for use when 'zope.hookable'
  is not present.
  

Changed:
  U   zope.component/branches/tseaver-wo_zope_deferred/CHANGES.txt
  U   zope.component/branches/tseaver-wo_zope_deferred/buildout.cfg
  U   zope.component/branches/tseaver-wo_zope_deferred/src/zope/component/_api.py
  A   zope.component/branches/tseaver-wo_zope_deferred/src/zope/component/hookable.py
  U   zope.component/branches/tseaver-wo_zope_deferred/src/zope/component/tests.py

-=-
Modified: zope.component/branches/tseaver-wo_zope_deferred/CHANGES.txt
===================================================================
--- zope.component/branches/tseaver-wo_zope_deferred/CHANGES.txt	2009-03-04 23:17:08 UTC (rev 97497)
+++ zope.component/branches/tseaver-wo_zope_deferred/CHANGES.txt	2009-03-04 23:29:00 UTC (rev 97498)
@@ -4,6 +4,9 @@
 3.6.0 (unreleased)
 ==================
 
+- Added a pure-Python 'hookable' implementation, for use when
+  'zope.hookable' is not present.
+
 - Cleanup package documentation and changelog a bit. Add sphinx-based
   documentation building command to the buildout.
 

Modified: zope.component/branches/tseaver-wo_zope_deferred/buildout.cfg
===================================================================
--- zope.component/branches/tseaver-wo_zope_deferred/buildout.cfg	2009-03-04 23:17:08 UTC (rev 97497)
+++ zope.component/branches/tseaver-wo_zope_deferred/buildout.cfg	2009-03-04 23:29:00 UTC (rev 97498)
@@ -1,11 +1,16 @@
 [buildout]
 develop = .
-parts = test python docs
+parts = test test_c_hookable python docs
+unzip = true
 
 [test]
 recipe = zc.recipe.testrunner
 eggs = zope.component [test,zcml]
 
+[test_c_hookable]
+recipe = zc.recipe.testrunner
+eggs = zope.component [test,zcml,hook]
+
 [python]
 recipe = zc.recipe.egg
 interpreter = python

Modified: zope.component/branches/tseaver-wo_zope_deferred/src/zope/component/_api.py
===================================================================
--- zope.component/branches/tseaver-wo_zope_deferred/src/zope/component/_api.py	2009-03-04 23:17:08 UTC (rev 97497)
+++ zope.component/branches/tseaver-wo_zope_deferred/src/zope/component/_api.py	2009-03-04 23:29:00 UTC (rev 97498)
@@ -31,12 +31,12 @@
 from zope.component._declaration import adapter
 from zope.component._declaration import adapts
 
-# Try to be hookable. Do so in a try/except to avoid a hard dependency.
+# Use the C implementation in zope.hookable, if available;  fall back
+# to our Python version if not.
 try:
     from zope.hookable import hookable
 except ImportError:
-    def hookable(ob):
-        return ob
+    from zope.component.hookable import hookable
 
 # getSiteManager() returns a component registry.  Although the term
 # "site manager" is deprecated in favor of "component registry",

Added: zope.component/branches/tseaver-wo_zope_deferred/src/zope/component/hookable.py
===================================================================
--- zope.component/branches/tseaver-wo_zope_deferred/src/zope/component/hookable.py	                        (rev 0)
+++ zope.component/branches/tseaver-wo_zope_deferred/src/zope/component/hookable.py	2009-03-04 23:29:00 UTC (rev 97498)
@@ -0,0 +1,33 @@
+##############################################################################
+#
+# Copyright (c) 2009 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+""" This module supplies a pure-Python version of zope.hookable.hookable.
+"""
+class hookable(object):
+    __slots__ = ('__original', '__implementation')
+
+    original = property(lambda self: self.__original,)
+    implementation = property(lambda self: self.__implementation,)
+
+    def __init__(self, implementation):
+        self.__original = self.__implementation = implementation
+
+    def sethook(self, newimplementation):
+        old, self.__implementation = self.__implementation, newimplementation
+        return old
+
+    def reset(self):
+        self.__implementation = self.__original
+
+    def __call__(self, *args, **kw):
+        return self.__implementation(*args, **kw)

Modified: zope.component/branches/tseaver-wo_zope_deferred/src/zope/component/tests.py
===================================================================
--- zope.component/branches/tseaver-wo_zope_deferred/src/zope/component/tests.py	2009-03-04 23:17:08 UTC (rev 97497)
+++ zope.component/branches/tseaver-wo_zope_deferred/src/zope/component/tests.py	2009-03-04 23:29:00 UTC (rev 97498)
@@ -1,6 +1,6 @@
 ##############################################################################
 #
-# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# Copyright (c) 2001, 2002, 2009 Zope Corporation and Contributors.
 # All Rights Reserved.
 #
 # This software is subject to the provisions of the Zope Public License,
@@ -987,6 +987,116 @@
         if not success:
             self.fail(''.join(lines))
 
+class HookableTests(unittest.TestCase):
+
+    def test_ctor_no_func(self):
+        from zope.component.hookable import hookable
+        self.assertRaises(TypeError, hookable)
+
+    def test_ctor_simple(self):
+        from zope.component.hookable import hookable
+        def foo():
+            pass
+        hooked = hookable(foo)
+        self.failUnless(hooked.original is foo)
+        self.failUnless(hooked.implementation is foo)
+
+    def test_ctor_extra_arg(self):
+        from zope.component.hookable import hookable
+        def foo():
+            pass
+        self.assertRaises(TypeError, hookable, foo, foo)
+
+    def test_ctor_extra_arg(self):
+        from zope.component.hookable import hookable
+        def foo():
+            pass
+        self.assertRaises(TypeError, hookable, foo, nonesuch=foo)
+
+    def test_sethook(self):
+        from zope.component.hookable import hookable
+        def foo():
+            pass
+        def bar():
+            pass
+        hooked = hookable(foo)
+        hooked.sethook(bar)
+        self.failUnless(hooked.original is foo)
+        self.failUnless(hooked.implementation is bar)
+
+    def test_reset(self):
+        from zope.component.hookable import hookable
+        def foo():
+            pass
+        def bar():
+            pass
+        hooked = hookable(foo)
+        hooked.sethook(bar)
+        hooked.reset()
+        self.failUnless(hooked.original is foo)
+        self.failUnless(hooked.implementation is foo)
+
+    def test_cant_assign_original(self):
+        from zope.component.hookable import hookable
+        def foo():
+            pass
+        def bar():
+            pass
+        hooked = hookable(foo)
+        try:
+            hooked.original = bar
+        except TypeError:
+            pass
+        except AttributeError:
+            pass
+        else:
+            self.fail('Assigned original')
+
+    def test_cant_delete_original(self):
+        from zope.component.hookable import hookable
+        def foo():
+            pass
+        hooked = hookable(foo)
+        try:
+            del hooked.original
+        except TypeError:
+            pass
+        except AttributeError:
+            pass
+        else:
+            self.fail('Deleted original')
+
+    def test_cant_assign_original(self):
+        from zope.component.hookable import hookable
+        def foo():
+            pass
+        def bar():
+            pass
+        hooked = hookable(foo)
+        try:
+            hooked.implementation = bar
+        except TypeError:
+            pass
+        except AttributeError:
+            pass
+        else:
+            self.fail('Assigned implementation')
+
+    def test_readonly_original(self):
+        from zope.component.hookable import hookable
+        def foo():
+            pass
+        hooked = hookable(foo)
+        try:
+            del hooked.implementation
+        except TypeError:
+            pass
+        except AttributeError:
+            pass
+        else:
+            self.fail('Deleted implementation')
+
+
 def setUpRegistryTests(tests):
     setUp()
 



More information about the Checkins mailing list