Skip to content

Commit

Permalink
Render *args, **kwargs properly in facade (#70)
Browse files Browse the repository at this point in the history
render *args, **kwargs properly in method call; make buildfacade method public
  • Loading branch information
tschorr committed Oct 8, 2018
1 parent 605ec75 commit 15ab8d2
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 8 deletions.
3 changes: 2 additions & 1 deletion CHANGES.rst
Expand Up @@ -6,7 +6,8 @@ For changes before version 3.0, see ``HISTORY.rst``.
4.0b6 (unreleased)
------------------

- Nothing changed yet.
- Fix deprecation warnings for Python 3 and
change visibility of `buildfacade` to public. (#68, #69, #70)


4.0b5 (2018-10-05)
Expand Down
13 changes: 7 additions & 6 deletions src/AccessControl/requestmethod.py
Expand Up @@ -25,7 +25,7 @@
_default = []


def _buildFacade(name, method, docstring):
def buildfacade(name, method, docstring):
"""Build a facade function, matching the decorated method in signature.
Note that defaults are replaced by _default, and _curried will reconstruct
Expand All @@ -34,13 +34,14 @@ def _buildFacade(name, method, docstring):
"""
sig = signature(method)
args = []
callargs = []
for v in sig.parameters.values():
argstr = str(v)
parts = str(v).split('=')
args.append(
argstr if '=' not in argstr else '{}=_default'.format(v.name))
callargs = ', '.join(sig.parameters.keys())
parts[0] if len(parts) == 1 else '{}=_default'.format(parts[0]))
callargs.append(parts[0])
return 'def %s(%s):\n """%s"""\n return _curried(%s)' % (
name, ', '.join(args), docstring, callargs)
name, ', '.join(args), docstring, ', '.join(callargs))


def requestmethod(*methods):
Expand Down Expand Up @@ -86,7 +87,7 @@ def _curried(*args, **kw):
# Build a facade, with a reference to our locally-scoped _curried
name = callable.__name__
facade_globs = dict(_curried=_curried, _default=_default)
exec(_buildFacade(name, callable, callable.__doc__), facade_globs)
exec(buildfacade(name, callable, callable.__doc__), facade_globs)
return facade_globs[name]

return _methodtest
Expand Down
15 changes: 14 additions & 1 deletion src/AccessControl/tests/test_requestmethod.py
Expand Up @@ -13,6 +13,7 @@

from AccessControl.requestmethod import requestmethod
from AccessControl.requestmethod import getfullargspec
from AccessControl.requestmethod import buildfacade
from zope.interface import implementer
from zope.publisher.interfaces.browser import IBrowserRequest
import unittest
Expand Down Expand Up @@ -84,7 +85,6 @@ def test_preserves_keyword_parameter_defaults(self):
# 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')
Expand Down Expand Up @@ -121,3 +121,16 @@ def foo(bar, REQUEST=None):
foo('spam', POST)
self.assertEqual('Request must be GET, HEAD or PROPFIND',
str(err.exception))

def test_facade_render_correct_args_kwargs(self):
""" s. https://github.com/zopefoundation/AccessControl/issues/69
"""
def foo(bar, baz, *args, **kwargs):
"""foo doc"""
return baz
got = buildfacade('foo', foo, foo.__doc__)
expected = '\n'.join([
'def foo(bar, baz, *args, **kwargs):',
' """foo doc"""',
' return _curried(bar, baz, *args, **kwargs)'])
self.assertEqual(expected, got)

0 comments on commit 15ab8d2

Please sign in to comment.