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 | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|  |         if ismethod(state.controller): | ||||||
|             args = [state.request, state.response] + args |             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
	 Jenkins
					Jenkins