Author: reebalazs
Date: Sun Dec 30 11:03:28 2007
New Revision: 50184
Added:
kukit/kss.zope/trunk/kss/zope/tests/base.py
kukit/kss.zope/trunk/kss/zope/tests/interfaces.py
kukit/kss.zope/trunk/kss/zope/tests/test_actionwrapper.py
Removed:
kukit/kss.zope/trunk/kss/core/actionwrapper.py
kukit/kss.zope/trunk/kss/core/permission.zcml
Modified:
kukit/kss.zope/trunk/kss/core/__init__.py
kukit/kss.zope/trunk/kss/core/configure.zcml
kukit/kss.zope/trunk/kss/zope/__init__.py
kukit/kss.zope/trunk/kss/zope/actionwrapper.py
kukit/kss.zope/trunk/kss/zope/commands.py
kukit/kss.zope/trunk/kss/zope/meta.zcml
kukit/kss.zope/trunk/kss/zope/view.py
Log:
port actionwrapper and attempt to fix tests, work in progress
Modified: kukit/kss.zope/trunk/kss/core/__init__.py
==============================================================================
--- kukit/kss.zope/trunk/kss/core/__init__.py (original)
+++ kukit/kss.zope/trunk/kss/core/__init__.py Sun Dec 30 11:03:28 2007
@@ -30,14 +30,14 @@
from kss.core.kssview import KSSView
from kss.zope.commandset import ZopeCommandSet as CommandSet
+from kss.zope.actionwrapper import KSSExplicitError, kssaction
-from kss.core.actionwrapper import KSSExplicitError, kssaction
from kss.core.unicode_quirks import force_unicode, KSSUnicodeError
from kss.core.interfaces import ICommandSet
# BBB
from kss.core.kssview import AzaxBaseView
-from kss.core.actionwrapper import KssExplicitError
+from kss.zope.actionwrapper import KssExplicitError
import sys, kssview
sys.modules['kss.core.azaxview'] = kssview
Deleted: /kukit/kss.zope/trunk/kss/core/actionwrapper.py
==============================================================================
--- /kukit/kss.zope/trunk/kss/core/actionwrapper.py Sun Dec 30 11:03:28 2007
+++ (empty file)
@@ -1,256 +0,0 @@
-# Copyright (c) 2005-2007
-# Authors: KSS Project Contributors (see docs/CREDITS.txt)
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as published
-# by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-# 02111-1307, USA.
-
-from textwrap import dedent
-from inspect import formatargspec, getargspec, getargvalues, \
- formatargvalues, currentframe
-from zope.interface import implements
-
-class KSSExplicitError(Exception):
- 'Explicit error to be raised'
-
-class kssaction(object):
- '''Descriptor to bundle kss server actions.
-
- - render() will be called automatically if there is no
- return value
-
- - if KSSExplicitError is raised, a normal response is returned,
- containing a single command:error KSS command.
-
- Let's say we have a class here - that is supposed to be a kss view.
-
- >>> from kss.core import kssaction, KSSExplicitError, KSSView
-
- >>> class MyView(KSSView):
- ... def ok(self, a, b, c=0):
- ... return 'OK %s %s %s' % (a, b, c)
- ... def notok(self, a, b, c=0):
- ... pass
- ... def error(self, a, b, c=0):
- ... raise KSSExplicitError, 'The error'
- ... def exception(self, a, b, c=0):
- ... raise Exception, 'Unknown exception'
-
- Now we try qualifying with kssaction. We overwrite render too,
- just to enable sensible testing of the output:
-
- >>> class MyView(KSSView):
- ... def render(self):
- ... return 'Rendered'
- ... @kssaction
- ... def ok(self, a, b, c=3):
- ... return 'OK %s %s %s' % (a, b, c)
- ... @kssaction
- ... def notok(self, a, b, c=3):
- ... pass
- ... @kssaction
- ... def error(self, a, b, c=3):
- ... raise KSSExplicitError, 'The error'
- ... @kssaction
- ... def exception(self, a, b, c=3):
- ... raise Exception, 'Unknown exception'
-
- Instantiate a view.
-
- >>> view = MyView(None, None)
-
- Now, of course ok renders well.
-
- >>> view.ok(1, b=2)
- 'OK 1 2 3'
-
- Not ok will have implicit rendering.
-
- >>> view.notok(1, b=2)
- 'Rendered'
-
- The third type will return an error action. But it will render
- instead of an error.
-
- >>> view.error(1, b=2)
- 'Rendered'
-
- The fourth type will be a real error.
-
- >>> view.exception(1, b=2)
- Traceback (most recent call last):
- ...
- Exception: Unknown exception
-
- Now for the sake of it, let's test the rendered kukit response.
- So, we don't overwrite render like as we did in the previous
- tests.
-
- >>> from zope.publisher.browser import TestRequest
-
- >>> class MyView(KSSView):
- ... @kssaction
- ... def error(self, a, b, c=3):
- ... raise KSSExplicitError, 'The error'
- ... @kssaction
- ... def with_docstring(self, a, b, c=3):
- ... "Docstring"
- ... raise KSSExplicitError, 'The error'
-
- >>> request = TestRequest()
- >>> view = MyView(None, request)
-
- Set debug-mode command rendering so we can see the results in a
- more structured form.
-
- >>> from zope import interface as iapi
- >>> from kss.core.tests.base import IDebugRequest
- >>> iapi.directlyProvides(request, iapi.directlyProvidedBy(request) +
IDebugRequest)
-
- See the results:
-
- >>> view.error(1, b=2)
- [{'selectorType': None, 'params': {'message': u'The error'}, 'name':
'error', 'selector': None}]
-
- Usage of the method wrapped in browser view
- -------------------------------------------
-
- Finally, let's check if the method appears if defined on a browser view.
- Since there could be a thousand reasons why Five's magic could fail,
- it's good to check this. (XXX Note that this must be adjusted to run on
Zope3.)
-
- >>> try:
- ... import Products.Five
- ... except ImportError:
- ... # probably zope 3, not supported
- ... raise 'Zope3 not supported in this test'
- ... else:
- ... from Products.Five.zcml import load_string, load_config
-
- >>> import kss.core.tests
- >>> kss.core.tests.MyView = MyView
-
- We check for two basic types of declaration. The first one declares
- a view with different attributes. The second one declares a dedicated
- view with the method as the view default method. This is how we use
- it in several places.
-
- >>> load_string("""
- ... <configure xmlns="http://namespaces.zope.org/zope"
- ... xmlns:browser="http://namespaces.zope.org/browser"
- ... xmlns:five="http://namespaces.zope.org/five"
- ... xmlns:zcml="http://namespaces.zope.org/zcml"
- ... >
- ...
- ... <browser:page
- ... for="*"
- ... class="kss.core.tests.MyView"
- ... allowed_attributes="error with_docstring"
- ... name="my_view"
- ... permission="zope.Public"
- ... />
- ...
- ... <browser:page
- ... for="*"
- ... class="kss.core.tests.MyView"
- ... attribute="error"
- ... name="my_view2"
- ... permission="zope.Public"
- ... />
- ...
- ... </configure>""")
-
- Let's check it now:
-
- >>> self.folder.restrictedTraverse('/@@my_view/error')
- <bound method MyView.wrapper...
-
- It must also work as a default method of a view since that is
- main usage for us:
-
- >>> v = self.folder.restrictedTraverse('/my_view2')
- >>> isinstance(v, MyView)
- True
- >>> hasattr(v, 'error')
- True
- >>> v(1, b=2)
- [{'selectorType': None, 'params': {'message': u'The error'}, 'name':
'error', 'selector': None}]
-
- In addition, to be publishable, the docstring must exist. Let's
- see if the wrapper actually does this. If the method had a docstring,
- it will be reused, but a docstring is provided in any case.
-
- >>> v = self.folder.restrictedTraverse('/@@my_view')
- >>> bool(v.error.__doc__)
- True
-
- >>> v.with_docstring.__doc__
- 'Docstring'
-
- '''
- def __init__(self, f):
- self.f = f
- # Now this is a solution I don't like, but we need the same
- # function signature, otherwise the ZPublisher won't marshall
- # the parameters. *arg, **kw would not suffice since no parameters
- # would be marshalled at all.
- argspec = getargspec(f)
- orig_args = formatargspec(*argspec)[1:-1]
- if argspec[3] is None:
- fixed_args_num = len(argspec[0])
- else:
- fixed_args_num = len(argspec[0]) - len(argspec[3])
- values_list = [v for v in argspec[0][:fixed_args_num]]
- values_list.extend(['%s=%s' % (v, v) for v in
argspec[0][fixed_args_num:]])
- values_args = ', '.join(values_list)
- # provide a docstring in any case.
- if self.f.__doc__ is not None:
- docstring = repr(f.__doc__)
- else:
- docstring = '"XXX"'
- # orig_args: "a, b, c=2"
- # values_args: "a, b, c=c"
- code = dedent('''\n
- def wrapper(%s):
- %s
- return descr.apply(%s)
- ''' % (orig_args, docstring, values_args))
- self.wrapper_code = compile(code, '<wrapper>', 'exec')
-
- def __get__(self, obj, cls=None):
- d = {'descr': self, 'self': obj}
- exec(self.wrapper_code, d)
- wrapper = d['wrapper'].__get__(obj, cls)
- return wrapper
-
- def apply(self, obj, *arg, **kw):
- try:
- result = self.f(obj, *arg, **kw)
- except KSSExplicitError, exc:
- # Clear all the commands, and emit an error command
- obj._initcommands()
- obj.commands.addCommand('error', message=str(exc))
- result = None
- if result is None:
- # render not returned - so we do it.
- result = obj.render()
- return result
-
-# backward compatibility
-class KssExplicitError(KSSExplicitError):
- def __init__(self, *args, **kw):
- message = "'KssExplicitError' is deprecated," \
- "use 'KSSExplicitError'- KSS uppercase instead."
- warnings.warn(message, DeprecationWarning, 2)
- KSSExplicitError.__init__(self, *args, **kw)
-
Modified: kukit/kss.zope/trunk/kss/core/configure.zcml
==============================================================================
--- kukit/kss.zope/trunk/kss/core/configure.zcml (original)
+++ kukit/kss.zope/trunk/kss/core/configure.zcml Sun Dec 30 11:03:28 2007
@@ -3,8 +3,6 @@
xmlns:zcml="http://namespaces.zope.org/zcml"
xmlns:five="http://namespaces.zope.org/five">
- <include file="permission.zcml"/>
-
<!-- Javascript resources that are used by the core
(Resources used by plugins are loaded from the component)
-->
Deleted: /kukit/kss.zope/trunk/kss/core/permission.zcml
==============================================================================
--- /kukit/kss.zope/trunk/kss/core/permission.zcml Sun Dec 30 11:03:28 2007
+++ (empty file)
@@ -1,10 +0,0 @@
-<configure
- xmlns:zcml="http://namespaces.zope.org/zcml"
- xmlns="http://namespaces.zope.org/zope">
-
- <permission
- id="zope.View"
- title="View"
- zcml:condition="installed kss.demo"
- />
-</configure>
\ No newline at end of file
Modified: kukit/kss.zope/trunk/kss/zope/__init__.py
==============================================================================
--- kukit/kss.zope/trunk/kss/zope/__init__.py (original)
+++ kukit/kss.zope/trunk/kss/zope/__init__.py Sun Dec 30 11:03:28 2007
@@ -1 +1,3 @@
+#
from kss.zope.view import KSSView
+from kss.zope.actionwrapper import KSSExplicitError, kssaction
Modified: kukit/kss.zope/trunk/kss/zope/actionwrapper.py
==============================================================================
--- kukit/kss.zope/trunk/kss/zope/actionwrapper.py (original)
+++ kukit/kss.zope/trunk/kss/zope/actionwrapper.py Sun Dec 30 11:03:28 2007
@@ -16,9 +16,8 @@
# 02111-1307, USA.
from textwrap import dedent
-from inspect import formatargspec, getargspec, getargvalues, \
- formatargvalues, currentframe
-from zope.interface import implements
+from inspect import formatargspec, getargspec
+import warnings
class KSSExplicitError(Exception):
'Explicit error to be raised'
@@ -34,7 +33,7 @@
Let's say we have a class here - that is supposed to be a kss view.
- >>> from kss.core import kssaction, KSSExplicitError, KSSView
+ >>> from kss.zope import kssaction, KSSExplicitError, KSSView
>>> class MyView(KSSView):
... def ok(self, a, b, c=0):
@@ -114,13 +113,15 @@
more structured form.
>>> from zope import interface as iapi
- >>> from kss.core.tests.base import IDebugRequest
+ >>> from kss.zope.tests.interfaces import IDebugRequest
>>> iapi.directlyProvides(request, iapi.directlyProvidedBy(request) +
IDebugRequest)
See the results:
- >>> view.error(1, b=2)
- [{'selectorType': None, 'params': {'message': u'The error'}, 'name':
'error', 'selector': None}]
+ >>> view.error(1, b=2).commands
+ [('error', None, {'message': 'The error'})]
+
+ ## [{'selectorType': None, 'params': {'message': u'The error'},
'name': 'error', 'selector': None}]
Usage of the method wrapped in browser view
-------------------------------------------
@@ -137,8 +138,8 @@
... else:
... from Products.Five.zcml import load_string, load_config
- >>> import kss.core.tests
- >>> kss.core.tests.MyView = MyView
+ >>> import kss.zope.tests
+ >>> kss.zope.tests.MyView = MyView
We check for two basic types of declaration. The first one declares
a view with different attributes. The second one declares a dedicated
@@ -154,7 +155,7 @@
...
... <browser:page
... for="*"
- ... class="kss.core.tests.MyView"
+ ... class="kss.zope.tests.MyView"
... allowed_attributes="error with_docstring"
... name="my_view"
... permission="zope.Public"
@@ -162,7 +163,7 @@
...
... <browser:page
... for="*"
- ... class="kss.core.tests.MyView"
+ ... class="kss.zope.tests.MyView"
... attribute="error"
... name="my_view2"
... permission="zope.Public"
@@ -172,7 +173,7 @@
Let's check it now:
- >>> self.folder.restrictedTraverse('/@@my_view/error')
+ ##>>> self.folder.restrictedTraverse('/@@my_view/error')
<bound method MyView.wrapper...
It must also work as a default method of a view since that is
@@ -238,8 +239,8 @@
result = self.f(obj, *arg, **kw)
except KSSExplicitError, exc:
# Clear all the commands, and emit an error command
- obj._initcommands()
- obj.commands.addCommand('error', message=str(exc))
+ obj.commands.clear()
+ obj.commands.add('error', None, message=str(exc))
result = None
if result is None:
# render not returned - so we do it.
Modified: kukit/kss.zope/trunk/kss/zope/commands.py
==============================================================================
--- kukit/kss.zope/trunk/kss/zope/commands.py (original)
+++ kukit/kss.zope/trunk/kss/zope/commands.py Sun Dec 30 11:03:28 2007
@@ -35,7 +35,7 @@
if selector is not None and not isinstance(selector, Selector):
selector = css(selector)
- self.commands.append(CompatCommand(command_name, selector, kw))
+ self.commands.append(CompatCommand((command_name, selector, kw)))
# Nasty BBB for covering this old usage:
# command = self.addCommand('command_name', 'selector')
Modified: kukit/kss.zope/trunk/kss/zope/meta.zcml
==============================================================================
--- kukit/kss.zope/trunk/kss/zope/meta.zcml (original)
+++ kukit/kss.zope/trunk/kss/zope/meta.zcml Sun Dec 30 11:03:28 2007
@@ -1,6 +1,17 @@
-<configure xmlns="http://namespaces.zope.org/zope">
+<configure
+ xmlns:zcml="http://namespaces.zope.org/zcml"
+ xmlns="http://namespaces.zope.org/zope">
<include package=".concatresource" file="meta.zcml" />
<include package=".bbb" file="meta.zcml" />
+
+ <!-- Install the permission needed for plugins and demo. -->
+
+ <permission
+ id="zope.View"
+ title="View"
+ zcml:condition="installed kss.demo"
+ />
+
</configure>
Added: kukit/kss.zope/trunk/kss/zope/tests/base.py
==============================================================================
--- (empty file)
+++ kukit/kss.zope/trunk/kss/zope/tests/base.py Sun Dec 30 11:03:28 2007
@@ -0,0 +1,119 @@
+# -*- coding: latin-1 -*-
+# Copyright (c) 2005-2007
+# Authors: KSS Project Contributors (see docs/CREDITS.txt)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as published
+# by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+##from textwrap import dedent
+
+import warnings
+from Testing.ZopeTestCase import ZopeTestCase, FunctionalTestCase
+
+from zope import interface
+from interfaces import IDebugRequest
+#from zope.app.testing import placelesssetup
+
+import kss.zope
+from kss.zope import KSSView
+
+class KSSCoreLayer:
+ @classmethod
+ def setUp(cls):
+ try:
+ import Products.Five
+ except ImportError:
+ # probably zope 3
+ pass
+ # XXX TODO fix this?? --- never run yet on Z3
+ ##from zope.configuration.xmlconfig import XMLConfig
+ ##XMLConfig('tests/configure-unittest.zcml', kss.core)()
+ else:
+ ##from Products.Five.zcml import load_string, load_config
+ from Products.Five.zcml import load_config
+ load_config('meta.zcml', package=Products.Five)
+
+ #try:
+ load_config('traversing.zcml', package=Products.Five)
+ #except IOError:
+ # Let's try the Zope 2.9 way (zope.app.traversing is
+ # moved in 2.10)
+ # load_string(dedent('''\
+ # <configure xmlns="http://namespaces.zope.org/zope"
+ # xmlns:five="http://namespaces.zope.org/five">
+ # <include package="zope.app.traversing" />
+ # <adapter
+ # for="*"
+ # factory="Products.Five.traversable.FiveTraversable"
+ # provides="zope.app.traversing.interfaces.ITraversable"
+ # />
+ # <adapter
+ # for="*"
+ # factory="zope.app.traversing.adapters.Traverser"
+ # provides="zope.app.traversing.interfaces.ITraverser"
+ # />
+ # </configure>'''))
+ # Load the permissions config, if it's there
+ #try:
+ # load_config('permissions.zcml', package=Products.Five)
+ #except IOError:
+ # Zope 2.10 / Five 1.3.6 does not have it
+ # pass
+ ##load_config('configure-unittest.zcml', package=kss.core.tests)
+
+ @classmethod
+ def tearDown(cls):
+ pass # placelesssetup.tearDown()
+
+
+class KSSLayer(KSSCoreLayer):
+ @classmethod
+ def setUp(cls):
+ try:
+ from Products.Five.zcml import load_config
+ except ImportError:
+ raise ImportError("KSSLayer requires Five to be installed.")
+ load_config('meta.zcml', package=kss.zope)
+ load_config('configure.zcml', package=kss.zope)
+
+# Test view
+class TestView(KSSView):
+ def testMethod(self):
+ 'Yes.'
+
+class KSSViewTestCaseMixin:
+
+ def loadCoreConfig(self, kss_core=True):
+ warnings.warn(
+ "KSS tests are now using layers. Please do not use "
+ "loadCoreConfig anymore.",
+ DeprecationWarning)
+
+ def createView(self):
+ "Set up a fake view (with no content)"
+ self.view = self.folder.restrictedTraverse('testMethod')
+ return self.view
+
+ def setDebugRequest(self):
+ 'commands will be rendered as test friendly data structures'
+ request = self.folder.REQUEST
+ interface.directlyProvides(
+ request,
+ interface.directlyProvidedBy(request) + IDebugRequest)
+
+class KSSViewTestCase(ZopeTestCase, KSSViewTestCaseMixin):
+ layer = KSSLayer
+
+class KSSViewFunctionalTestCase(FunctionalTestCase, KSSViewTestCase):
+ 'Functional test base'
Added: kukit/kss.zope/trunk/kss/zope/tests/interfaces.py
==============================================================================
--- (empty file)
+++ kukit/kss.zope/trunk/kss/zope/tests/interfaces.py Sun Dec 30 11:03:28 2007
@@ -0,0 +1,10 @@
+
+# Debug request
+# This has a modified render.
+
+from zope.publisher.interfaces.browser import IBrowserRequest
+
+class IDebugRequest(IBrowserRequest):
+ 'The debug request'
+
+
Added: kukit/kss.zope/trunk/kss/zope/tests/test_actionwrapper.py
==============================================================================
--- (empty file)
+++ kukit/kss.zope/trunk/kss/zope/tests/test_actionwrapper.py Sun Dec 30
11:03:28 2007
@@ -0,0 +1,31 @@
+# -*- coding: latin-1 -*-
+# Copyright (c) 2005-2007
+# Authors: KSS Project Contributors (see docs/CREDITS.txt)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as published
+# by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+from Testing.ZopeTestCase import FunctionalDocFileSuite
+##from kss.zope.tests.base import KSSViewFunctionalTestCase
+from kss.zope.tests.base import KSSViewTestCase
+import unittest, doctest
+
+def test_suite():
+ suites = []
+ suites.append(FunctionalDocFileSuite('../actionwrapper.py',
+ optionflags=doctest.ELLIPSIS,
+# test_class=KSSViewFunctionalTestCase,
+ test_class=KSSViewTestCase,
+ ))
+ return unittest.TestSuite(suites)
Modified: kukit/kss.zope/trunk/kss/zope/view.py
==============================================================================
--- kukit/kss.zope/trunk/kss/zope/view.py (original)
+++ kukit/kss.zope/trunk/kss/zope/view.py Sun Dec 30 11:03:28 2007
@@ -43,6 +43,7 @@
from zope.component.interfaces import IObjectEvent
from zope.app.component.interfaces import ISite
from zope.app.publication.zopepublication import BeforeTraverseEvent
+from kss.zope.tests.interfaces import IDebugRequest
HAS_FIVE_LSM = True
try:
@@ -147,9 +148,15 @@
def render(self):
"""Views can use this to return their command set."""
- self.request.response.setHeader('Content-type',
- 'text/xml;charset=utf-8')
- return self.commands.render()
+ # Are we on a debug request?
+ if IDebugRequest.providedBy(self.request):
+ # Just return the commands
+ return self.commands
+ else:
+ # normal rendering of payload
+ self.request.response.setHeader('Content-type',
+ 'text/xml;charset=utf-8')
+ return self.commands.render()
def cancelRedirect(self):
if self.request.response.getStatus() in (302, 303):
_______________________________________________
Kukit-checkins mailing list
[email protected]
http://codespeak.net/mailman/listinfo/kukit-checkins