[Checkins] SVN: grok/trunk/ Merge the jw-refer-to-permission-class
branch
Jan-Wijbrand Kolman
janwijbrand at gmail.com
Fri May 2 05:57:37 EDT 2008
Log message for revision 86068:
Merge the jw-refer-to-permission-class branch
Changed:
U grok/trunk/CHANGES.txt
U grok/trunk/src/grok/__init__.py
U grok/trunk/src/grok/components.py
U grok/trunk/src/grok/directive.py
U grok/trunk/src/grok/ftests/rest/rest.py
U grok/trunk/src/grok/ftests/security/require.py
U grok/trunk/src/grok/ftests/security/roles.py
U grok/trunk/src/grok/ftests/security/xmlrpc.py
U grok/trunk/src/grok/ftests/viewlet/viewlet_security.py
U grok/trunk/src/grok/interfaces.py
U grok/trunk/src/grok/tests/security/missing_permission_json3.py
U grok/trunk/src/grok/tests/security/missing_permission_xmlrpc3.py
U grok/trunk/src/grok/tests/security/multiple_require.py
U grok/trunk/src/grok/tests/security/multiple_require_json.py
U grok/trunk/src/grok/tests/security/multiple_require_xmlrpc.py
A grok/trunk/src/grok/tests/security/not_a_permissionclass.py
U grok/trunk/src/grok/tests/security/view_decorator.py
-=-
Modified: grok/trunk/CHANGES.txt
===================================================================
--- grok/trunk/CHANGES.txt 2008-05-02 09:54:50 UTC (rev 86067)
+++ grok/trunk/CHANGES.txt 2008-05-02 09:57:37 UTC (rev 86068)
@@ -7,16 +7,21 @@
Feature changes
---------------
+* grok.require() can refer to subclasses of grok.Permission directly, instead
+ of their id. This, for one, avoids making typos in permission ids. Permission
+ components *do* still need the grok.name() directive for defining the
+ permission's id.
+
* The basic component base classes (``Adapter``, ``MultiAdapter``,
``GlobalUtility``), their grokkers, as well as many of the basic
directives have been factored out to a reusable
``grokcore.component`` package.
* Added an optional parameter 'data' to the method 'url()' that accepts
- a dictionary that is then converted to a query string. See
-
+ a dictionary that is then converted to a query string. See
+
http://grok.zope.org/documentation/how-to/generate-urls-with-the-url-function-in-views/view
-
+
* Added an ``OrderedContainer`` component.
* Introduced the new `sphinx`-based documentation engine. See
Modified: grok/trunk/src/grok/__init__.py
===================================================================
--- grok/trunk/src/grok/__init__.py 2008-05-02 09:54:50 UTC (rev 86067)
+++ grok/trunk/src/grok/__init__.py 2008-05-02 09:57:37 UTC (rev 86068)
@@ -38,7 +38,7 @@
from grok.components import Site, LocalUtility, Annotation
from grok.components import Application, Form, AddForm, EditForm, DisplayForm
from grok.components import Indexes
-from grok.components import Permission, Role
+from grok.components import Permission, Role, Public
from grok.components import Skin, IGrokLayer
from grok.components import RESTProtocol, IRESTLayer
from grok.interfaces import IRESTSkinType
Modified: grok/trunk/src/grok/components.py
===================================================================
--- grok/trunk/src/grok/components.py 2008-05-02 09:54:50 UTC (rev 86067)
+++ grok/trunk/src/grok/components.py 2008-05-02 09:57:37 UTC (rev 86068)
@@ -192,7 +192,7 @@
def url(self, obj=None, name=None, data=None):
- """Return string for the URL based on the obj and name. The data
+ """Return string for the URL based on the obj and name. The data
argument is used to form a CGI query string.
"""
if isinstance(obj, basestring):
@@ -209,7 +209,7 @@
elif name is not None and obj is None:
# create URL to view on context
obj = self.context
-
+
if data is None:
data = {}
else:
@@ -635,6 +635,8 @@
class Permission(Permission):
pass
+Public = 'zope.Public'
+
class Role(Role):
pass
Modified: grok/trunk/src/grok/directive.py
===================================================================
--- grok/trunk/src/grok/directive.py 2008-05-02 09:54:50 UTC (rev 86067)
+++ grok/trunk/src/grok/directive.py 2008-05-02 09:57:37 UTC (rev 86068)
@@ -30,6 +30,7 @@
ClassOrModuleDirectiveContext)
from martian import util
from grokcore.component.directive import MultiValueOnceDirective
+from grok import components
class LocalUtilityDirective(MultipleTimesDirective):
def check_arguments(self, factory, provides=None, name=u'',
@@ -55,9 +56,20 @@
self.name_in_container = name_in_container
-class RequireDirective(BaseTextDirective, SingleValue, MultipleTimesDirective):
+class RequireDirective(SingleValue, MultipleTimesDirective):
+ def check_arguments(self, value):
+ if util.check_subclass(value, components.Permission):
+ return
+ if util.not_unicode_or_ascii(value):
+ raise GrokImportError(
+ "You can only pass unicode, ASCII, or a subclass "
+ "of grok.Permission %s." % self.name)
+
def store(self, frame, value):
+ if util.check_subclass(value, components.Permission):
+ value = getattr(value, '__grok_name__')
+
super(RequireDirective, self).store(frame, value)
values = frame.f_locals.get(self.local_name, [])
@@ -71,6 +83,7 @@
return func
return decorator
+
# Define grok directives
template = SingleTextDirective('grok.template', ClassDirectiveContext())
templatedir = SingleTextDirective('grok.templatedir', ModuleDirectiveContext())
Modified: grok/trunk/src/grok/ftests/rest/rest.py
===================================================================
--- grok/trunk/src/grok/ftests/rest/rest.py 2008-05-02 09:54:50 UTC (rev 86067)
+++ grok/trunk/src/grok/ftests/rest/rest.py 2008-05-02 09:57:37 UTC (rev 86068)
@@ -7,7 +7,7 @@
>>> root = getRootFolder()
>>> root['app'] = MyApp()
>>> root['app']['alpha'] = MyContent()
-
+
Issue a GET request::
>>> response = http_call('GET', 'http://localhost/++rest++a/app')
@@ -100,7 +100,7 @@
Traceback (most recent call last):
...
GrokMethodNotAllowed: <grok.ftests.rest.rest.MyApp object at ...
-
+
We have added support for GET for the ``alpha`` subobject only, in
the default rest layer::
@@ -133,10 +133,10 @@
Content-Length: 18
<BLANKLINE>
Method Not Allowed
-
+
>>> print http('POST /++rest++c/app HTTP/1.1')
HTTP/1. 405 Method Not Allowed
- Allow:
+ Allow:
Content-Length: 18
Content-Type: text/plain
<BLANKLINE>
@@ -233,7 +233,7 @@
<BLANKLINE>
We shouldn't be allowed to PUT either::
-
+
>>> print http('PUT /app/beta HTTP/1.1')
HTTP/1. 404 Not Found
Content-Length: 0
@@ -264,7 +264,7 @@
>>> response = http_call('PUT', 'http://localhost/++rest++g/app/two')
>>> print response.getBody()
PUT directly registered
-
+
We expect POST and DELETE to be the same on both. For the directly
registered object (two) it should fall back to the interface as there
is none more specifically declared::
@@ -301,7 +301,7 @@
class MyContent(grok.Model):
pass
-
+
class LayerA(grok.IRESTLayer):
pass
@@ -340,11 +340,11 @@
class G(grok.RESTProtocol):
grok.layer(LayerInterface)
-
+
class ARest(grok.REST):
grok.layer(LayerA)
grok.context(MyApp)
-
+
def GET(self):
return "GET"
@@ -360,7 +360,7 @@
class BRest(grok.REST):
grok.layer(LayerB)
grok.context(MyApp)
-
+
def GET(self):
return "GET"
@@ -373,15 +373,15 @@
class DRest(grok.REST):
grok.context(MyContent)
-
+
def GET(self):
return "GET2"
class SecurityRest(grok.REST):
grok.context(MyContent)
grok.layer(LayerSecurity)
-
- @grok.require('zope.Public')
+
+ @grok.require(grok.Public)
def GET(self):
return "GET3"
@@ -396,7 +396,7 @@
@grok.require('zope.ManageContent')
def DELETE(self):
return "DELETE3"
-
+
class BodyTest(grok.REST):
grok.context(MyContent)
grok.layer(LayerContent)
@@ -416,7 +416,7 @@
class InterfaceRest(grok.REST):
grok.context(IFoo)
grok.layer(LayerInterface)
-
+
def GET(self):
return "GET interface registered"
@@ -432,7 +432,7 @@
class NoInterfaceRest(grok.REST):
grok.context(MyNoInterfaceContent)
grok.layer(LayerInterface)
-
+
def GET(self):
return "GET directly registered"
Modified: grok/trunk/src/grok/ftests/security/require.py
===================================================================
--- grok/trunk/src/grok/ftests/security/require.py 2008-05-02 09:54:50 UTC (rev 86067)
+++ grok/trunk/src/grok/ftests/security/require.py 2008-05-02 09:57:37 UTC (rev 86068)
@@ -34,17 +34,15 @@
grok.name('cave.ViewPainting')
class Painting(grok.View):
-
grok.context(zope.interface.Interface)
- grok.require('cave.ViewPainting')
+ grok.require(ViewPainting)
def render(self):
return 'What a beautiful painting.'
class PublicNudity(grok.View):
-
grok.context(zope.interface.Interface)
- grok.require('zope.Public')
+ grok.require(grok.Public)
def render(self):
return 'Everybody can see this.'
Modified: grok/trunk/src/grok/ftests/security/roles.py
===================================================================
--- grok/trunk/src/grok/ftests/security/roles.py 2008-05-02 09:54:50 UTC (rev 86067)
+++ grok/trunk/src/grok/ftests/security/roles.py 2008-05-02 09:57:37 UTC (rev 86068)
@@ -46,16 +46,16 @@
import grok
import zope.interface
-class View(grok.Permission):
+class ViewPermission(grok.Permission):
grok.name('paint.ViewPainting')
-class Edit(grok.Permission):
+class EditPermission(grok.Permission):
grok.name('paint.EditPainting')
-class Erase(grok.Permission):
+class ErasePermission(grok.Permission):
grok.name('paint.ErasePainting')
-class Approve(grok.Permission):
+class ApprovePermission(grok.Permission):
grok.name('paint.ApprovePainting')
class PaintingOwner(grok.Role):
@@ -67,7 +67,7 @@
class CavePainting(grok.View):
grok.context(zope.interface.Interface)
- grok.require('paint.ViewPainting')
+ grok.require(ViewPermission)
def render(self):
return 'What a beautiful painting.'
@@ -75,7 +75,7 @@
class EditCavePainting(grok.View):
grok.context(zope.interface.Interface)
- grok.require('paint.EditPainting')
+ grok.require(EditPermission)
def render(self):
return 'Let\'s make it even prettier.'
@@ -83,7 +83,7 @@
class EraseCavePainting(grok.View):
grok.context(zope.interface.Interface)
- grok.require('paint.ErasePainting')
+ grok.require(ErasePermission)
def render(self):
return 'Oops, mistake, let\'s erase it.'
@@ -91,7 +91,7 @@
class ApproveCavePainting(grok.View):
grok.context(zope.interface.Interface)
- grok.require('paint.ApprovePainting')
+ grok.require(ApprovePermission)
def render(self):
return 'Painting owners cannot approve their paintings.'
Modified: grok/trunk/src/grok/ftests/security/xmlrpc.py
===================================================================
--- grok/trunk/src/grok/ftests/security/xmlrpc.py 2008-05-02 09:54:50 UTC (rev 86067)
+++ grok/trunk/src/grok/ftests/security/xmlrpc.py 2008-05-02 09:57:37 UTC (rev 86068)
@@ -15,7 +15,7 @@
With manager privileges, the protected method is accessible, however:
- >>> print mgr_server.dance()
+ >>> print mgr_server.dance()
Manfred doesn't like to dance.
The same applies when a default permission is defined for all XML-RPC
@@ -58,6 +58,6 @@
def eat(self):
return 'MMM, MANFRED TASTE GOOD!'
- @grok.require('zope.Public')
+ @grok.require(grok.Public)
def rest(self):
return 'ME GROK TIRED!'
Modified: grok/trunk/src/grok/ftests/viewlet/viewlet_security.py
===================================================================
--- grok/trunk/src/grok/ftests/viewlet/viewlet_security.py 2008-05-02 09:54:50 UTC (rev 86067)
+++ grok/trunk/src/grok/ftests/viewlet/viewlet_security.py 2008-05-02 09:57:37 UTC (rev 86068)
@@ -149,7 +149,7 @@
class GoldBone(grok.Viewlet):
grok.context(Interface)
grok.viewletmanager(Pot)
- grok.require('bone.gold')
+ grok.require(Gold)
def render(self):
return 'Gold Bone'
Modified: grok/trunk/src/grok/interfaces.py
===================================================================
--- grok/trunk/src/grok/interfaces.py 2008-05-02 09:54:50 UTC (rev 86067)
+++ grok/trunk/src/grok/interfaces.py 2008-05-02 09:57:37 UTC (rev 86068)
@@ -50,6 +50,9 @@
Skin = interface.Attribute("Base class for skin.")
ViewletManager = interface.Attribute("Base class for viewletmanager.")
Viewlet = interface.Attribute("Base class for viewlet.")
+ Permission = interface.Attribute("Base class for permissions.")
+ Role = interface.Attribute("Base class for roles.")
+ Public = interface.Attribute("Marker for explicitly not requiring a permission.")
class IGrokErrors(interface.Interface):
@@ -308,8 +311,8 @@
If both object and name arguments are supplied, construct
URL to obj/name.
-
- Optionally pass a 'data' keyword argument which gets added to the URL
+
+ Optionally pass a 'data' keyword argument which gets added to the URL
as a cgi query string.
"""
Modified: grok/trunk/src/grok/tests/security/missing_permission_json3.py
===================================================================
--- grok/trunk/src/grok/tests/security/missing_permission_json3.py 2008-05-02 09:54:50 UTC (rev 86067)
+++ grok/trunk/src/grok/tests/security/missing_permission_json3.py 2008-05-02 09:57:37 UTC (rev 86068)
@@ -20,8 +20,8 @@
grok.context(zope.interface.Interface)
grok.require('doesnt.exist')
-
- @grok.require('json.exists')
+
+ @grok.require(Permission)
def foo(self):
pass
Modified: grok/trunk/src/grok/tests/security/missing_permission_xmlrpc3.py
===================================================================
--- grok/trunk/src/grok/tests/security/missing_permission_xmlrpc3.py 2008-05-02 09:54:50 UTC (rev 86067)
+++ grok/trunk/src/grok/tests/security/missing_permission_xmlrpc3.py 2008-05-02 09:57:37 UTC (rev 86068)
@@ -21,6 +21,6 @@
grok.context(zope.interface.Interface)
grok.require('doesnt.exist')
- @grok.require('foo')
+ @grok.require(Foo)
def foo(self):
pass
Modified: grok/trunk/src/grok/tests/security/multiple_require.py
===================================================================
--- grok/trunk/src/grok/tests/security/multiple_require.py 2008-05-02 09:54:50 UTC (rev 86067)
+++ grok/trunk/src/grok/tests/security/multiple_require.py 2008-05-02 09:57:37 UTC (rev 86068)
@@ -18,8 +18,8 @@
class MultipleView(grok.View):
grok.context(zope.interface.Interface)
- grok.require('permission.1')
- grok.require('permission.2')
+ grok.require(One)
+ grok.require(Two)
def render(self):
pass
Modified: grok/trunk/src/grok/tests/security/multiple_require_json.py
===================================================================
--- grok/trunk/src/grok/tests/security/multiple_require_json.py 2008-05-02 09:54:50 UTC (rev 86067)
+++ grok/trunk/src/grok/tests/security/multiple_require_json.py 2008-05-02 09:57:37 UTC (rev 86068)
@@ -18,8 +18,8 @@
class MultipleJSON(grok.JSON):
grok.context(zope.interface.Interface)
- grok.require('permission.1')
- grok.require('permission.2')
+ grok.require(One)
+ grok.require(Two)
def render(self):
pass
Modified: grok/trunk/src/grok/tests/security/multiple_require_xmlrpc.py
===================================================================
--- grok/trunk/src/grok/tests/security/multiple_require_xmlrpc.py 2008-05-02 09:54:50 UTC (rev 86067)
+++ grok/trunk/src/grok/tests/security/multiple_require_xmlrpc.py 2008-05-02 09:57:37 UTC (rev 86068)
@@ -17,8 +17,8 @@
class MultipleXMLRPC(grok.XMLRPC):
grok.context(zope.interface.Interface)
- grok.require('permission.1')
- grok.require('permission.2')
+ grok.require(One)
+ grok.require(Two)
def render(self):
pass
Copied: grok/trunk/src/grok/tests/security/not_a_permissionclass.py (from rev 86056, grok/branches/jw-refer-to-permission-class/src/grok/tests/security/not_a_permissionclass.py)
===================================================================
--- grok/trunk/src/grok/tests/security/not_a_permissionclass.py (rev 0)
+++ grok/trunk/src/grok/tests/security/not_a_permissionclass.py 2008-05-02 09:57:37 UTC (rev 86068)
@@ -0,0 +1,23 @@
+"""
+When refering to a class in the grok.require() directive, this class needs
+to implement the zope.security.interfaces.IPermission interface::
+
+ >>> from zope.interface import Interface
+ >>> class NotAProperPermission(object):
+ ... pass
+ >>>
+ >>> class NoPermission(grok.View):
+ ... grok.context(zope.interface.Interface)
+ ... grok.require(NotAProperPermission)
+ ...
+ ... def render(self):
+ ... pass
+ Traceback (most recent call last):
+ ...
+ GrokImportError: You can only pass unicode, ASCII, or a subclass of
+ grok.Permission grok.require.
+
+"""
+
+import grok
+import zope.interface
Modified: grok/trunk/src/grok/tests/security/view_decorator.py
===================================================================
--- grok/trunk/src/grok/tests/security/view_decorator.py 2008-05-02 09:54:50 UTC (rev 86067)
+++ grok/trunk/src/grok/tests/security/view_decorator.py 2008-05-02 09:57:37 UTC (rev 86068)
@@ -17,6 +17,6 @@
class BogusView(grok.View):
grok.context(zope.interface.Interface)
- @grok.require('bogus.perm')
+ @grok.require(Bogus)
def render(self):
pass
More information about the Checkins
mailing list