Skip to content

Commit

Permalink
Merge branch 'py3-pure-python' of https://github.com/zopefoundation/A…
Browse files Browse the repository at this point in the history
…ccessControl into py3-pure-python
  • Loading branch information
dwt committed Sep 30, 2016
2 parents db92b78 + 15f34b0 commit 40c0314
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 104 deletions.
92 changes: 0 additions & 92 deletions src/AccessControl/requestmethod.txt

This file was deleted.

4 changes: 1 addition & 3 deletions src/AccessControl/rolemanager.py
Original file line number Diff line number Diff line change
Expand Up @@ -318,9 +318,7 @@ def get_valid_userids(self):
item = getattr(item, '__parent__', _notfound)
if item is _notfound:
break
keys=dict.keys()
keys.sort()
return tuple(keys)
return tuple(sorted(dict.keys()))

def get_local_roles_for_userid(self, userid):
dict=self.__ac_local_roles__ or {}
Expand Down
103 changes: 98 additions & 5 deletions src/AccessControl/tests/test_requestmethod.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,11 @@
#
##############################################################################

from AccessControl.requestmethod import requestmethod
from zope.interface import implementer
from zope.publisher.interfaces.browser import IBrowserRequest
import unittest
import zExceptions


@implementer(IBrowserRequest)
Expand All @@ -22,8 +25,98 @@ def __init__(self, method):
self.method = method


def test_suite():
from doctest import DocFileSuite
return DocFileSuite('../requestmethod.txt',
globs=dict(GET=DummyRequest('GET'),
POST=DummyRequest('POST')))
GET = DummyRequest('GET')
POST = DummyRequest('POST')


class RequestMethodDecoratorsTests(unittest.TestCase):
"""Using request method decorators, you can limit functions or methods to
only be callable when the HTTP request was made using a particular method.
"""

def test_requires_the_defined_HTTP_mehtod(self):
# To limit access to a function or method to POST requests, use the
# requestmethod decorator factory:
@requestmethod('POST')
def foo(bar, REQUEST):
return bar

# When this method is accessed through a request that does not use
# POST, the Forbidden exception will be raised:
with self.assertRaises(zExceptions.Forbidden) as err:
foo('spam', GET)
self.assertEqual('Request must be POST', str(err.exception))

# Only when the request was made using POST, will the call succeed:
self.assertEqual('spam', foo('spam', POST))

def test_it_does_not_matter_if_REQUEST_is_positional_or_keyword_arg(self):
# It doesn't matter if REQUEST is a positional or a keyword parameter:

@requestmethod('POST')
def foo(bar, REQUEST=None):
return bar

with self.assertRaises(zExceptions.Forbidden) as err:
foo('spam', GET)
self.assertEqual('Request must be POST', str(err.exception))

# *Not* passing an optional REQUEST always succeeds::
self.assertEqual('spam', foo('spam', POST))

def test_REQUEST_parameter_is_a_requirement(self):
# Note that the REQUEST parameter is a requirement for the decorator to
# operate, not including it in the callable signature results in an
# error:
try:
@requestmethod('POST')
def foo(bar):
return bar
except ValueError as e:
self.assertEqual(
'No REQUEST parameter in callable signature', str(e))
else:
self.fail('Did not raise')

def test_preserves_keyword_parameter_defaults(self):
# Because the Zope Publisher uses introspection to match REQUEST
# variables against callable signatures, the result of the decorator
# must match the original closely, and keyword parameter defaults must
# be preserved:
import inspect
mutabledefault = dict()

@requestmethod('POST')
def foo(bar, baz=mutabledefault, egg=mutabledefault, REQUEST=None,
*args):
return bar, baz is mutabledefault, egg is None, REQUEST
self.assertEqual((['bar', 'baz', 'egg', 'REQUEST'], 'args', None),
inspect.getargspec(foo)[:3])
self.assertEqual(('spam', True, True, None), foo('spam', egg=None))
with self.assertRaises(TypeError) as err:
foo(monty='python')
self.assertEqual("foo() got an unexpected keyword argument 'monty'",
str(err.exception))

def test_can_be_used_for_any_request_method(self):
# The `requestmethod` decorator factory can be used for any request
# method, simply pass in the desired request method:
@requestmethod('PUT')
def foo(bar, REQUEST=None):
return bar

with self.assertRaises(zExceptions.Forbidden) as err:
foo('spam', GET)
self.assertEqual('Request must be PUT', str(err.exception))

def test_allows_multiple_request_methods(self):
# You can pass in multiple request methods allow access by any of them:
@requestmethod('GET', 'HEAD', 'PROPFIND')
def foo(bar, REQUEST=None):
return bar

self.assertEqual('spam', foo('spam', GET))
with self.assertRaises(zExceptions.Forbidden) as err:
foo('spam', POST)
self.assertEqual('Request must be GET, HEAD or PROPFIND',
str(err.exception))
6 changes: 2 additions & 4 deletions src/AccessControl/userfolder.py
Original file line number Diff line number Diff line change
Expand Up @@ -377,15 +377,13 @@ def __init__(self):
def getUserNames(self):
"""Return a list of usernames"""
names=self.data.keys()
names.sort()
return names
return sorted(names)

def getUsers(self):
"""Return a list of user objects"""
data=self.data
names=data.keys()
names.sort()
return [data[n] for n in names]
return [data[n] for n in sorted(names)]

def getUser(self, name):
"""Return the named user object or None"""
Expand Down

0 comments on commit 40c0314

Please sign in to comment.