[Zope3-checkins] SVN: Zope3/trunk/src/zope/ Merged from ZopeX3-3.0
branch:
Jim Fulton
jim at zope.com
Fri Aug 27 20:59:05 EDT 2004
Log message for revision 27322:
Merged from ZopeX3-3.0 branch:
r27321 | jim | 2004-08-27 20:43:53 -0400 (Fri, 27 Aug 2004) | 2 lines
Changed to import removeSecurityProxy from zope.security.proxy
------------------------------------------------------------------------
r27320 | jim | 2004-08-27 20:43:51 -0400 (Fri, 27 Aug 2004) | 4 lines
Changed so that removeAllProxies is no-longer needed.
Updated README.txt to test handling of faults.
------------------------------------------------------------------------
r27319 | jim | 2004-08-27 20:43:49 -0400 (Fri, 27 Aug 2004) | 3 lines
Removed unneeded removeAllProxies call. I'm pretty sure it was
unneeded. No tests failed. ;)
------------------------------------------------------------------------
r27318 | jim | 2004-08-27 20:43:48 -0400 (Fri, 27 Aug 2004) | 2 lines
Moved the proxy-aware isinstance to zope.security.proxy
Changed:
U Zope3/trunk/src/zope/app/apidoc/classmodule/browser.py
U Zope3/trunk/src/zope/app/apidoc/ifacemodule/browser.py
U Zope3/trunk/src/zope/app/apidoc/ifacemodule/menu.py
U Zope3/trunk/src/zope/app/apidoc/utilities.py
U Zope3/trunk/src/zope/app/apidoc/zcmlmodule/browser.py
U Zope3/trunk/src/zope/app/i18n/xmlrpc/methods.py
U Zope3/trunk/src/zope/app/publisher/xmlrpc/README.txt
U Zope3/trunk/src/zope/app/publisher/xmlrpc/configure.zcml
U Zope3/trunk/src/zope/app/zapi/__init__.py
D Zope3/trunk/src/zope/app/zapi/tests.py
A Zope3/trunk/src/zope/publisher/tests/test_xmlrpc.py
U Zope3/trunk/src/zope/publisher/xmlrpc.py
U Zope3/trunk/src/zope/security/proxy.py
U Zope3/trunk/src/zope/security/tests/test_proxy.py
-=-
Modified: Zope3/trunk/src/zope/app/apidoc/classmodule/browser.py
===================================================================
--- Zope3/trunk/src/zope/app/apidoc/classmodule/browser.py 2004-08-28 00:43:53 UTC (rev 27321)
+++ Zope3/trunk/src/zope/app/apidoc/classmodule/browser.py 2004-08-28 00:59:04 UTC (rev 27322)
@@ -31,6 +31,7 @@
from zope.interface.interface import InterfaceClass
from zope.proxy import removeAllProxies
from zope.schema import getFieldsInOrder
+from zope.security.proxy import removeSecurityProxy
import zope.app
from zope.app import zapi
@@ -134,7 +135,7 @@
self.request = request
# TODO: This is not the best way to do this. We really need to revisit
# the entire implementation and move more to the ZCMLFile object.
- package = zapi.removeSecurityProxy(
+ package = removeSecurityProxy(
zapi.getParent(context))._Module__module
# Keep track of the package that is used for relative paths
self._package_stack = [package]
@@ -557,7 +558,7 @@
# we have to remove the security wrapper to get to the API calls.
checker = self.context.getSecurityChecker()
entry.update(
- getPermissionIds(name, zapi.removeSecurityProxy(checker)))
+ getPermissionIds(name, removeSecurityProxy(checker)))
attrs.append(entry)
return attrs
@@ -597,7 +598,7 @@
#
# `getPermissionIds()` also expects the class's security checker not
# to be proxied.
- klass = zapi.removeSecurityProxy(self.context)
+ klass = removeSecurityProxy(self.context)
for name, attr, iface in klass.getMethods():
entry = {'name': name,
'signature': getFunctionSignature(attr),
@@ -719,7 +720,7 @@
crumbs = []
module = self.context
# I really need the class here, so remove the proxy.
- while zapi.removeSecurityProxy(module).__class__ is Module:
+ while removeSecurityProxy(module).__class__ is Module:
crumbs.append(
{'name': zapi.name(module),
'url': zapi.getView(module, 'absolute_url', self.request)()}
Modified: Zope3/trunk/src/zope/app/apidoc/ifacemodule/browser.py
===================================================================
--- Zope3/trunk/src/zope/app/apidoc/ifacemodule/browser.py 2004-08-28 00:43:53 UTC (rev 27321)
+++ Zope3/trunk/src/zope/app/apidoc/ifacemodule/browser.py 2004-08-28 00:59:04 UTC (rev 27322)
@@ -23,6 +23,7 @@
from zope.interface.interfaces import IMethod, IInterface
from zope.proxy import removeAllProxies
from zope.schema.interfaces import IField
+from zope.security.proxy import removeSecurityProxy
from zope.app import zapi
from zope.app.i18n import ZopeMessageIDFactory as _
@@ -233,20 +234,20 @@
return zapi.name(self.context)
def getDoc(self):
- """Return the main documentation string of the interface.
+ r"""Return the main documentation string of the interface.
Example::
>>> from tests import getInterfaceDetails
>>> details = getInterfaceDetails()
- >>> details.getDoc()[:34]
- '<h1>This is the Foo interface</h1>'
+ >>> details.getDoc()[:55]
+ '<div class="document">\n<p>This is the Foo interface</p>'
"""
# We must remove all proxies here, so that we get the context's
# __module__ attribute. If we only remove security proxies, the
# location proxy's module will be returned.
return renderText(self.context.__doc__,
- removeAllProxies(self.context).__module__)
+ removeSecurityProxy(self.context).__module__)
def getBases(self):
"""Get all bases of this class
@@ -431,7 +432,7 @@
service = zapi.getService('Adapters')
# Must remove security proxies, so that we have access to the API
# methods.
- iface = zapi.removeSecurityProxy(self.context)
+ iface = removeSecurityProxy(self.context)
adapters = []
for reg in service.registrations():
# Only grab the adapters for which this interface is required
Modified: Zope3/trunk/src/zope/app/apidoc/ifacemodule/menu.py
===================================================================
--- Zope3/trunk/src/zope/app/apidoc/ifacemodule/menu.py 2004-08-28 00:43:53 UTC (rev 27321)
+++ Zope3/trunk/src/zope/app/apidoc/ifacemodule/menu.py 2004-08-28 00:59:04 UTC (rev 27322)
@@ -22,6 +22,7 @@
__docformat__ = 'restructuredtext'
from zope.interface import implements
+from zope.security.proxy import removeSecurityProxy
from zope.app import zapi
from zope.app.location.interfaces import ILocation
@@ -113,7 +114,7 @@
def getChildObjects(self):
"""See zope.app.tree.interfaces.IChildObject"""
objects = {}
- names = zapi.removeSecurityProxy(self.context.keys())
+ names = removeSecurityProxy(self.context.keys())
names.sort()
for name in names:
# Split these long names and make part of the module path separate
Modified: Zope3/trunk/src/zope/app/apidoc/utilities.py
===================================================================
--- Zope3/trunk/src/zope/app/apidoc/utilities.py 2004-08-28 00:43:53 UTC (rev 27321)
+++ Zope3/trunk/src/zope/app/apidoc/utilities.py 2004-08-28 00:59:04 UTC (rev 27322)
@@ -28,6 +28,7 @@
from zope.publisher.browser import TestRequest
from zope.security.checker import getCheckerForInstancesOf, Global
from zope.security.interfaces import INameBasedChecker
+from zope.security.proxy import removeSecurityProxy
from zope.app import zapi
from zope.app.i18n import ZopeMessageIDFactory as _
@@ -157,7 +158,7 @@
# Even for methods `im_class` and `__module__` is not allowed to be
# accessed (which is probably not a bad idea). So, we remove the security
# proxies for this check.
- naked = zapi.removeSecurityProxy(obj)
+ naked = removeSecurityProxy(obj)
if hasattr(naked, "im_class"):
naked = naked.im_class
module = naked.__module__
Modified: Zope3/trunk/src/zope/app/apidoc/zcmlmodule/browser.py
===================================================================
--- Zope3/trunk/src/zope/app/apidoc/zcmlmodule/browser.py 2004-08-28 00:43:53 UTC (rev 27321)
+++ Zope3/trunk/src/zope/app/apidoc/zcmlmodule/browser.py 2004-08-28 00:59:04 UTC (rev 27322)
@@ -18,6 +18,7 @@
__docformat__ = 'restructuredtext'
from zope.configuration.xmlconfig import ParserInfo
+from zope.security.proxy import removeSecurityProxy
from zope.app import zapi
from zope.app.location import LocationProxy
@@ -167,7 +168,7 @@
# ZCML directive `info` objects do not have security declarations, so
# everything is forbidden by default. We need to remove the security
# proxies in order to get to the data.
- info = zapi.removeSecurityProxy(self.context.info)
+ info = removeSecurityProxy(self.context.info)
if zapi.isinstance(info, ParserInfo):
return {'file': relativizePath(info.file),
'line': info.line,
Modified: Zope3/trunk/src/zope/app/i18n/xmlrpc/methods.py
===================================================================
--- Zope3/trunk/src/zope/app/i18n/xmlrpc/methods.py 2004-08-28 00:43:53 UTC (rev 27321)
+++ Zope3/trunk/src/zope/app/i18n/xmlrpc/methods.py 2004-08-28 00:59:04 UTC (rev 27322)
@@ -17,10 +17,8 @@
"""
__docformat__ = 'restructuredtext'
-from zope.proxy import removeAllProxies
from zope.app.publisher.xmlrpc import XMLRPCView
-
class Methods(XMLRPCView):
def getAllLanguages(self):
@@ -30,6 +28,6 @@
messages = []
for msg in self.context.getMessages():
if msg['language'] in languages:
- messages.append(removeAllProxies(msg))
+ messages.append(msg)
return messages
Modified: Zope3/trunk/src/zope/app/publisher/xmlrpc/README.txt
===================================================================
--- Zope3/trunk/src/zope/app/publisher/xmlrpc/README.txt 2004-08-28 00:43:53 UTC (rev 27321)
+++ Zope3/trunk/src/zope/app/publisher/xmlrpc/README.txt 2004-08-28 00:59:04 UTC (rev 27322)
@@ -1,6 +1,9 @@
XML-RPC views
=============
+XML-RPC Methods
+---------------
+
There are two ways to write XML-RPV views. You can write views that
provide "methods" for other objects, and you can write views that have
their own methods. Let's look at the former case first, since it's a
@@ -45,8 +48,7 @@
... Content-Length: 73
... Content-Type: application/x-www-form-urlencoded
...
- ... type_name=zope.app.browser.add.zope.app.folder.folder.Folder&new_value=f1"""
- ... , handle_errors=False)
+ ... type_name=zope.app.browser.add.zope.app.folder.folder.Folder&new_value=f1""")
HTTP/1.1 303 See Other
...
@@ -123,6 +125,8 @@
</methodResponse>
<BLANKLINE>
+Named XM-RPC Views
+------------------
Now let's look at views that have their own methods or other
subobjects. Views that have their own methods have names that appear
@@ -194,7 +198,7 @@
... <params>
... </params>
... </methodCall>
- ... """, handle_errors=False)
+ ... """)
HTTP/1.0 200 Ok
Content-Length: 208
Content-Type: text/xml;charset=utf-8
@@ -240,3 +244,78 @@
</params>
</methodResponse>
<BLANKLINE>
+
+Faults
+------
+
+If you need to raise an error, the prefered way to do it is via an
+`xmlrpclib.Fault`:
+
+ >>> import xmlrpclib
+
+ >>> class FaultDemo:
+ ... def __init__(self, context, request):
+ ... self.context = context
+ ... self.request = request
+ ...
+ ... def your_fault(self):
+ ... return xmlrpclib.Fault(42, "It's your fault!")
+
+Now we'll register it as a view:
+
+ >>> from zope.configuration import xmlconfig
+ >>> ignored = xmlconfig.string("""
+ ... <configure
+ ... xmlns="http://namespaces.zope.org/zope"
+ ... xmlns:xmlrpc="http://namespaces.zope.org/xmlrpc"
+ ... >
+ ... <!-- We only need to do this include in this example,
+ ... Normally the include has already been done for us. -->
+ ... <include package="zope.app.publisher.xmlrpc" file="meta.zcml" />
+ ...
+ ... <xmlrpc:view
+ ... for="zope.app.folder.folder.IFolder"
+ ... methods="your_fault"
+ ... class="zope.app.publisher.xmlrpc.README.FaultDemo"
+ ... permission="zope.ManageContent"
+ ... />
+ ... </configure>
+ ... """)
+
+Now, when we call it, we get a proper XML-RPC fault:
+
+ >>> print http(r"""
+ ... POST / HTTP/1.0
+ ... Authorization: Basic bWdyOm1ncnB3
+ ... Content-Length: 104
+ ... Content-Type: text/xml
+ ...
+ ... <?xml version='1.0'?>
+ ... <methodCall>
+ ... <methodName>your_fault</methodName>
+ ... <params>
+ ... </params>
+ ... </methodCall>
+ ... """, handle_errors=False)
+ HTTP/1.0 200 Ok
+ Content-Length: 272
+ Content-Type: text/xml;charset=utf-8
+ <BLANKLINE>
+ <?xml version='1.0'?>
+ <methodResponse>
+ <fault>
+ <value><struct>
+ <member>
+ <name>faultCode</name>
+ <value><int>42</int></value>
+ </member>
+ <member>
+ <name>faultString</name>
+ <value><string>It's your fault!</string></value>
+ </member>
+ </struct></value>
+ </fault>
+ </methodResponse>
+ <BLANKLINE>
+
+
Modified: Zope3/trunk/src/zope/app/publisher/xmlrpc/configure.zcml
===================================================================
--- Zope3/trunk/src/zope/app/publisher/xmlrpc/configure.zcml 2004-08-28 00:43:53 UTC (rev 27321)
+++ Zope3/trunk/src/zope/app/publisher/xmlrpc/configure.zcml 2004-08-28 00:59:04 UTC (rev 27322)
@@ -3,6 +3,10 @@
xmlns:xmlrpc="http://namespaces.zope.org/xmlrpc"
>
+ <class class="xmlrpclib.Fault">
+ <require permission="zope.Public" attributes="faultCode faultString" />
+ </class>
+
<view
for="zope.interface.Interface"
type="zope.publisher.interfaces.xmlrpc.IXMLRPCRequest"
Modified: Zope3/trunk/src/zope/app/zapi/__init__.py
===================================================================
--- Zope3/trunk/src/zope/app/zapi/__init__.py 2004-08-28 00:43:53 UTC (rev 27321)
+++ Zope3/trunk/src/zope/app/zapi/__init__.py 2004-08-28 00:59:04 UTC (rev 27322)
@@ -21,7 +21,7 @@
from interfaces import IZAPI
from zope.interface import moduleProvides
-from zope.security.proxy import removeSecurityProxy
+from zope.security.proxy import isinstance
from zope.app import servicenames
from zope.app.interface import queryType
@@ -36,38 +36,3 @@
from zope.app.exception.interfaces import UserError
name = getName
-
-builtin_isinstance = isinstance
-def isinstance(object, cls):
- """Test whether an object is an instance of a type.
-
- This works even if the object is security proxied:
-
- >>> class C1(object):
- ... pass
-
- >>> c = C1()
- >>> isinstance(c, C1)
- True
-
- >>> from zope.security.checker import ProxyFactory
- >>> isinstance(ProxyFactory(c), C1)
- True
-
- >>> class C2(C1):
- ... pass
-
- >>> c = C2()
- >>> isinstance(c, C1)
- True
-
- >>> from zope.security.checker import ProxyFactory
- >>> isinstance(ProxyFactory(c), C1)
- True
-
- """
-
- # The removeSecurityProxy call is OK here because it is *only*
- # being used for isinstance
-
- return builtin_isinstance(removeSecurityProxy(object), cls)
Deleted: Zope3/trunk/src/zope/app/zapi/tests.py
===================================================================
--- Zope3/trunk/src/zope/app/zapi/tests.py 2004-08-28 00:43:53 UTC (rev 27321)
+++ Zope3/trunk/src/zope/app/zapi/tests.py 2004-08-28 00:59:04 UTC (rev 27322)
@@ -1,28 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2004 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.0 (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.
-#
-##############################################################################
-"""Test zapi-provided implementation
-
-$Id$
-"""
-import unittest
-from zope.testing.doctestunit import DocTestSuite
-
-def test_suite():
- return unittest.TestSuite((
- DocTestSuite('zope.app.zapi.__init__'),
- ))
-
-if __name__ == '__main__':
- unittest.main(defaultTest='test_suite')
-
Copied: Zope3/trunk/src/zope/publisher/tests/test_xmlrpc.py (from rev 27321, Zope3/branches/ZopeX3-3.0/src/zope/publisher/tests/test_xmlrpc.py)
Property changes on: Zope3/trunk/src/zope/publisher/tests/test_xmlrpc.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Modified: Zope3/trunk/src/zope/publisher/xmlrpc.py
===================================================================
--- Zope3/trunk/src/zope/publisher/xmlrpc.py 2004-08-28 00:43:53 UTC (rev 27321)
+++ Zope3/trunk/src/zope/publisher/xmlrpc.py 2004-08-28 00:59:04 UTC (rev 27322)
@@ -26,8 +26,9 @@
from zope.publisher.interfaces.xmlrpc import IXMLRPCRequest
from zope.publisher.http import HTTPRequest, HTTPResponse
-from zope.proxy import removeAllProxies
+from zope.security.proxy import isinstance
+
class XMLRPCRequest(HTTPRequest):
implements(IXMLRPCRequest)
@@ -93,18 +94,17 @@
If is_error is true then the HTML will be formatted as a Zope error
message instead of a generic HTML page.
"""
- body = removeAllProxies(body)
+ body = premarshal(body)
if isinstance(body, xmlrpclib.Fault):
# Convert Fault object to XML-RPC response.
- body = xmlrpclib.dumps(body, methodresponse=1)
+ body = xmlrpclib.dumps(body, methodresponse=True)
else:
# Marshall our body as an XML-RPC response. Strings will be sent
# strings, integers as integers, etc. We do *not* convert
# everything to a string first.
- if body is None:
- body = xmlrpclib.False # Argh, XML-RPC doesn't handle null
try:
- body = xmlrpclib.dumps((body,), methodresponse=1)
+ body = xmlrpclib.dumps((body,), methodresponse=True,
+ allow_none=True)
except:
# We really want to catch all exceptions at this point!
self.handleException(sys.exc_info())
@@ -143,3 +143,83 @@
# Do the damage.
self.setBody(fault_text)
self.setStatus(200)
+
+
+def premarshal_dict(data):
+ return dict([(premarshal(k), premarshal(v))
+ for (k, v) in data.items()])
+
+def premarshal_list(data):
+ return map(premarshal, data)
+
+def premarshal_fault(data):
+ return xmlrpclib.Fault(
+ premarshal(data.faultCode),
+ premarshal(data.faultString),
+ )
+
+premarshal_dispatch_table = {
+ dict: premarshal_dict,
+ list: premarshal_list,
+ tuple: premarshal_list,
+ xmlrpclib.Fault: premarshal_fault,
+ }
+premarshal_dispatch = premarshal_dispatch_table.get
+
+def premarshal(data):
+ """Premarshal data before handing it to xmlrpclib for marhalling
+
+ The initial putpuse of this function is to remove security proxies
+ without resorting to removeSecurityProxy. This way, we can avoid
+ inadvertently providing access to data that should be protected.
+
+ Suppose we have a sample data structure:
+
+ >>> sample = {'foo': (1, ['x', 'y', 1.2])}
+
+ if we put the sample in a security procy:
+
+ >>> from zope.security.checker import ProxyFactory
+ >>> proxied_sample = ProxyFactory(sample)
+
+ We can still get to the data, but the non-rock data is proxied:
+
+ >>> from zope.security.proxy import Proxy
+ >>> proxied_sample['foo']
+ (1, ['x', 'y', 1.2])
+
+ >>> type(proxied_sample['foo']) is Proxy
+ True
+ >>> type(proxied_sample['foo'][1]) is Proxy
+ True
+
+ But we can strip the proxies using premarshal:
+
+ >>> stripped = premarshal(proxied_sample)
+ >>> stripped
+ {'foo': [1, ['x', 'y', 1.2]]}
+
+ >>> type(stripped['foo']) is Proxy
+ False
+ >>> type(stripped['foo'][1]) is Proxy
+ False
+
+ So xmlrpclib will be happy. :)
+
+ We can also use premarshal to strip proxies off of Fault objects.
+ We have to make a security declaration first though:
+
+ >>> from zope.security.checker import NamesChecker, defineChecker
+ >>> defineChecker(xmlrpclib.Fault,
+ ... NamesChecker(['faultCode', 'faultString']))
+
+ >>> fault = xmlrpclib.Fault(1, 'waaa')
+ >>> proxied_fault = ProxyFactory(fault)
+ >>> stripped_fault = premarshal(proxied_fault)
+ >>> type(stripped_fault) is Proxy
+ False
+ """
+ premarshaller = premarshal_dispatch(data.__class__)
+ if premarshaller is not None:
+ return premarshaller(data)
+ return data
Modified: Zope3/trunk/src/zope/security/proxy.py
===================================================================
--- Zope3/trunk/src/zope/security/proxy.py 2004-08-28 00:43:53 UTC (rev 27321)
+++ Zope3/trunk/src/zope/security/proxy.py 2004-08-28 00:59:04 UTC (rev 27322)
@@ -54,3 +54,39 @@
items = checker.get_permissions.items()
items.sort()
return items
+
+
+builtin_isinstance = isinstance
+def isinstance(object, cls):
+ """Test whether an object is an instance of a type.
+
+ This works even if the object is security proxied:
+
+ >>> class C1(object):
+ ... pass
+
+ >>> c = C1()
+ >>> isinstance(c, C1)
+ True
+
+ >>> from zope.security.checker import ProxyFactory
+ >>> isinstance(ProxyFactory(c), C1)
+ True
+
+ >>> class C2(C1):
+ ... pass
+
+ >>> c = C2()
+ >>> isinstance(c, C1)
+ True
+
+ >>> from zope.security.checker import ProxyFactory
+ >>> isinstance(ProxyFactory(c), C1)
+ True
+
+ """
+
+ # The removeSecurityProxy call is OK here because it is *only*
+ # being used for isinstance
+
+ return builtin_isinstance(removeSecurityProxy(object), cls)
Modified: Zope3/trunk/src/zope/security/tests/test_proxy.py
===================================================================
--- Zope3/trunk/src/zope/security/tests/test_proxy.py 2004-08-28 00:43:53 UTC (rev 27321)
+++ Zope3/trunk/src/zope/security/tests/test_proxy.py 2004-08-28 00:59:04 UTC (rev 27322)
@@ -436,6 +436,7 @@
suite = unittest.makeSuite(ProxyTests)
from doctest import DocTestSuite
suite.addTest(DocTestSuite())
+ suite.addTest(DocTestSuite('zope.security.proxy'))
return suite
if __name__=='__main__':
More information about the Zope3-Checkins
mailing list