Merge "Resolve a bug that mixes up argument order for generic functions."
This commit is contained in:
@@ -11,6 +11,10 @@ import operator
|
|||||||
import types
|
import types
|
||||||
|
|
||||||
import six
|
import six
|
||||||
|
if six.PY3:
|
||||||
|
from .compat import is_bound_method as ismethod
|
||||||
|
else:
|
||||||
|
from inspect import ismethod
|
||||||
|
|
||||||
from webob import (Request as WebObRequest, Response as WebObResponse, exc,
|
from webob import (Request as WebObRequest, Response as WebObResponse, exc,
|
||||||
acceptparse)
|
acceptparse)
|
||||||
@@ -738,7 +742,13 @@ class ExplicitPecan(PecanBase):
|
|||||||
args, varargs, kwargs = super(ExplicitPecan, self).get_args(
|
args, varargs, kwargs = super(ExplicitPecan, self).get_args(
|
||||||
state, all_params, remainder, argspec, im_self
|
state, all_params, remainder, argspec, im_self
|
||||||
)
|
)
|
||||||
args = [state.request, state.response] + args
|
|
||||||
|
if ismethod(state.controller):
|
||||||
|
args = [state.request, state.response] + args
|
||||||
|
else:
|
||||||
|
# generic controllers have an explicit self *first*
|
||||||
|
# (because they're decorated functions, not instance methods)
|
||||||
|
args[1:1] = [state.request, state.response]
|
||||||
return args, varargs, kwargs
|
return args, varargs, kwargs
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
from json import dumps
|
import time
|
||||||
|
from json import dumps, loads
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
from webtest import TestApp
|
from webtest import TestApp
|
||||||
@@ -7,7 +8,7 @@ from six import u as u_
|
|||||||
import webob
|
import webob
|
||||||
import mock
|
import mock
|
||||||
|
|
||||||
from pecan import Pecan, expose, abort
|
from pecan import Pecan, expose, abort, Request, Response
|
||||||
from pecan.rest import RestController
|
from pecan.rest import RestController
|
||||||
from pecan.hooks import PecanHook, HookController
|
from pecan.hooks import PecanHook, HookController
|
||||||
from pecan.tests import PecanTestCase
|
from pecan.tests import PecanTestCase
|
||||||
@@ -1355,3 +1356,85 @@ class TestHooks(PecanTestCase):
|
|||||||
assert run_hook[3] == 'inside_sub'
|
assert run_hook[3] == 'inside_sub'
|
||||||
assert run_hook[4] == 'after1'
|
assert run_hook[4] == 'after1'
|
||||||
assert run_hook[5] == 'after2'
|
assert run_hook[5] == 'after2'
|
||||||
|
|
||||||
|
|
||||||
|
class TestGeneric(PecanTestCase):
|
||||||
|
|
||||||
|
@property
|
||||||
|
def root(self):
|
||||||
|
class RootController(object):
|
||||||
|
|
||||||
|
def __init__(self, unique):
|
||||||
|
self.unique = unique
|
||||||
|
|
||||||
|
@expose(generic=True, template='json')
|
||||||
|
def index(self, req, resp):
|
||||||
|
assert self.__class__.__name__ == 'RootController'
|
||||||
|
assert isinstance(req, Request)
|
||||||
|
assert isinstance(resp, Response)
|
||||||
|
assert self.unique == req.headers.get('X-Unique')
|
||||||
|
return {'hello': 'world'}
|
||||||
|
|
||||||
|
@index.when(method='POST', template='json')
|
||||||
|
def index_post(self, req, resp):
|
||||||
|
assert self.__class__.__name__ == 'RootController'
|
||||||
|
assert isinstance(req, Request)
|
||||||
|
assert isinstance(resp, Response)
|
||||||
|
assert self.unique == req.headers.get('X-Unique')
|
||||||
|
return req.json
|
||||||
|
|
||||||
|
@expose(template='json')
|
||||||
|
def echo(self, req, resp):
|
||||||
|
assert self.__class__.__name__ == 'RootController'
|
||||||
|
assert isinstance(req, Request)
|
||||||
|
assert isinstance(resp, Response)
|
||||||
|
assert self.unique == req.headers.get('X-Unique')
|
||||||
|
return req.json
|
||||||
|
|
||||||
|
@expose(template='json')
|
||||||
|
def extra(self, req, resp, first, second):
|
||||||
|
assert self.__class__.__name__ == 'RootController'
|
||||||
|
assert isinstance(req, Request)
|
||||||
|
assert isinstance(resp, Response)
|
||||||
|
assert self.unique == req.headers.get('X-Unique')
|
||||||
|
return {'first': first, 'second': second}
|
||||||
|
|
||||||
|
return RootController
|
||||||
|
|
||||||
|
def test_generics_with_im_self_default(self):
|
||||||
|
uniq = str(time.time())
|
||||||
|
with mock.patch('threading.local', side_effect=AssertionError()):
|
||||||
|
app = TestApp(Pecan(self.root(uniq), use_context_locals=False))
|
||||||
|
r = app.get('/', headers={'X-Unique': uniq})
|
||||||
|
assert r.status_int == 200
|
||||||
|
json_resp = loads(r.body.decode())
|
||||||
|
assert json_resp['hello'] == 'world'
|
||||||
|
|
||||||
|
def test_generics_with_im_self_with_method(self):
|
||||||
|
uniq = str(time.time())
|
||||||
|
with mock.patch('threading.local', side_effect=AssertionError()):
|
||||||
|
app = TestApp(Pecan(self.root(uniq), use_context_locals=False))
|
||||||
|
r = app.post_json('/', {'foo': 'bar'}, headers={'X-Unique': uniq})
|
||||||
|
assert r.status_int == 200
|
||||||
|
json_resp = loads(r.body.decode())
|
||||||
|
assert json_resp['foo'] == 'bar'
|
||||||
|
|
||||||
|
def test_generics_with_im_self_with_path(self):
|
||||||
|
uniq = str(time.time())
|
||||||
|
with mock.patch('threading.local', side_effect=AssertionError()):
|
||||||
|
app = TestApp(Pecan(self.root(uniq), use_context_locals=False))
|
||||||
|
r = app.post_json('/echo/', {'foo': 'bar'},
|
||||||
|
headers={'X-Unique': uniq})
|
||||||
|
assert r.status_int == 200
|
||||||
|
json_resp = loads(r.body.decode())
|
||||||
|
assert json_resp['foo'] == 'bar'
|
||||||
|
|
||||||
|
def test_generics_with_im_self_with_extra_args(self):
|
||||||
|
uniq = str(time.time())
|
||||||
|
with mock.patch('threading.local', side_effect=AssertionError()):
|
||||||
|
app = TestApp(Pecan(self.root(uniq), use_context_locals=False))
|
||||||
|
r = app.get('/extra/123/456', headers={'X-Unique': uniq})
|
||||||
|
assert r.status_int == 200
|
||||||
|
json_resp = loads(r.body.decode())
|
||||||
|
assert json_resp['first'] == '123'
|
||||||
|
assert json_resp['second'] == '456'
|
||||||
|
|||||||
Reference in New Issue
Block a user