diff options
Diffstat (limited to 'pecan/tests')
50 files changed, 0 insertions, 9289 deletions
diff --git a/pecan/tests/__init__.py b/pecan/tests/__init__.py deleted file mode 100644 index 4d2df74..0000000 --- a/pecan/tests/__init__.py +++ /dev/null @@ -1,20 +0,0 @@ -import sys -import os -if sys.version_info < (2, 7): - from unittest2 import TestCase # pragma: nocover -else: - from unittest import TestCase # pragma: nocover - - -class PecanTestCase(TestCase): - - def setUp(self): - self.addCleanup(self._reset_global_config) - - def _reset_global_config(self): - from pecan import configuration - configuration.set_config( - dict(configuration.initconf()), - overwrite=True - ) - os.environ.pop('PECAN_CONFIG', None) diff --git a/pecan/tests/config_fixtures/bad/importerror.py b/pecan/tests/config_fixtures/bad/importerror.py deleted file mode 100644 index 592fa5b..0000000 --- a/pecan/tests/config_fixtures/bad/importerror.py +++ /dev/null @@ -1 +0,0 @@ -import pecan.thismoduledoesnotexist diff --git a/pecan/tests/config_fixtures/bad/module_and_underscore.py b/pecan/tests/config_fixtures/bad/module_and_underscore.py deleted file mode 100644 index e53f416..0000000 --- a/pecan/tests/config_fixtures/bad/module_and_underscore.py +++ /dev/null @@ -1,4 +0,0 @@ -import sys - -__badattr__ = True -moduleattr = sys diff --git a/pecan/tests/config_fixtures/config.py b/pecan/tests/config_fixtures/config.py deleted file mode 100644 index bba299b..0000000 --- a/pecan/tests/config_fixtures/config.py +++ /dev/null @@ -1,22 +0,0 @@ - - -# Server Specific Configurations -server = { - 'port': '8081', - 'host': '1.1.1.1', - 'hostport': '{pecan.conf.server.host}:{pecan.conf.server.port}' -} - -# Pecan Application Configurations -app = { - 'static_root': 'public', - 'template_path': 'myproject/templates', - 'debug': True -} - -# Custom Configurations must be in Python dictionary format:: -# -# foo = {'bar':'baz'} -# -# All configurations are accessible at:: -# pecan.conf diff --git a/pecan/tests/config_fixtures/empty.py b/pecan/tests/config_fixtures/empty.py deleted file mode 100644 index b4a9332..0000000 --- a/pecan/tests/config_fixtures/empty.py +++ /dev/null @@ -1,2 +0,0 @@ -app = {} -server = {} diff --git a/pecan/tests/config_fixtures/foobar.py b/pecan/tests/config_fixtures/foobar.py deleted file mode 100644 index 5abc475..0000000 --- a/pecan/tests/config_fixtures/foobar.py +++ /dev/null @@ -1 +0,0 @@ -foo = "bar" diff --git a/pecan/tests/config_fixtures/forcedict.py b/pecan/tests/config_fixtures/forcedict.py deleted file mode 100644 index 4e2c83a..0000000 --- a/pecan/tests/config_fixtures/forcedict.py +++ /dev/null @@ -1,14 +0,0 @@ -# Pecan Application Configurations -beaker = { - 'session.key': 'key', - 'session.type': 'cookie', - 'session.validate_key': '1a971a7df182df3e1dec0af7c6913ec7', - '__force_dict__': True -} - -# Custom Configurations must be in Python dictionary format:: -# -# foo = {'bar':'baz'} -# -# All configurations are accessible at:: -# pecan.conf diff --git a/pecan/tests/middleware/__init__.py b/pecan/tests/middleware/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/pecan/tests/middleware/__init__.py +++ /dev/null diff --git a/pecan/tests/middleware/static_fixtures/self.png b/pecan/tests/middleware/static_fixtures/self.png Binary files differdeleted file mode 100644 index 9b30321..0000000 --- a/pecan/tests/middleware/static_fixtures/self.png +++ /dev/null diff --git a/pecan/tests/middleware/static_fixtures/text.txt b/pecan/tests/middleware/static_fixtures/text.txt deleted file mode 100644 index c6defe5..0000000 --- a/pecan/tests/middleware/static_fixtures/text.txt +++ /dev/null @@ -1,9 +0,0 @@ -This is a test text file. - -Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod -tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim -veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea -commodo consequat. Duis aute irure dolor in reprehenderit in voluptate -velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint -occaecat cupidatat non proident, sunt in culpa qui officia deserunt -mollit anim id est laborum.
\ No newline at end of file diff --git a/pecan/tests/middleware/test_errordocument.py b/pecan/tests/middleware/test_errordocument.py deleted file mode 100644 index 29f46e5..0000000 --- a/pecan/tests/middleware/test_errordocument.py +++ /dev/null @@ -1,92 +0,0 @@ -import json - -from webtest import TestApp -from six import b as b_ - -import pecan -from pecan.middleware.errordocument import ErrorDocumentMiddleware -from pecan.middleware.recursive import RecursiveMiddleware -from pecan.tests import PecanTestCase - - -def four_oh_four_app(environ, start_response): - if environ['PATH_INFO'].startswith('/error'): - code = environ['PATH_INFO'].split('/')[2] - start_response("200 OK", [('Content-type', 'text/plain')]) - - body = "Error: %s" % code - if environ['QUERY_STRING']: - body += "\nQS: %s" % environ['QUERY_STRING'] - return [b_(body)] - start_response("404 Not Found", [('Content-type', 'text/plain')]) - return [] - - -class TestErrorDocumentMiddleware(PecanTestCase): - - def setUp(self): - super(TestErrorDocumentMiddleware, self).setUp() - self.app = TestApp(RecursiveMiddleware(ErrorDocumentMiddleware( - four_oh_four_app, {404: '/error/404'} - ))) - - def test_hit_error_page(self): - r = self.app.get('/error/404') - assert r.status_int == 200 - assert r.body == b_('Error: 404') - - def test_middleware_routes_to_404_message(self): - r = self.app.get('/', expect_errors=True) - assert r.status_int == 404 - assert r.body == b_('Error: 404') - - def test_error_endpoint_with_query_string(self): - app = TestApp(RecursiveMiddleware(ErrorDocumentMiddleware( - four_oh_four_app, {404: '/error/404?foo=bar'} - ))) - r = app.get('/', expect_errors=True) - assert r.status_int == 404 - assert r.body == b_('Error: 404\nQS: foo=bar') - - def test_error_with_recursion_loop(self): - app = TestApp(RecursiveMiddleware(ErrorDocumentMiddleware( - four_oh_four_app, {404: '/'} - ))) - r = app.get('/', expect_errors=True) - assert r.status_int == 404 - assert r.body == b_( - 'Error: 404 Not Found. (Error page could not be fetched)' - ) - - def test_original_exception(self): - - class RootController(object): - - @pecan.expose() - def index(self): - if pecan.request.method != 'POST': - pecan.abort(405, 'You have to POST, dummy!') - return 'Hello, World!' - - @pecan.expose('json') - def error(self, status): - return dict( - status=int(status), - reason=pecan.request.environ[ - 'pecan.original_exception' - ].detail - ) - - app = pecan.Pecan(RootController()) - app = RecursiveMiddleware(ErrorDocumentMiddleware(app, { - 405: '/error/405' - })) - app = TestApp(app) - - assert app.post('/').status_int == 200 - r = app.get('/', expect_errors=405) - assert r.status_int == 405 - - resp = json.loads(r.body.decode()) - assert resp['status'] == 405 - assert resp['reason'] == 'You have to POST, dummy!' diff --git a/pecan/tests/middleware/test_recursive.py b/pecan/tests/middleware/test_recursive.py deleted file mode 100644 index ed95d50..0000000 --- a/pecan/tests/middleware/test_recursive.py +++ /dev/null @@ -1,142 +0,0 @@ -from webtest import TestApp -from six import b as b_ - -from pecan.middleware.recursive import (RecursiveMiddleware, - ForwardRequestException) -from pecan.tests import PecanTestCase - - -def simple_app(environ, start_response): - start_response("200 OK", [('Content-type', 'text/plain')]) - return [b_('requested page returned')] - - -def error_docs_app(environ, start_response): - if environ['PATH_INFO'] == '/not_found': - start_response("404 Not found", [('Content-type', 'text/plain')]) - return [b_('Not found')] - elif environ['PATH_INFO'] == '/error': - start_response("200 OK", [('Content-type', 'text/plain')]) - return [b_('Page not found')] - elif environ['PATH_INFO'] == '/recurse': - raise ForwardRequestException('/recurse') - else: - return simple_app(environ, start_response) - - -class Middleware(object): - def __init__(self, app, url='/error'): - self.app = app - self.url = url - - def __call__(self, environ, start_response): - raise ForwardRequestException(self.url) - - -def forward(app): - app = TestApp(RecursiveMiddleware(app)) - res = app.get('') - - assert res.headers['content-type'] == 'text/plain' - assert res.status == '200 OK' - assert 'requested page returned' in res - res = app.get('/error') - assert res.headers['content-type'] == 'text/plain' - assert res.status == '200 OK' - assert 'Page not found' in res - res = app.get('/not_found') - assert res.headers['content-type'] == 'text/plain' - assert res.status == '200 OK' - assert 'Page not found' in res - try: - res = app.get('/recurse') - except AssertionError as e: - if str(e).startswith('Forwarding loop detected'): - pass - else: - raise AssertionError('Failed to detect forwarding loop') - - -class TestRecursiveMiddleware(PecanTestCase): - - def test_ForwardRequest_url(self): - class TestForwardRequestMiddleware(Middleware): - def __call__(self, environ, start_response): - if environ['PATH_INFO'] != '/not_found': - return self.app(environ, start_response) - raise ForwardRequestException(self.url) - forward(TestForwardRequestMiddleware(error_docs_app)) - - def test_ForwardRequest_url_with_params(self): - class TestForwardRequestMiddleware(Middleware): - def __call__(self, environ, start_response): - if environ['PATH_INFO'] != '/not_found': - return self.app(environ, start_response) - raise ForwardRequestException(self.url + '?q=1') - forward(TestForwardRequestMiddleware(error_docs_app)) - - def test_ForwardRequest_environ(self): - class TestForwardRequestMiddleware(Middleware): - def __call__(self, environ, start_response): - if environ['PATH_INFO'] != '/not_found': - return self.app(environ, start_response) - environ['PATH_INFO'] = self.url - raise ForwardRequestException(environ=environ) - forward(TestForwardRequestMiddleware(error_docs_app)) - - def test_ForwardRequest_factory(self): - - class TestForwardRequestMiddleware(Middleware): - def __call__(self, environ, start_response): - if environ['PATH_INFO'] != '/not_found': - return self.app(environ, start_response) - environ['PATH_INFO'] = self.url - - def factory(app): - - class WSGIApp(object): - - def __init__(self, app): - self.app = app - - def __call__(self, e, start_response): - def keep_status_start_response(status, headers, - exc_info=None): - return start_response( - '404 Not Found', headers, exc_info - ) - return self.app(e, keep_status_start_response) - - return WSGIApp(app) - - raise ForwardRequestException(factory=factory) - - app = TestForwardRequestMiddleware(error_docs_app) - app = TestApp(RecursiveMiddleware(app)) - res = app.get('') - assert res.headers['content-type'] == 'text/plain' - assert res.status == '200 OK' - assert 'requested page returned' in res - res = app.get('/error') - assert res.headers['content-type'] == 'text/plain' - assert res.status == '200 OK' - assert 'Page not found' in res - res = app.get('/not_found', status=404) - assert res.headers['content-type'] == 'text/plain' - assert res.status == '404 Not Found' # Different status - assert 'Page not found' in res - try: - res = app.get('/recurse') - except AssertionError as e: - if str(e).startswith('Forwarding loop detected'): - pass - else: - raise AssertionError('Failed to detect forwarding loop') - - def test_ForwardRequestException(self): - class TestForwardRequestExceptionMiddleware(Middleware): - def __call__(self, environ, start_response): - if environ['PATH_INFO'] != '/not_found': - return self.app(environ, start_response) - raise ForwardRequestException(path_info=self.url) - forward(TestForwardRequestExceptionMiddleware(error_docs_app)) diff --git a/pecan/tests/middleware/test_static.py b/pecan/tests/middleware/test_static.py deleted file mode 100644 index 9a0c08c..0000000 --- a/pecan/tests/middleware/test_static.py +++ /dev/null @@ -1,68 +0,0 @@ -from pecan.middleware.static import (StaticFileMiddleware, FileWrapper, - _dump_date) -from pecan.tests import PecanTestCase - -import os - - -class TestStaticFileMiddleware(PecanTestCase): - - def setUp(self): - super(TestStaticFileMiddleware, self).setUp() - - def app(environ, start_response): - response_headers = [('Content-type', 'text/plain')] - start_response('200 OK', response_headers) - return ['Hello world!\n'] - - self.app = StaticFileMiddleware( - app, os.path.dirname(__file__) - ) - - self._status = None - self._response_headers = None - - def _request(self, path): - def start_response(status, response_headers, exc_info=None): - self._status = status - self._response_headers = response_headers - return self.app( - dict(PATH_INFO=path), - start_response - ) - - def _get_response_header(self, header): - for k, v in self._response_headers: - if k.upper() == header.upper(): - return v - return None - - def test_file_can_be_found(self): - result = self._request('/static_fixtures/text.txt') - assert isinstance(result, FileWrapper) - - def test_no_file_found_causes_passthrough(self): - result = self._request('/static_fixtures/nosuchfile.txt') - assert not isinstance(result, FileWrapper) - assert result == ['Hello world!\n'] - - def test_mime_type_works_for_png_files(self): - self._request('/static_fixtures/self.png') - assert self._get_response_header('Content-Type') == 'image/png' - - def test_file_can_be_closed(self): - result = self._request('/static_fixtures/text.txt') - assert result.close() is None - - def test_file_can_be_iterated_over(self): - result = self._request('/static_fixtures/text.txt') - assert len([x for x in result]) - - def test_date_dumping_on_unix_timestamps(self): - result = _dump_date(1331755274.59, ' ') - assert result == 'Wed, 14 Mar 2012 20:01:14 GMT' - - def test_separator_sanitization_still_finds_file(self): - os.altsep = ':' - result = self._request(':static_fixtures:text.txt') - assert isinstance(result, FileWrapper) diff --git a/pecan/tests/scaffold_builder.py b/pecan/tests/scaffold_builder.py deleted file mode 100644 index dc039da..0000000 --- a/pecan/tests/scaffold_builder.py +++ /dev/null @@ -1,172 +0,0 @@ -import os -import sys -import subprocess -import time - -from six import b as b_ - -from pecan.compat import urlopen, URLError -from pecan.tests import PecanTestCase - -if sys.version_info < (2, 7): - import unittest2 as unittest -else: - import unittest # noqa - - -if __name__ == '__main__': - - class TestTemplateBuilds(PecanTestCase): - """ - Used to test the templated quickstart project(s). - """ - - @property - def bin(self): - return os.path.dirname(sys.executable) - - def poll(self, proc): - limit = 30 - for i in range(limit): - proc.poll() - - # Make sure it's running - if proc.returncode is None: - break - elif i == limit: # pragma: no cover - raise RuntimeError("Server process didn't start.") - time.sleep(.1) - - def test_project_pecan_serve_command(self): - # Start the server - proc = subprocess.Popen([ - os.path.join(self.bin, 'pecan'), - 'serve', - 'testing123/config.py' - ]) - - try: - self.poll(proc) - retries = 30 - while True: - retries -= 1 - if retries < 0: # pragma: nocover - raise RuntimeError( - "The HTTP server has not replied within 3 seconds." - ) - try: - # ...and that it's serving (valid) content... - resp = urlopen('http://localhost:8080/') - assert resp.getcode() - assert len(resp.read().decode()) - except URLError: - pass - else: - break - time.sleep(.1) - finally: - proc.terminate() - - def test_project_pecan_shell_command(self): - # Start the server - proc = subprocess.Popen([ - os.path.join(self.bin, 'pecan'), - 'shell', - 'testing123/config.py' - ], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - stdin=subprocess.PIPE - ) - - self.poll(proc) - - out, _ = proc.communicate( - b_('{"model" : model, "conf" : conf, "app" : app}') - ) - assert 'testing123.model' in out.decode(), out - assert 'Config(' in out.decode(), out - assert 'webtest.app.TestApp' in out.decode(), out - - try: - # just in case stdin doesn't close - proc.terminate() - except: - pass - - class TestThirdPartyServe(TestTemplateBuilds): - - def poll_http(self, name, proc, port): - try: - self.poll(proc) - retries = 30 - while True: - retries -= 1 - if retries < 0: # pragma: nocover - raise RuntimeError( - "The %s server has not replied within" - " 3 seconds." % name - ) - try: - # ...and that it's serving (valid) content... - resp = urlopen('http://localhost:%d/' % port) - assert resp.getcode() - assert len(resp.read().decode()) - except URLError: - pass - else: - break - time.sleep(.1) - finally: - proc.terminate() - - class TestGunicornServeCommand(TestThirdPartyServe): - - def test_serve_from_config(self): - # Start the server - proc = subprocess.Popen([ - os.path.join(self.bin, 'gunicorn_pecan'), - 'testing123/config.py' - ]) - - self.poll_http('gunicorn', proc, 8080) - - def test_serve_with_custom_bind(self): - # Start the server - proc = subprocess.Popen([ - os.path.join(self.bin, 'gunicorn_pecan'), - '--bind=0.0.0.0:9191', - 'testing123/config.py' - ]) - - self.poll_http('gunicorn', proc, 9191) - - class TestUWSGIServiceCommand(TestThirdPartyServe): - - def test_serve_from_config(self): - # Start the server - proc = subprocess.Popen([ - os.path.join(self.bin, 'uwsgi'), - '--http-socket', - ':8080', - '--venv', - sys.prefix, - '--pecan', - 'testing123/config.py' - ]) - - self.poll_http('uwsgi', proc, 8080) - - # First, ensure that the `testing123` package has been installed - args = [ - os.path.join(os.path.dirname(sys.executable), 'pip'), - 'install', - '-U', - '-e', - './testing123' - ] - process = subprocess.Popen(args) - _, unused_err = process.communicate() - assert not process.poll() - - unittest.main() diff --git a/pecan/tests/scaffold_fixtures/__init__.py b/pecan/tests/scaffold_fixtures/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/pecan/tests/scaffold_fixtures/__init__.py +++ /dev/null diff --git a/pecan/tests/scaffold_fixtures/content_sub/bar/spam.txt_tmpl b/pecan/tests/scaffold_fixtures/content_sub/bar/spam.txt_tmpl deleted file mode 100644 index 95a9c91..0000000 --- a/pecan/tests/scaffold_fixtures/content_sub/bar/spam.txt_tmpl +++ /dev/null @@ -1 +0,0 @@ -Pecan ${package} diff --git a/pecan/tests/scaffold_fixtures/content_sub/foo_tmpl b/pecan/tests/scaffold_fixtures/content_sub/foo_tmpl deleted file mode 100644 index 25591f3..0000000 --- a/pecan/tests/scaffold_fixtures/content_sub/foo_tmpl +++ /dev/null @@ -1 +0,0 @@ -YAR ${package} diff --git a/pecan/tests/scaffold_fixtures/file_sub/bar_+package+/spam.txt b/pecan/tests/scaffold_fixtures/file_sub/bar_+package+/spam.txt deleted file mode 100644 index 02c61ad..0000000 --- a/pecan/tests/scaffold_fixtures/file_sub/bar_+package+/spam.txt +++ /dev/null @@ -1 +0,0 @@ -Pecan diff --git a/pecan/tests/scaffold_fixtures/file_sub/foo_+package+ b/pecan/tests/scaffold_fixtures/file_sub/foo_+package+ deleted file mode 100644 index 035599b..0000000 --- a/pecan/tests/scaffold_fixtures/file_sub/foo_+package+ +++ /dev/null @@ -1 +0,0 @@ -YAR diff --git a/pecan/tests/scaffold_fixtures/simple/bar/spam.txt b/pecan/tests/scaffold_fixtures/simple/bar/spam.txt deleted file mode 100644 index 02c61ad..0000000 --- a/pecan/tests/scaffold_fixtures/simple/bar/spam.txt +++ /dev/null @@ -1 +0,0 @@ -Pecan diff --git a/pecan/tests/scaffold_fixtures/simple/foo b/pecan/tests/scaffold_fixtures/simple/foo deleted file mode 100644 index 035599b..0000000 --- a/pecan/tests/scaffold_fixtures/simple/foo +++ /dev/null @@ -1 +0,0 @@ -YAR diff --git a/pecan/tests/templates/__init__.py b/pecan/tests/templates/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/pecan/tests/templates/__init__.py +++ /dev/null diff --git a/pecan/tests/templates/form_colors.html b/pecan/tests/templates/form_colors.html deleted file mode 100644 index cd4fea9..0000000 --- a/pecan/tests/templates/form_colors.html +++ /dev/null @@ -1,2 +0,0 @@ -<input type="text" id="colors-0" name="colors-0" value="${data['colors'][0] if data else 'A color'}" /> -<input type="text" id="colors-1" name="colors-1" value="${data['colors'][1] if data else 'A color'}" />
\ No newline at end of file diff --git a/pecan/tests/templates/form_colors_invalid.html b/pecan/tests/templates/form_colors_invalid.html deleted file mode 100644 index d2d4ed7..0000000 --- a/pecan/tests/templates/form_colors_invalid.html +++ /dev/null @@ -1,2 +0,0 @@ -<input type="text" id="colors-0" name="colors-0" value="blue" /> -<input type="text" id="colors-1" name="colors-1" value="" class="error" />
\ No newline at end of file diff --git a/pecan/tests/templates/form_colors_valid.html b/pecan/tests/templates/form_colors_valid.html deleted file mode 100644 index adecfbf..0000000 --- a/pecan/tests/templates/form_colors_valid.html +++ /dev/null @@ -1,2 +0,0 @@ -<input type="text" id="colors-0" name="colors-0" value="blue" /> -<input type="text" id="colors-1" name="colors-1" value="red" />
\ No newline at end of file diff --git a/pecan/tests/templates/form_login_invalid.html b/pecan/tests/templates/form_login_invalid.html deleted file mode 100644 index cede816..0000000 --- a/pecan/tests/templates/form_login_invalid.html +++ /dev/null @@ -1,2 +0,0 @@ -<input type="text" id="username" name="username" value="ryan" /> -<input type="password" id="password" name="password" value="" class="error" />
\ No newline at end of file diff --git a/pecan/tests/templates/form_login_valid.html b/pecan/tests/templates/form_login_valid.html deleted file mode 100644 index 0587754..0000000 --- a/pecan/tests/templates/form_login_valid.html +++ /dev/null @@ -1,2 +0,0 @@ -<input type="text" id="username" name="username" /> -<input type="password" id="password" name="password" value="" />
\ No newline at end of file diff --git a/pecan/tests/templates/form_name.html b/pecan/tests/templates/form_name.html deleted file mode 100644 index b46181d..0000000 --- a/pecan/tests/templates/form_name.html +++ /dev/null @@ -1 +0,0 @@ -<input type="text" id="name" name="name" value="${name if name else ''}" />
\ No newline at end of file diff --git a/pecan/tests/templates/form_name_invalid.html b/pecan/tests/templates/form_name_invalid.html deleted file mode 100644 index bcbd035..0000000 --- a/pecan/tests/templates/form_name_invalid.html +++ /dev/null @@ -1,3 +0,0 @@ -<!-- for: name --> -<span class="error-message">Please enter a value</span><br /> -<input type="text" id="name" name="name" value="" class="error" />
\ No newline at end of file diff --git a/pecan/tests/templates/form_name_invalid_custom.html b/pecan/tests/templates/form_name_invalid_custom.html deleted file mode 100644 index cbb631f..0000000 --- a/pecan/tests/templates/form_name_invalid_custom.html +++ /dev/null @@ -1,3 +0,0 @@ -<!-- for: name --> -<span class="error-message">Names must be unique</span><br /> -<input type="text" id="name" name="name" value="Yoann" class="error" />
\ No newline at end of file diff --git a/pecan/tests/templates/form_name_valid.html b/pecan/tests/templates/form_name_valid.html deleted file mode 100644 index fc7d693..0000000 --- a/pecan/tests/templates/form_name_valid.html +++ /dev/null @@ -1 +0,0 @@ -<input type="text" id="name" name="name" value="Yoann" />
\ No newline at end of file diff --git a/pecan/tests/templates/genshi.html b/pecan/tests/templates/genshi.html deleted file mode 100644 index a42aa32..0000000 --- a/pecan/tests/templates/genshi.html +++ /dev/null @@ -1,16 +0,0 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" - xmlns:py="http://genshi.edgewall.org/" - xmlns:xi="http://www.w3.org/2001/XInclude"> - -<head> - <meta content="text/html; charset=UTF-8" http-equiv="content-type" py:replace="''"/> - <title>Hello, ${name}!</title> -</head> - -<body> - <h1>Hello, ${name}!</h1> -</body> - -</html> diff --git a/pecan/tests/templates/genshi_bad.html b/pecan/tests/templates/genshi_bad.html deleted file mode 100644 index 557bc55..0000000 --- a/pecan/tests/templates/genshi_bad.html +++ /dev/null @@ -1,18 +0,0 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" - xmlns:py="http://genshi.edgewall.org/" - xmlns:xi="http://www.w3.org/2001/XInclude"> - -<head> - <meta content="text/html; charset=UTF-8" http-equiv="content-type" py:replace="''"/> - <title>Hello, ${name}!</title> -<!-- comment out close tag to cause error -</head> ---> - -<body> - <h1>Hello, ${name}!</h1> -</body> - -</html> diff --git a/pecan/tests/templates/jinja.html b/pecan/tests/templates/jinja.html deleted file mode 100644 index e96835a..0000000 --- a/pecan/tests/templates/jinja.html +++ /dev/null @@ -1,11 +0,0 @@ -<html> - -<head> - <title>Hello, {{name}}!</title> -</head> - -<body> - <h1>Hello, {{name}}!</h1> -</body> - -</html> diff --git a/pecan/tests/templates/jinja_bad.html b/pecan/tests/templates/jinja_bad.html deleted file mode 100644 index 3513871..0000000 --- a/pecan/tests/templates/jinja_bad.html +++ /dev/null @@ -1,13 +0,0 @@ -<html> - -<head> - <title>Hello, {{name}}!</title> -</head> - -<body> - <h1>Hello, {{name}}!</h1> -</body> -{# open a block without and name #} -{% block %} - -</html> diff --git a/pecan/tests/templates/kajiki.html b/pecan/tests/templates/kajiki.html deleted file mode 100644 index 41c308c..0000000 --- a/pecan/tests/templates/kajiki.html +++ /dev/null @@ -1,11 +0,0 @@ -<html> - -<head> - <title>Hello, ${name}!</title> -</head> - -<body> - <h1>Hello, ${name}!</h1> -</body> - -</html> diff --git a/pecan/tests/templates/mako.html b/pecan/tests/templates/mako.html deleted file mode 100644 index db60fec..0000000 --- a/pecan/tests/templates/mako.html +++ /dev/null @@ -1,11 +0,0 @@ -<html> - -<head> - <title>Hello, ${name}!</title> -</head> - -<body> - <h1>Hello, ${name}!</h1> -</body> - -</html>
\ No newline at end of file diff --git a/pecan/tests/templates/mako_bad.html b/pecan/tests/templates/mako_bad.html deleted file mode 100644 index e6caea2..0000000 --- a/pecan/tests/templates/mako_bad.html +++ /dev/null @@ -1,6 +0,0 @@ -<% - - def bad_indentation: -return None - -%> diff --git a/pecan/tests/test_base.py b/pecan/tests/test_base.py deleted file mode 100644 index 8558f82..0000000 --- a/pecan/tests/test_base.py +++ /dev/null @@ -1,2227 +0,0 @@ -# -*- coding: utf-8 -*- - -import sys -import os -import json -import traceback -import warnings - -import webob -from webob.exc import HTTPNotFound -import mock -from webtest import TestApp -import six -from six import b as b_ -from six import u as u_ -from six.moves import cStringIO as StringIO - -from pecan import ( - Pecan, Request, Response, expose, request, response, redirect, - abort, make_app, override_template, render, route -) -from pecan.templating import ( - _builtin_renderers as builtin_renderers, error_formatters -) -from pecan.decorators import accept_noncanonical -from pecan.tests import PecanTestCase - -if sys.version_info < (2, 7): - import unittest2 as unittest # pragma: nocover -else: - import unittest # pragma: nocover - - -class SampleRootController(object): - pass - - -class TestAppRoot(PecanTestCase): - - def test_controller_lookup_by_string_path(self): - app = Pecan('pecan.tests.test_base.SampleRootController') - assert app.root and isinstance(app.root, SampleRootController) - - -class TestEmptyContent(PecanTestCase): - @property - def app_(self): - class RootController(object): - @expose() - def index(self): - pass - - @expose() - def explicit_body(self): - response.body = b_('Hello, World!') - - @expose() - def empty_body(self): - response.body = b_('') - - @expose() - def explicit_text(self): - response.text = six.text_type('Hello, World!') - - @expose() - def empty_text(self): - response.text = six.text_type('') - - @expose() - def explicit_json(self): - response.json = {'foo': 'bar'} - - @expose() - def explicit_json_body(self): - response.json_body = {'foo': 'bar'} - - @expose() - def non_unicode(self): - return chr(0xc0) - - return TestApp(Pecan(RootController())) - - def test_empty_index(self): - r = self.app_.get('/') - self.assertEqual(r.status_int, 204) - self.assertNotIn('Content-Type', r.headers) - self.assertEqual(r.headers['Content-Length'], '0') - self.assertEqual(len(r.body), 0) - - def test_index_with_non_unicode(self): - r = self.app_.get('/non_unicode/') - self.assertEqual(r.status_int, 200) - - def test_explicit_body(self): - r = self.app_.get('/explicit_body/') - self.assertEqual(r.status_int, 200) - self.assertEqual(r.body, b_('Hello, World!')) - - def test_empty_body(self): - r = self.app_.get('/empty_body/') - self.assertEqual(r.status_int, 204) - self.assertEqual(r.body, b_('')) - - def test_explicit_text(self): - r = self.app_.get('/explicit_text/') - self.assertEqual(r.status_int, 200) - self.assertEqual(r.body, b_('Hello, World!')) - - def test_empty_text(self): - r = self.app_.get('/empty_text/') - self.assertEqual(r.status_int, 204) - self.assertEqual(r.body, b_('')) - - def test_explicit_json(self): - r = self.app_.get('/explicit_json/') - self.assertEqual(r.status_int, 200) - json_resp = json.loads(r.body.decode()) - assert json_resp == {'foo': 'bar'} - - def test_explicit_json_body(self): - r = self.app_.get('/explicit_json_body/') - self.assertEqual(r.status_int, 200) - json_resp = json.loads(r.body.decode()) - assert json_resp == {'foo': 'bar'} - - -class TestAppIterFile(PecanTestCase): - @property - def app_(self): - class RootController(object): - @expose() - def index(self): - body = six.BytesIO(b_('Hello, World!')) - response.body_file = body - - @expose() - def empty(self): - body = six.BytesIO(b_('')) - response.body_file = body - - return TestApp(Pecan(RootController())) - - def test_body_generator(self): - r = self.app_.get('/') - self.assertEqual(r.status_int, 200) - assert r.body == b_('Hello, World!') - - def test_empty_body_generator(self): - r = self.app_.get('/empty') - self.assertEqual(r.status_int, 204) - assert len(r.body) == 0 - - -class TestInvalidURLEncoding(PecanTestCase): - - @property - def app_(self): - class RootController(object): - - @expose() - def _route(self, args, request): - assert request.path - - return TestApp(Pecan(RootController())) - - def test_rest_with_non_utf_8_body(self): - r = self.app_.get('/%aa/', expect_errors=True) - assert r.status_int == 400 - - -class TestIndexRouting(PecanTestCase): - - @property - def app_(self): - class RootController(object): - @expose() - def index(self): - return 'Hello, World!' - - return TestApp(Pecan(RootController())) - - def test_empty_root(self): - r = self.app_.get('/') - assert r.status_int == 200 - assert r.body == b_('Hello, World!') - - def test_index(self): - r = self.app_.get('/index') - assert r.status_int == 200 - assert r.body == b_('Hello, World!') - - def test_index_html(self): - r = self.app_.get('/index.html') - assert r.status_int == 200 - assert r.body == b_('Hello, World!') - - -class TestObjectDispatch(PecanTestCase): - - @property - def app_(self): - class SubSubController(object): - @expose() - def index(self): - return '/sub/sub/' - - @expose() - def deeper(self): - return '/sub/sub/deeper' - - class SubController(object): - @expose() - def index(self): - return '/sub/' - - @expose() - def deeper(self): - return '/sub/deeper' - - sub = SubSubController() - - class RootController(object): - @expose() - def index(self): - return '/' - - @expose() - def deeper(self): - return '/deeper' - - sub = SubController() - - return TestApp(Pecan(RootController())) - - def test_index(self): - r = self.app_.get('/') - assert r.status_int == 200 - assert r.body == b_('/') - - def test_one_level(self): - r = self.app_.get('/deeper') - assert r.status_int == 200 - assert r.body == b_('/deeper') - - def test_one_level_with_trailing(self): - r = self.app_.get('/sub/') - assert r.status_int == 200 - assert r.body == b_('/sub/') - - def test_two_levels(self): - r = self.app_.get('/sub/deeper') - assert r.status_int == 200 - assert r.body == b_('/sub/deeper') - - def test_two_levels_with_trailing(self): - r = self.app_.get('/sub/sub/') - assert r.status_int == 200 - - def test_three_levels(self): - r = self.app_.get('/sub/sub/deeper') - assert r.status_int == 200 - assert r.body == b_('/sub/sub/deeper') - - -@unittest.skipIf(not six.PY3, "tests are Python3 specific") -class TestUnicodePathSegments(PecanTestCase): - - def test_unicode_methods(self): - class RootController(object): - pass - setattr(RootController, '🌰', expose()(lambda self: 'Hello, World!')) - app = TestApp(Pecan(RootController())) - - resp = app.get('/%F0%9F%8C%B0/') - assert resp.status_int == 200 - assert resp.body == b_('Hello, World!') - - def test_unicode_child(self): - class ChildController(object): - @expose() - def index(self): - return 'Hello, World!' - - class RootController(object): - pass - setattr(RootController, '🌰', ChildController()) - app = TestApp(Pecan(RootController())) - - resp = app.get('/%F0%9F%8C%B0/') - assert resp.status_int == 200 - assert resp.body == b_('Hello, World!') - - -class TestLookups(PecanTestCase): - - @property - def app_(self): - class LookupController(object): - def __init__(self, someID): - self.someID = someID - - @expose() - def index(self): - return '/%s' % self.someID - - @expose() - def name(self): - return '/%s/name' % self.someID - - class RootController(object): - @expose() - def index(self): - return '/' - - @expose() - def _lookup(self, someID, *remainder): - return LookupController(someID), remainder - - return TestApp(Pecan(RootController())) - - def test_index(self): - r = self.app_.get('/') - assert r.status_int == 200 - assert r.body == b_('/') - - def test_lookup(self): - r = self.app_.get('/100/') - assert r.status_int == 200 - assert r.body == b_('/100') - - def test_lookup_with_method(self): - r = self.app_.get('/100/name') - assert r.status_int == 200 - assert r.body == b_('/100/name') - - def test_lookup_with_wrong_argspec(self): - class RootController(object): - @expose() - def _lookup(self, someID): - return 'Bad arg spec' # pragma: nocover - - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - app = TestApp(Pecan(RootController())) - r = app.get('/foo/bar', expect_errors=True) - assert r.status_int == 404 - - -class TestCanonicalLookups(PecanTestCase): - - @property - def app_(self): - class LookupController(object): - def __init__(self, someID): - self.someID = someID - - @expose() - def index(self): - return self.someID - - class UserController(object): - @expose() - def _lookup(self, someID, *remainder): - return LookupController(someID), remainder - - class RootController(object): - users = UserController() - - return TestApp(Pecan(RootController())) - - def test_canonical_lookup(self): - assert self.app_.get('/users', expect_errors=404).status_int == 404 - assert self.app_.get('/users/', expect_errors=404).status_int == 404 - assert self.app_.get('/users/100').status_int == 302 - assert self.app_.get('/users/100/').body == b_('100') - - -class TestControllerArguments(PecanTestCase): - - @property - def app_(self): - class RootController(object): - @expose() - def index(self, id): - return 'index: %s' % id - - @expose() - def multiple(self, one, two): - return 'multiple: %s, %s' % (one, two) - - @expose() - def optional(self, id=None): - return 'optional: %s' % str(id) - - @expose() - def multiple_optional(self, one=None, two=None, three=None): - return 'multiple_optional: %s, %s, %s' % (one, two, three) - - @expose() - def variable_args(self, *args): - return 'variable_args: %s' % ', '.join(args) - - @expose() - def variable_kwargs(self, **kwargs): - data = [ - '%s=%s' % (key, kwargs[key]) - for key in sorted(kwargs.keys()) - ] - return 'variable_kwargs: %s' % ', '.join(data) - - @expose() - def variable_all(self, *args, **kwargs): - data = [ - '%s=%s' % (key, kwargs[key]) - for key in sorted(kwargs.keys()) - ] - return 'variable_all: %s' % ', '.join(list(args) + data) - - @expose() - def eater(self, id, dummy=None, *args, **kwargs): - data = [ - '%s=%s' % (key, kwargs[key]) - for key in sorted(kwargs.keys()) - ] - return 'eater: %s, %s, %s' % ( - id, - dummy, - ', '.join(list(args) + data) - ) - - @staticmethod - @expose() - def static(id): - return "id is %s" % id - - @expose() - def _route(self, args, request): - if hasattr(self, args[0]): - return getattr(self, args[0]), args[1:] - else: - return self.index, args - - return TestApp(Pecan(RootController())) - - def test_required_argument(self): - try: - r = self.app_.get('/') - assert r.status_int != 200 # pragma: nocover - except Exception as ex: - assert type(ex) == TypeError - assert ex.args[0] in ( - "index() takes exactly 2 arguments (1 given)", - "index() missing 1 required positional argument: 'id'" - ) # this messaging changed in Python 3.3 - - def test_single_argument(self): - r = self.app_.get('/1') - assert r.status_int == 200 - assert r.body == b_('index: 1') - - def test_single_argument_with_encoded_url(self): - r = self.app_.get('/This%20is%20a%20test%21') - assert r.status_int == 200 - assert r.body == b_('index: This is a test!') - - def test_single_argument_with_plus(self): - r = self.app_.get('/foo+bar') - assert r.status_int == 200 - assert r.body == b_('index: foo+bar') - - def test_single_argument_with_encoded_plus(self): - r = self.app_.get('/foo%2Bbar') - assert r.status_int == 200 - assert r.body == b_('index: foo+bar') - - def test_two_arguments(self): - r = self.app_.get('/1/dummy', status=404) - assert r.status_int == 404 - - def test_keyword_argument(self): - r = self.app_.get('/?id=2') - assert r.status_int == 200 - assert r.body == b_('index: 2') - - def test_keyword_argument_with_encoded_url(self): - r = self.app_.get('/?id=This%20is%20a%20test%21') - assert r.status_int == 200 - assert r.body == b_('index: This is a test!') - - def test_keyword_argument_with_plus(self): - r = self.app_.get('/?id=foo+bar') - assert r.status_int == 200 - assert r.body == b_('index: foo bar') - - def test_keyword_argument_with_encoded_plus(self): - r = self.app_.get('/?id=foo%2Bbar') - assert r.status_int == 200 - assert r.body == b_('index: foo+bar') - - def test_argument_and_keyword_argument(self): - r = self.app_.get('/3?id=three') - assert r.status_int == 200 - assert r.body == b_('index: 3') - - def test_encoded_argument_and_keyword_argument(self): - r = self.app_.get('/This%20is%20a%20test%21?id=three') - assert r.status_int == 200 - assert r.body == b_('index: This is a test!') - - def test_explicit_kwargs(self): - r = self.app_.post('/', {'id': '4'}) - assert r.status_int == 200 - assert r.body == b_('index: 4') - - def test_path_with_explicit_kwargs(self): - r = self.app_.post('/4', {'id': 'four'}) - assert r.status_int == 200 - assert r.body == b_('index: 4') - - def test_explicit_json_kwargs(self): - r = self.app_.post_json('/', {'id': '4'}) - assert r.status_int == 200 - assert r.body == b_('index: 4') - - def test_path_with_explicit_json_kwargs(self): - r = self.app_.post_json('/4', {'id': 'four'}) - assert r.status_int == 200 - assert r.body == b_('index: 4') - - def test_multiple_kwargs(self): - r = self.app_.get('/?id=5&dummy=dummy') - assert r.status_int == 200 - assert r.body == b_('index: 5') - - def test_kwargs_from_root(self): - r = self.app_.post('/', {'id': '6', 'dummy': 'dummy'}) - assert r.status_int == 200 - assert r.body == b_('index: 6') - - def test_json_kwargs_from_root(self): - r = self.app_.post_json('/', {'id': '6', 'dummy': 'dummy'}) - assert r.status_int == 200 - assert r.body == b_('index: 6') - - # multiple args - - def test_multiple_positional_arguments(self): - r = self.app_.get('/multiple/one/two') - assert r.status_int == 200 - assert r.body == b_('multiple: one, two') - - def test_multiple_positional_arguments_with_url_encode(self): - r = self.app_.get('/multiple/One%20/Two%21') - assert r.status_int == 200 - assert r.body == b_('multiple: One , Two!') - - def test_multiple_positional_arguments_with_kwargs(self): - r = self.app_.get('/multiple?one=three&two=four') - assert r.status_int == 200 - assert r.body == b_('multiple: three, four') - - def test_multiple_positional_arguments_with_url_encoded_kwargs(self): - r = self.app_.get('/multiple?one=Three%20&two=Four%20%21') - assert r.status_int == 200 - assert r.body == b_('multiple: Three , Four !') - - def test_positional_args_with_dictionary_kwargs(self): - r = self.app_.post('/multiple', {'one': 'five', 'two': 'six'}) - assert r.status_int == 200 - assert r.body == b_('multiple: five, six') - - def test_positional_args_with_json_kwargs(self): - r = self.app_.post_json('/multiple', {'one': 'five', 'two': 'six'}) - assert r.status_int == 200 - assert r.body == b_('multiple: five, six') - - def test_positional_args_with_url_encoded_dictionary_kwargs(self): - r = self.app_.post('/multiple', {'one': 'Five%20', 'two': 'Six%20%21'}) - assert r.status_int == 200 - assert r.body == b_('multiple: Five%20, Six%20%21') - - # optional arg - def test_optional_arg(self): - r = self.app_.get('/optional') - assert r.status_int == 200 - assert r.body == b_('optional: None') - - def test_multiple_optional(self): - r = self.app_.get('/optional/1') - assert r.status_int == 200 - assert r.body == b_('optional: 1') - - def test_multiple_optional_url_encoded(self): - r = self.app_.get('/optional/Some%20Number') - assert r.status_int == 200 - assert r.body == b_('optional: Some Number') - - def test_multiple_optional_missing(self): - r = self.app_.get('/optional/2/dummy', status=404) - assert r.status_int == 404 - - def test_multiple_with_kwargs(self): - r = self.app_.get('/optional?id=2') - assert r.status_int == 200 - assert r.body == b_('optional: 2') - - def test_multiple_with_url_encoded_kwargs(self): - r = self.app_.get('/optional?id=Some%20Number') - assert r.status_int == 200 - assert r.body == b_('optional: Some Number') - - def test_multiple_args_with_url_encoded_kwargs(self): - r = self.app_.get('/optional/3?id=three') - assert r.status_int == 200 - assert r.body == b_('optional: 3') - - def test_url_encoded_positional_args(self): - r = self.app_.get('/optional/Some%20Number?id=three') - assert r.status_int == 200 - assert r.body == b_('optional: Some Number') - - def test_optional_arg_with_kwargs(self): - r = self.app_.post('/optional', {'id': '4'}) - assert r.status_int == 200 - assert r.body == b_('optional: 4') - - def test_optional_arg_with_json_kwargs(self): - r = self.app_.post_json('/optional', {'id': '4'}) - assert r.status_int == 200 - assert r.body == b_('optional: 4') - - def test_optional_arg_with_url_encoded_kwargs(self): - r = self.app_.post('/optional', {'id': 'Some%20Number'}) - assert r.status_int == 200 - assert r.body == b_('optional: Some%20Number') - - def test_multiple_positional_arguments_with_dictionary_kwargs(self): - r = self.app_.post('/optional/5', {'id': 'five'}) - assert r.status_int == 200 - assert r.body == b_('optional: 5') - - def test_multiple_positional_arguments_with_json_kwargs(self): - r = self.app_.post_json('/optional/5', {'id': 'five'}) - assert r.status_int == 200 - assert r.body == b_('optional: 5') - - def test_multiple_positional_url_encoded_arguments_with_kwargs(self): - r = self.app_.post('/optional/Some%20Number', {'id': 'five'}) - assert r.status_int == 200 - assert r.body == b_('optional: Some Number') - - def test_optional_arg_with_multiple_kwargs(self): - r = self.app_.get('/optional?id=6&dummy=dummy') - assert r.status_int == 200 - assert r.body == b_('optional: 6') - - def test_optional_arg_with_multiple_url_encoded_kwargs(self): - r = self.app_.get('/optional?id=Some%20Number&dummy=dummy') - assert r.status_int == 200 - assert r.body == b_('optional: Some Number') - - def test_optional_arg_with_multiple_dictionary_kwargs(self): - r = self.app_.post('/optional', {'id': '7', 'dummy': 'dummy'}) - assert r.status_int == 200 - assert r.body == b_('optional: 7') - - def test_optional_arg_with_multiple_json_kwargs(self): - r = self.app_.post_json('/optional', {'id': '7', 'dummy': 'dummy'}) - assert r.status_int == 200 - assert r.body == b_('optional: 7') - - def test_optional_arg_with_multiple_url_encoded_dictionary_kwargs(self): - r = self.app_.post('/optional', { - 'id': 'Some%20Number', - 'dummy': 'dummy' - }) - assert r.status_int == 200 - assert r.body == b_('optional: Some%20Number') - - # multiple optional args - - def test_multiple_optional_positional_args(self): - r = self.app_.get('/multiple_optional') - assert r.status_int == 200 - assert r.body == b_('multiple_optional: None, None, None') - - def test_multiple_optional_positional_args_one_arg(self): - r = self.app_.get('/multiple_optional/1') - assert r.status_int == 200 - assert r.body == b_('multiple_optional: 1, None, None') - - def test_multiple_optional_positional_args_one_url_encoded_arg(self): - r = self.app_.get('/multiple_optional/One%21') - assert r.status_int == 200 - assert r.body == b_('multiple_optional: One!, None, None') - - def test_multiple_optional_positional_args_all_args(self): - r = self.app_.get('/multiple_optional/1/2/3') - assert r.status_int == 200 - assert r.body == b_('multiple_optional: 1, 2, 3') - - def test_multiple_optional_positional_args_all_url_encoded_args(self): - r = self.app_.get('/multiple_optional/One%21/Two%21/Three%21') - assert r.status_int == 200 - assert r.body == b_('multiple_optional: One!, Two!, Three!') - - def test_multiple_optional_positional_args_too_many_args(self): - r = self.app_.get('/multiple_optional/1/2/3/dummy', status=404) - assert r.status_int == 404 - - def test_multiple_optional_positional_args_with_kwargs(self): - r = self.app_.get('/multiple_optional?one=1') - assert r.status_int == 200 - assert r.body == b_('multiple_optional: 1, None, None') - - def test_multiple_optional_positional_args_with_url_encoded_kwargs(self): - r = self.app_.get('/multiple_optional?one=One%21') - assert r.status_int == 200 - assert r.body == b_('multiple_optional: One!, None, None') - - def test_multiple_optional_positional_args_with_string_kwargs(self): - r = self.app_.get('/multiple_optional/1?one=one') - assert r.status_int == 200 - assert r.body == b_('multiple_optional: 1, None, None') - - def test_multiple_optional_positional_args_with_encoded_str_kwargs(self): - r = self.app_.get('/multiple_optional/One%21?one=one') - assert r.status_int == 200 - assert r.body == b_('multiple_optional: One!, None, None') - - def test_multiple_optional_positional_args_with_dict_kwargs(self): - r = self.app_.post('/multiple_optional', {'one': '1'}) - assert r.status_int == 200 - assert r.body == b_('multiple_optional: 1, None, None') - - def test_multiple_optional_positional_args_with_json_kwargs(self): - r = self.app_.post_json('/multiple_optional', {'one': '1'}) - assert r.status_int == 200 - assert r.body == b_('multiple_optional: 1, None, None') - - def test_multiple_optional_positional_args_with_encoded_dict_kwargs(self): - r = self.app_.post('/multiple_optional', {'one': 'One%21'}) - assert r.status_int == 200 - assert r.body == b_('multiple_optional: One%21, None, None') - - def test_multiple_optional_positional_args_and_dict_kwargs(self): - r = self.app_.post('/multiple_optional/1', {'one': 'one'}) - assert r.status_int == 200 - assert r.body == b_('multiple_optional: 1, None, None') - - def test_multiple_optional_positional_args_and_json_kwargs(self): - r = self.app_.post_json('/multiple_optional/1', {'one': 'one'}) - assert r.status_int == 200 - assert r.body == b_('multiple_optional: 1, None, None') - - def test_multiple_optional_encoded_positional_args_and_dict_kwargs(self): - r = self.app_.post('/multiple_optional/One%21', {'one': 'one'}) - assert r.status_int == 200 - assert r.body == b_('multiple_optional: One!, None, None') - - def test_multiple_optional_args_with_multiple_kwargs(self): - r = self.app_.get('/multiple_optional?one=1&two=2&three=3&four=4') - assert r.status_int == 200 - assert r.body == b_('multiple_optional: 1, 2, 3') - - def test_multiple_optional_args_with_multiple_encoded_kwargs(self): - r = self.app_.get( - '/multiple_optional?one=One%21&two=Two%21&three=Three%21&four=4' - ) - assert r.status_int == 200 - assert r.body == b_('multiple_optional: One!, Two!, Three!') - - def test_multiple_optional_args_with_multiple_dict_kwargs(self): - r = self.app_.post( - '/multiple_optional', - {'one': '1', 'two': '2', 'three': '3', 'four': '4'} - ) - assert r.status_int == 200 - assert r.body == b_('multiple_optional: 1, 2, 3') - - def test_multiple_optional_args_with_multiple_json_kwargs(self): - r = self.app_.post_json( - '/multiple_optional', - {'one': '1', 'two': '2', 'three': '3', 'four': '4'} - ) - assert r.status_int == 200 - assert r.body == b_('multiple_optional: 1, 2, 3') - - def test_multiple_optional_args_with_multiple_encoded_dict_kwargs(self): - r = self.app_.post( - '/multiple_optional', - { - 'one': 'One%21', - 'two': 'Two%21', - 'three': 'Three%21', - 'four': '4' - } - ) - assert r.status_int == 200 - assert r.body == b_('multiple_optional: One%21, Two%21, Three%21') - - def test_multiple_optional_args_with_last_kwarg(self): - r = self.app_.get('/multiple_optional?three=3') - assert r.status_int == 200 - assert r.body == b_('multiple_optional: None, None, 3') - - def test_multiple_optional_args_with_last_encoded_kwarg(self): - r = self.app_.get('/multiple_optional?three=Three%21') - assert r.status_int == 200 - assert r.body == b_('multiple_optional: None, None, Three!') - - def test_multiple_optional_args_with_middle_arg(self): - r = self.app_.get('/multiple_optional', {'two': '2'}) - assert r.status_int == 200 - assert r.body == b_('multiple_optional: None, 2, None') - - def test_variable_args(self): - r = self.app_.get('/variable_args') - assert r.status_int == 200 - assert r.body == b_('variable_args: ') - - def test_multiple_variable_args(self): - r = self.app_.get('/variable_args/1/dummy') - assert r.status_int == 200 - assert r.body == b_('variable_args: 1, dummy') - - def test_multiple_encoded_variable_args(self): - r = self.app_.get('/variable_args/Testing%20One%20Two/Three%21') - assert r.status_int == 200 - assert r.body == b_('variable_args: Testing One Two, Three!') - - def test_variable_args_with_kwargs(self): - r = self.app_.get('/variable_args?id=2&dummy=dummy') - assert r.status_int == 200 - assert r.body == b_('variable_args: ') - - def test_variable_args_with_dict_kwargs(self): - r = self.app_.post('/variable_args', {'id': '3', 'dummy': 'dummy'}) - assert r.status_int == 200 - assert r.body == b_('variable_args: ') - - def test_variable_args_with_json_kwargs(self): - r = self.app_.post_json( - '/variable_args', - {'id': '3', 'dummy': 'dummy'} - ) - assert r.status_int == 200 - assert r.body == b_('variable_args: ') - - def test_variable_kwargs(self): - r = self.app_.get('/variable_kwargs') - assert r.status_int == 200 - assert r.body == b_('variable_kwargs: ') - - def test_multiple_variable_kwargs(self): - r = self.app_.get('/variable_kwargs/1/dummy', status=404) - assert r.status_int == 404 - - def test_multiple_variable_kwargs_with_explicit_kwargs(self): - r = self.app_.get('/variable_kwargs?id=2&dummy=dummy') - assert r.status_int == 200 - assert r.body == b_('variable_kwargs: dummy=dummy, id=2') - - def test_multiple_variable_kwargs_with_explicit_encoded_kwargs(self): - r = self.app_.get( - '/variable_kwargs?id=Two%21&dummy=This%20is%20a%20test' - ) - assert r.status_int == 200 - assert r.body == b_('variable_kwargs: dummy=This is a test, id=Two!') - - def test_multiple_variable_kwargs_with_dict_kwargs(self): - r = self.app_.post('/variable_kwargs', {'id': '3', 'dummy': 'dummy'}) - assert r.status_int == 200 - assert r.body == b_('variable_kwargs: dummy=dummy, id=3') - - def test_multiple_variable_kwargs_with_json_kwargs(self): - r = self.app_.post_json( - '/variable_kwargs', - {'id': '3', 'dummy': 'dummy'} - ) - assert r.status_int == 200 - assert r.body == b_('variable_kwargs: dummy=dummy, id=3') - - def test_multiple_variable_kwargs_with_encoded_dict_kwargs(self): - r = self.app_.post( - '/variable_kwargs', - {'id': 'Three%21', 'dummy': 'This%20is%20a%20test'} - ) - assert r.status_int == 200 - result = 'variable_kwargs: dummy=This%20is%20a%20test, id=Three%21' - assert r.body == b_(result) - - def test_variable_all(self): - r = self.app_.get('/variable_all') - assert r.status_int == 200 - assert r.body == b_('variable_all: ') - - def test_variable_all_with_one_extra(self): - r = self.app_.get('/variable_all/1') - assert r.status_int == 200 - assert r.body == b_('variable_all: 1') - - def test_variable_all_with_two_extras(self): - r = self.app_.get('/variable_all/2/dummy') - assert r.status_int == 200 - assert r.body == b_('variable_all: 2, dummy') - - def test_variable_mixed(self): - r = self.app_.get('/variable_all/3?month=1&day=12') - assert r.status_int == 200 - assert r.body == b_('variable_all: 3, day=12, month=1') - - def test_variable_mixed_explicit(self): - r = self.app_.get('/variable_all/4?id=four&month=1&day=12') - assert r.status_int == 200 - assert r.body == b_('variable_all: 4, day=12, id=four, month=1') - - def test_variable_post(self): - r = self.app_.post('/variable_all/5/dummy') - assert r.status_int == 200 - assert r.body == b_('variable_all: 5, dummy') - - def test_variable_post_with_kwargs(self): - r = self.app_.post('/variable_all/6', {'month': '1', 'day': '12'}) - assert r.status_int == 200 - assert r.body == b_('variable_all: 6, day=12, month=1') - - def test_variable_post_with_json_kwargs(self): - r = self.app_.post_json( - '/variable_all/6', - {'month': '1', 'day': '12'} - ) - assert r.status_int == 200 - assert r.body == b_('variable_all: 6, day=12, month=1') - - def test_variable_post_mixed(self): - r = self.app_.post( - '/variable_all/7', - {'id': 'seven', 'month': '1', 'day': '12'} - ) - assert r.status_int == 200 - assert r.body == b_('variable_all: 7, day=12, id=seven, month=1') - - def test_variable_post_mixed_with_json(self): - r = self.app_.post_json( - '/variable_all/7', - {'id': 'seven', 'month': '1', 'day': '12'} - ) - assert r.status_int == 200 - assert r.body == b_('variable_all: 7, day=12, id=seven, month=1') - - def test_duplicate_query_parameters_GET(self): - r = self.app_.get('/variable_kwargs?list=1&list=2') - l = [u_('1'), u_('2')] - assert r.status_int == 200 - assert r.body == b_('variable_kwargs: list=%s' % l) - - def test_duplicate_query_parameters_POST(self): - r = self.app_.post('/variable_kwargs', - {'list': ['1', '2']}) - l = [u_('1'), u_('2')] - assert r.status_int == 200 - assert r.body == b_('variable_kwargs: list=%s' % l) - - def test_duplicate_query_parameters_POST_mixed(self): - r = self.app_.post('/variable_kwargs?list=1&list=2', - {'list': ['3', '4']}) - l = [u_('1'), u_('2'), u_('3'), u_('4')] - assert r.status_int == 200 - assert r.body == b_('variable_kwargs: list=%s' % l) - - def test_duplicate_query_parameters_POST_mixed_json(self): - r = self.app_.post('/variable_kwargs?list=1&list=2', - {'list': 3}) - l = [u_('1'), u_('2'), u_('3')] - assert r.status_int == 200 - assert r.body == b_('variable_kwargs: list=%s' % l) - - def test_staticmethod(self): - r = self.app_.get('/static/foobar') - assert r.status_int == 200 - assert r.body == b_('id is foobar') - - def test_no_remainder(self): - try: - r = self.app_.get('/eater') - assert r.status_int != 200 # pragma: nocover - except Exception as ex: - assert type(ex) == TypeError - assert ex.args[0] in ( - "eater() takes at least 2 arguments (1 given)", - "eater() missing 1 required positional argument: 'id'" - ) # this messaging changed in Python 3.3 - - def test_one_remainder(self): - r = self.app_.get('/eater/1') - assert r.status_int == 200 - assert r.body == b_('eater: 1, None, ') - - def test_two_remainders(self): - r = self.app_.get('/eater/2/dummy') - assert r.status_int == 200 - assert r.body == b_('eater: 2, dummy, ') - - def test_many_remainders(self): - r = self.app_.get('/eater/3/dummy/foo/bar') - assert r.status_int == 200 - assert r.body == b_('eater: 3, dummy, foo, bar') - - def test_remainder_with_kwargs(self): - r = self.app_.get('/eater/4?month=1&day=12') - assert r.status_int == 200 - assert r.body == b_('eater: 4, None, day=12, month=1') - - def test_remainder_with_many_kwargs(self): - r = self.app_.get('/eater/5?id=five&month=1&day=12&dummy=dummy') - assert r.status_int == 200 - assert r.body == b_('eater: 5, dummy, day=12, month=1') - - def test_post_remainder(self): - r = self.app_.post('/eater/6') - assert r.status_int == 200 - assert r.body == b_('eater: 6, None, ') - - def test_post_three_remainders(self): - r = self.app_.post('/eater/7/dummy') - assert r.status_int == 200 - assert r.body == b_('eater: 7, dummy, ') - - def test_post_many_remainders(self): - r = self.app_.post('/eater/8/dummy/foo/bar') - assert r.status_int == 200 - assert r.body == b_('eater: 8, dummy, foo, bar') - - def test_post_remainder_with_kwargs(self): - r = self.app_.post('/eater/9', {'month': '1', 'day': '12'}) - assert r.status_int == 200 - assert r.body == b_('eater: 9, None, day=12, month=1') - - def test_post_empty_remainder_with_json_kwargs(self): - r = self.app_.post_json('/eater/9/', {'month': '1', 'day': '12'}) - assert r.status_int == 200 - assert r.body == b_('eater: 9, None, day=12, month=1') - - def test_post_remainder_with_json_kwargs(self): - r = self.app_.post_json('/eater/9', {'month': '1', 'day': '12'}) - assert r.status_int == 200 - assert r.body == b_('eater: 9, None, day=12, month=1') - - def test_post_many_remainders_with_many_kwargs(self): - r = self.app_.post( - '/eater/10', - {'id': 'ten', 'month': '1', 'day': '12', 'dummy': 'dummy'} - ) - assert r.status_int == 200 - assert r.body == b_('eater: 10, dummy, day=12, month=1') - - def test_post_many_remainders_with_many_json_kwargs(self): - r = self.app_.post_json( - '/eater/10', - {'id': 'ten', 'month': '1', 'day': '12', 'dummy': 'dummy'} - ) - assert r.status_int == 200 - assert r.body == b_('eater: 10, dummy, day=12, month=1') - - -class TestDefaultErrorRendering(PecanTestCase): - - def test_plain_error(self): - class RootController(object): - pass - - app = TestApp(Pecan(RootController())) - r = app.get('/', status=404) - assert r.status_int == 404 - assert r.content_type == 'text/plain' - assert r.body == b_(HTTPNotFound().plain_body({})) - - def test_html_error(self): - class RootController(object): - pass - - app = TestApp(Pecan(RootController())) - r = app.get('/', headers={'Accept': 'text/html'}, status=404) - assert r.status_int == 404 - assert r.content_type == 'text/html' - assert r.body == b_(HTTPNotFound().html_body({})) - - def test_json_error(self): - class RootController(object): - pass - - app = TestApp(Pecan(RootController())) - r = app.get('/', headers={'Accept': 'application/json'}, status=404) - assert r.status_int == 404 - json_resp = json.loads(r.body.decode()) - assert json_resp['code'] == 404 - assert json_resp['description'] is None - assert json_resp['title'] == 'Not Found' - assert r.content_type == 'application/json' - - -class TestAbort(PecanTestCase): - - def test_abort(self): - class RootController(object): - @expose() - def index(self): - abort(404) - - app = TestApp(Pecan(RootController())) - r = app.get('/', status=404) - assert r.status_int == 404 - - def test_abort_with_detail(self): - class RootController(object): - @expose() - def index(self): - abort(status_code=401, detail='Not Authorized') - - app = TestApp(Pecan(RootController())) - r = app.get('/', status=401) - assert r.status_int == 401 - - def test_abort_keeps_traceback(self): - last_exc, last_traceback = None, None - - try: - try: - raise Exception('Bottom Exception') - except: - abort(404) - except Exception: - last_exc, _, last_traceback = sys.exc_info() - - assert last_exc is HTTPNotFound - assert 'Bottom Exception' in traceback.format_tb(last_traceback)[-1] - - -class TestScriptName(PecanTestCase): - - def setUp(self): - super(TestScriptName, self).setUp() - self.environ = {'SCRIPT_NAME': '/foo'} - - def test_handle_script_name(self): - class RootController(object): - @expose() - def index(self): - return 'Root Index' - - app = TestApp(Pecan(RootController()), extra_environ=self.environ) - r = app.get('/foo/') - assert r.status_int == 200 - - -class TestRedirect(PecanTestCase): - - @property - def app_(self): - class RootController(object): - @expose() - def index(self): - redirect('/testing') - - @expose() - def internal(self): - redirect('/testing', internal=True) - - @expose() - def bad_internal(self): - redirect('/testing', internal=True, code=301) - - @expose() - def permanent(self): - redirect('/testing', code=301) - - @expose() - def testing(self): - return 'it worked!' - - return TestApp(make_app(RootController(), debug=False)) - - def test_index(self): - r = self.app_.get('/') - assert r.status_int == 302 - r = r.follow() - assert r.status_int == 200 - assert r.body == b_('it worked!') - - def test_internal(self): - r = self.app_.get('/internal') - assert r.status_int == 200 - assert r.body == b_('it worked!') - - def test_internal_with_301(self): - self.assertRaises(ValueError, self.app_.get, '/bad_internal') - - def test_permanent_redirect(self): - r = self.app_.get('/permanent') - assert r.status_int == 301 - r = r.follow() - assert r.status_int == 200 - assert r.body == b_('it worked!') - - def test_x_forward_proto(self): - class ChildController(object): - @expose() - def index(self): - redirect('/testing') # pragma: nocover - - class RootController(object): - @expose() - def index(self): - redirect('/testing') # pragma: nocover - - @expose() - def testing(self): - return 'it worked!' # pragma: nocover - child = ChildController() - - app = TestApp(make_app(RootController(), debug=True)) - res = app.get( - '/child', extra_environ=dict(HTTP_X_FORWARDED_PROTO='https') - ) - # non-canonical url will redirect, so we won't get a 301 - assert res.status_int == 302 - # should add trailing / and changes location to https - assert res.location == 'https://localhost/child/' - assert res.request.environ['HTTP_X_FORWARDED_PROTO'] == 'https' - - -class TestInternalRedirectContext(PecanTestCase): - - @property - def app_(self): - class RootController(object): - - @expose() - def redirect_with_context(self): - request.context['foo'] = 'bar' - redirect('/testing') - - @expose() - def internal_with_context(self): - request.context['foo'] = 'bar' - redirect('/testing', internal=True) - - @expose('json') - def testing(self): - return request.context - - return TestApp(make_app(RootController(), debug=False)) - - def test_internal_with_request_context(self): - r = self.app_.get('/internal_with_context') - assert r.status_int == 200 - assert json.loads(r.body.decode()) == {'foo': 'bar'} - - def test_context_does_not_bleed(self): - r = self.app_.get('/redirect_with_context').follow() - assert r.status_int == 200 - assert json.loads(r.body.decode()) == {} - - -class TestStreamedResponse(PecanTestCase): - - def test_streaming_response(self): - - class RootController(object): - @expose(content_type='text/plain') - def test(self, foo): - if foo == 'stream': - # mimic large file - contents = six.BytesIO(b_('stream')) - response.content_type = 'application/octet-stream' - contents.seek(0, os.SEEK_END) - response.content_length = contents.tell() - contents.seek(0, os.SEEK_SET) - response.app_iter = contents - return response - else: - return 'plain text' - - app = TestApp(Pecan(RootController())) - r = app.get('/test/stream') - assert r.content_type == 'application/octet-stream' - assert r.body == b_('stream') - - r = app.get('/test/plain') - assert r.content_type == 'text/plain' - assert r.body == b_('plain text') - - -class TestManualResponse(PecanTestCase): - - def test_manual_response(self): - - class RootController(object): - @expose() - def index(self): - resp = webob.Response(response.environ) - resp.body = b_('Hello, World!') - return resp - - app = TestApp(Pecan(RootController())) - r = app.get('/') - assert r.body == b_('Hello, World!') - - -class TestCustomResponseandRequest(PecanTestCase): - - def test_custom_objects(self): - - class CustomRequest(Request): - - @property - def headers(self): - headers = super(CustomRequest, self).headers - headers['X-Custom-Request'] = 'ABC' - return headers - - class CustomResponse(Response): - - @property - def headers(self): - headers = super(CustomResponse, self).headers - headers['X-Custom-Response'] = 'XYZ' - return headers - - class RootController(object): - @expose() - def index(self): - return request.headers.get('X-Custom-Request') - - app = TestApp(Pecan( - RootController(), - request_cls=CustomRequest, - response_cls=CustomResponse - )) - r = app.get('/') - assert r.body == b_('ABC') - assert r.headers.get('X-Custom-Response') == 'XYZ' - - -class TestThreadLocalState(PecanTestCase): - - def test_thread_local_dir(self): - """ - Threadlocal proxies for request and response should properly - proxy ``dir()`` calls to the underlying webob class. - """ - class RootController(object): - @expose() - def index(self): - assert 'method' in dir(request) - assert 'status' in dir(response) - return '/' - - app = TestApp(Pecan(RootController())) - r = app.get('/') - assert r.status_int == 200 - assert r.body == b_('/') - - def test_request_state_cleanup(self): - """ - After a request, the state local() should be totally clean - except for state.app (so that objects don't leak between requests) - """ - from pecan.core import state - - class RootController(object): - @expose() - def index(self): - return '/' - - app = TestApp(Pecan(RootController())) - r = app.get('/') - assert r.status_int == 200 - assert r.body == b_('/') - - assert state.__dict__ == {} - - -class TestFileTypeExtensions(PecanTestCase): - - @property - def app_(self): - """ - Test extension splits - """ - class RootController(object): - @expose(content_type=None) - def _default(self, *args): - ext = request.pecan['extension'] - assert len(args) == 1 - if ext: - assert ext not in args[0] - return ext or '' - - return TestApp(Pecan(RootController())) - - def test_html_extension(self): - r = self.app_.get('/index.html') - assert r.status_int == 200 - assert r.body == b_('.html') - - def test_image_extension(self): - r = self.app_.get('/image.png') - assert r.status_int == 200 - assert r.body == b_('.png') - - def test_hidden_file(self): - r = self.app_.get('/.vimrc') - assert r.status_int == 204 - assert r.body == b_('') - - def test_multi_dot_extension(self): - r = self.app_.get('/gradient.min.js') - assert r.status_int == 200 - assert r.body == b_('.js') - - def test_bad_content_type(self): - class RootController(object): - @expose() - def index(self): - return '/' - - app = TestApp(Pecan(RootController())) - r = app.get('/') - assert r.status_int == 200 - assert r.body == b_('/') - - r = app.get('/index.html', expect_errors=True) - assert r.status_int == 200 - assert r.body == b_('/') - - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - r = app.get('/index.txt', expect_errors=True) - assert r.status_int == 404 - - def test_unknown_file_extension(self): - class RootController(object): - @expose(content_type=None) - def _default(self, *args): - assert 'example:x.tiny' in args - assert request.pecan['extension'] is None - return 'SOME VALUE' - - app = TestApp(Pecan(RootController())) - - r = app.get('/example:x.tiny') - assert r.status_int == 200 - assert r.body == b_('SOME VALUE') - - def test_guessing_disabled(self): - class RootController(object): - @expose(content_type=None) - def _default(self, *args): - assert 'index.html' in args - assert request.pecan['extension'] is None - return 'SOME VALUE' - - app = TestApp(Pecan(RootController(), - guess_content_type_from_ext=False)) - - r = app.get('/index.html') - assert r.status_int == 200 - assert r.body == b_('SOME VALUE') - - -class TestContentTypeByAcceptHeaders(PecanTestCase): - - @property - def app_(self): - """ - Test that content type is set appropriately based on Accept headers. - """ - class RootController(object): - - @expose(content_type='text/html') - @expose(content_type='application/json') - def index(self, *args): - return 'Foo' - - return TestApp(Pecan(RootController())) - - def test_quality(self): - r = self.app_.get('/', headers={ - 'Accept': 'text/html,application/json;q=0.9,*/*;q=0.8' - }) - assert r.status_int == 200 - assert r.content_type == 'text/html' - - r = self.app_.get('/', headers={ - 'Accept': 'application/json,text/html;q=0.9,*/*;q=0.8' - }) - assert r.status_int == 200 - assert r.content_type == 'application/json' - - def test_file_extension_has_higher_precedence(self): - r = self.app_.get('/index.html', headers={ - 'Accept': 'application/json,text/html;q=0.9,*/*;q=0.8' - }) - assert r.status_int == 200 - assert r.content_type == 'text/html' - - def test_not_acceptable(self): - r = self.app_.get('/', headers={ - 'Accept': 'application/xml', - }, status=406) - assert r.status_int == 406 - - def test_accept_header_missing(self): - r = self.app_.get('/') - assert r.status_int == 200 - assert r.content_type == 'text/html' - - -class TestCanonicalRouting(PecanTestCase): - - @property - def app_(self): - class ArgSubController(object): - @expose() - def index(self, arg): - return arg - - class AcceptController(object): - @accept_noncanonical - @expose() - def index(self): - return 'accept' - - class SubController(object): - @expose() - def index(self, **kw): - return 'subindex' - - class RootController(object): - @expose() - def index(self): - return 'index' - - sub = SubController() - arg = ArgSubController() - accept = AcceptController() - - return TestApp(Pecan(RootController())) - - def test_root(self): - r = self.app_.get('/') - assert r.status_int == 200 - assert b_('index') in r.body - - def test_index(self): - r = self.app_.get('/index') - assert r.status_int == 200 - assert b_('index') in r.body - - def test_broken_clients(self): - # for broken clients - r = self.app_.get('', status=302) - assert r.status_int == 302 - assert r.location == 'http://localhost/' - - def test_sub_controller_with_trailing(self): - r = self.app_.get('/sub/') - assert r.status_int == 200 - assert b_('subindex') in r.body - - def test_sub_controller_redirect(self): - r = self.app_.get('/sub', status=302) - assert r.status_int == 302 - assert r.location == 'http://localhost/sub/' - - def test_with_query_string(self): - # try with query string - r = self.app_.get('/sub?foo=bar', status=302) - assert r.status_int == 302 - assert r.location == 'http://localhost/sub/?foo=bar' - - def test_posts_fail(self): - try: - self.app_.post('/sub', dict(foo=1)) - raise Exception("Post should fail") # pragma: nocover - except Exception as e: - assert isinstance(e, RuntimeError) - - def test_with_args(self): - r = self.app_.get('/arg/index/foo') - assert r.status_int == 200 - assert r.body == b_('foo') - - def test_accept_noncanonical(self): - r = self.app_.get('/accept/') - assert r.status_int == 200 - assert r.body == b_('accept') - - def test_accept_noncanonical_no_trailing_slash(self): - r = self.app_.get('/accept') - assert r.status_int == 200 - assert r.body == b_('accept') - - -class TestNonCanonical(PecanTestCase): - - @property - def app_(self): - class ArgSubController(object): - @expose() - def index(self, arg): - return arg # pragma: nocover - - class AcceptController(object): - @accept_noncanonical - @expose() - def index(self): - return 'accept' # pragma: nocover - - class SubController(object): - @expose() - def index(self, **kw): - return 'subindex' - - class RootController(object): - @expose() - def index(self): - return 'index' - - sub = SubController() - arg = ArgSubController() - accept = AcceptController() - - return TestApp(Pecan(RootController(), force_canonical=False)) - - def test_index(self): - r = self.app_.get('/') - assert r.status_int == 200 - assert b_('index') in r.body - - def test_subcontroller(self): - r = self.app_.get('/sub') - assert r.status_int == 200 - assert b_('subindex') in r.body - - def test_subcontroller_with_kwargs(self): - r = self.app_.post('/sub', dict(foo=1)) - assert r.status_int == 200 - assert b_('subindex') in r.body - - def test_sub_controller_with_trailing(self): - r = self.app_.get('/sub/') - assert r.status_int == 200 - assert b_('subindex') in r.body - - def test_proxy(self): - class RootController(object): - @expose() - def index(self): - request.testing = True - assert request.testing is True - del request.testing - assert hasattr(request, 'testing') is False - return '/' - - app = TestApp(make_app(RootController(), debug=True)) - r = app.get('/') - assert r.status_int == 200 - - def test_app_wrap(self): - class RootController(object): - pass - - wrapped_apps = [] - - def wrap(app): - wrapped_apps.append(app) - return app - - make_app(RootController(), wrap_app=wrap, debug=True) - assert len(wrapped_apps) == 1 - - -class TestLogging(PecanTestCase): - - def test_logging_setup(self): - class RootController(object): - @expose() - def index(self): - import logging - logging.getLogger('pecantesting').info('HELLO WORLD') - return "HELLO WORLD" - - f = StringIO() - - app = TestApp(make_app(RootController(), logging={ - 'loggers': { - 'pecantesting': { - 'level': 'INFO', 'handlers': ['memory'] - } - }, - 'handlers': { - 'memory': { - 'level': 'INFO', - 'class': 'logging.StreamHandler', - 'stream': f - } - } - })) - - app.get('/') - assert f.getvalue() == 'HELLO WORLD\n' - - def test_logging_setup_with_config_obj(self): - class RootController(object): - @expose() - def index(self): - import logging - logging.getLogger('pecantesting').info('HELLO WORLD') - return "HELLO WORLD" - - f = StringIO() - - from pecan.configuration import conf_from_dict - app = TestApp(make_app(RootController(), logging=conf_from_dict({ - 'loggers': { - 'pecantesting': { - 'level': 'INFO', 'handlers': ['memory'] - } - }, - 'handlers': { - 'memory': { - 'level': 'INFO', - 'class': 'logging.StreamHandler', - 'stream': f - } - } - }))) - - app.get('/') - assert f.getvalue() == 'HELLO WORLD\n' - - -class TestEngines(PecanTestCase): - - template_path = os.path.join(os.path.dirname(__file__), 'templates') - - @unittest.skipIf('genshi' not in builtin_renderers, 'Genshi not installed') - def test_genshi(self): - - class RootController(object): - @expose('genshi:genshi.html') - def index(self, name='Jonathan'): - return dict(name=name) - - @expose('genshi:genshi_bad.html') - def badtemplate(self): - return dict() - - app = TestApp( - Pecan(RootController(), template_path=self.template_path) - ) - r = app.get('/') - assert r.status_int == 200 - assert b_("<h1>Hello, Jonathan!</h1>") in r.body - - r = app.get('/index.html?name=World') - assert r.status_int == 200 - assert b_("<h1>Hello, World!</h1>") in r.body - - error_msg = None - try: - r = app.get('/badtemplate.html') - except Exception as e: - for error_f in error_formatters: - error_msg = error_f(e) - if error_msg: - break - assert error_msg is not None - - @unittest.skipIf('kajiki' not in builtin_renderers, 'Kajiki not installed') - def test_kajiki(self): - - class RootController(object): - @expose('kajiki:kajiki.html') - def index(self, name='Jonathan'): - return dict(name=name) - - app = TestApp( - Pecan(RootController(), template_path=self.template_path) - ) - r = app.get('/') - assert r.status_int == 200 - assert b_("<h1>Hello, Jonathan!</h1>") in r.body - - r = app.get('/index.html?name=World') - assert r.status_int == 200 - assert b_("<h1>Hello, World!</h1>") in r.body - - @unittest.skipIf('jinja' not in builtin_renderers, 'Jinja not installed') - def test_jinja(self): - - class RootController(object): - @expose('jinja:jinja.html') - def index(self, name='Jonathan'): - return dict(name=name) - - @expose('jinja:jinja_bad.html') - def badtemplate(self): - return dict() - - app = TestApp( - Pecan(RootController(), template_path=self.template_path) - ) - r = app.get('/') - assert r.status_int == 200 - assert b_("<h1>Hello, Jonathan!</h1>") in r.body - - error_msg = None - try: - r = app.get('/badtemplate.html') - except Exception as e: - for error_f in error_formatters: - error_msg = error_f(e) - if error_msg: - break - assert error_msg is not None - - @unittest.skipIf('mako' not in builtin_renderers, 'Mako not installed') - def test_mako(self): - - class RootController(object): - @expose('mako:mako.html') - def index(self, name='Jonathan'): - return dict(name=name) - - @expose('mako:mako_bad.html') - def badtemplate(self): - return dict() - - app = TestApp( - Pecan(RootController(), template_path=self.template_path) - ) - r = app.get('/') - assert r.status_int == 200 - assert b_("<h1>Hello, Jonathan!</h1>") in r.body - - r = app.get('/index.html?name=World') - assert r.status_int == 200 - assert b_("<h1>Hello, World!</h1>") in r.body - - error_msg = None - try: - r = app.get('/badtemplate.html') - except Exception as e: - for error_f in error_formatters: - error_msg = error_f(e) - if error_msg: - break - assert error_msg is not None - - def test_json(self): - try: - from simplejson import loads - except: - from json import loads # noqa - - expected_result = dict( - name='Jonathan', - age=30, nested=dict(works=True) - ) - - class RootController(object): - @expose('json') - def index(self): - return expected_result - - app = TestApp(Pecan(RootController())) - r = app.get('/') - assert r.status_int == 200 - result = dict(loads(r.body.decode())) - assert result == expected_result - - def test_override_template(self): - class RootController(object): - @expose('foo.html') - def index(self): - override_template(None, content_type='text/plain') - return 'Override' - - app = TestApp(Pecan(RootController())) - r = app.get('/') - assert r.status_int == 200 - assert b_('Override') in r.body - assert r.content_type == 'text/plain' - - def test_render(self): - class RootController(object): - @expose() - def index(self, name='Jonathan'): - return render('mako.html', dict(name=name)) - - app = TestApp( - Pecan(RootController(), template_path=self.template_path) - ) - r = app.get('/') - assert r.status_int == 200 - assert b_("<h1>Hello, Jonathan!</h1>") in r.body - - def test_default_json_renderer(self): - - class RootController(object): - @expose() - def index(self, name='Bill'): - return dict(name=name) - - app = TestApp(Pecan(RootController(), default_renderer='json')) - r = app.get('/') - assert r.status_int == 200 - result = dict(json.loads(r.body.decode())) - assert result == {'name': 'Bill'} - - def test_default_json_renderer_with_explicit_content_type(self): - - class RootController(object): - @expose(content_type='text/plain') - def index(self, name='Bill'): - return name - - app = TestApp(Pecan(RootController(), default_renderer='json')) - r = app.get('/') - assert r.status_int == 200 - assert r.body == b_("Bill") - - -class TestDeprecatedRouteMethod(PecanTestCase): - - @property - def app_(self): - class RootController(object): - - @expose() - def index(self, *args): - return ', '.join(args) - - @expose() - def _route(self, args): - return self.index, args - - return TestApp(Pecan(RootController())) - - def test_required_argument(self): - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - r = self.app_.get('/foo/bar/') - assert r.status_int == 200 - assert b_('foo, bar') in r.body - - -class TestExplicitRoute(PecanTestCase): - - def test_alternate_route(self): - - class RootController(object): - - @expose(route='some-path') - def some_path(self): - return 'Hello, World!' - - app = TestApp(Pecan(RootController())) - - r = app.get('/some-path/') - assert r.status_int == 200 - assert r.body == b_('Hello, World!') - - r = app.get('/some_path/', expect_errors=True) - assert r.status_int == 404 - - def test_manual_route(self): - - class SubController(object): - - @expose(route='some-path') - def some_path(self): - return 'Hello, World!' - - class RootController(object): - pass - - route(RootController, 'some-controller', SubController()) - - app = TestApp(Pecan(RootController())) - - r = app.get('/some-controller/some-path/') - assert r.status_int == 200 - assert r.body == b_('Hello, World!') - - r = app.get('/some-controller/some_path/', expect_errors=True) - assert r.status_int == 404 - - def test_manual_route_conflict(self): - - class SubController(object): - pass - - class RootController(object): - - @expose() - def hello(self): - return 'Hello, World!' - - self.assertRaises( - RuntimeError, - route, - RootController, - 'hello', - SubController() - ) - - def test_custom_route_on_index(self): - - class RootController(object): - - @expose(route='some-path') - def index(self): - return 'Hello, World!' - - app = TestApp(Pecan(RootController())) - - r = app.get('/some-path/') - assert r.status_int == 200 - assert r.body == b_('Hello, World!') - - r = app.get('/') - assert r.status_int == 200 - assert r.body == b_('Hello, World!') - - r = app.get('/index/', expect_errors=True) - assert r.status_int == 404 - - def test_custom_route_with_attribute_conflict(self): - - class RootController(object): - - @expose(route='mock') - def greet(self): - return 'Hello, World!' - - @expose() - def mock(self): - return 'You are not worthy!' - - app = TestApp(Pecan(RootController())) - - self.assertRaises( - RuntimeError, - app.get, - '/mock/' - ) - - def test_conflicting_custom_routes(self): - - class RootController(object): - - @expose(route='testing') - def foo(self): - return 'Foo!' - - @expose(route='testing') - def bar(self): - return 'Bar!' - - app = TestApp(Pecan(RootController())) - - self.assertRaises( - RuntimeError, - app.get, - '/testing/' - ) - - def test_conflicting_custom_routes_in_subclass(self): - - class BaseController(object): - - @expose(route='testing') - def foo(self): - return request.path - - class ChildController(BaseController): - pass - - class RootController(BaseController): - child = ChildController() - - app = TestApp(Pecan(RootController())) - - r = app.get('/testing/') - assert r.body == b_('/testing/') - - r = app.get('/child/testing/') - assert r.body == b_('/child/testing/') - - def test_custom_route_prohibited_on_lookup(self): - try: - class RootController(object): - - @expose(route='some-path') - def _lookup(self): - return 'Hello, World!' - except ValueError: - pass - else: - raise AssertionError( - '_lookup cannot be used with a custom path segment' - ) - - def test_custom_route_prohibited_on_default(self): - try: - class RootController(object): - - @expose(route='some-path') - def _default(self): - return 'Hello, World!' - except ValueError: - pass - else: - raise AssertionError( - '_default cannot be used with a custom path segment' - ) - - def test_custom_route_prohibited_on_route(self): - try: - class RootController(object): - - @expose(route='some-path') - def _route(self): - return 'Hello, World!' - except ValueError: - pass - else: - raise AssertionError( - '_route cannot be used with a custom path segment' - ) - - def test_custom_route_with_generic_controllers(self): - - class RootController(object): - - @expose(route='some-path', generic=True) - def foo(self): - return 'Hello, World!' - - @foo.when(method='POST') - def handle_post(self): - return 'POST!' - - app = TestApp(Pecan(RootController())) - - r = app.get('/some-path/') - assert r.status_int == 200 - assert r.body == b_('Hello, World!') - - r = app.get('/foo/', expect_errors=True) - assert r.status_int == 404 - - r = app.post('/some-path/') - assert r.status_int == 200 - assert r.body == b_('POST!') - - r = app.post('/foo/', expect_errors=True) - assert r.status_int == 404 - - def test_custom_route_prohibited_on_generic_controllers(self): - try: - class RootController(object): - - @expose(generic=True) - def foo(self): - return 'Hello, World!' - - @foo.when(method='POST', route='some-path') - def handle_post(self): - return 'POST!' - except ValueError: - pass - else: - raise AssertionError( - 'generic controllers cannot be used with a custom path segment' - ) - - def test_invalid_route_arguments(self): - class C(object): - - def secret(self): - return {} - - self.assertRaises(TypeError, route) - self.assertRaises(TypeError, route, 'some-path', lambda x: x) - self.assertRaises(TypeError, route, 'some-path', C.secret) - self.assertRaises(TypeError, route, C, {}, C()) - - for path in ( - 'VARIED-case-PATH', - 'this,custom,path', - '123-path', - 'path(with-parens)', - 'path;with;semicolons', - 'path:with:colons', - 'v2.0', - '~username', - 'somepath!', - 'four*four', - 'one+two', - '@twitterhandle', - 'package=pecan' - ): - handler = C() - route(C, path, handler) - assert getattr(C, path, handler) - - self.assertRaises(ValueError, route, C, '/path/', C()) - self.assertRaises(ValueError, route, C, '.', C()) - self.assertRaises(ValueError, route, C, '..', C()) - self.assertRaises(ValueError, route, C, 'path?', C()) - self.assertRaises(ValueError, route, C, 'percent%20encoded', C()) diff --git a/pecan/tests/test_commands.py b/pecan/tests/test_commands.py deleted file mode 100644 index e9d6ead..0000000 --- a/pecan/tests/test_commands.py +++ /dev/null @@ -1,56 +0,0 @@ -from pecan.tests import PecanTestCase - - -class TestCommandManager(PecanTestCase): - - def test_commands(self): - from pecan.commands import ServeCommand, ShellCommand, CreateCommand - from pecan.commands.base import CommandManager - m = CommandManager() - assert m.commands['serve'] == ServeCommand - assert m.commands['shell'] == ShellCommand - assert m.commands['create'] == CreateCommand - - -class TestCommandRunner(PecanTestCase): - - def test_commands(self): - from pecan.commands import ( - ServeCommand, ShellCommand, CreateCommand, CommandRunner - ) - runner = CommandRunner() - assert runner.commands['serve'] == ServeCommand - assert runner.commands['shell'] == ShellCommand - assert runner.commands['create'] == CreateCommand - - def test_run(self): - from pecan.commands import CommandRunner - runner = CommandRunner() - self.assertRaises( - RuntimeError, - runner.run, - ['serve', 'missing_file.py'] - ) - - -class TestCreateCommand(PecanTestCase): - - def test_run(self): - from pecan.commands import CreateCommand - - class FakeArg(object): - project_name = 'default' - template_name = 'default' - - class FakeScaffold(object): - def copy_to(self, project_name): - assert project_name == 'default' - - class FakeManager(object): - scaffolds = { - 'default': FakeScaffold - } - - c = CreateCommand() - c.manager = FakeManager() - c.run(FakeArg()) diff --git a/pecan/tests/test_conf.py b/pecan/tests/test_conf.py deleted file mode 100644 index e682885..0000000 --- a/pecan/tests/test_conf.py +++ /dev/null @@ -1,346 +0,0 @@ -import os -import sys -import tempfile - -from pecan.tests import PecanTestCase -from six import b as b_ - - -__here__ = os.path.dirname(__file__) - - -class TestConf(PecanTestCase): - - def test_update_config_fail_identifier(self): - """Fail when naming does not pass correctness""" - from pecan import configuration - bad_dict = {'bad name': 'value'} - self.assertRaises(ValueError, configuration.Config, bad_dict) - - def test_update_set_config(self): - """Update an empty configuration with the default values""" - from pecan import configuration - - conf = configuration.initconf() - conf.update(configuration.conf_from_file(os.path.join( - __here__, - 'config_fixtures/config.py' - ))) - - self.assertEqual(conf.app.root, None) - self.assertEqual(conf.app.template_path, 'myproject/templates') - self.assertEqual(conf.app.static_root, 'public') - - self.assertEqual(conf.server.host, '1.1.1.1') - self.assertEqual(conf.server.port, '8081') - - def test_update_set_default_config(self): - """Update an empty configuration with the default values""" - from pecan import configuration - - conf = configuration.initconf() - conf.update(configuration.conf_from_file(os.path.join( - __here__, - 'config_fixtures/empty.py' - ))) - - self.assertEqual(conf.app.root, None) - self.assertEqual(conf.app.template_path, '') - self.assertEqual(conf.app.static_root, 'public') - - self.assertEqual(conf.server.host, '0.0.0.0') - self.assertEqual(conf.server.port, '8080') - - def test_update_force_dict(self): - """Update an empty configuration with the default values""" - from pecan import configuration - conf = configuration.initconf() - conf.update(configuration.conf_from_file(os.path.join( - __here__, - 'config_fixtures/forcedict.py' - ))) - - self.assertEqual(conf.app.root, None) - self.assertEqual(conf.app.template_path, '') - self.assertEqual(conf.app.static_root, 'public') - - self.assertEqual(conf.server.host, '0.0.0.0') - self.assertEqual(conf.server.port, '8080') - - self.assertTrue(isinstance(conf.beaker, dict)) - self.assertEqual(conf.beaker['session.key'], 'key') - self.assertEqual(conf.beaker['session.type'], 'cookie') - self.assertEqual( - conf.beaker['session.validate_key'], - '1a971a7df182df3e1dec0af7c6913ec7' - ) - self.assertEqual(conf.beaker.get('__force_dict__'), None) - - def test_update_config_with_dict(self): - from pecan import configuration - conf = configuration.initconf() - d = {'attr': True} - conf['attr'] = d - self.assertTrue(conf.attr.attr) - - def test_config_repr(self): - from pecan import configuration - conf = configuration.Config({'a': 1}) - self.assertEqual(repr(conf), "Config({'a': 1})") - - def test_config_from_dict(self): - from pecan import configuration - conf = configuration.conf_from_dict({}) - conf['path'] = '%(confdir)s' - self.assertTrue(os.path.samefile(conf['path'], os.getcwd())) - - def test_config_from_file(self): - from pecan import configuration - path = os.path.join( - os.path.dirname(__file__), 'config_fixtures', 'config.py' - ) - configuration.conf_from_file(path) - - def test_config_illegal_ids(self): - from pecan import configuration - conf = configuration.Config({}) - conf.update(configuration.conf_from_file(os.path.join( - __here__, - 'config_fixtures/bad/module_and_underscore.py' - ))) - self.assertEqual([], list(conf)) - - def test_config_missing_file(self): - from pecan import configuration - path = ('doesnotexist.py',) - configuration.Config({}) - self.assertRaises( - RuntimeError, - configuration.conf_from_file, - os.path.join(__here__, 'config_fixtures', *path) - ) - - def test_config_missing_file_on_path(self): - from pecan import configuration - path = ('bad', 'bad', 'doesnotexist.py',) - configuration.Config({}) - - self.assertRaises( - RuntimeError, - configuration.conf_from_file, - os.path.join(__here__, 'config_fixtures', *path) - ) - - def test_config_with_syntax_error(self): - from pecan import configuration - with tempfile.NamedTemporaryFile('wb') as f: - f.write(b_('\n'.join(['if false', 'var = 3']))) - f.flush() - configuration.Config({}) - - self.assertRaises( - SyntaxError, - configuration.conf_from_file, - f.name - ) - - def test_config_with_non_package_relative_import(self): - from pecan import configuration - with tempfile.NamedTemporaryFile('wb', suffix='.py') as f: - f.write(b_('\n'.join(['from . import variables']))) - f.flush() - configuration.Config({}) - - try: - configuration.conf_from_file(f.name) - except (ValueError, SystemError) as e: - assert 'relative import' in str(e) - else: - raise AssertionError( - "A relative import-related error should have been raised" - ) - - def test_config_with_bad_import(self): - from pecan import configuration - path = ('bad', 'importerror.py') - configuration.Config({}) - - self.assertRaises( - ImportError, - configuration.conf_from_file, - os.path.join( - __here__, - 'config_fixtures', - *path - ) - ) - - def test_config_dir(self): - from pecan import configuration - if sys.version_info >= (2, 6): - conf = configuration.Config({}) - self.assertEqual([], dir(conf)) - conf = configuration.Config({'a': 1}) - self.assertEqual(['a'], dir(conf)) - - def test_config_bad_key(self): - from pecan import configuration - conf = configuration.Config({'a': 1}) - assert conf.a == 1 - self.assertRaises(AttributeError, getattr, conf, 'b') - - def test_config_get_valid_key(self): - from pecan import configuration - conf = configuration.Config({'a': 1}) - assert conf.get('a') == 1 - - def test_config_get_invalid_key(self): - from pecan import configuration - conf = configuration.Config({'a': 1}) - assert conf.get('b') is None - - def test_config_get_invalid_key_return_default(self): - from pecan import configuration - conf = configuration.Config({'a': 1}) - assert conf.get('b', True) is True - - def test_config_to_dict(self): - from pecan import configuration - conf = configuration.initconf() - - assert isinstance(conf, configuration.Config) - - to_dict = conf.to_dict() - - assert isinstance(to_dict, dict) - assert to_dict['server']['host'] == '0.0.0.0' - assert to_dict['server']['port'] == '8080' - assert to_dict['app']['modules'] == [] - assert to_dict['app']['root'] is None - assert to_dict['app']['static_root'] == 'public' - assert to_dict['app']['template_path'] == '' - - def test_config_to_dict_nested(self): - from pecan import configuration - """have more than one level nesting and convert to dict""" - conf = configuration.initconf() - nested = {'one': {'two': 2}} - conf['nested'] = nested - - to_dict = conf.to_dict() - - assert isinstance(to_dict, dict) - assert to_dict['server']['host'] == '0.0.0.0' - assert to_dict['server']['port'] == '8080' - assert to_dict['app']['modules'] == [] - assert to_dict['app']['root'] is None - assert to_dict['app']['static_root'] == 'public' - assert to_dict['app']['template_path'] == '' - assert to_dict['nested']['one']['two'] == 2 - - def test_config_to_dict_prefixed(self): - from pecan import configuration - """Add a prefix for keys""" - conf = configuration.initconf() - - assert isinstance(conf, configuration.Config) - - to_dict = conf.to_dict('prefix_') - - assert isinstance(to_dict, dict) - assert to_dict['prefix_server']['prefix_host'] == '0.0.0.0' - assert to_dict['prefix_server']['prefix_port'] == '8080' - assert to_dict['prefix_app']['prefix_modules'] == [] - assert to_dict['prefix_app']['prefix_root'] is None - assert to_dict['prefix_app']['prefix_static_root'] == 'public' - assert to_dict['prefix_app']['prefix_template_path'] == '' - - -class TestGlobalConfig(PecanTestCase): - - def tearDown(self): - from pecan import configuration - configuration.set_config( - dict(configuration.initconf()), - overwrite=True - ) - - def test_paint_from_dict(self): - from pecan import configuration - configuration.set_config({'foo': 'bar'}) - assert dict(configuration._runtime_conf) != {'foo': 'bar'} - self.assertEqual(configuration._runtime_conf.foo, 'bar') - - def test_overwrite_from_dict(self): - from pecan import configuration - configuration.set_config({'foo': 'bar'}, overwrite=True) - assert dict(configuration._runtime_conf) == {'foo': 'bar'} - - def test_paint_from_file(self): - from pecan import configuration - configuration.set_config(os.path.join( - __here__, - 'config_fixtures/foobar.py' - )) - assert dict(configuration._runtime_conf) != {'foo': 'bar'} - assert configuration._runtime_conf.foo == 'bar' - - def test_overwrite_from_file(self): - from pecan import configuration - configuration.set_config( - os.path.join( - __here__, - 'config_fixtures/foobar.py', - ), - overwrite=True - ) - assert dict(configuration._runtime_conf) == {'foo': 'bar'} - - def test_set_config_none_type(self): - from pecan import configuration - self.assertRaises(RuntimeError, configuration.set_config, None) - - def test_set_config_to_dir(self): - from pecan import configuration - self.assertRaises(RuntimeError, configuration.set_config, '/') - - -class TestConfFromEnv(PecanTestCase): - # - # Note that there is a good chance of pollution if ``tearDown`` does not - # reset the configuration like this class does. If implementing new classes - # for configuration this tearDown **needs to be implemented** - # - - def setUp(self): - super(TestConfFromEnv, self).setUp() - self.addCleanup(self._remove_config_key) - - from pecan import configuration - self.get_conf_path_from_env = configuration.get_conf_path_from_env - - def _remove_config_key(self): - os.environ.pop('PECAN_CONFIG', None) - - def test_invalid_path(self): - os.environ['PECAN_CONFIG'] = '/' - msg = "PECAN_CONFIG was set to an invalid path: /" - self.assertRaisesRegexp( - RuntimeError, - msg, - self.get_conf_path_from_env - ) - - def test_is_not_set(self): - msg = "PECAN_CONFIG is not set and " \ - "no config file was passed as an argument." - self.assertRaisesRegexp( - RuntimeError, - msg, - self.get_conf_path_from_env - ) - - def test_return_valid_path(self): - __here__ = os.path.abspath(__file__) - os.environ['PECAN_CONFIG'] = __here__ - assert self.get_conf_path_from_env() == __here__ diff --git a/pecan/tests/test_generic.py b/pecan/tests/test_generic.py deleted file mode 100644 index 0478799..0000000 --- a/pecan/tests/test_generic.py +++ /dev/null @@ -1,111 +0,0 @@ -from webtest import TestApp -try: - from simplejson import dumps -except: - from json import dumps # noqa - -from six import b as b_ - -from pecan import Pecan, expose, abort -from pecan.tests import PecanTestCase - - -class TestGeneric(PecanTestCase): - - def test_simple_generic(self): - class RootController(object): - @expose(generic=True) - def index(self): - pass - - @index.when(method='POST', template='json') - def do_post(self): - return dict(result='POST') - - @index.when(method='GET') - def do_get(self): - return 'GET' - - app = TestApp(Pecan(RootController())) - r = app.get('/') - assert r.status_int == 200 - assert r.body == b_('GET') - - r = app.post('/') - assert r.status_int == 200 - assert r.body == b_(dumps(dict(result='POST'))) - - r = app.get('/do_get', status=404) - assert r.status_int == 404 - - def test_generic_allow_header(self): - class RootController(object): - @expose(generic=True) - def index(self): - abort(405) - - @index.when(method='POST', template='json') - def do_post(self): - return dict(result='POST') - - @index.when(method='GET') - def do_get(self): - return 'GET' - - @index.when(method='PATCH') - def do_patch(self): - return 'PATCH' - - app = TestApp(Pecan(RootController())) - r = app.delete('/', expect_errors=True) - assert r.status_int == 405 - assert r.headers['Allow'] == 'GET, PATCH, POST' - - def test_nested_generic(self): - - class SubSubController(object): - @expose(generic=True) - def index(self): - return 'GET' - - @index.when(method='DELETE', template='json') - def do_delete(self, name, *args): - return dict(result=name, args=', '.join(args)) - - class SubController(object): - sub = SubSubController() - - class RootController(object): - sub = SubController() - - app = TestApp(Pecan(RootController())) - r = app.get('/sub/sub/') - assert r.status_int == 200 - assert r.body == b_('GET') - - r = app.delete('/sub/sub/joe/is/cool') - assert r.status_int == 200 - assert r.body == b_(dumps(dict(result='joe', args='is, cool'))) - - -class TestGenericWithSpecialMethods(PecanTestCase): - - def test_generics_not_allowed(self): - - class C(object): - - def _default(self): - pass - - def _lookup(self): - pass - - def _route(self): - pass - - for method in (C._default, C._lookup, C._route): - self.assertRaises( - ValueError, - expose(generic=True), - getattr(method, '__func__', method) - ) diff --git a/pecan/tests/test_hooks.py b/pecan/tests/test_hooks.py deleted file mode 100644 index a15368e..0000000 --- a/pecan/tests/test_hooks.py +++ /dev/null @@ -1,1711 +0,0 @@ -import inspect -import operator - -from webtest import TestApp -from six import PY3 -from six import b as b_ -from six import u as u_ -from six.moves import cStringIO as StringIO - -from pecan import make_app, expose, redirect, abort, rest, Request, Response -from pecan.hooks import ( - PecanHook, TransactionHook, HookController, RequestViewerHook -) -from pecan.configuration import Config -from pecan.decorators import transactional, after_commit, after_rollback -from pecan.tests import PecanTestCase - -# The `inspect.Arguments` namedtuple is different between PY2/3 -kwargs = operator.attrgetter('varkw' if PY3 else 'keywords') - - -class TestHooks(PecanTestCase): - - def test_basic_single_hook(self): - run_hook = [] - - class RootController(object): - @expose() - def index(self): - run_hook.append('inside') - return 'Hello, World!' - - class SimpleHook(PecanHook): - def on_route(self, state): - run_hook.append('on_route') - - def before(self, state): - run_hook.append('before') - - def after(self, state): - run_hook.append('after') - - def on_error(self, state, e): - run_hook.append('error') - - app = TestApp(make_app(RootController(), hooks=[SimpleHook()])) - response = app.get('/') - assert response.status_int == 200 - assert response.body == b_('Hello, World!') - - assert len(run_hook) == 4 - assert run_hook[0] == 'on_route' - assert run_hook[1] == 'before' - assert run_hook[2] == 'inside' - assert run_hook[3] == 'after' - - def test_basic_multi_hook(self): - run_hook = [] - - class RootController(object): - @expose() - def index(self): - run_hook.append('inside') - return 'Hello, World!' - - class SimpleHook(PecanHook): - def __init__(self, id): - self.id = str(id) - - def on_route(self, state): - run_hook.append('on_route' + self.id) - - def before(self, state): - run_hook.append('before' + self.id) - - def after(self, state): - run_hook.append('after' + self.id) - - def on_error(self, state, e): - run_hook.append('error' + self.id) - - app = TestApp(make_app(RootController(), hooks=[ - SimpleHook(1), SimpleHook(2), SimpleHook(3) - ])) - response = app.get('/') - assert response.status_int == 200 - assert response.body == b_('Hello, World!') - - assert len(run_hook) == 10 - assert run_hook[0] == 'on_route1' - assert run_hook[1] == 'on_route2' - assert run_hook[2] == 'on_route3' - assert run_hook[3] == 'before1' - assert run_hook[4] == 'before2' - assert run_hook[5] == 'before3' - assert run_hook[6] == 'inside' - assert run_hook[7] == 'after3' - assert run_hook[8] == 'after2' - assert run_hook[9] == 'after1' - - def test_partial_hooks(self): - run_hook = [] - - class RootController(object): - @expose() - def index(self): - run_hook.append('inside') - return 'Hello World!' - - @expose() - def causeerror(self): - return [][1] - - class ErrorHook(PecanHook): - def on_error(self, state, e): - run_hook.append('error') - - class OnRouteHook(PecanHook): - def on_route(self, state): - run_hook.append('on_route') - - app = TestApp(make_app(RootController(), hooks=[ - ErrorHook(), OnRouteHook() - ])) - - response = app.get('/') - assert response.status_int == 200 - assert response.body == b_('Hello World!') - - assert len(run_hook) == 2 - assert run_hook[0] == 'on_route' - assert run_hook[1] == 'inside' - - run_hook = [] - try: - response = app.get('/causeerror') - except Exception as e: - assert isinstance(e, IndexError) - - assert len(run_hook) == 2 - assert run_hook[0] == 'on_route' - assert run_hook[1] == 'error' - - def test_on_error_response_hook(self): - run_hook = [] - - class RootController(object): - @expose() - def causeerror(self): - return [][1] - - class ErrorHook(PecanHook): - def on_error(self, state, e): - run_hook.append('error') - - r = Response() - r.text = u_('on_error') - - return r - - app = TestApp(make_app(RootController(), hooks=[ - ErrorHook() - ])) - - response = app.get('/causeerror') - - assert len(run_hook) == 1 - assert run_hook[0] == 'error' - assert response.text == 'on_error' - - def test_prioritized_hooks(self): - run_hook = [] - - class RootController(object): - @expose() - def index(self): - run_hook.append('inside') - return 'Hello, World!' - - class SimpleHook(PecanHook): - def __init__(self, id, priority=None): - self.id = str(id) - if priority: - self.priority = priority - - def on_route(self, state): - run_hook.append('on_route' + self.id) - - def before(self, state): - run_hook.append('before' + self.id) - - def after(self, state): - run_hook.append('after' + self.id) - - def on_error(self, state, e): - run_hook.append('error' + self.id) - - papp = make_app(RootController(), hooks=[ - SimpleHook(1, 3), SimpleHook(2, 2), SimpleHook(3, 1) - ]) - app = TestApp(papp) - response = app.get('/') - assert response.status_int == 200 - assert response.body == b_('Hello, World!') - - assert len(run_hook) == 10 - assert run_hook[0] == 'on_route3' - assert run_hook[1] == 'on_route2' - assert run_hook[2] == 'on_route1' - assert run_hook[3] == 'before3' - assert run_hook[4] == 'before2' - assert run_hook[5] == 'before1' - assert run_hook[6] == 'inside' - assert run_hook[7] == 'after1' - assert run_hook[8] == 'after2' - assert run_hook[9] == 'after3' - - def test_basic_isolated_hook(self): - run_hook = [] - - class SimpleHook(PecanHook): - def on_route(self, state): - run_hook.append('on_route') - - def before(self, state): - run_hook.append('before') - - def after(self, state): - run_hook.append('after') - - def on_error(self, state, e): - run_hook.append('error') - - class SubSubController(object): - @expose() - def index(self): - run_hook.append('inside_sub_sub') - return 'Deep inside here!' - - class SubController(HookController): - __hooks__ = [SimpleHook()] - - @expose() - def index(self): - run_hook.append('inside_sub') - return 'Inside here!' - - sub = SubSubController() - - class RootController(object): - @expose() - def index(self): - run_hook.append('inside') - return 'Hello, World!' - - sub = SubController() - - app = TestApp(make_app(RootController())) - response = app.get('/') - assert response.status_int == 200 - assert response.body == b_('Hello, World!') - - assert len(run_hook) == 1 - assert run_hook[0] == 'inside' - - run_hook = [] - - response = app.get('/sub/') - assert response.status_int == 200 - assert response.body == b_('Inside here!') - - assert len(run_hook) == 3 - assert run_hook[0] == 'before' - assert run_hook[1] == 'inside_sub' - assert run_hook[2] == 'after' - - run_hook = [] - response = app.get('/sub/sub/') - assert response.status_int == 200 - assert response.body == b_('Deep inside here!') - - assert len(run_hook) == 3 - assert run_hook[0] == 'before' - assert run_hook[1] == 'inside_sub_sub' - assert run_hook[2] == 'after' - - def test_isolated_hook_with_global_hook(self): - run_hook = [] - - class SimpleHook(PecanHook): - def __init__(self, id): - self.id = str(id) - - def on_route(self, state): - run_hook.append('on_route' + self.id) - - def before(self, state): - run_hook.append('before' + self.id) - - def after(self, state): - run_hook.append('after' + self.id) - - def on_error(self, state, e): - run_hook.append('error' + self.id) - - class SubController(HookController): - __hooks__ = [SimpleHook(2)] - - @expose() - def index(self): - run_hook.append('inside_sub') - return 'Inside here!' - - class RootController(object): - @expose() - def index(self): - run_hook.append('inside') - return 'Hello, World!' - - sub = SubController() - - app = TestApp(make_app(RootController(), hooks=[SimpleHook(1)])) - response = app.get('/') - assert response.status_int == 200 - assert response.body == b_('Hello, World!') - - assert len(run_hook) == 4 - assert run_hook[0] == 'on_route1' - assert run_hook[1] == 'before1' - assert run_hook[2] == 'inside' - assert run_hook[3] == 'after1' - - run_hook = [] - - response = app.get('/sub/') - assert response.status_int == 200 - assert response.body == b_('Inside here!') - - assert len(run_hook) == 6 - assert run_hook[0] == 'on_route1' - assert run_hook[1] == 'before2' - assert run_hook[2] == 'before1' - assert run_hook[3] == 'inside_sub' - assert run_hook[4] == 'after1' - assert run_hook[5] == 'after2' - - def test_mixin_hooks(self): - run_hook = [] - - class HelperHook(PecanHook): - priority = 2 - - def before(self, state): - run_hook.append('helper - before hook') - - # we'll use the same hook instance to avoid duplicate calls - helper_hook = HelperHook() - - class LastHook(PecanHook): - priority = 200 - - def before(self, state): - run_hook.append('last - before hook') - - class SimpleHook(PecanHook): - priority = 1 - - def before(self, state): - run_hook.append('simple - before hook') - - class HelperMixin(object): - __hooks__ = [helper_hook] - - class LastMixin(object): - __hooks__ = [LastHook()] - - class SubController(HookController, HelperMixin): - __hooks__ = [LastHook()] - - @expose() - def index(self): - return "This is sub controller!" - - class RootController(HookController, LastMixin): - __hooks__ = [SimpleHook(), helper_hook] - - @expose() - def index(self): - run_hook.append('inside') - return 'Hello, World!' - - sub = SubController() - - papp = make_app(RootController()) - app = TestApp(papp) - response = app.get('/') - assert response.status_int == 200 - assert response.body == b_('Hello, World!') - - assert len(run_hook) == 4 - assert run_hook[0] == 'simple - before hook', run_hook[0] - assert run_hook[1] == 'helper - before hook', run_hook[1] - assert run_hook[2] == 'last - before hook', run_hook[2] - assert run_hook[3] == 'inside', run_hook[3] - - run_hook = [] - response = app.get('/sub/') - assert response.status_int == 200 - assert response.body == b_('This is sub controller!') - - assert len(run_hook) == 4, run_hook - assert run_hook[0] == 'simple - before hook', run_hook[0] - assert run_hook[1] == 'helper - before hook', run_hook[1] - assert run_hook[2] == 'last - before hook', run_hook[2] - # LastHook is invoked once again - - # for each different instance of the Hook in the two Controllers - assert run_hook[3] == 'last - before hook', run_hook[3] - - -class TestStateAccess(PecanTestCase): - - def setUp(self): - super(TestStateAccess, self).setUp() - self.args = None - - class RootController(object): - @expose() - def index(self): - return 'Hello, World!' - - @expose() - def greet(self, name): - return 'Hello, %s!' % name - - @expose() - def greetmore(self, *args): - return 'Hello, %s!' % args[0] - - @expose() - def kwargs(self, **kw): - return 'Hello, %s!' % kw['name'] - - @expose() - def mixed(self, first, second, *args): - return 'Mixed' - - class SimpleHook(PecanHook): - def before(inself, state): - self.args = (state.controller, state.arguments) - - self.root = RootController() - self.app = TestApp(make_app(self.root, hooks=[SimpleHook()])) - - def test_no_args(self): - self.app.get('/') - assert self.args[0] == self.root.index - assert isinstance(self.args[1], inspect.Arguments) - assert self.args[1].args == [] - assert self.args[1].varargs == [] - assert kwargs(self.args[1]) == {} - - def test_single_arg(self): - self.app.get('/greet/joe') - assert self.args[0] == self.root.greet - assert isinstance(self.args[1], inspect.Arguments) - assert self.args[1].args == ['joe'] - assert self.args[1].varargs == [] - assert kwargs(self.args[1]) == {} - - def test_single_vararg(self): - self.app.get('/greetmore/joe') - assert self.args[0] == self.root.greetmore - assert isinstance(self.args[1], inspect.Arguments) - assert self.args[1].args == [] - assert self.args[1].varargs == ['joe'] - assert kwargs(self.args[1]) == {} - - def test_single_kw(self): - self.app.get('/kwargs/?name=joe') - assert self.args[0] == self.root.kwargs - assert isinstance(self.args[1], inspect.Arguments) - assert self.args[1].args == [] - assert self.args[1].varargs == [] - assert kwargs(self.args[1]) == {'name': 'joe'} - - def test_single_kw_post(self): - self.app.post('/kwargs/', params={'name': 'joe'}) - assert self.args[0] == self.root.kwargs - assert isinstance(self.args[1], inspect.Arguments) - assert self.args[1].args == [] - assert self.args[1].varargs == [] - assert kwargs(self.args[1]) == {'name': 'joe'} - - def test_mixed_args(self): - self.app.get('/mixed/foo/bar/spam/eggs') - assert self.args[0] == self.root.mixed - assert isinstance(self.args[1], inspect.Arguments) - assert self.args[1].args == ['foo', 'bar'] - assert self.args[1].varargs == ['spam', 'eggs'] - - -class TestStateAccessWithoutThreadLocals(PecanTestCase): - - def setUp(self): - super(TestStateAccessWithoutThreadLocals, self).setUp() - self.args = None - - class RootController(object): - @expose() - def index(self, req, resp): - return 'Hello, World!' - - @expose() - def greet(self, req, resp, name): - return 'Hello, %s!' % name - - @expose() - def greetmore(self, req, resp, *args): - return 'Hello, %s!' % args[0] - - @expose() - def kwargs(self, req, resp, **kw): - return 'Hello, %s!' % kw['name'] - - @expose() - def mixed(self, req, resp, first, second, *args): - return 'Mixed' - - class SimpleHook(PecanHook): - def before(inself, state): - self.args = (state.controller, state.arguments) - - self.root = RootController() - self.app = TestApp(make_app( - self.root, - hooks=[SimpleHook()], - use_context_locals=False - )) - - def test_no_args(self): - self.app.get('/') - assert self.args[0] == self.root.index - assert isinstance(self.args[1], inspect.Arguments) - assert len(self.args[1].args) == 2 - assert isinstance(self.args[1].args[0], Request) - assert isinstance(self.args[1].args[1], Response) - assert self.args[1].varargs == [] - assert kwargs(self.args[1]) == {} - - def test_single_arg(self): - self.app.get('/greet/joe') - assert self.args[0] == self.root.greet - assert isinstance(self.args[1], inspect.Arguments) - assert len(self.args[1].args) == 3 - assert isinstance(self.args[1].args[0], Request) - assert isinstance(self.args[1].args[1], Response) - assert self.args[1].args[2] == 'joe' - assert self.args[1].varargs == [] - assert kwargs(self.args[1]) == {} - - def test_single_vararg(self): - self.app.get('/greetmore/joe') - assert self.args[0] == self.root.greetmore - assert isinstance(self.args[1], inspect.Arguments) - assert len(self.args[1].args) == 2 - assert isinstance(self.args[1].args[0], Request) - assert isinstance(self.args[1].args[1], Response) - assert self.args[1].varargs == ['joe'] - assert kwargs(self.args[1]) == {} - - def test_single_kw(self): - self.app.get('/kwargs/?name=joe') - assert self.args[0] == self.root.kwargs - assert isinstance(self.args[1], inspect.Arguments) - assert len(self.args[1].args) == 2 - assert isinstance(self.args[1].args[0], Request) - assert isinstance(self.args[1].args[1], Response) - assert self.args[1].varargs == [] - assert kwargs(self.args[1]) == {'name': 'joe'} - - def test_single_kw_post(self): - self.app.post('/kwargs/', params={'name': 'joe'}) - assert self.args[0] == self.root.kwargs - assert isinstance(self.args[1], inspect.Arguments) - assert len(self.args[1].args) == 2 - assert isinstance(self.args[1].args[0], Request) - assert isinstance(self.args[1].args[1], Response) - assert self.args[1].varargs == [] - assert kwargs(self.args[1]) == {'name': 'joe'} - - def test_mixed_args(self): - self.app.get('/mixed/foo/bar/spam/eggs') - assert self.args[0] == self.root.mixed - assert isinstance(self.args[1], inspect.Arguments) - assert len(self.args[1].args) == 4 - assert isinstance(self.args[1].args[0], Request) - assert isinstance(self.args[1].args[1], Response) - assert self.args[1].args[2:] == ['foo', 'bar'] - assert self.args[1].varargs == ['spam', 'eggs'] - - -class TestRestControllerStateAccess(PecanTestCase): - - def setUp(self): - super(TestRestControllerStateAccess, self).setUp() - self.args = None - - class RootController(rest.RestController): - - @expose() - def _default(self, _id, *args, **kw): - return 'Default' - - @expose() - def get_all(self, **kw): - return 'All' - - @expose() - def get_one(self, _id, *args, **kw): - return 'One' - - @expose() - def post(self, *args, **kw): - return 'POST' - - @expose() - def put(self, _id, *args, **kw): - return 'PUT' - - @expose() - def delete(self, _id, *args, **kw): - return 'DELETE' - - class SimpleHook(PecanHook): - def before(inself, state): - self.args = (state.controller, state.arguments) - - self.root = RootController() - self.app = TestApp(make_app(self.root, hooks=[SimpleHook()])) - - def test_get_all(self): - self.app.get('/') - assert self.args[0] == self.root.get_all - assert isinstance(self.args[1], inspect.Arguments) - assert self.args[1].args == [] - assert self.args[1].varargs == [] - assert kwargs(self.args[1]) == {} - - def test_get_all_with_kwargs(self): - self.app.get('/?foo=bar') - assert self.args[0] == self.root.get_all - assert isinstance(self.args[1], inspect.Arguments) - assert self.args[1].args == [] - assert self.args[1].varargs == [] - assert kwargs(self.args[1]) == {'foo': 'bar'} - - def test_get_one(self): - self.app.get('/1') - assert self.args[0] == self.root.get_one - assert isinstance(self.args[1], inspect.Arguments) - assert self.args[1].args == ['1'] - assert self.args[1].varargs == [] - assert kwargs(self.args[1]) == {} - - def test_get_one_with_varargs(self): - self.app.get('/1/2/3') - assert self.args[0] == self.root.get_one - assert isinstance(self.args[1], inspect.Arguments) - assert self.args[1].args == ['1'] - assert self.args[1].varargs == ['2', '3'] - assert kwargs(self.args[1]) == {} - - def test_get_one_with_kwargs(self): - self.app.get('/1?foo=bar') - assert self.args[0] == self.root.get_one - assert isinstance(self.args[1], inspect.Arguments) - assert self.args[1].args == ['1'] - assert self.args[1].varargs == [] - assert kwargs(self.args[1]) == {'foo': 'bar'} - - def test_post(self): - self.app.post('/') - assert self.args[0] == self.root.post - assert isinstance(self.args[1], inspect.Arguments) - assert self.args[1].args == [] - assert self.args[1].varargs == [] - assert kwargs(self.args[1]) == {} - - def test_post_with_varargs(self): - self.app.post('/foo/bar') - assert self.args[0] == self.root.post - assert isinstance(self.args[1], inspect.Arguments) - assert self.args[1].args == [] - assert self.args[1].varargs == ['foo', 'bar'] - assert kwargs(self.args[1]) == {} - - def test_post_with_kwargs(self): - self.app.post('/', params={'foo': 'bar'}) - assert self.args[0] == self.root.post - assert isinstance(self.args[1], inspect.Arguments) - assert self.args[1].args == [] - assert self.args[1].varargs == [] - assert kwargs(self.args[1]) == {'foo': 'bar'} - - def test_put(self): - self.app.put('/1') - assert self.args[0] == self.root.put - assert isinstance(self.args[1], inspect.Arguments) - assert self.args[1].args == ['1'] - assert self.args[1].varargs == [] - assert kwargs(self.args[1]) == {} - - def test_put_with_method_argument(self): - self.app.post('/1?_method=put') - assert self.args[0] == self.root.put - assert isinstance(self.args[1], inspect.Arguments) - assert self.args[1].args == ['1'] - assert self.args[1].varargs == [] - assert kwargs(self.args[1]) == {'_method': 'put'} - - def test_put_with_varargs(self): - self.app.put('/1/2/3') - assert self.args[0] == self.root.put - assert isinstance(self.args[1], inspect.Arguments) - assert self.args[1].args == ['1'] - assert self.args[1].varargs == ['2', '3'] - assert kwargs(self.args[1]) == {} - - def test_put_with_kwargs(self): - self.app.put('/1?foo=bar') - assert self.args[0] == self.root.put - assert isinstance(self.args[1], inspect.Arguments) - assert self.args[1].args == ['1'] - assert self.args[1].varargs == [] - assert kwargs(self.args[1]) == {'foo': 'bar'} - - def test_delete(self): - self.app.delete('/1') - assert self.args[0] == self.root.delete - assert isinstance(self.args[1], inspect.Arguments) - assert self.args[1].args == ['1'] - assert self.args[1].varargs == [] - assert kwargs(self.args[1]) == {} - - def test_delete_with_method_argument(self): - self.app.post('/1?_method=delete') - assert self.args[0] == self.root.delete - assert isinstance(self.args[1], inspect.Arguments) - assert self.args[1].args == ['1'] - assert self.args[1].varargs == [] - assert kwargs(self.args[1]) == {'_method': 'delete'} - - def test_delete_with_varargs(self): - self.app.delete('/1/2/3') - assert self.args[0] == self.root.delete - assert isinstance(self.args[1], inspect.Arguments) - assert self.args[1].args == ['1'] - assert self.args[1].varargs == ['2', '3'] - assert kwargs(self.args[1]) == {} - - def test_delete_with_kwargs(self): - self.app.delete('/1?foo=bar') - assert self.args[0] == self.root.delete - assert isinstance(self.args[1], inspect.Arguments) - assert self.args[1].args == ['1'] - assert self.args[1].varargs == [] - assert kwargs(self.args[1]) == {'foo': 'bar'} - - def test_post_with_invalid_method_kwarg(self): - self.app.post('/1?_method=invalid') - assert self.args[0] == self.root._default - assert isinstance(self.args[1], inspect.Arguments) - assert self.args[1].args == ['1'] - assert self.args[1].varargs == [] - assert kwargs(self.args[1]) == {'_method': 'invalid'} - - -class TestTransactionHook(PecanTestCase): - def test_transaction_hook(self): - run_hook = [] - - class RootController(object): - @expose() - def index(self): - run_hook.append('inside') - return 'Hello, World!' - - @expose() - def redirect(self): - redirect('/') - - @expose() - def error(self): - return [][1] - - def gen(event): - return lambda: run_hook.append(event) - - app = TestApp(make_app(RootController(), hooks=[ - TransactionHook( - start=gen('start'), - start_ro=gen('start_ro'), - commit=gen('commit'), - rollback=gen('rollback'), - clear=gen('clear') - ) - ])) - - response = app.get('/') - assert response.status_int == 200 - assert response.body == b_('Hello, World!') - - assert len(run_hook) == 3 - assert run_hook[0] == 'start_ro' - assert run_hook[1] == 'inside' - assert run_hook[2] == 'clear' - - run_hook = [] - - response = app.post('/') - assert response.status_int == 200 - assert response.body == b_('Hello, World!') - - assert len(run_hook) == 4 - assert run_hook[0] == 'start' - assert run_hook[1] == 'inside' - assert run_hook[2] == 'commit' - assert run_hook[3] == 'clear' - - # - # test hooks for GET /redirect - # This controller should always be non-transactional - # - - run_hook = [] - - response = app.get('/redirect') - assert response.status_int == 302 - assert len(run_hook) == 2 - assert run_hook[0] == 'start_ro' - assert run_hook[1] == 'clear' - - # - # test hooks for POST /redirect - # This controller should always be transactional, - # even in the case of redirects - # - - run_hook = [] - - response = app.post('/redirect') - assert response.status_int == 302 - assert len(run_hook) == 3 - assert run_hook[0] == 'start' - assert run_hook[1] == 'commit' - assert run_hook[2] == 'clear' - - run_hook = [] - try: - response = app.post('/error') - except IndexError: - pass - - assert len(run_hook) == 3 - assert run_hook[0] == 'start' - assert run_hook[1] == 'rollback' - assert run_hook[2] == 'clear' - - def test_transaction_hook_with_after_actions(self): - run_hook = [] - - def action(name): - def action_impl(): - run_hook.append(name) - return action_impl - - class RootController(object): - @expose() - @after_commit(action('action-one')) - def index(self): - run_hook.append('inside') - return 'Index Method!' - - @expose() - @transactional() - @after_commit(action('action-two')) - def decorated(self): - run_hook.append('inside') - return 'Decorated Method!' - - @expose() - @after_rollback(action('action-three')) - def rollback(self): - abort(500) - - @expose() - @transactional() - @after_rollback(action('action-four')) - def rollback_decorated(self): - abort(500) - - def gen(event): - return lambda: run_hook.append(event) - - app = TestApp(make_app(RootController(), hooks=[ - TransactionHook( - start=gen('start'), - start_ro=gen('start_ro'), - commit=gen('commit'), - rollback=gen('rollback'), - clear=gen('clear') - ) - ])) - - response = app.get('/') - assert response.status_int == 200 - assert response.body == b_('Index Method!') - - assert len(run_hook) == 3 - assert run_hook[0] == 'start_ro' - assert run_hook[1] == 'inside' - assert run_hook[2] == 'clear' - - run_hook = [] - - response = app.post('/') - assert response.status_int == 200 - assert response.body == b_('Index Method!') - - assert len(run_hook) == 5 - assert run_hook[0] == 'start' - assert run_hook[1] == 'inside' - assert run_hook[2] == 'commit' - assert run_hook[3] == 'action-one' - assert run_hook[4] == 'clear' - - run_hook = [] - - response = app.get('/decorated') - assert response.status_int == 200 - assert response.body == b_('Decorated Method!') - - assert len(run_hook) == 7 - assert run_hook[0] == 'start_ro' - assert run_hook[1] == 'clear' - assert run_hook[2] == 'start' - assert run_hook[3] == 'inside' - assert run_hook[4] == 'commit' - assert run_hook[5] == 'action-two' - assert run_hook[6] == 'clear' - - run_hook = [] - - response = app.get('/rollback', expect_errors=True) - assert response.status_int == 500 - - assert len(run_hook) == 2 - assert run_hook[0] == 'start_ro' - assert run_hook[1] == 'clear' - - run_hook = [] - - response = app.post('/rollback', expect_errors=True) - assert response.status_int == 500 - - assert len(run_hook) == 4 - assert run_hook[0] == 'start' - assert run_hook[1] == 'rollback' - assert run_hook[2] == 'action-three' - assert run_hook[3] == 'clear' - - run_hook = [] - - response = app.get('/rollback_decorated', expect_errors=True) - assert response.status_int == 500 - - assert len(run_hook) == 6 - assert run_hook[0] == 'start_ro' - assert run_hook[1] == 'clear' - assert run_hook[2] == 'start' - assert run_hook[3] == 'rollback' - assert run_hook[4] == 'action-four' - assert run_hook[5] == 'clear' - - run_hook = [] - - response = app.get('/fourohfour', status=404) - assert response.status_int == 404 - - assert len(run_hook) == 2 - assert run_hook[0] == 'start_ro' - assert run_hook[1] == 'clear' - - def test_transaction_hook_with_transactional_decorator(self): - run_hook = [] - - class RootController(object): - @expose() - def index(self): - run_hook.append('inside') - return 'Hello, World!' - - @expose() - def redirect(self): - redirect('/') - - @expose() - @transactional() - def redirect_transactional(self): - redirect('/') - - @expose() - @transactional(False) - def redirect_rollback(self): - redirect('/') - - @expose() - def error(self): - return [][1] - - @expose() - @transactional(False) - def error_rollback(self): - return [][1] - - @expose() - @transactional() - def error_transactional(self): - return [][1] - - def gen(event): - return lambda: run_hook.append(event) - - app = TestApp(make_app(RootController(), hooks=[ - TransactionHook( - start=gen('start'), - start_ro=gen('start_ro'), - commit=gen('commit'), - rollback=gen('rollback'), - clear=gen('clear') - ) - ])) - - response = app.get('/') - assert response.status_int == 200 - assert response.body == b_('Hello, World!') - - assert len(run_hook) == 3 - assert run_hook[0] == 'start_ro' - assert run_hook[1] == 'inside' - assert run_hook[2] == 'clear' - - run_hook = [] - - # test hooks for / - - response = app.post('/') - assert response.status_int == 200 - assert response.body == b_('Hello, World!') - - assert len(run_hook) == 4 - assert run_hook[0] == 'start' - assert run_hook[1] == 'inside' - assert run_hook[2] == 'commit' - assert run_hook[3] == 'clear' - - # - # test hooks for GET /redirect - # This controller should always be non-transactional - # - - run_hook = [] - - response = app.get('/redirect') - assert response.status_int == 302 - assert len(run_hook) == 2 - assert run_hook[0] == 'start_ro' - assert run_hook[1] == 'clear' - - # - # test hooks for POST /redirect - # This controller should always be transactional, - # even in the case of redirects - # - - run_hook = [] - - response = app.post('/redirect') - assert response.status_int == 302 - assert len(run_hook) == 3 - assert run_hook[0] == 'start' - assert run_hook[1] == 'commit' - assert run_hook[2] == 'clear' - - # - # test hooks for GET /redirect_transactional - # This controller should always be transactional, - # even in the case of redirects - # - - run_hook = [] - - response = app.get('/redirect_transactional') - assert response.status_int == 302 - assert len(run_hook) == 5 - assert run_hook[0] == 'start_ro' - assert run_hook[1] == 'clear' - assert run_hook[2] == 'start' - assert run_hook[3] == 'commit' - assert run_hook[4] == 'clear' - - # - # test hooks for POST /redirect_transactional - # This controller should always be transactional, - # even in the case of redirects - # - - run_hook = [] - - response = app.post('/redirect_transactional') - assert response.status_int == 302 - assert len(run_hook) == 3 - assert run_hook[0] == 'start' - assert run_hook[1] == 'commit' - assert run_hook[2] == 'clear' - - # - # test hooks for GET /redirect_rollback - # This controller should always be transactional, - # *except* in the case of redirects - # - run_hook = [] - - response = app.get('/redirect_rollback') - assert response.status_int == 302 - assert len(run_hook) == 5 - assert run_hook[0] == 'start_ro' - assert run_hook[1] == 'clear' - assert run_hook[2] == 'start' - assert run_hook[3] == 'rollback' - assert run_hook[4] == 'clear' - - # - # test hooks for POST /redirect_rollback - # This controller should always be transactional, - # *except* in the case of redirects - # - - run_hook = [] - - response = app.post('/redirect_rollback') - assert response.status_int == 302 - assert len(run_hook) == 3 - assert run_hook[0] == 'start' - assert run_hook[1] == 'rollback' - assert run_hook[2] == 'clear' - - # - # Exceptions (other than HTTPFound) should *always* - # rollback no matter what - # - run_hook = [] - - try: - response = app.post('/error') - except IndexError: - pass - - assert len(run_hook) == 3 - assert run_hook[0] == 'start' - assert run_hook[1] == 'rollback' - assert run_hook[2] == 'clear' - - run_hook = [] - - try: - response = app.get('/error') - except IndexError: - pass - - assert len(run_hook) == 2 - assert run_hook[0] == 'start_ro' - assert run_hook[1] == 'clear' - - run_hook = [] - - try: - response = app.post('/error_transactional') - except IndexError: - pass - - assert len(run_hook) == 3 - assert run_hook[0] == 'start' - assert run_hook[1] == 'rollback' - assert run_hook[2] == 'clear' - - run_hook = [] - - try: - response = app.get('/error_transactional') - except IndexError: - pass - - assert len(run_hook) == 5 - assert run_hook[0] == 'start_ro' - assert run_hook[1] == 'clear' - assert run_hook[2] == 'start' - assert run_hook[3] == 'rollback' - assert run_hook[4] == 'clear' - - run_hook = [] - - try: - response = app.post('/error_rollback') - except IndexError: - pass - - assert len(run_hook) == 3 - assert run_hook[0] == 'start' - assert run_hook[1] == 'rollback' - assert run_hook[2] == 'clear' - - run_hook = [] - - try: - response = app.get('/error_rollback') - except IndexError: - pass - - assert len(run_hook) == 5 - assert run_hook[0] == 'start_ro' - assert run_hook[1] == 'clear' - assert run_hook[2] == 'start' - assert run_hook[3] == 'rollback' - assert run_hook[4] == 'clear' - - def test_transaction_hook_with_transactional_class_decorator(self): - run_hook = [] - - @transactional() - class RootController(object): - @expose() - def index(self): - run_hook.append('inside') - return 'Hello, World!' - - @expose() - def redirect(self): - redirect('/') - - @expose() - @transactional(False) - def redirect_rollback(self): - redirect('/') - - @expose() - def error(self): - return [][1] - - @expose(generic=True) - def generic(self): - pass - - @generic.when(method='GET') - def generic_get(self): - run_hook.append('inside') - return 'generic get' - - @generic.when(method='POST') - def generic_post(self): - run_hook.append('inside') - return 'generic post' - - def gen(event): - return lambda: run_hook.append(event) - - app = TestApp(make_app(RootController(), hooks=[ - TransactionHook( - start=gen('start'), - start_ro=gen('start_ro'), - commit=gen('commit'), - rollback=gen('rollback'), - clear=gen('clear') - ) - ])) - - response = app.get('/') - assert response.status_int == 200 - assert response.body == b_('Hello, World!') - - assert len(run_hook) == 6 - assert run_hook[0] == 'start_ro' - assert run_hook[1] == 'clear' - assert run_hook[2] == 'start' - assert run_hook[3] == 'inside' - assert run_hook[4] == 'commit' - assert run_hook[5] == 'clear' - - run_hook = [] - - # test hooks for / - - response = app.post('/') - assert response.status_int == 200 - assert response.body == b_('Hello, World!') - - assert len(run_hook) == 4 - assert run_hook[0] == 'start' - assert run_hook[1] == 'inside' - assert run_hook[2] == 'commit' - assert run_hook[3] == 'clear' - - # - # test hooks for GET /redirect - # This controller should always be transactional, - # even in the case of redirects - # - - run_hook = [] - response = app.get('/redirect') - assert response.status_int == 302 - assert len(run_hook) == 5 - assert run_hook[0] == 'start_ro' - assert run_hook[1] == 'clear' - assert run_hook[2] == 'start' - assert run_hook[3] == 'commit' - assert run_hook[4] == 'clear' - - # - # test hooks for POST /redirect - # This controller should always be transactional, - # even in the case of redirects - # - - run_hook = [] - - response = app.post('/redirect') - assert response.status_int == 302 - assert len(run_hook) == 3 - assert run_hook[0] == 'start' - assert run_hook[1] == 'commit' - assert run_hook[2] == 'clear' - - # - # test hooks for GET /redirect_rollback - # This controller should always be transactional, - # *except* in the case of redirects - # - run_hook = [] - - response = app.get('/redirect_rollback') - assert response.status_int == 302 - assert len(run_hook) == 5 - assert run_hook[0] == 'start_ro' - assert run_hook[1] == 'clear' - assert run_hook[2] == 'start' - assert run_hook[3] == 'rollback' - assert run_hook[4] == 'clear' - - # - # test hooks for POST /redirect_rollback - # This controller should always be transactional, - # *except* in the case of redirects - # - - run_hook = [] - - response = app.post('/redirect_rollback') - assert response.status_int == 302 - assert len(run_hook) == 3 - assert run_hook[0] == 'start' - assert run_hook[1] == 'rollback' - assert run_hook[2] == 'clear' - - # - # Exceptions (other than HTTPFound) should *always* - # rollback no matter what - # - run_hook = [] - - try: - response = app.post('/error') - except IndexError: - pass - - assert len(run_hook) == 3 - assert run_hook[0] == 'start' - assert run_hook[1] == 'rollback' - assert run_hook[2] == 'clear' - - run_hook = [] - - try: - response = app.get('/error') - except IndexError: - pass - - assert len(run_hook) == 5 - assert run_hook[0] == 'start_ro' - assert run_hook[1] == 'clear' - assert run_hook[2] == 'start' - assert run_hook[3] == 'rollback' - assert run_hook[4] == 'clear' - - # - # test hooks for GET /generic - # This controller should always be transactional, - # - - run_hook = [] - - response = app.get('/generic') - assert response.status_int == 200 - assert response.body == b_('generic get') - assert len(run_hook) == 6 - assert run_hook[0] == 'start_ro' - assert run_hook[1] == 'clear' - assert run_hook[2] == 'start' - assert run_hook[3] == 'inside' - assert run_hook[4] == 'commit' - assert run_hook[5] == 'clear' - - # - # test hooks for POST /generic - # This controller should always be transactional, - # - - run_hook = [] - - response = app.post('/generic') - assert response.status_int == 200 - assert response.body == b_('generic post') - assert len(run_hook) == 4 - assert run_hook[0] == 'start' - assert run_hook[1] == 'inside' - assert run_hook[2] == 'commit' - assert run_hook[3] == 'clear' - - def test_transaction_hook_with_broken_hook(self): - """ - In a scenario where a preceding hook throws an exception, - ensure that TransactionHook still rolls back properly. - """ - run_hook = [] - - class RootController(object): - @expose() - def index(self): - return 'Hello, World!' - - def gen(event): - return lambda: run_hook.append(event) - - class MyCustomException(Exception): - pass - - class MyHook(PecanHook): - - def on_route(self, state): - raise MyCustomException('BROKEN!') - - app = TestApp(make_app(RootController(), hooks=[ - MyHook(), - TransactionHook( - start=gen('start'), - start_ro=gen('start_ro'), - commit=gen('commit'), - rollback=gen('rollback'), - clear=gen('clear') - ) - ])) - - self.assertRaises( - MyCustomException, - app.get, - '/' - ) - - assert len(run_hook) == 1 - assert run_hook[0] == 'clear' - - -class TestRequestViewerHook(PecanTestCase): - - def test_basic_single_default_hook(self): - - _stdout = StringIO() - - class RootController(object): - @expose() - def index(self): - return 'Hello, World!' - - app = TestApp( - make_app( - RootController(), hooks=lambda: [ - RequestViewerHook(writer=_stdout) - ] - ) - ) - response = app.get('/') - - out = _stdout.getvalue() - - assert response.status_int == 200 - assert response.body == b_('Hello, World!') - assert 'path' in out - assert 'method' in out - assert 'status' in out - assert 'method' in out - assert 'params' in out - assert 'hooks' in out - assert '200 OK' in out - assert "['RequestViewerHook']" in out - assert '/' in out - - def test_bad_response_from_app(self): - """When exceptions are raised the hook deals with them properly""" - - _stdout = StringIO() - - class RootController(object): - @expose() - def index(self): - return 'Hello, World!' - - app = TestApp( - make_app( - RootController(), hooks=lambda: [ - RequestViewerHook(writer=_stdout) - ] - ) - ) - response = app.get('/404', expect_errors=True) - - out = _stdout.getvalue() - - assert response.status_int == 404 - assert 'path' in out - assert 'method' in out - assert 'status' in out - assert 'method' in out - assert 'params' in out - assert 'hooks' in out - assert '404 Not Found' in out - assert "['RequestViewerHook']" in out - assert '/' in out - - def test_single_item(self): - - _stdout = StringIO() - - class RootController(object): - @expose() - def index(self): - return 'Hello, World!' - - app = TestApp( - make_app( - RootController(), - hooks=lambda: [ - RequestViewerHook( - config={'items': ['path']}, writer=_stdout - ) - ] - ) - ) - response = app.get('/') - - out = _stdout.getvalue() - - assert response.status_int == 200 - assert response.body == b_('Hello, World!') - assert '/' in out - assert 'path' in out - assert 'method' not in out - assert 'status' not in out - assert 'method' not in out - assert 'params' not in out - assert 'hooks' not in out - assert '200 OK' not in out - assert "['RequestViewerHook']" not in out - - def test_single_blacklist_item(self): - - _stdout = StringIO() - - class RootController(object): - @expose() - def index(self): - return 'Hello, World!' - - app = TestApp( - make_app( - RootController(), - hooks=lambda: [ - RequestViewerHook( - config={'blacklist': ['/']}, writer=_stdout - ) - ] - ) - ) - response = app.get('/') - - out = _stdout.getvalue() - - assert response.status_int == 200 - assert response.body == b_('Hello, World!') - assert out == '' - - def test_item_not_in_defaults(self): - - _stdout = StringIO() - - class RootController(object): - @expose() - def index(self): - return 'Hello, World!' - - app = TestApp( - make_app( - RootController(), - hooks=lambda: [ - RequestViewerHook( - config={'items': ['date']}, writer=_stdout - ) - ] - ) - ) - response = app.get('/') - - out = _stdout.getvalue() - - assert response.status_int == 200 - assert response.body == b_('Hello, World!') - assert 'date' in out - assert 'method' not in out - assert 'status' not in out - assert 'method' not in out - assert 'params' not in out - assert 'hooks' not in out - assert '200 OK' not in out - assert "['RequestViewerHook']" not in out - assert '/' not in out - - def test_hook_formatting(self): - hooks = ['<pecan.hooks.RequestViewerHook object at 0x103a5f910>'] - viewer = RequestViewerHook() - formatted = viewer.format_hooks(hooks) - - assert formatted == ['RequestViewerHook'] - - def test_deal_with_pecan_configs(self): - """If config comes from pecan.conf convert it to dict""" - conf = Config(conf_dict={'items': ['url']}) - viewer = RequestViewerHook(conf) - - assert viewer.items == ['url'] - - -class TestRestControllerWithHooks(PecanTestCase): - - def test_restcontroller_with_hooks(self): - - class SomeHook(PecanHook): - - def before(self, state): - state.response.headers['X-Testing'] = 'XYZ' - - class BaseController(rest.RestController): - - @expose() - def delete(self, _id): - return 'Deleting %s' % _id - - class RootController(BaseController, HookController): - - __hooks__ = [SomeHook()] - - @expose() - def get_all(self): - return 'Hello, World!' - - @staticmethod - def static(cls): - return 'static' - - @property - def foo(self): - return 'bar' - - def testing123(self): - return 'bar' - - unhashable = [1, 'two', 3] - - app = TestApp( - make_app( - RootController() - ) - ) - - response = app.get('/') - assert response.status_int == 200 - assert response.body == b_('Hello, World!') - assert response.headers['X-Testing'] == 'XYZ' - - response = app.delete('/100/') - assert response.status_int == 200 - assert response.body == b_('Deleting 100') - assert response.headers['X-Testing'] == 'XYZ' diff --git a/pecan/tests/test_jsonify.py b/pecan/tests/test_jsonify.py deleted file mode 100644 index 2dcd663..0000000 --- a/pecan/tests/test_jsonify.py +++ /dev/null @@ -1,233 +0,0 @@ -from datetime import datetime, date -from decimal import Decimal -try: - from simplejson import loads -except: - from json import loads # noqa -try: - from sqlalchemy import orm, schema, types - from sqlalchemy.engine import create_engine -except ImportError: - create_engine = None # noqa - -from webtest import TestApp -from webob.multidict import MultiDict - -from pecan.jsonify import jsonify, encode, ResultProxy, RowProxy -from pecan import Pecan, expose -from pecan.tests import PecanTestCase - - -def make_person(): - class Person(object): - def __init__(self, first_name, last_name): - self.first_name = first_name - self.last_name = last_name - - @property - def name(self): - return '%s %s' % (self.first_name, self.last_name) - return Person - - -def test_simple_rule(): - Person = make_person() - - # create a Person instance - p = Person('Jonathan', 'LaCour') - - # register a generic JSON rule - @jsonify.when_type(Person) - def jsonify_person(obj): - return dict( - name=obj.name - ) - - # encode the object using our new rule - result = loads(encode(p)) - assert result['name'] == 'Jonathan LaCour' - assert len(result) == 1 - - -class TestJsonify(PecanTestCase): - - def test_simple_jsonify(self): - Person = make_person() - - # register a generic JSON rule - @jsonify.when_type(Person) - def jsonify_person(obj): - return dict( - name=obj.name - ) - - class RootController(object): - @expose('json') - def index(self): - # create a Person instance - p = Person('Jonathan', 'LaCour') - return p - - app = TestApp(Pecan(RootController())) - - r = app.get('/') - assert r.status_int == 200 - assert loads(r.body.decode()) == {'name': 'Jonathan LaCour'} - - -class TestJsonifyGenericEncoder(PecanTestCase): - def test_json_callable(self): - class JsonCallable(object): - def __init__(self, arg): - self.arg = arg - - def __json__(self): - return {"arg": self.arg} - - result = encode(JsonCallable('foo')) - assert loads(result) == {'arg': 'foo'} - - def test_datetime(self): - today = date.today() - now = datetime.now() - - result = encode(today) - assert loads(result) == str(today) - - result = encode(now) - assert loads(result) == str(now) - - def test_decimal(self): - # XXX Testing for float match which is inexact - - d = Decimal('1.1') - result = encode(d) - assert loads(result) == float(d) - - def test_multidict(self): - md = MultiDict() - md.add('arg', 'foo') - md.add('arg', 'bar') - result = encode(md) - assert loads(result) == {'arg': ['foo', 'bar']} - - def test_fallback_to_builtin_encoder(self): - class Foo(object): - pass - - self.assertRaises(TypeError, encode, Foo()) - - -class TestJsonifySQLAlchemyGenericEncoder(PecanTestCase): - - def setUp(self): - super(TestJsonifySQLAlchemyGenericEncoder, self).setUp() - if not create_engine: - self.create_fake_proxies() - else: - self.create_sa_proxies() - - def create_fake_proxies(self): - - # create a fake SA object - class FakeSAObject(object): - def __init__(self): - self._sa_class_manager = object() - self._sa_instance_state = 'awesome' - self.id = 1 - self.first_name = 'Jonathan' - self.last_name = 'LaCour' - - # create a fake result proxy - class FakeResultProxy(ResultProxy): - def __init__(self): - self.rowcount = -1 - self.rows = [] - - def __iter__(self): - return iter(self.rows) - - def append(self, row): - self.rows.append(row) - - # create a fake row proxy - class FakeRowProxy(RowProxy): - def __init__(self, arg=None): - self.row = dict(arg) - - def __getitem__(self, key): - return self.row.__getitem__(key) - - def keys(self): - return self.row.keys() - - # get the SA objects - self.sa_object = FakeSAObject() - self.result_proxy = FakeResultProxy() - self.result_proxy.append( - FakeRowProxy([ - ('id', 1), - ('first_name', 'Jonathan'), - ('last_name', 'LaCour') - ]) - ) - self.result_proxy.append( - FakeRowProxy([ - ('id', 2), ('first_name', 'Yoann'), ('last_name', 'Roman') - ])) - self.row_proxy = FakeRowProxy([ - ('id', 1), ('first_name', 'Jonathan'), ('last_name', 'LaCour') - ]) - - def create_sa_proxies(self): - - # create the table and mapper - metadata = schema.MetaData() - user_table = schema.Table( - 'user', - metadata, - schema.Column('id', types.Integer, primary_key=True), - schema.Column('first_name', types.Unicode(25)), - schema.Column('last_name', types.Unicode(25)) - ) - - class User(object): - pass - orm.mapper(User, user_table) - - # create the session - engine = create_engine('sqlite:///:memory:') - metadata.bind = engine - metadata.create_all() - session = orm.sessionmaker(bind=engine)() - - # add some dummy data - user_table.insert().execute([ - {'first_name': 'Jonathan', 'last_name': 'LaCour'}, - {'first_name': 'Yoann', 'last_name': 'Roman'} - ]) - - # get the SA objects - self.sa_object = session.query(User).first() - select = user_table.select() - self.result_proxy = select.execute() - self.row_proxy = select.execute().fetchone() - - def test_sa_object(self): - result = encode(self.sa_object) - assert loads(result) == { - 'id': 1, 'first_name': 'Jonathan', 'last_name': 'LaCour' - } - - def test_result_proxy(self): - result = encode(self.result_proxy) - assert loads(result) == {'count': 2, 'rows': [ - {'id': 1, 'first_name': 'Jonathan', 'last_name': 'LaCour'}, - {'id': 2, 'first_name': 'Yoann', 'last_name': 'Roman'} - ]} - - def test_row_proxy(self): - result = encode(self.row_proxy) - assert loads(result) == { - 'id': 1, 'first_name': 'Jonathan', 'last_name': 'LaCour' - } diff --git a/pecan/tests/test_no_thread_locals.py b/pecan/tests/test_no_thread_locals.py deleted file mode 100644 index 1ca418e..0000000 --- a/pecan/tests/test_no_thread_locals.py +++ /dev/null @@ -1,1440 +0,0 @@ -import time -from json import dumps, loads -import warnings - -from webtest import TestApp -from six import b as b_ -from six import u as u_ -import webob -import mock - -from pecan import Pecan, expose, abort, Request, Response -from pecan.rest import RestController -from pecan.hooks import PecanHook, HookController -from pecan.tests import PecanTestCase - - -class TestThreadingLocalUsage(PecanTestCase): - - @property - def root(self): - class RootController(object): - @expose() - def index(self, req, resp): - assert isinstance(req, webob.BaseRequest) - assert isinstance(resp, webob.Response) - return 'Hello, World!' - - @expose() - def warning(self): - return ("This should be unroutable because (req, resp) are not" - " arguments. It should raise a TypeError.") - - @expose(generic=True) - def generic(self): - return ("This should be unroutable because (req, resp) are not" - " arguments. It should raise a TypeError.") - - @generic.when(method='PUT') - def generic_put(self, _id): - return ("This should be unroutable because (req, resp) are not" - " arguments. It should raise a TypeError.") - - return RootController - - def test_locals_are_not_used(self): - with mock.patch('threading.local', side_effect=AssertionError()): - - app = TestApp(Pecan(self.root(), use_context_locals=False)) - r = app.get('/') - assert r.status_int == 200 - assert r.body == b_('Hello, World!') - - self.assertRaises(AssertionError, Pecan, self.root) - - def test_threadlocal_argument_warning(self): - with mock.patch('threading.local', side_effect=AssertionError()): - - app = TestApp(Pecan(self.root(), use_context_locals=False)) - self.assertRaises( - TypeError, - app.get, - '/warning/' - ) - - def test_threadlocal_argument_warning_on_generic(self): - with mock.patch('threading.local', side_effect=AssertionError()): - - app = TestApp(Pecan(self.root(), use_context_locals=False)) - self.assertRaises( - TypeError, - app.get, - '/generic/' - ) - - def test_threadlocal_argument_warning_on_generic_delegate(self): - with mock.patch('threading.local', side_effect=AssertionError()): - - app = TestApp(Pecan(self.root(), use_context_locals=False)) - self.assertRaises( - TypeError, - app.put, - '/generic/' - ) - - -class TestIndexRouting(PecanTestCase): - - @property - def app_(self): - class RootController(object): - @expose() - def index(self, req, resp): - assert isinstance(req, webob.BaseRequest) - assert isinstance(resp, webob.Response) - return 'Hello, World!' - - return TestApp(Pecan(RootController(), use_context_locals=False)) - - def test_empty_root(self): - r = self.app_.get('/') - assert r.status_int == 200 - assert r.body == b_('Hello, World!') - - def test_index(self): - r = self.app_.get('/index') - assert r.status_int == 200 - assert r.body == b_('Hello, World!') - - def test_index_html(self): - r = self.app_.get('/index.html') - assert r.status_int == 200 - assert r.body == b_('Hello, World!') - - -class TestManualResponse(PecanTestCase): - - def test_manual_response(self): - - class RootController(object): - @expose() - def index(self, req, resp): - resp = webob.Response(resp.environ) - resp.body = b_('Hello, World!') - return resp - - app = TestApp(Pecan(RootController(), use_context_locals=False)) - r = app.get('/') - assert r.body == b_('Hello, World!'), r.body - - -class TestDispatch(PecanTestCase): - - @property - def app_(self): - class SubSubController(object): - @expose() - def index(self, req, resp): - assert isinstance(req, webob.BaseRequest) - assert isinstance(resp, webob.Response) - return '/sub/sub/' - - @expose() - def deeper(self, req, resp): - assert isinstance(req, webob.BaseRequest) - assert isinstance(resp, webob.Response) - return '/sub/sub/deeper' - - class SubController(object): - @expose() - def index(self, req, resp): - assert isinstance(req, webob.BaseRequest) - assert isinstance(resp, webob.Response) - return '/sub/' - - @expose() - def deeper(self, req, resp): - assert isinstance(req, webob.BaseRequest) - assert isinstance(resp, webob.Response) - return '/sub/deeper' - - sub = SubSubController() - - class RootController(object): - @expose() - def index(self, req, resp): - assert isinstance(req, webob.BaseRequest) - assert isinstance(resp, webob.Response) - return '/' - - @expose() - def deeper(self, req, resp): - assert isinstance(req, webob.BaseRequest) - assert isinstance(resp, webob.Response) - return '/deeper' - - sub = SubController() - - return TestApp(Pecan(RootController(), use_context_locals=False)) - - def test_index(self): - r = self.app_.get('/') - assert r.status_int == 200 - assert r.body == b_('/') - - def test_one_level(self): - r = self.app_.get('/deeper') - assert r.status_int == 200 - assert r.body == b_('/deeper') - - def test_one_level_with_trailing(self): - r = self.app_.get('/sub/') - assert r.status_int == 200 - assert r.body == b_('/sub/') - - def test_two_levels(self): - r = self.app_.get('/sub/deeper') - assert r.status_int == 200 - assert r.body == b_('/sub/deeper') - - def test_two_levels_with_trailing(self): - r = self.app_.get('/sub/sub/') - assert r.status_int == 200 - - def test_three_levels(self): - r = self.app_.get('/sub/sub/deeper') - assert r.status_int == 200 - assert r.body == b_('/sub/sub/deeper') - - -class TestLookups(PecanTestCase): - - @property - def app_(self): - class LookupController(object): - def __init__(self, someID): - self.someID = someID - - @expose() - def index(self, req, resp): - return '/%s' % self.someID - - @expose() - def name(self, req, resp): - return '/%s/name' % self.someID - - class RootController(object): - @expose() - def index(self, req, resp): - return '/' - - @expose() - def _lookup(self, someID, *remainder): - return LookupController(someID), remainder - - return TestApp(Pecan(RootController(), use_context_locals=False)) - - def test_index(self): - r = self.app_.get('/') - assert r.status_int == 200 - assert r.body == b_('/') - - def test_lookup(self): - r = self.app_.get('/100/') - assert r.status_int == 200 - assert r.body == b_('/100') - - def test_lookup_with_method(self): - r = self.app_.get('/100/name') - assert r.status_int == 200 - assert r.body == b_('/100/name') - - def test_lookup_with_wrong_argspec(self): - class RootController(object): - @expose() - def _lookup(self, someID): - return 'Bad arg spec' # pragma: nocover - - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - app = TestApp(Pecan(RootController(), use_context_locals=False)) - r = app.get('/foo/bar', expect_errors=True) - assert r.status_int == 404 - - -class TestCanonicalLookups(PecanTestCase): - - @property - def app_(self): - class LookupController(object): - def __init__(self, someID): - self.someID = someID - - @expose() - def index(self, req, resp): - return self.someID - - class UserController(object): - @expose() - def _lookup(self, someID, *remainder): - return LookupController(someID), remainder - - class RootController(object): - users = UserController() - - return TestApp(Pecan(RootController(), use_context_locals=False)) - - def test_canonical_lookup(self): - assert self.app_.get('/users', expect_errors=404).status_int == 404 - assert self.app_.get('/users/', expect_errors=404).status_int == 404 - assert self.app_.get('/users/100').status_int == 302 - assert self.app_.get('/users/100/').body == b_('100') - - -class TestControllerArguments(PecanTestCase): - - @property - def app_(self): - class RootController(object): - @expose() - def index(self, req, resp, id): - return 'index: %s' % id - - @expose() - def multiple(self, req, resp, one, two): - return 'multiple: %s, %s' % (one, two) - - @expose() - def optional(self, req, resp, id=None): - return 'optional: %s' % str(id) - - @expose() - def multiple_optional(self, req, resp, one=None, two=None, - three=None): - return 'multiple_optional: %s, %s, %s' % (one, two, three) - - @expose() - def variable_args(self, req, resp, *args): - return 'variable_args: %s' % ', '.join(args) - - @expose() - def variable_kwargs(self, req, resp, **kwargs): - data = [ - '%s=%s' % (key, kwargs[key]) - for key in sorted(kwargs.keys()) - ] - return 'variable_kwargs: %s' % ', '.join(data) - - @expose() - def variable_all(self, req, resp, *args, **kwargs): - data = [ - '%s=%s' % (key, kwargs[key]) - for key in sorted(kwargs.keys()) - ] - return 'variable_all: %s' % ', '.join(list(args) + data) - - @expose() - def eater(self, req, resp, id, dummy=None, *args, **kwargs): - data = [ - '%s=%s' % (key, kwargs[key]) - for key in sorted(kwargs.keys()) - ] - return 'eater: %s, %s, %s' % ( - id, - dummy, - ', '.join(list(args) + data) - ) - - @expose() - def _route(self, args, request): - if hasattr(self, args[0]): - return getattr(self, args[0]), args[1:] - else: - return self.index, args - - return TestApp(Pecan(RootController(), use_context_locals=False)) - - def test_required_argument(self): - try: - r = self.app_.get('/') - assert r.status_int != 200 # pragma: nocover - except Exception as ex: - assert type(ex) == TypeError - assert ex.args[0] in ( - "index() takes exactly 4 arguments (3 given)", - "index() missing 1 required positional argument: 'id'" - ) # this messaging changed in Python 3.3 - - def test_single_argument(self): - r = self.app_.get('/1') - assert r.status_int == 200 - assert r.body == b_('index: 1') - - def test_single_argument_with_encoded_url(self): - r = self.app_.get('/This%20is%20a%20test%21') - assert r.status_int == 200 - assert r.body == b_('index: This is a test!') - - def test_two_arguments(self): - r = self.app_.get('/1/dummy', status=404) - assert r.status_int == 404 - - def test_keyword_argument(self): - r = self.app_.get('/?id=2') - assert r.status_int == 200 - assert r.body == b_('index: 2') - - def test_keyword_argument_with_encoded_url(self): - r = self.app_.get('/?id=This%20is%20a%20test%21') - assert r.status_int == 200 - assert r.body == b_('index: This is a test!') - - def test_argument_and_keyword_argument(self): - r = self.app_.get('/3?id=three') - assert r.status_int == 200 - assert r.body == b_('index: 3') - - def test_encoded_argument_and_keyword_argument(self): - r = self.app_.get('/This%20is%20a%20test%21?id=three') - assert r.status_int == 200 - assert r.body == b_('index: This is a test!') - - def test_explicit_kwargs(self): - r = self.app_.post('/', {'id': '4'}) - assert r.status_int == 200 - assert r.body == b_('index: 4') - - def test_path_with_explicit_kwargs(self): - r = self.app_.post('/4', {'id': 'four'}) - assert r.status_int == 200 - assert r.body == b_('index: 4') - - def test_multiple_kwargs(self): - r = self.app_.get('/?id=5&dummy=dummy') - assert r.status_int == 200 - assert r.body == b_('index: 5') - - def test_kwargs_from_root(self): - r = self.app_.post('/', {'id': '6', 'dummy': 'dummy'}) - assert r.status_int == 200 - assert r.body == b_('index: 6') - - # multiple args - - def test_multiple_positional_arguments(self): - r = self.app_.get('/multiple/one/two') - assert r.status_int == 200 - assert r.body == b_('multiple: one, two') - - def test_multiple_positional_arguments_with_url_encode(self): - r = self.app_.get('/multiple/One%20/Two%21') - assert r.status_int == 200 - assert r.body == b_('multiple: One , Two!') - - def test_multiple_positional_arguments_with_kwargs(self): - r = self.app_.get('/multiple?one=three&two=four') - assert r.status_int == 200 - assert r.body == b_('multiple: three, four') - - def test_multiple_positional_arguments_with_url_encoded_kwargs(self): - r = self.app_.get('/multiple?one=Three%20&two=Four%20%21') - assert r.status_int == 200 - assert r.body == b_('multiple: Three , Four !') - - def test_positional_args_with_dictionary_kwargs(self): - r = self.app_.post('/multiple', {'one': 'five', 'two': 'six'}) - assert r.status_int == 200 - assert r.body == b_('multiple: five, six') - - def test_positional_args_with_url_encoded_dictionary_kwargs(self): - r = self.app_.post('/multiple', {'one': 'Five%20', 'two': 'Six%20%21'}) - assert r.status_int == 200 - assert r.body == b_('multiple: Five%20, Six%20%21') - - # optional arg - def test_optional_arg(self): - r = self.app_.get('/optional') - assert r.status_int == 200 - assert r.body == b_('optional: None') - - def test_multiple_optional(self): - r = self.app_.get('/optional/1') - assert r.status_int == 200 - assert r.body == b_('optional: 1') - - def test_multiple_optional_url_encoded(self): - r = self.app_.get('/optional/Some%20Number') - assert r.status_int == 200 - assert r.body == b_('optional: Some Number') - - def test_multiple_optional_missing(self): - r = self.app_.get('/optional/2/dummy', status=404) - assert r.status_int == 404 - - def test_multiple_with_kwargs(self): - r = self.app_.get('/optional?id=2') - assert r.status_int == 200 - assert r.body == b_('optional: 2') - - def test_multiple_with_url_encoded_kwargs(self): - r = self.app_.get('/optional?id=Some%20Number') - assert r.status_int == 200 - assert r.body == b_('optional: Some Number') - - def test_multiple_args_with_url_encoded_kwargs(self): - r = self.app_.get('/optional/3?id=three') - assert r.status_int == 200 - assert r.body == b_('optional: 3') - - def test_url_encoded_positional_args(self): - r = self.app_.get('/optional/Some%20Number?id=three') - assert r.status_int == 200 - assert r.body == b_('optional: Some Number') - - def test_optional_arg_with_kwargs(self): - r = self.app_.post('/optional', {'id': '4'}) - assert r.status_int == 200 - assert r.body == b_('optional: 4') - - def test_optional_arg_with_url_encoded_kwargs(self): - r = self.app_.post('/optional', {'id': 'Some%20Number'}) - assert r.status_int == 200 - assert r.body == b_('optional: Some%20Number') - - def test_multiple_positional_arguments_with_dictionary_kwargs(self): - r = self.app_.post('/optional/5', {'id': 'five'}) - assert r.status_int == 200 - assert r.body == b_('optional: 5') - - def test_multiple_positional_url_encoded_arguments_with_kwargs(self): - r = self.app_.post('/optional/Some%20Number', {'id': 'five'}) - assert r.status_int == 200 - assert r.body == b_('optional: Some Number') - - def test_optional_arg_with_multiple_kwargs(self): - r = self.app_.get('/optional?id=6&dummy=dummy') - assert r.status_int == 200 - assert r.body == b_('optional: 6') - - def test_optional_arg_with_multiple_url_encoded_kwargs(self): - r = self.app_.get('/optional?id=Some%20Number&dummy=dummy') - assert r.status_int == 200 - assert r.body == b_('optional: Some Number') - - def test_optional_arg_with_multiple_dictionary_kwargs(self): - r = self.app_.post('/optional', {'id': '7', 'dummy': 'dummy'}) - assert r.status_int == 200 - assert r.body == b_('optional: 7') - - def test_optional_arg_with_multiple_url_encoded_dictionary_kwargs(self): - r = self.app_.post('/optional', { - 'id': 'Some%20Number', - 'dummy': 'dummy' - }) - assert r.status_int == 200 - assert r.body == b_('optional: Some%20Number') - - # multiple optional args - - def test_multiple_optional_positional_args(self): - r = self.app_.get('/multiple_optional') - assert r.status_int == 200 - assert r.body == b_('multiple_optional: None, None, None') - - def test_multiple_optional_positional_args_one_arg(self): - r = self.app_.get('/multiple_optional/1') - assert r.status_int == 200 - assert r.body == b_('multiple_optional: 1, None, None') - - def test_multiple_optional_positional_args_one_url_encoded_arg(self): - r = self.app_.get('/multiple_optional/One%21') - assert r.status_int == 200 - assert r.body == b_('multiple_optional: One!, None, None') - - def test_multiple_optional_positional_args_all_args(self): - r = self.app_.get('/multiple_optional/1/2/3') - assert r.status_int == 200 - assert r.body == b_('multiple_optional: 1, 2, 3') - - def test_multiple_optional_positional_args_all_url_encoded_args(self): - r = self.app_.get('/multiple_optional/One%21/Two%21/Three%21') - assert r.status_int == 200 - assert r.body == b_('multiple_optional: One!, Two!, Three!') - - def test_multiple_optional_positional_args_too_many_args(self): - r = self.app_.get('/multiple_optional/1/2/3/dummy', status=404) - assert r.status_int == 404 - - def test_multiple_optional_positional_args_with_kwargs(self): - r = self.app_.get('/multiple_optional?one=1') - assert r.status_int == 200 - assert r.body == b_('multiple_optional: 1, None, None') - - def test_multiple_optional_positional_args_with_url_encoded_kwargs(self): - r = self.app_.get('/multiple_optional?one=One%21') - assert r.status_int == 200 - assert r.body == b_('multiple_optional: One!, None, None') - - def test_multiple_optional_positional_args_with_string_kwargs(self): - r = self.app_.get('/multiple_optional/1?one=one') - assert r.status_int == 200 - assert r.body == b_('multiple_optional: 1, None, None') - - def test_multiple_optional_positional_args_with_encoded_str_kwargs(self): - r = self.app_.get('/multiple_optional/One%21?one=one') - assert r.status_int == 200 - assert r.body == b_('multiple_optional: One!, None, None') - - def test_multiple_optional_positional_args_with_dict_kwargs(self): - r = self.app_.post('/multiple_optional', {'one': '1'}) - assert r.status_int == 200 - assert r.body == b_('multiple_optional: 1, None, None') - - def test_multiple_optional_positional_args_with_encoded_dict_kwargs(self): - r = self.app_.post('/multiple_optional', {'one': 'One%21'}) - assert r.status_int == 200 - assert r.body == b_('multiple_optional: One%21, None, None') - - def test_multiple_optional_positional_args_and_dict_kwargs(self): - r = self.app_.post('/multiple_optional/1', {'one': 'one'}) - assert r.status_int == 200 - assert r.body == b_('multiple_optional: 1, None, None') - - def test_multiple_optional_encoded_positional_args_and_dict_kwargs(self): - r = self.app_.post('/multiple_optional/One%21', {'one': 'one'}) - assert r.status_int == 200 - assert r.body == b_('multiple_optional: One!, None, None') - - def test_multiple_optional_args_with_multiple_kwargs(self): - r = self.app_.get('/multiple_optional?one=1&two=2&three=3&four=4') - assert r.status_int == 200 - assert r.body == b_('multiple_optional: 1, 2, 3') - - def test_multiple_optional_args_with_multiple_encoded_kwargs(self): - r = self.app_.get( - '/multiple_optional?one=One%21&two=Two%21&three=Three%21&four=4' - ) - assert r.status_int == 200 - assert r.body == b_('multiple_optional: One!, Two!, Three!') - - def test_multiple_optional_args_with_multiple_dict_kwargs(self): - r = self.app_.post( - '/multiple_optional', - {'one': '1', 'two': '2', 'three': '3', 'four': '4'} - ) - assert r.status_int == 200 - assert r.body == b_('multiple_optional: 1, 2, 3') - - def test_multiple_optional_args_with_multiple_encoded_dict_kwargs(self): - r = self.app_.post( - '/multiple_optional', - { - 'one': 'One%21', - 'two': 'Two%21', - 'three': 'Three%21', - 'four': '4' - } - ) - assert r.status_int == 200 - assert r.body == b_('multiple_optional: One%21, Two%21, Three%21') - - def test_multiple_optional_args_with_last_kwarg(self): - r = self.app_.get('/multiple_optional?three=3') - assert r.status_int == 200 - assert r.body == b_('multiple_optional: None, None, 3') - - def test_multiple_optional_args_with_last_encoded_kwarg(self): - r = self.app_.get('/multiple_optional?three=Three%21') - assert r.status_int == 200 - assert r.body == b_('multiple_optional: None, None, Three!') - - def test_multiple_optional_args_with_middle_arg(self): - r = self.app_.get('/multiple_optional', {'two': '2'}) - assert r.status_int == 200 - assert r.body == b_('multiple_optional: None, 2, None') - - def test_variable_args(self): - r = self.app_.get('/variable_args') - assert r.status_int == 200 - assert r.body == b_('variable_args: ') - - def test_multiple_variable_args(self): - r = self.app_.get('/variable_args/1/dummy') - assert r.status_int == 200 - assert r.body == b_('variable_args: 1, dummy') - - def test_multiple_encoded_variable_args(self): - r = self.app_.get('/variable_args/Testing%20One%20Two/Three%21') - assert r.status_int == 200 - assert r.body == b_('variable_args: Testing One Two, Three!') - - def test_variable_args_with_kwargs(self): - r = self.app_.get('/variable_args?id=2&dummy=dummy') - assert r.status_int == 200 - assert r.body == b_('variable_args: ') - - def test_variable_args_with_dict_kwargs(self): - r = self.app_.post('/variable_args', {'id': '3', 'dummy': 'dummy'}) - assert r.status_int == 200 - assert r.body == b_('variable_args: ') - - def test_variable_kwargs(self): - r = self.app_.get('/variable_kwargs') - assert r.status_int == 200 - assert r.body == b_('variable_kwargs: ') - - def test_multiple_variable_kwargs(self): - r = self.app_.get('/variable_kwargs/1/dummy', status=404) - assert r.status_int == 404 - - def test_multiple_variable_kwargs_with_explicit_kwargs(self): - r = self.app_.get('/variable_kwargs?id=2&dummy=dummy') - assert r.status_int == 200 - assert r.body == b_('variable_kwargs: dummy=dummy, id=2') - - def test_multiple_variable_kwargs_with_explicit_encoded_kwargs(self): - r = self.app_.get( - '/variable_kwargs?id=Two%21&dummy=This%20is%20a%20test' - ) - assert r.status_int == 200 - assert r.body == b_('variable_kwargs: dummy=This is a test, id=Two!') - - def test_multiple_variable_kwargs_with_dict_kwargs(self): - r = self.app_.post('/variable_kwargs', {'id': '3', 'dummy': 'dummy'}) - assert r.status_int == 200 - assert r.body == b_('variable_kwargs: dummy=dummy, id=3') - - def test_multiple_variable_kwargs_with_encoded_dict_kwargs(self): - r = self.app_.post( - '/variable_kwargs', - {'id': 'Three%21', 'dummy': 'This%20is%20a%20test'} - ) - assert r.status_int == 200 - result = 'variable_kwargs: dummy=This%20is%20a%20test, id=Three%21' - assert r.body == b_(result) - - def test_variable_all(self): - r = self.app_.get('/variable_all') - assert r.status_int == 200 - assert r.body == b_('variable_all: ') - - def test_variable_all_with_one_extra(self): - r = self.app_.get('/variable_all/1') - assert r.status_int == 200 - assert r.body == b_('variable_all: 1') - - def test_variable_all_with_two_extras(self): - r = self.app_.get('/variable_all/2/dummy') - assert r.status_int == 200 - assert r.body == b_('variable_all: 2, dummy') - - def test_variable_mixed(self): - r = self.app_.get('/variable_all/3?month=1&day=12') - assert r.status_int == 200 - assert r.body == b_('variable_all: 3, day=12, month=1') - - def test_variable_mixed_explicit(self): - r = self.app_.get('/variable_all/4?id=four&month=1&day=12') - assert r.status_int == 200 - assert r.body == b_('variable_all: 4, day=12, id=four, month=1') - - def test_variable_post(self): - r = self.app_.post('/variable_all/5/dummy') - assert r.status_int == 200 - assert r.body == b_('variable_all: 5, dummy') - - def test_variable_post_with_kwargs(self): - r = self.app_.post('/variable_all/6', {'month': '1', 'day': '12'}) - assert r.status_int == 200 - assert r.body == b_('variable_all: 6, day=12, month=1') - - def test_variable_post_mixed(self): - r = self.app_.post( - '/variable_all/7', - {'id': 'seven', 'month': '1', 'day': '12'} - ) - assert r.status_int == 200 - assert r.body == b_('variable_all: 7, day=12, id=seven, month=1') - - def test_no_remainder(self): - try: - r = self.app_.get('/eater') - assert r.status_int != 200 # pragma: nocover - except Exception as ex: - assert type(ex) == TypeError - assert ex.args[0] in ( - "eater() takes at least 4 arguments (3 given)", - "eater() missing 1 required positional argument: 'id'" - ) # this messaging changed in Python 3.3 - - def test_one_remainder(self): - r = self.app_.get('/eater/1') - assert r.status_int == 200 - assert r.body == b_('eater: 1, None, ') - - def test_two_remainders(self): - r = self.app_.get('/eater/2/dummy') - assert r.status_int == 200 - assert r.body == b_('eater: 2, dummy, ') - - def test_many_remainders(self): - r = self.app_.get('/eater/3/dummy/foo/bar') - assert r.status_int == 200 - assert r.body == b_('eater: 3, dummy, foo, bar') - - def test_remainder_with_kwargs(self): - r = self.app_.get('/eater/4?month=1&day=12') - assert r.status_int == 200 - assert r.body == b_('eater: 4, None, day=12, month=1') - - def test_remainder_with_many_kwargs(self): - r = self.app_.get('/eater/5?id=five&month=1&day=12&dummy=dummy') - assert r.status_int == 200 - assert r.body == b_('eater: 5, dummy, day=12, month=1') - - def test_post_remainder(self): - r = self.app_.post('/eater/6') - assert r.status_int == 200 - assert r.body == b_('eater: 6, None, ') - - def test_post_three_remainders(self): - r = self.app_.post('/eater/7/dummy') - assert r.status_int == 200 - assert r.body == b_('eater: 7, dummy, ') - - def test_post_many_remainders(self): - r = self.app_.post('/eater/8/dummy/foo/bar') - assert r.status_int == 200 - assert r.body == b_('eater: 8, dummy, foo, bar') - - def test_post_remainder_with_kwargs(self): - r = self.app_.post('/eater/9', {'month': '1', 'day': '12'}) - assert r.status_int == 200 - assert r.body == b_('eater: 9, None, day=12, month=1') - - def test_post_many_remainders_with_many_kwargs(self): - r = self.app_.post( - '/eater/10', - {'id': 'ten', 'month': '1', 'day': '12', 'dummy': 'dummy'} - ) - assert r.status_int == 200 - assert r.body == b_('eater: 10, dummy, day=12, month=1') - - -class TestRestController(PecanTestCase): - - @property - def app_(self): - - class OthersController(object): - - @expose() - def index(self, req, resp): - return 'OTHERS' - - @expose() - def echo(self, req, resp, value): - return str(value) - - class ThingsController(RestController): - data = ['zero', 'one', 'two', 'three'] - - _custom_actions = {'count': ['GET'], 'length': ['GET', 'POST']} - - others = OthersController() - - @expose() - def get_one(self, req, resp, id): - return self.data[int(id)] - - @expose('json') - def get_all(self, req, resp): - return dict(items=self.data) - - @expose() - def length(self, req, resp, id, value=None): - length = len(self.data[int(id)]) - if value: - length += len(value) - return str(length) - - @expose() - def post(self, req, resp, value): - self.data.append(value) - resp.status = 302 - return 'CREATED' - - @expose() - def edit(self, req, resp, id): - return 'EDIT %s' % self.data[int(id)] - - @expose() - def put(self, req, resp, id, value): - self.data[int(id)] = value - return 'UPDATED' - - @expose() - def get_delete(self, req, resp, id): - return 'DELETE %s' % self.data[int(id)] - - @expose() - def delete(self, req, resp, id): - del self.data[int(id)] - return 'DELETED' - - @expose() - def reset(self, req, resp): - return 'RESET' - - @expose() - def post_options(self, req, resp): - return 'OPTIONS' - - @expose() - def options(self, req, resp): - abort(500) - - @expose() - def other(self, req, resp): - abort(500) - - class RootController(object): - things = ThingsController() - - # create the app - return TestApp(Pecan(RootController(), use_context_locals=False)) - - def test_get_all(self): - r = self.app_.get('/things') - assert r.status_int == 200 - assert r.body == b_(dumps(dict(items=['zero', 'one', 'two', 'three']))) - - def test_get_one(self): - for i, value in enumerate(['zero', 'one', 'two', 'three']): - r = self.app_.get('/things/%d' % i) - assert r.status_int == 200 - assert r.body == b_(value) - - def test_post(self): - r = self.app_.post('/things', {'value': 'four'}) - assert r.status_int == 302 - assert r.body == b_('CREATED') - - def test_custom_action(self): - r = self.app_.get('/things/3/edit') - assert r.status_int == 200 - assert r.body == b_('EDIT three') - - def test_put(self): - r = self.app_.put('/things/3', {'value': 'THREE!'}) - assert r.status_int == 200 - assert r.body == b_('UPDATED') - - def test_put_with_method_parameter_and_get(self): - r = self.app_.get('/things/3?_method=put', {'value': 'X'}, status=405) - assert r.status_int == 405 - - def test_put_with_method_parameter_and_post(self): - r = self.app_.post('/things/3?_method=put', {'value': 'THREE!'}) - assert r.status_int == 200 - assert r.body == b_('UPDATED') - - def test_get_delete(self): - r = self.app_.get('/things/3/delete') - assert r.status_int == 200 - assert r.body == b_('DELETE three') - - def test_delete_method(self): - r = self.app_.delete('/things/3') - assert r.status_int == 200 - assert r.body == b_('DELETED') - - def test_delete_with_method_parameter(self): - r = self.app_.get('/things/3?_method=DELETE', status=405) - assert r.status_int == 405 - - def test_delete_with_method_parameter_and_post(self): - r = self.app_.post('/things/3?_method=DELETE') - assert r.status_int == 200 - assert r.body == b_('DELETED') - - def test_custom_method_type(self): - r = self.app_.request('/things', method='RESET') - assert r.status_int == 200 - assert r.body == b_('RESET') - - def test_custom_method_type_with_method_parameter(self): - r = self.app_.get('/things?_method=RESET') - assert r.status_int == 200 - assert r.body == b_('RESET') - - def test_options(self): - r = self.app_.request('/things', method='OPTIONS') - assert r.status_int == 200 - assert r.body == b_('OPTIONS') - - def test_options_with_method_parameter(self): - r = self.app_.post('/things', {'_method': 'OPTIONS'}) - assert r.status_int == 200 - assert r.body == b_('OPTIONS') - - def test_other_custom_action(self): - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - r = self.app_.request('/things/other', method='MISC', status=405) - assert r.status_int == 405 - - def test_other_custom_action_with_method_parameter(self): - r = self.app_.post('/things/other', {'_method': 'MISC'}, status=405) - assert r.status_int == 405 - - def test_nested_controller_with_trailing_slash(self): - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - r = self.app_.request('/things/others/', method='MISC') - assert r.status_int == 200 - assert r.body == b_('OTHERS') - - def test_nested_controller_without_trailing_slash(self): - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - r = self.app_.request('/things/others', method='MISC', status=302) - assert r.status_int == 302 - - def test_invalid_custom_action(self): - r = self.app_.get('/things?_method=BAD', status=405) - assert r.status_int == 405 - - def test_named_action(self): - # test custom "GET" request "length" - r = self.app_.get('/things/1/length') - assert r.status_int == 200 - assert r.body == b_(str(len('one'))) - - def test_named_nested_action(self): - # test custom "GET" request through subcontroller - r = self.app_.get('/things/others/echo?value=test') - assert r.status_int == 200 - assert r.body == b_('test') - - def test_nested_post(self): - # test custom "POST" request through subcontroller - r = self.app_.post('/things/others/echo', {'value': 'test'}) - assert r.status_int == 200 - assert r.body == b_('test') - - -class TestHooks(PecanTestCase): - - def test_basic_single_hook(self): - run_hook = [] - - class RootController(object): - @expose() - def index(self, req, resp): - run_hook.append('inside') - return 'Hello, World!' - - class SimpleHook(PecanHook): - def on_route(self, state): - run_hook.append('on_route') - - def before(self, state): - run_hook.append('before') - - def after(self, state): - run_hook.append('after') - - def on_error(self, state, e): - run_hook.append('error') - - app = TestApp(Pecan( - RootController(), - hooks=[SimpleHook()], - use_context_locals=False - )) - response = app.get('/') - assert response.status_int == 200 - assert response.body == b_('Hello, World!') - - assert len(run_hook) == 4 - assert run_hook[0] == 'on_route' - assert run_hook[1] == 'before' - assert run_hook[2] == 'inside' - assert run_hook[3] == 'after' - - def test_basic_multi_hook(self): - run_hook = [] - - class RootController(object): - @expose() - def index(self, req, resp): - run_hook.append('inside') - return 'Hello, World!' - - class SimpleHook(PecanHook): - def __init__(self, id): - self.id = str(id) - - def on_route(self, state): - run_hook.append('on_route' + self.id) - - def before(self, state): - run_hook.append('before' + self.id) - - def after(self, state): - run_hook.append('after' + self.id) - - def on_error(self, state, e): - run_hook.append('error' + self.id) - - app = TestApp(Pecan(RootController(), hooks=[ - SimpleHook(1), SimpleHook(2), SimpleHook(3) - ], use_context_locals=False)) - response = app.get('/') - assert response.status_int == 200 - assert response.body == b_('Hello, World!') - - assert len(run_hook) == 10 - assert run_hook[0] == 'on_route1' - assert run_hook[1] == 'on_route2' - assert run_hook[2] == 'on_route3' - assert run_hook[3] == 'before1' - assert run_hook[4] == 'before2' - assert run_hook[5] == 'before3' - assert run_hook[6] == 'inside' - assert run_hook[7] == 'after3' - assert run_hook[8] == 'after2' - assert run_hook[9] == 'after1' - - def test_partial_hooks(self): - run_hook = [] - - class RootController(object): - @expose() - def index(self, req, resp): - run_hook.append('inside') - return 'Hello World!' - - @expose() - def causeerror(self, req, resp): - return [][1] - - class ErrorHook(PecanHook): - def on_error(self, state, e): - run_hook.append('error') - - class OnRouteHook(PecanHook): - def on_route(self, state): - run_hook.append('on_route') - - app = TestApp(Pecan(RootController(), hooks=[ - ErrorHook(), OnRouteHook() - ], use_context_locals=False)) - - response = app.get('/') - assert response.status_int == 200 - assert response.body == b_('Hello World!') - - assert len(run_hook) == 2 - assert run_hook[0] == 'on_route' - assert run_hook[1] == 'inside' - - run_hook = [] - try: - response = app.get('/causeerror') - except Exception as e: - assert isinstance(e, IndexError) - - assert len(run_hook) == 2 - assert run_hook[0] == 'on_route' - assert run_hook[1] == 'error' - - def test_on_error_response_hook(self): - run_hook = [] - - class RootController(object): - @expose() - def causeerror(self, req, resp): - return [][1] - - class ErrorHook(PecanHook): - def on_error(self, state, e): - run_hook.append('error') - - r = webob.Response() - r.text = u_('on_error') - - return r - - app = TestApp(Pecan(RootController(), hooks=[ - ErrorHook() - ], use_context_locals=False)) - - response = app.get('/causeerror') - - assert len(run_hook) == 1 - assert run_hook[0] == 'error' - assert response.text == 'on_error' - - def test_prioritized_hooks(self): - run_hook = [] - - class RootController(object): - @expose() - def index(self, req, resp): - run_hook.append('inside') - return 'Hello, World!' - - class SimpleHook(PecanHook): - def __init__(self, id, priority=None): - self.id = str(id) - if priority: - self.priority = priority - - def on_route(self, state): - run_hook.append('on_route' + self.id) - - def before(self, state): - run_hook.append('before' + self.id) - - def after(self, state): - run_hook.append('after' + self.id) - - def on_error(self, state, e): - run_hook.append('error' + self.id) - - papp = Pecan(RootController(), hooks=[ - SimpleHook(1, 3), SimpleHook(2, 2), SimpleHook(3, 1) - ], use_context_locals=False) - app = TestApp(papp) - response = app.get('/') - assert response.status_int == 200 - assert response.body == b_('Hello, World!') - - assert len(run_hook) == 10 - assert run_hook[0] == 'on_route3' - assert run_hook[1] == 'on_route2' - assert run_hook[2] == 'on_route1' - assert run_hook[3] == 'before3' - assert run_hook[4] == 'before2' - assert run_hook[5] == 'before1' - assert run_hook[6] == 'inside' - assert run_hook[7] == 'after1' - assert run_hook[8] == 'after2' - assert run_hook[9] == 'after3' - - def test_basic_isolated_hook(self): - run_hook = [] - - class SimpleHook(PecanHook): - def on_route(self, state): - run_hook.append('on_route') - - def before(self, state): - run_hook.append('before') - - def after(self, state): - run_hook.append('after') - - def on_error(self, state, e): - run_hook.append('error') - - class SubSubController(object): - @expose() - def index(self, req, resp): - run_hook.append('inside_sub_sub') - return 'Deep inside here!' - - class SubController(HookController): - __hooks__ = [SimpleHook()] - - @expose() - def index(self, req, resp): - run_hook.append('inside_sub') - return 'Inside here!' - - sub = SubSubController() - - class RootController(object): - @expose() - def index(self, req, resp): - run_hook.append('inside') - return 'Hello, World!' - - sub = SubController() - - app = TestApp(Pecan(RootController(), use_context_locals=False)) - response = app.get('/') - assert response.status_int == 200 - assert response.body == b_('Hello, World!') - - assert len(run_hook) == 1 - assert run_hook[0] == 'inside' - - run_hook = [] - - response = app.get('/sub/') - assert response.status_int == 200 - assert response.body == b_('Inside here!') - - assert len(run_hook) == 3 - assert run_hook[0] == 'before' - assert run_hook[1] == 'inside_sub' - assert run_hook[2] == 'after' - - run_hook = [] - response = app.get('/sub/sub/') - assert response.status_int == 200 - assert response.body == b_('Deep inside here!') - - assert len(run_hook) == 3 - assert run_hook[0] == 'before' - assert run_hook[1] == 'inside_sub_sub' - assert run_hook[2] == 'after' - - def test_isolated_hook_with_global_hook(self): - run_hook = [] - - class SimpleHook(PecanHook): - def __init__(self, id): - self.id = str(id) - - def on_route(self, state): - run_hook.append('on_route' + self.id) - - def before(self, state): - run_hook.append('before' + self.id) - - def after(self, state): - run_hook.append('after' + self.id) - - def on_error(self, state, e): - run_hook.append('error' + self.id) - - class SubController(HookController): - __hooks__ = [SimpleHook(2)] - - @expose() - def index(self, req, resp): - run_hook.append('inside_sub') - return 'Inside here!' - - class RootController(object): - @expose() - def index(self, req, resp): - run_hook.append('inside') - return 'Hello, World!' - - sub = SubController() - - app = TestApp(Pecan( - RootController(), - hooks=[SimpleHook(1)], - use_context_locals=False - )) - response = app.get('/') - assert response.status_int == 200 - assert response.body == b_('Hello, World!') - - assert len(run_hook) == 4 - assert run_hook[0] == 'on_route1' - assert run_hook[1] == 'before1' - assert run_hook[2] == 'inside' - assert run_hook[3] == 'after1' - - run_hook = [] - - response = app.get('/sub/') - assert response.status_int == 200 - assert response.body == b_('Inside here!') - - assert len(run_hook) == 6 - assert run_hook[0] == 'on_route1' - assert run_hook[1] == 'before2' - assert run_hook[2] == 'before1' - assert run_hook[3] == 'inside_sub' - assert run_hook[4] == 'after1' - 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' diff --git a/pecan/tests/test_rest.py b/pecan/tests/test_rest.py deleted file mode 100644 index ba4d141..0000000 --- a/pecan/tests/test_rest.py +++ /dev/null @@ -1,1640 +0,0 @@ -# -*- coding: utf-8 -*- - -import struct -import sys -import warnings - -if sys.version_info < (2, 7): - import unittest2 as unittest # pragma: nocover -else: - import unittest # pragma: nocover - -try: - from simplejson import dumps, loads -except: - from json import dumps, loads # noqa - -from six import b as b_, PY3 -from webtest import TestApp - -from pecan import abort, expose, make_app, response, redirect -from pecan.rest import RestController -from pecan.tests import PecanTestCase - - -class TestRestController(PecanTestCase): - - def test_basic_rest(self): - - class OthersController(object): - - @expose() - def index(self): - return 'OTHERS' - - @expose() - def echo(self, value): - return str(value) - - class ThingsController(RestController): - data = ['zero', 'one', 'two', 'three'] - - _custom_actions = {'count': ['GET'], 'length': ['GET', 'POST']} - - others = OthersController() - - @expose() - def get_one(self, id): - return self.data[int(id)] - - @expose('json') - def get_all(self): - return dict(items=self.data) - - @expose() - def length(self, id, value=None): - length = len(self.data[int(id)]) - if value: - length += len(value) - return str(length) - - @expose() - def get_count(self): - return str(len(self.data)) - - @expose() - def new(self): - return 'NEW' - - @expose() - def post(self, value): - self.data.append(value) - response.status = 302 - return 'CREATED' - - @expose() - def edit(self, id): - return 'EDIT %s' % self.data[int(id)] - - @expose() - def put(self, id, value): - self.data[int(id)] = value - return 'UPDATED' - - @expose() - def get_delete(self, id): - return 'DELETE %s' % self.data[int(id)] - - @expose() - def delete(self, id): - del self.data[int(id)] - return 'DELETED' - - @expose() - def reset(self): - return 'RESET' - - @expose() - def post_options(self): - return 'OPTIONS' - - @expose() - def options(self): - abort(500) - - @expose() - def other(self): - abort(500) - - class RootController(object): - things = ThingsController() - - # create the app - app = TestApp(make_app(RootController())) - - # test get_all - r = app.get('/things') - assert r.status_int == 200 - assert r.body == b_(dumps(dict(items=ThingsController.data))) - - # test get_one - for i, value in enumerate(ThingsController.data): - r = app.get('/things/%d' % i) - assert r.status_int == 200 - assert r.body == b_(value) - - # test post - r = app.post('/things', {'value': 'four'}) - assert r.status_int == 302 - assert r.body == b_('CREATED') - - # make sure it works - r = app.get('/things/4') - assert r.status_int == 200 - assert r.body == b_('four') - - # test edit - r = app.get('/things/3/edit') - assert r.status_int == 200 - assert r.body == b_('EDIT three') - - # test put - r = app.put('/things/4', {'value': 'FOUR'}) - assert r.status_int == 200 - assert r.body == b_('UPDATED') - - # make sure it works - r = app.get('/things/4') - assert r.status_int == 200 - assert r.body == b_('FOUR') - - # test put with _method parameter and GET - r = app.get('/things/4?_method=put', {'value': 'FOUR!'}, status=405) - assert r.status_int == 405 - - # make sure it works - r = app.get('/things/4') - assert r.status_int == 200 - assert r.body == b_('FOUR') - - # test put with _method parameter and POST - r = app.post('/things/4?_method=put', {'value': 'FOUR!'}) - assert r.status_int == 200 - assert r.body == b_('UPDATED') - - # make sure it works - r = app.get('/things/4') - assert r.status_int == 200 - assert r.body == b_('FOUR!') - - # test get delete - r = app.get('/things/4/delete') - assert r.status_int == 200 - assert r.body == b_('DELETE FOUR!') - - # test delete - r = app.delete('/things/4') - assert r.status_int == 200 - assert r.body == b_('DELETED') - - # make sure it works - r = app.get('/things') - assert r.status_int == 200 - assert len(loads(r.body.decode())['items']) == 4 - - # test delete with _method parameter and GET - r = app.get('/things/3?_method=DELETE', status=405) - assert r.status_int == 405 - - # make sure it works - r = app.get('/things') - assert r.status_int == 200 - assert len(loads(r.body.decode())['items']) == 4 - - # test delete with _method parameter and POST - r = app.post('/things/3?_method=DELETE') - assert r.status_int == 200 - assert r.body == b_('DELETED') - - # make sure it works - r = app.get('/things') - assert r.status_int == 200 - assert len(loads(r.body.decode())['items']) == 3 - - # test "RESET" custom action - r = app.request('/things', method='RESET') - assert r.status_int == 200 - assert r.body == b_('RESET') - - # test "RESET" custom action with _method parameter - r = app.get('/things?_method=RESET') - assert r.status_int == 200 - assert r.body == b_('RESET') - - # test the "OPTIONS" custom action - r = app.request('/things', method='OPTIONS') - assert r.status_int == 200 - assert r.body == b_('OPTIONS') - - # test the "OPTIONS" custom action with the _method parameter - r = app.post('/things', {'_method': 'OPTIONS'}) - assert r.status_int == 200 - assert r.body == b_('OPTIONS') - - # test the "other" custom action - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - r = app.request('/things/other', method='MISC', status=405) - assert r.status_int == 405 - - # test the "other" custom action with the _method parameter - r = app.post('/things/other', {'_method': 'MISC'}, status=405) - assert r.status_int == 405 - - # test the "others" custom action - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - r = app.request('/things/others/', method='MISC') - assert r.status_int == 200 - assert r.body == b_('OTHERS') - - # test the "others" custom action missing trailing slash - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - r = app.request('/things/others', method='MISC', status=302) - assert r.status_int == 302 - - # test the "others" custom action with the _method parameter - r = app.get('/things/others/?_method=MISC') - assert r.status_int == 200 - assert r.body == b_('OTHERS') - - # test an invalid custom action - r = app.get('/things?_method=BAD', status=405) - assert r.status_int == 405 - - # test custom "GET" request "count" - r = app.get('/things/count') - assert r.status_int == 200 - assert r.body == b_('3') - - # test custom "GET" request "length" - r = app.get('/things/1/length') - assert r.status_int == 200 - assert r.body == b_(str(len('one'))) - - # test custom "GET" request through subcontroller - r = app.get('/things/others/echo?value=test') - assert r.status_int == 200 - assert r.body == b_('test') - - # test custom "POST" request "length" - r = app.post('/things/1/length', {'value': 'test'}) - assert r.status_int == 200 - assert r.body == b_(str(len('onetest'))) - - # test custom "POST" request through subcontroller - r = app.post('/things/others/echo', {'value': 'test'}) - assert r.status_int == 200 - assert r.body == b_('test') - - def test_getall_with_trailing_slash(self): - - class ThingsController(RestController): - - data = ['zero', 'one', 'two', 'three'] - - @expose('json') - def get_all(self): - return dict(items=self.data) - - class RootController(object): - things = ThingsController() - - # create the app - app = TestApp(make_app(RootController())) - - # test get_all - r = app.get('/things/') - assert r.status_int == 200 - assert r.body == b_(dumps(dict(items=ThingsController.data))) - - def test_405_with_lookup(self): - - class LookupController(RestController): - - def __init__(self, _id): - self._id = _id - - @expose() - def get_all(self): - return 'ID: %s' % self._id - - class ThingsController(RestController): - - @expose() - def _lookup(self, _id, *remainder): - return LookupController(_id), remainder - - class RootController(object): - things = ThingsController() - - # create the app - app = TestApp(make_app(RootController())) - - # these should 405 - for path in ('/things', '/things/'): - r = app.get(path, expect_errors=True) - assert r.status_int == 405 - - r = app.get('/things/foo') - assert r.status_int == 200 - assert r.body == b_('ID: foo') - - def test_getall_with_lookup(self): - - class LookupController(RestController): - - def __init__(self, _id): - self._id = _id - - @expose() - def get_all(self): - return 'ID: %s' % self._id - - class ThingsController(RestController): - - data = ['zero', 'one', 'two', 'three'] - - @expose() - def _lookup(self, _id, *remainder): - return LookupController(_id), remainder - - @expose('json') - def get_all(self): - return dict(items=self.data) - - class RootController(object): - things = ThingsController() - - # create the app - app = TestApp(make_app(RootController())) - - # test get_all - for path in ('/things', '/things/'): - r = app.get(path) - assert r.status_int == 200 - assert r.body == b_(dumps(dict(items=ThingsController.data))) - - r = app.get('/things/foo') - assert r.status_int == 200 - assert r.body == b_('ID: foo') - - def test_simple_nested_rest(self): - - class BarController(RestController): - - @expose() - def post(self): - return "BAR-POST" - - @expose() - def delete(self, id_): - return "BAR-%s" % id_ - - class FooController(RestController): - - bar = BarController() - - @expose() - def post(self): - return "FOO-POST" - - @expose() - def delete(self, id_): - return "FOO-%s" % id_ - - class RootController(object): - foo = FooController() - - # create the app - app = TestApp(make_app(RootController())) - - r = app.post('/foo') - assert r.status_int == 200 - assert r.body == b_("FOO-POST") - - r = app.delete('/foo/1') - assert r.status_int == 200 - assert r.body == b_("FOO-1") - - r = app.post('/foo/bar') - assert r.status_int == 200 - assert r.body == b_("BAR-POST") - - r = app.delete('/foo/bar/2') - assert r.status_int == 200 - assert r.body == b_("BAR-2") - - def test_complicated_nested_rest(self): - - class BarsController(RestController): - - data = [['zero-zero', 'zero-one'], ['one-zero', 'one-one']] - - @expose() - def get_one(self, foo_id, id): - return self.data[int(foo_id)][int(id)] - - @expose('json') - def get_all(self, foo_id): - return dict(items=self.data[int(foo_id)]) - - @expose() - def new(self, foo_id): - return 'NEW FOR %s' % foo_id - - @expose() - def post(self, foo_id, value): - foo_id = int(foo_id) - if len(self.data) < foo_id + 1: - self.data.extend([[]] * (foo_id - len(self.data) + 1)) - self.data[foo_id].append(value) - response.status = 302 - return 'CREATED FOR %s' % foo_id - - @expose() - def edit(self, foo_id, id): - return 'EDIT %s' % self.data[int(foo_id)][int(id)] - - @expose() - def put(self, foo_id, id, value): - self.data[int(foo_id)][int(id)] = value - return 'UPDATED' - - @expose() - def get_delete(self, foo_id, id): - return 'DELETE %s' % self.data[int(foo_id)][int(id)] - - @expose() - def delete(self, foo_id, id): - del self.data[int(foo_id)][int(id)] - return 'DELETED' - - class FoosController(RestController): - - data = ['zero', 'one'] - - bars = BarsController() - - @expose() - def get_one(self, id): - return self.data[int(id)] - - @expose('json') - def get_all(self): - return dict(items=self.data) - - @expose() - def new(self): - return 'NEW' - - @expose() - def edit(self, id): - return 'EDIT %s' % self.data[int(id)] - - @expose() - def post(self, value): - self.data.append(value) - response.status = 302 - return 'CREATED' - - @expose() - def put(self, id, value): - self.data[int(id)] = value - return 'UPDATED' - - @expose() - def get_delete(self, id): - return 'DELETE %s' % self.data[int(id)] - - @expose() - def delete(self, id): - del self.data[int(id)] - return 'DELETED' - - class RootController(object): - foos = FoosController() - - # create the app - app = TestApp(make_app(RootController())) - - # test get_all - r = app.get('/foos') - assert r.status_int == 200 - assert r.body == b_(dumps(dict(items=FoosController.data))) - - # test nested get_all - r = app.get('/foos/1/bars') - assert r.status_int == 200 - assert r.body == b_(dumps(dict(items=BarsController.data[1]))) - - # test get_one - for i, value in enumerate(FoosController.data): - r = app.get('/foos/%d' % i) - assert r.status_int == 200 - assert r.body == b_(value) - - # test nested get_one - for i, value in enumerate(FoosController.data): - for j, value in enumerate(BarsController.data[i]): - r = app.get('/foos/%s/bars/%s' % (i, j)) - assert r.status_int == 200 - assert r.body == b_(value) - - # test post - r = app.post('/foos', {'value': 'two'}) - assert r.status_int == 302 - assert r.body == b_('CREATED') - - # make sure it works - r = app.get('/foos/2') - assert r.status_int == 200 - assert r.body == b_('two') - - # test nested post - r = app.post('/foos/2/bars', {'value': 'two-zero'}) - assert r.status_int == 302 - assert r.body == b_('CREATED FOR 2') - - # make sure it works - r = app.get('/foos/2/bars/0') - assert r.status_int == 200 - assert r.body == b_('two-zero') - - # test edit - r = app.get('/foos/1/edit') - assert r.status_int == 200 - assert r.body == b_('EDIT one') - - # test nested edit - r = app.get('/foos/1/bars/1/edit') - assert r.status_int == 200 - assert r.body == b_('EDIT one-one') - - # test put - r = app.put('/foos/2', {'value': 'TWO'}) - assert r.status_int == 200 - assert r.body == b_('UPDATED') - - # make sure it works - r = app.get('/foos/2') - assert r.status_int == 200 - assert r.body == b_('TWO') - - # test nested put - r = app.put('/foos/2/bars/0', {'value': 'TWO-ZERO'}) - assert r.status_int == 200 - assert r.body == b_('UPDATED') - - # make sure it works - r = app.get('/foos/2/bars/0') - assert r.status_int == 200 - assert r.body == b_('TWO-ZERO') - - # test put with _method parameter and GET - r = app.get('/foos/2?_method=put', {'value': 'TWO!'}, status=405) - assert r.status_int == 405 - - # make sure it works - r = app.get('/foos/2') - assert r.status_int == 200 - assert r.body == b_('TWO') - - # test nested put with _method parameter and GET - r = app.get( - '/foos/2/bars/0?_method=put', - {'value': 'ZERO-TWO!'}, status=405 - ) - assert r.status_int == 405 - - # make sure it works - r = app.get('/foos/2/bars/0') - assert r.status_int == 200 - assert r.body == b_('TWO-ZERO') - - # test put with _method parameter and POST - r = app.post('/foos/2?_method=put', {'value': 'TWO!'}) - assert r.status_int == 200 - assert r.body == b_('UPDATED') - - # make sure it works - r = app.get('/foos/2') - assert r.status_int == 200 - assert r.body == b_('TWO!') - - # test nested put with _method parameter and POST - r = app.post('/foos/2/bars/0?_method=put', {'value': 'TWO-ZERO!'}) - assert r.status_int == 200 - assert r.body == b_('UPDATED') - - # make sure it works - r = app.get('/foos/2/bars/0') - assert r.status_int == 200 - assert r.body == b_('TWO-ZERO!') - - # test get delete - r = app.get('/foos/2/delete') - assert r.status_int == 200 - assert r.body == b_('DELETE TWO!') - - # test nested get delete - r = app.get('/foos/2/bars/0/delete') - assert r.status_int == 200 - assert r.body == b_('DELETE TWO-ZERO!') - - # test nested delete - r = app.delete('/foos/2/bars/0') - assert r.status_int == 200 - assert r.body == b_('DELETED') - - # make sure it works - r = app.get('/foos/2/bars') - assert r.status_int == 200 - assert len(loads(r.body.decode())['items']) == 0 - - # test delete - r = app.delete('/foos/2') - assert r.status_int == 200 - assert r.body == b_('DELETED') - - # make sure it works - r = app.get('/foos') - assert r.status_int == 200 - assert len(loads(r.body.decode())['items']) == 2 - - # test nested delete with _method parameter and GET - r = app.get('/foos/1/bars/1?_method=DELETE', status=405) - assert r.status_int == 405 - - # make sure it works - r = app.get('/foos/1/bars') - assert r.status_int == 200 - assert len(loads(r.body.decode())['items']) == 2 - - # test delete with _method parameter and GET - r = app.get('/foos/1?_method=DELETE', status=405) - assert r.status_int == 405 - - # make sure it works - r = app.get('/foos') - assert r.status_int == 200 - assert len(loads(r.body.decode())['items']) == 2 - - # test nested delete with _method parameter and POST - r = app.post('/foos/1/bars/1?_method=DELETE') - assert r.status_int == 200 - assert r.body == b_('DELETED') - - # make sure it works - r = app.get('/foos/1/bars') - assert r.status_int == 200 - assert len(loads(r.body.decode())['items']) == 1 - - # test delete with _method parameter and POST - r = app.post('/foos/1?_method=DELETE') - assert r.status_int == 200 - assert r.body == b_('DELETED') - - # make sure it works - r = app.get('/foos') - assert r.status_int == 200 - assert len(loads(r.body.decode())['items']) == 1 - - def test_nested_get_all(self): - - class BarsController(RestController): - - @expose() - def get_one(self, foo_id, id): - return '4' - - @expose() - def get_all(self, foo_id): - return '3' - - class FoosController(RestController): - - bars = BarsController() - - @expose() - def get_one(self, id): - return '2' - - @expose() - def get_all(self): - return '1' - - class RootController(object): - foos = FoosController() - - # create the app - app = TestApp(make_app(RootController())) - - r = app.get('/foos/') - assert r.status_int == 200 - assert r.body == b_('1') - - r = app.get('/foos/1/') - assert r.status_int == 200 - assert r.body == b_('2') - - r = app.get('/foos/1/bars/') - assert r.status_int == 200 - assert r.body == b_('3') - - r = app.get('/foos/1/bars/2/') - assert r.status_int == 200 - assert r.body == b_('4') - - r = app.get('/foos/bars/', status=404) - assert r.status_int == 404 - - r = app.get('/foos/bars/1', status=404) - assert r.status_int == 404 - - def test_nested_get_all_with_lookup(self): - - class BarsController(RestController): - - @expose() - def get_one(self, foo_id, id): - return '4' - - @expose() - def get_all(self, foo_id): - return '3' - - @expose('json') - def _lookup(self, id, *remainder): - redirect('/lookup-hit/') - - class FoosController(RestController): - - bars = BarsController() - - @expose() - def get_one(self, id): - return '2' - - @expose() - def get_all(self): - return '1' - - class RootController(object): - foos = FoosController() - - # create the app - app = TestApp(make_app(RootController())) - - r = app.get('/foos/') - assert r.status_int == 200 - assert r.body == b_('1') - - r = app.get('/foos/1/') - assert r.status_int == 200 - assert r.body == b_('2') - - r = app.get('/foos/1/bars/') - assert r.status_int == 200 - assert r.body == b_('3') - - r = app.get('/foos/1/bars/2/') - assert r.status_int == 200 - assert r.body == b_('4') - - r = app.get('/foos/bars/') - assert r.status_int == 302 - assert r.headers['Location'].endswith('/lookup-hit/') - - r = app.get('/foos/bars/1') - assert r.status_int == 302 - assert r.headers['Location'].endswith('/lookup-hit/') - - def test_bad_rest(self): - - class ThingsController(RestController): - pass - - class RootController(object): - things = ThingsController() - - # create the app - app = TestApp(make_app(RootController())) - - # test get_all - r = app.get('/things', status=405) - assert r.status_int == 405 - - # test get_one - r = app.get('/things/1', status=405) - assert r.status_int == 405 - - # test post - r = app.post('/things', {'value': 'one'}, status=405) - assert r.status_int == 405 - - # test edit - r = app.get('/things/1/edit', status=405) - assert r.status_int == 405 - - # test put - r = app.put('/things/1', {'value': 'ONE'}, status=405) - - # test put with _method parameter and GET - r = app.get('/things/1?_method=put', {'value': 'ONE!'}, status=405) - assert r.status_int == 405 - - # test put with _method parameter and POST - r = app.post('/things/1?_method=put', {'value': 'ONE!'}, status=405) - assert r.status_int == 405 - - # test get delete - r = app.get('/things/1/delete', status=405) - assert r.status_int == 405 - - # test delete - r = app.delete('/things/1', status=405) - assert r.status_int == 405 - - # test delete with _method parameter and GET - r = app.get('/things/1?_method=DELETE', status=405) - assert r.status_int == 405 - - # test delete with _method parameter and POST - r = app.post('/things/1?_method=DELETE', status=405) - assert r.status_int == 405 - - # test "RESET" custom action - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - r = app.request('/things', method='RESET', status=405) - assert r.status_int == 405 - - def test_nested_rest_with_missing_intermediate_id(self): - - class BarsController(RestController): - - data = [['zero-zero', 'zero-one'], ['one-zero', 'one-one']] - - @expose('json') - def get_all(self, foo_id): - return dict(items=self.data[int(foo_id)]) - - class FoosController(RestController): - - data = ['zero', 'one'] - - bars = BarsController() - - @expose() - def get_one(self, id): - return self.data[int(id)] - - @expose('json') - def get_all(self): - return dict(items=self.data) - - class RootController(object): - foos = FoosController() - - # create the app - app = TestApp(make_app(RootController())) - - # test get_all - r = app.get('/foos') - self.assertEqual(r.status_int, 200) - self.assertEqual(r.body, b_(dumps(dict(items=FoosController.data)))) - - # test nested get_all - r = app.get('/foos/1/bars') - self.assertEqual(r.status_int, 200) - self.assertEqual(r.body, b_(dumps(dict(items=BarsController.data[1])))) - - r = app.get('/foos/bars', expect_errors=True) - self.assertEqual(r.status_int, 404) - - def test_custom_with_trailing_slash(self): - - class CustomController(RestController): - - _custom_actions = { - 'detail': ['GET'], - 'create': ['POST'], - 'update': ['PUT'], - 'remove': ['DELETE'], - } - - @expose() - def detail(self): - return 'DETAIL' - - @expose() - def create(self): - return 'CREATE' - - @expose() - def update(self, id): - return id - - @expose() - def remove(self, id): - return id - - app = TestApp(make_app(CustomController())) - - r = app.get('/detail') - assert r.status_int == 200 - assert r.body == b_('DETAIL') - - r = app.get('/detail/') - assert r.status_int == 200 - assert r.body == b_('DETAIL') - - r = app.post('/create') - assert r.status_int == 200 - assert r.body == b_('CREATE') - - r = app.post('/create/') - assert r.status_int == 200 - assert r.body == b_('CREATE') - - r = app.put('/update/123') - assert r.status_int == 200 - assert r.body == b_('123') - - r = app.put('/update/123/') - assert r.status_int == 200 - assert r.body == b_('123') - - r = app.delete('/remove/456') - assert r.status_int == 200 - assert r.body == b_('456') - - r = app.delete('/remove/456/') - assert r.status_int == 200 - assert r.body == b_('456') - - def test_custom_delete(self): - - class OthersController(object): - - @expose() - def index(self): - return 'DELETE' - - @expose() - def reset(self, id): - return str(id) - - class ThingsController(RestController): - - others = OthersController() - - @expose() - def delete_fail(self): - abort(500) - - class RootController(object): - things = ThingsController() - - # create the app - app = TestApp(make_app(RootController())) - - # test bad delete - r = app.delete('/things/delete_fail', status=405) - assert r.status_int == 405 - - # test bad delete with _method parameter and GET - r = app.get('/things/delete_fail?_method=delete', status=405) - assert r.status_int == 405 - - # test bad delete with _method parameter and POST - r = app.post('/things/delete_fail', {'_method': 'delete'}, status=405) - assert r.status_int == 405 - - # test custom delete without ID - r = app.delete('/things/others/') - assert r.status_int == 200 - assert r.body == b_('DELETE') - - # test custom delete without ID with _method parameter and GET - r = app.get('/things/others/?_method=delete', status=405) - assert r.status_int == 405 - - # test custom delete without ID with _method parameter and POST - r = app.post('/things/others/', {'_method': 'delete'}) - assert r.status_int == 200 - assert r.body == b_('DELETE') - - # test custom delete with ID - r = app.delete('/things/others/reset/1') - assert r.status_int == 200 - assert r.body == b_('1') - - # test custom delete with ID with _method parameter and GET - r = app.get('/things/others/reset/1?_method=delete', status=405) - assert r.status_int == 405 - - # test custom delete with ID with _method parameter and POST - r = app.post('/things/others/reset/1', {'_method': 'delete'}) - assert r.status_int == 200 - assert r.body == b_('1') - - def test_get_with_var_args(self): - - class OthersController(object): - - @expose() - def index(self, one, two, three): - return 'NESTED: %s, %s, %s' % (one, two, three) - - class ThingsController(RestController): - - others = OthersController() - - @expose() - def get_one(self, *args): - return ', '.join(args) - - class RootController(object): - things = ThingsController() - - # create the app - app = TestApp(make_app(RootController())) - - # test get request - r = app.get('/things/one/two/three') - assert r.status_int == 200 - assert r.body == b_('one, two, three') - - # test nested get request - r = app.get('/things/one/two/three/others/') - assert r.status_int == 200 - assert r.body == b_('NESTED: one, two, three') - - def test_sub_nested_rest(self): - - class BazsController(RestController): - - data = [[['zero-zero-zero']]] - - @expose() - def get_one(self, foo_id, bar_id, id): - return self.data[int(foo_id)][int(bar_id)][int(id)] - - class BarsController(RestController): - - data = [['zero-zero']] - - bazs = BazsController() - - @expose() - def get_one(self, foo_id, id): - return self.data[int(foo_id)][int(id)] - - class FoosController(RestController): - - data = ['zero'] - - bars = BarsController() - - @expose() - def get_one(self, id): - return self.data[int(id)] - - class RootController(object): - foos = FoosController() - - # create the app - app = TestApp(make_app(RootController())) - - # test sub-nested get_one - r = app.get('/foos/0/bars/0/bazs/0') - assert r.status_int == 200 - assert r.body == b_('zero-zero-zero') - - def test_sub_nested_rest_with_overwrites(self): - - class FinalController(object): - - @expose() - def index(self): - return 'FINAL' - - @expose() - def named(self): - return 'NAMED' - - class BazsController(RestController): - - data = [[['zero-zero-zero']]] - - final = FinalController() - - @expose() - def get_one(self, foo_id, bar_id, id): - return self.data[int(foo_id)][int(bar_id)][int(id)] - - @expose() - def post(self): - return 'POST-GRAND-CHILD' - - @expose() - def put(self, id): - return 'PUT-GRAND-CHILD' - - class BarsController(RestController): - - data = [['zero-zero']] - - bazs = BazsController() - - @expose() - def get_one(self, foo_id, id): - return self.data[int(foo_id)][int(id)] - - @expose() - def post(self): - return 'POST-CHILD' - - @expose() - def put(self, id): - return 'PUT-CHILD' - - class FoosController(RestController): - - data = ['zero'] - - bars = BarsController() - - @expose() - def get_one(self, id): - return self.data[int(id)] - - @expose() - def post(self): - return 'POST' - - @expose() - def put(self, id): - return 'PUT' - - class RootController(object): - foos = FoosController() - - # create the app - app = TestApp(make_app(RootController())) - - r = app.post('/foos') - assert r.status_int == 200 - assert r.body == b_('POST') - - r = app.put('/foos/0') - assert r.status_int == 200 - assert r.body == b_('PUT') - - r = app.post('/foos/bars') - assert r.status_int == 200 - assert r.body == b_('POST-CHILD') - - r = app.put('/foos/bars/0') - assert r.status_int == 200 - assert r.body == b_('PUT-CHILD') - - r = app.post('/foos/bars/bazs') - assert r.status_int == 200 - assert r.body == b_('POST-GRAND-CHILD') - - r = app.put('/foos/bars/bazs/0') - assert r.status_int == 200 - assert r.body == b_('PUT-GRAND-CHILD') - - r = app.get('/foos/bars/bazs/final/') - assert r.status_int == 200 - assert r.body == b_('FINAL') - - r = app.get('/foos/bars/bazs/final/named') - assert r.status_int == 200 - assert r.body == b_('NAMED') - - def test_post_with_kwargs_only(self): - - class RootController(RestController): - - @expose() - def get_all(self): - return 'INDEX' - - @expose('json') - def post(self, **kw): - return kw - - # create the app - app = TestApp(make_app(RootController())) - - r = app.get('/') - assert r.status_int == 200 - assert r.body == b_('INDEX') - - kwargs = {'foo': 'bar', 'spam': 'eggs'} - r = app.post('/', kwargs) - assert r.status_int == 200 - assert r.namespace['foo'] == 'bar' - assert r.namespace['spam'] == 'eggs' - - def test_nested_rest_with_lookup(self): - - class SubController(RestController): - - @expose() - def get_all(self): - return "SUB" - - class FinalController(RestController): - - def __init__(self, id_): - self.id_ = id_ - - @expose() - def get_all(self): - return "FINAL-%s" % self.id_ - - @expose() - def post(self): - return "POST-%s" % self.id_ - - class LookupController(RestController): - - sub = SubController() - - def __init__(self, id_): - self.id_ = id_ - - @expose() - def _lookup(self, id_, *remainder): - return FinalController(id_), remainder - - @expose() - def get_all(self): - raise AssertionError("Never Reached") - - @expose() - def post(self): - return "POST-LOOKUP-%s" % self.id_ - - @expose() - def put(self, id_): - return "PUT-LOOKUP-%s-%s" % (self.id_, id_) - - @expose() - def delete(self, id_): - return "DELETE-LOOKUP-%s-%s" % (self.id_, id_) - - class FooController(RestController): - - @expose() - def _lookup(self, id_, *remainder): - return LookupController(id_), remainder - - @expose() - def get_one(self, id_): - return "GET ONE" - - @expose() - def get_all(self): - return "INDEX" - - @expose() - def post(self): - return "POST" - - @expose() - def put(self, id_): - return "PUT-%s" % id_ - - @expose() - def delete(self, id_): - return "DELETE-%s" % id_ - - class RootController(RestController): - foo = FooController() - - app = TestApp(make_app(RootController())) - - r = app.get('/foo') - assert r.status_int == 200 - assert r.body == b_('INDEX') - - r = app.post('/foo') - assert r.status_int == 200 - assert r.body == b_('POST') - - r = app.get('/foo/1') - assert r.status_int == 200 - assert r.body == b_('GET ONE') - - r = app.post('/foo/1') - assert r.status_int == 200 - assert r.body == b_('POST-LOOKUP-1') - - r = app.put('/foo/1') - assert r.status_int == 200 - assert r.body == b_('PUT-1') - - r = app.delete('/foo/1') - assert r.status_int == 200 - assert r.body == b_('DELETE-1') - - r = app.put('/foo/1/2') - assert r.status_int == 200 - assert r.body == b_('PUT-LOOKUP-1-2') - - r = app.delete('/foo/1/2') - assert r.status_int == 200 - assert r.body == b_('DELETE-LOOKUP-1-2') - - r = app.get('/foo/1/2') - assert r.status_int == 200 - assert r.body == b_('FINAL-2') - - r = app.post('/foo/1/2') - assert r.status_int == 200 - assert r.body == b_('POST-2') - - def test_nested_rest_with_default(self): - - class FooController(RestController): - - @expose() - def _default(self, *remainder): - return "DEFAULT %s" % remainder - - class RootController(RestController): - foo = FooController() - - app = TestApp(make_app(RootController())) - - r = app.get('/foo/missing') - assert r.status_int == 200 - assert r.body == b_("DEFAULT missing") - - def test_rest_with_non_utf_8_body(self): - if PY3: - # webob+PY3 doesn't suffer from this bug; the POST parsing in PY3 - # seems to more gracefully detect the bytestring - return - - class FooController(RestController): - - @expose() - def post(self): - return "POST" - - class RootController(RestController): - foo = FooController() - - app = TestApp(make_app(RootController())) - - data = struct.pack('255h', *range(0, 255)) - r = app.post('/foo/', data, expect_errors=True) - assert r.status_int == 400 - - def test_dynamic_rest_lookup(self): - class BarController(RestController): - @expose() - def get_all(self): - return "BAR" - - @expose() - def put(self): - return "PUT_BAR" - - @expose() - def delete(self): - return "DELETE_BAR" - - class BarsController(RestController): - @expose() - def _lookup(self, id_, *remainder): - return BarController(), remainder - - @expose() - def get_all(self): - return "BARS" - - @expose() - def post(self): - return "POST_BARS" - - class FooController(RestController): - bars = BarsController() - - @expose() - def get_all(self): - return "FOO" - - @expose() - def put(self): - return "PUT_FOO" - - @expose() - def delete(self): - return "DELETE_FOO" - - class FoosController(RestController): - @expose() - def _lookup(self, id_, *remainder): - return FooController(), remainder - - @expose() - def get_all(self): - return "FOOS" - - @expose() - def post(self): - return "POST_FOOS" - - class RootController(RestController): - foos = FoosController() - - app = TestApp(make_app(RootController())) - - r = app.get('/foos') - assert r.status_int == 200 - assert r.body == b_('FOOS') - - r = app.post('/foos') - assert r.status_int == 200 - assert r.body == b_('POST_FOOS') - - r = app.get('/foos/foo') - assert r.status_int == 200 - assert r.body == b_('FOO') - - r = app.put('/foos/foo') - assert r.status_int == 200 - assert r.body == b_('PUT_FOO') - - r = app.delete('/foos/foo') - assert r.status_int == 200 - assert r.body == b_('DELETE_FOO') - - r = app.get('/foos/foo/bars') - assert r.status_int == 200 - assert r.body == b_('BARS') - - r = app.post('/foos/foo/bars') - assert r.status_int == 200 - assert r.body == b_('POST_BARS') - - r = app.get('/foos/foo/bars/bar') - assert r.status_int == 200 - assert r.body == b_('BAR') - - r = app.put('/foos/foo/bars/bar') - assert r.status_int == 200 - assert r.body == b_('PUT_BAR') - - r = app.delete('/foos/foo/bars/bar') - assert r.status_int == 200 - assert r.body == b_('DELETE_BAR') - - def test_method_not_allowed_get(self): - class ThingsController(RestController): - - @expose() - def put(self, id_, value): - response.status = 200 - - @expose() - def delete(self, id_): - response.status = 200 - - app = TestApp(make_app(ThingsController())) - r = app.get('/', status=405) - assert r.status_int == 405 - assert r.headers['Allow'] == 'DELETE, PUT' - - def test_method_not_allowed_post(self): - class ThingsController(RestController): - - @expose() - def get_one(self): - return dict() - - app = TestApp(make_app(ThingsController())) - r = app.post('/', {'foo': 'bar'}, status=405) - assert r.status_int == 405 - assert r.headers['Allow'] == 'GET' - - def test_method_not_allowed_put(self): - class ThingsController(RestController): - - @expose() - def get_one(self): - return dict() - - app = TestApp(make_app(ThingsController())) - r = app.put('/123', status=405) - assert r.status_int == 405 - assert r.headers['Allow'] == 'GET' - - def test_method_not_allowed_delete(self): - class ThingsController(RestController): - - @expose() - def get_one(self): - return dict() - - app = TestApp(make_app(ThingsController())) - r = app.delete('/123', status=405) - assert r.status_int == 405 - assert r.headers['Allow'] == 'GET' - - def test_proper_allow_header_multiple_gets(self): - class ThingsController(RestController): - - @expose() - def get_all(self): - return dict() - - @expose() - def get(self): - return dict() - - app = TestApp(make_app(ThingsController())) - r = app.put('/123', status=405) - assert r.status_int == 405 - assert r.headers['Allow'] == 'GET' - - def test_rest_with_utf8_uri(self): - - class FooController(RestController): - key = chr(0x1F330) if PY3 else unichr(0x1F330) - data = {key: 'Success!'} - - @expose() - def get_one(self, id_): - return self.data[id_] - - @expose() - def get_all(self): - return "Hello, World!" - - @expose() - def put(self, id_, value): - return self.data[id_] - - @expose() - def delete(self, id_): - return self.data[id_] - - class RootController(RestController): - foo = FooController() - - app = TestApp(make_app(RootController())) - - r = app.get('/foo/%F0%9F%8C%B0') - assert r.status_int == 200 - assert r.body == b'Success!' - - r = app.put('/foo/%F0%9F%8C%B0', {'value': 'pecans'}) - assert r.status_int == 200 - assert r.body == b'Success!' - - r = app.delete('/foo/%F0%9F%8C%B0') - assert r.status_int == 200 - assert r.body == b'Success!' - - r = app.get('/foo/') - assert r.status_int == 200 - assert r.body == b'Hello, World!' - - @unittest.skipIf(not PY3, "test is Python3 specific") - def test_rest_with_utf8_endpoint(self): - class ChildController(object): - @expose() - def index(self): - return 'Hello, World!' - - class FooController(RestController): - pass - - # okay, so it's technically a chestnut, but close enough... - setattr(FooController, '🌰', ChildController()) - - class RootController(RestController): - foo = FooController() - - app = TestApp(make_app(RootController())) - - r = app.get('/foo/%F0%9F%8C%B0/') - assert r.status_int == 200 - assert r.body == b'Hello, World!' - - -class TestExplicitRoute(PecanTestCase): - - def test_alternate_route(self): - - class RootController(RestController): - - @expose(route='some-path') - def get_all(self): - return "Hello, World!" - - self.assertRaises( - ValueError, - RootController - ) diff --git a/pecan/tests/test_scaffolds.py b/pecan/tests/test_scaffolds.py deleted file mode 100644 index 669aa7d..0000000 --- a/pecan/tests/test_scaffolds.py +++ /dev/null @@ -1,160 +0,0 @@ -import os -import sys -import tempfile -import shutil - -from six.moves import cStringIO as StringIO - -from pecan.tests import PecanTestCase - -if sys.version_info < (2, 7): - import unittest2 as unittest -else: - import unittest # noqa - - -class TestPecanScaffold(PecanTestCase): - - def test_normalize_pkg_name(self): - from pecan.scaffolds import PecanScaffold - s = PecanScaffold() - assert s.normalize_pkg_name('sam') == 'sam' - assert s.normalize_pkg_name('sam1') == 'sam1' - assert s.normalize_pkg_name('sam_') == 'sam_' - assert s.normalize_pkg_name('Sam') == 'sam' - assert s.normalize_pkg_name('SAM') == 'sam' - assert s.normalize_pkg_name('sam ') == 'sam' - assert s.normalize_pkg_name(' sam') == 'sam' - assert s.normalize_pkg_name('sam$') == 'sam' - assert s.normalize_pkg_name('sam-sam') == 'samsam' - - -class TestScaffoldUtils(PecanTestCase): - - def setUp(self): - super(TestScaffoldUtils, self).setUp() - self.scaffold_destination = tempfile.mkdtemp() - self.out = sys.stdout - - sys.stdout = StringIO() - - def tearDown(self): - shutil.rmtree(self.scaffold_destination) - sys.stdout = self.out - - def test_copy_dir(self): - from pecan.scaffolds import PecanScaffold - - class SimpleScaffold(PecanScaffold): - _scaffold_dir = ('pecan', os.path.join( - 'tests', 'scaffold_fixtures', 'simple' - )) - - SimpleScaffold().copy_to(os.path.join( - self.scaffold_destination, - 'someapp' - ), out_=StringIO()) - - assert os.path.isfile(os.path.join( - self.scaffold_destination, 'someapp', 'foo' - )) - assert os.path.isfile(os.path.join( - self.scaffold_destination, 'someapp', 'bar', 'spam.txt' - )) - assert open(os.path.join( - self.scaffold_destination, 'someapp', 'foo' - ), 'r').read().strip() == 'YAR' - assert open(os.path.join( - self.scaffold_destination, 'someapp', 'foo' - ), 'r').read().strip() == 'YAR' - - def test_destination_directory_levels_deep(self): - from pecan.scaffolds import copy_dir - f = StringIO() - copy_dir( - ( - 'pecan', os.path.join('tests', 'scaffold_fixtures', 'simple') - ), - os.path.join(self.scaffold_destination, 'some', 'app'), - {}, - out_=f - ) - - assert os.path.isfile(os.path.join( - self.scaffold_destination, 'some', 'app', 'foo') - ) - assert os.path.isfile(os.path.join( - self.scaffold_destination, 'some', 'app', 'bar', 'spam.txt') - ) - assert open(os.path.join( - self.scaffold_destination, 'some', 'app', 'foo' - ), 'r').read().strip() == 'YAR' - assert open(os.path.join( - self.scaffold_destination, 'some', 'app', 'bar', 'spam.txt' - ), 'r').read().strip() == 'Pecan' - - def test_destination_directory_already_exists(self): - from pecan.scaffolds import copy_dir - f = StringIO() - copy_dir( - ( - 'pecan', os.path.join('tests', 'scaffold_fixtures', 'simple') - ), - os.path.join(self.scaffold_destination), - {}, - out_=f - ) - assert 'already exists' in f.getvalue() - - def test_copy_dir_with_filename_substitution(self): - from pecan.scaffolds import copy_dir - copy_dir( - ( - 'pecan', os.path.join('tests', 'scaffold_fixtures', 'file_sub') - ), - os.path.join( - self.scaffold_destination, 'someapp' - ), - {'package': 'thingy'}, - out_=StringIO() - ) - - assert os.path.isfile(os.path.join( - self.scaffold_destination, 'someapp', 'foo_thingy') - ) - assert os.path.isfile(os.path.join( - self.scaffold_destination, 'someapp', 'bar_thingy', 'spam.txt') - ) - assert open(os.path.join( - self.scaffold_destination, 'someapp', 'foo_thingy' - ), 'r').read().strip() == 'YAR' - assert open(os.path.join( - self.scaffold_destination, 'someapp', 'bar_thingy', 'spam.txt' - ), 'r').read().strip() == 'Pecan' - - def test_copy_dir_with_file_content_substitution(self): - from pecan.scaffolds import copy_dir - copy_dir( - ( - 'pecan', - os.path.join('tests', 'scaffold_fixtures', 'content_sub'), - ), - os.path.join( - self.scaffold_destination, 'someapp' - ), - {'package': 'thingy'}, - out_=StringIO() - ) - - assert os.path.isfile(os.path.join( - self.scaffold_destination, 'someapp', 'foo') - ) - assert os.path.isfile(os.path.join( - self.scaffold_destination, 'someapp', 'bar', 'spam.txt') - ) - assert open(os.path.join( - self.scaffold_destination, 'someapp', 'foo' - ), 'r').read().strip() == 'YAR thingy' - assert open(os.path.join( - self.scaffold_destination, 'someapp', 'bar', 'spam.txt' - ), 'r').read().strip() == 'Pecan thingy' diff --git a/pecan/tests/test_secure.py b/pecan/tests/test_secure.py deleted file mode 100644 index 1d30ea3..0000000 --- a/pecan/tests/test_secure.py +++ /dev/null @@ -1,563 +0,0 @@ -import sys - -from six import b as b_ -from webtest import TestApp - -from pecan import expose, make_app -from pecan.secure import secure, unlocked, SecureController -from pecan.tests import PecanTestCase - -if sys.version_info < (2, 7): - import unittest2 as unittest -else: - import unittest # noqa - -try: - set() -except: - from sets import Set as set - - -class TestSecure(PecanTestCase): - def test_simple_secure(self): - authorized = False - - class SecretController(SecureController): - @expose() - def index(self): - return 'Index' - - @expose() - @unlocked - def allowed(self): - return 'Allowed!' - - @classmethod - def check_permissions(cls): - return authorized - - class RootController(object): - @expose() - def index(self): - return 'Hello, World!' - - @expose() - @secure(lambda: False) - def locked(self): - return 'No dice!' - - @expose() - @secure(lambda: True) - def unlocked(self): - return 'Sure thing' - - secret = SecretController() - - app = TestApp(make_app( - RootController(), - debug=True, - static_root='tests/static' - )) - response = app.get('/') - assert response.status_int == 200 - assert response.body == b_('Hello, World!') - - response = app.get('/unlocked') - assert response.status_int == 200 - assert response.body == b_('Sure thing') - - response = app.get('/locked', expect_errors=True) - assert response.status_int == 401 - - response = app.get('/secret/', expect_errors=True) - assert response.status_int == 401 - - response = app.get('/secret/allowed') - assert response.status_int == 200 - assert response.body == b_('Allowed!') - - def test_unlocked_attribute(self): - class AuthorizedSubController(object): - @expose() - def index(self): - return 'Index' - - @expose() - def allowed(self): - return 'Allowed!' - - class SecretController(SecureController): - @expose() - def index(self): - return 'Index' - - @expose() - @unlocked - def allowed(self): - return 'Allowed!' - - authorized = unlocked(AuthorizedSubController()) - - class RootController(object): - @expose() - def index(self): - return 'Hello, World!' - - @expose() - @secure(lambda: False) - def locked(self): - return 'No dice!' - - @expose() - @secure(lambda: True) - def unlocked(self): - return 'Sure thing' - - secret = SecretController() - - app = TestApp(make_app( - RootController(), - debug=True, - static_root='tests/static' - )) - response = app.get('/') - assert response.status_int == 200 - assert response.body == b_('Hello, World!') - - response = app.get('/unlocked') - assert response.status_int == 200 - assert response.body == b_('Sure thing') - - response = app.get('/locked', expect_errors=True) - assert response.status_int == 401 - - response = app.get('/secret/', expect_errors=True) - assert response.status_int == 401 - - response = app.get('/secret/allowed') - assert response.status_int == 200 - assert response.body == b_('Allowed!') - - response = app.get('/secret/authorized/') - assert response.status_int == 200 - assert response.body == b_('Index') - - response = app.get('/secret/authorized/allowed') - assert response.status_int == 200 - assert response.body == b_('Allowed!') - - def test_secure_attribute(self): - authorized = False - - class SubController(object): - @expose() - def index(self): - return 'Hello from sub!' - - class RootController(object): - @expose() - def index(self): - return 'Hello from root!' - - sub = secure(SubController(), lambda: authorized) - - app = TestApp(make_app(RootController())) - response = app.get('/') - assert response.status_int == 200 - assert response.body == b_('Hello from root!') - - response = app.get('/sub/', expect_errors=True) - assert response.status_int == 401 - - authorized = True - response = app.get('/sub/') - assert response.status_int == 200 - assert response.body == b_('Hello from sub!') - - def test_secured_generic_controller(self): - authorized = False - - class RootController(object): - - @classmethod - def check_permissions(cls): - return authorized - - @expose(generic=True) - def index(self): - return 'Index' - - @secure('check_permissions') - @index.when(method='POST') - def index_post(self): - return 'I should not be allowed' - - @secure('check_permissions') - @expose(generic=True) - def secret(self): - return 'I should not be allowed' - - app = TestApp(make_app( - RootController(), - debug=True, - static_root='tests/static' - )) - response = app.get('/') - assert response.status_int == 200 - response = app.post('/', expect_errors=True) - assert response.status_int == 401 - response = app.get('/secret/', expect_errors=True) - assert response.status_int == 401 - - def test_secured_generic_controller_lambda(self): - authorized = False - - class RootController(object): - - @expose(generic=True) - def index(self): - return 'Index' - - @secure(lambda: authorized) - @index.when(method='POST') - def index_post(self): - return 'I should not be allowed' - - @secure(lambda: authorized) - @expose(generic=True) - def secret(self): - return 'I should not be allowed' - - app = TestApp(make_app( - RootController(), - debug=True, - static_root='tests/static' - )) - response = app.get('/') - assert response.status_int == 200 - response = app.post('/', expect_errors=True) - assert response.status_int == 401 - response = app.get('/secret/', expect_errors=True) - assert response.status_int == 401 - - def test_secured_generic_controller_secure_attribute(self): - authorized = False - - class SecureController(object): - - @expose(generic=True) - def index(self): - return 'I should not be allowed' - - @index.when(method='POST') - def index_post(self): - return 'I should not be allowed' - - @expose(generic=True) - def secret(self): - return 'I should not be allowed' - - class RootController(object): - sub = secure(SecureController(), lambda: authorized) - - app = TestApp(make_app( - RootController(), - debug=True, - static_root='tests/static' - )) - response = app.get('/sub/', expect_errors=True) - assert response.status_int == 401 - response = app.post('/sub/', expect_errors=True) - assert response.status_int == 401 - response = app.get('/sub/secret/', expect_errors=True) - assert response.status_int == 401 - - def test_secured_generic_controller_secure_attribute_with_unlocked(self): - - class RootController(SecureController): - - @unlocked - @expose(generic=True) - def index(self): - return 'Unlocked!' - - @unlocked - @index.when(method='POST') - def index_post(self): - return 'Unlocked!' - - @expose(generic=True) - def secret(self): - return 'I should not be allowed' - - app = TestApp(make_app( - RootController(), - debug=True, - static_root='tests/static' - )) - response = app.get('/') - assert response.status_int == 200 - response = app.post('/') - assert response.status_int == 200 - response = app.get('/secret/', expect_errors=True) - assert response.status_int == 401 - - def test_state_attribute(self): - from pecan.secure import Any, Protected - assert repr(Any) == '<SecureState Any>' - assert bool(Any) is False - - assert repr(Protected) == '<SecureState Protected>' - assert bool(Protected) is True - - def test_secure_obj_only_failure(self): - class Foo(object): - pass - - try: - secure(Foo()) - except Exception as e: - assert isinstance(e, TypeError) - - -class TestObjectPathSecurity(PecanTestCase): - - def setUp(self): - super(TestObjectPathSecurity, self).setUp() - permissions_checked = set() - - class DeepSecretController(SecureController): - authorized = False - - @expose() - @unlocked - def _lookup(self, someID, *remainder): - if someID == 'notfound': - return None - return SubController(someID), remainder - - @expose() - def index(self): - return 'Deep Secret' - - @classmethod - def check_permissions(cls): - permissions_checked.add('deepsecret') - return cls.authorized - - class SubController(object): - def __init__(self, myID): - self.myID = myID - - @expose() - def index(self): - return 'Index %s' % self.myID - - deepsecret = DeepSecretController() - - class SecretController(SecureController): - authorized = False - independent_authorization = False - - @expose() - def _lookup(self, someID, *remainder): - if someID == 'notfound': - return None - elif someID == 'lookup_wrapped': - return self.wrapped, remainder - return SubController(someID), remainder - - @secure('independent_check_permissions') - @expose() - def independent(self): - return 'Independent Security' - - wrapped = secure( - SubController('wrapped'), 'independent_check_permissions' - ) - - @classmethod - def check_permissions(cls): - permissions_checked.add('secretcontroller') - return cls.authorized - - @classmethod - def independent_check_permissions(cls): - permissions_checked.add('independent') - return cls.independent_authorization - - class NotSecretController(object): - @expose() - def _lookup(self, someID, *remainder): - if someID == 'notfound': - return None - return SubController(someID), remainder - - unlocked = unlocked(SubController('unlocked')) - - class RootController(object): - secret = SecretController() - notsecret = NotSecretController() - - self.deepsecret_cls = DeepSecretController - self.secret_cls = SecretController - - self.permissions_checked = permissions_checked - self.app = TestApp(make_app( - RootController(), - debug=True, - static_root='tests/static' - )) - - def tearDown(self): - self.permissions_checked.clear() - self.secret_cls.authorized = False - self.deepsecret_cls.authorized = False - - def test_sub_of_both_not_secret(self): - response = self.app.get('/notsecret/hi/') - assert response.status_int == 200 - assert response.body == b_('Index hi') - - def test_protected_lookup(self): - response = self.app.get('/secret/hi/', expect_errors=True) - assert response.status_int == 401 - - self.secret_cls.authorized = True - response = self.app.get('/secret/hi/') - assert response.status_int == 200 - assert response.body == b_('Index hi') - assert 'secretcontroller' in self.permissions_checked - - def test_secured_notfound_lookup(self): - response = self.app.get('/secret/notfound/', expect_errors=True) - assert response.status_int == 404 - - def test_secret_through_lookup(self): - response = self.app.get( - '/notsecret/hi/deepsecret/', expect_errors=True - ) - assert response.status_int == 401 - - def test_layered_protection(self): - response = self.app.get('/secret/hi/deepsecret/', expect_errors=True) - assert response.status_int == 401 - assert 'secretcontroller' in self.permissions_checked - - self.secret_cls.authorized = True - response = self.app.get('/secret/hi/deepsecret/', expect_errors=True) - assert response.status_int == 401 - assert 'secretcontroller' in self.permissions_checked - assert 'deepsecret' in self.permissions_checked - - self.deepsecret_cls.authorized = True - response = self.app.get('/secret/hi/deepsecret/') - assert response.status_int == 200 - assert response.body == b_('Deep Secret') - assert 'secretcontroller' in self.permissions_checked - assert 'deepsecret' in self.permissions_checked - - def test_cyclical_protection(self): - self.secret_cls.authorized = True - self.deepsecret_cls.authorized = True - response = self.app.get('/secret/1/deepsecret/2/deepsecret/') - assert response.status_int == 200 - assert response.body == b_('Deep Secret') - assert 'secretcontroller' in self.permissions_checked - assert 'deepsecret' in self.permissions_checked - - def test_unlocked_lookup(self): - response = self.app.get('/notsecret/1/deepsecret/2/') - assert response.status_int == 200 - assert response.body == b_('Index 2') - assert 'deepsecret' not in self.permissions_checked - - response = self.app.get( - '/notsecret/1/deepsecret/notfound/', expect_errors=True - ) - assert response.status_int == 404 - assert 'deepsecret' not in self.permissions_checked - - def test_mixed_protection(self): - self.secret_cls.authorized = True - response = self.app.get( - '/secret/1/deepsecret/notfound/', expect_errors=True - ) - assert response.status_int == 404 - assert 'secretcontroller' in self.permissions_checked - assert 'deepsecret' not in self.permissions_checked - - def test_independent_check_failure(self): - response = self.app.get('/secret/independent/', expect_errors=True) - assert response.status_int == 401 - assert len(self.permissions_checked) == 1 - assert 'independent' in self.permissions_checked - - def test_independent_check_success(self): - self.secret_cls.independent_authorization = True - response = self.app.get('/secret/independent') - assert response.status_int == 200 - assert response.body == b_('Independent Security') - assert len(self.permissions_checked) == 1 - assert 'independent' in self.permissions_checked - - def test_wrapped_attribute_failure(self): - self.secret_cls.independent_authorization = False - response = self.app.get('/secret/wrapped/', expect_errors=True) - assert response.status_int == 401 - assert len(self.permissions_checked) == 1 - assert 'independent' in self.permissions_checked - - def test_wrapped_attribute_success(self): - self.secret_cls.independent_authorization = True - response = self.app.get('/secret/wrapped/') - assert response.status_int == 200 - assert response.body == b_('Index wrapped') - assert len(self.permissions_checked) == 1 - assert 'independent' in self.permissions_checked - - def test_lookup_to_wrapped_attribute_on_self(self): - self.secret_cls.authorized = True - self.secret_cls.independent_authorization = True - response = self.app.get('/secret/lookup_wrapped/') - assert response.status_int == 200 - assert response.body == b_('Index wrapped') - assert len(self.permissions_checked) == 2 - assert 'independent' in self.permissions_checked - assert 'secretcontroller' in self.permissions_checked - - def test_unlocked_attribute_in_insecure(self): - response = self.app.get('/notsecret/unlocked/') - assert response.status_int == 200 - assert response.body == b_('Index unlocked') - - -class SecureControllerSharedPermissionsRegression(PecanTestCase): - """Regression tests for https://github.com/dreamhost/pecan/issues/131""" - - def setUp(self): - super(SecureControllerSharedPermissionsRegression, self).setUp() - - class Parent(object): - @expose() - def index(self): - return 'hello' - - class UnsecuredChild(Parent): - pass - - class SecureChild(Parent, SecureController): - @classmethod - def check_permissions(cls): - return False - - class RootController(object): - - secured = SecureChild() - unsecured = UnsecuredChild() - - self.app = TestApp(make_app(RootController())) - - def test_inherited_security(self): - assert self.app.get('/secured/', status=401).status_int == 401 - assert self.app.get('/unsecured/').status_int == 200 diff --git a/pecan/tests/test_templating.py b/pecan/tests/test_templating.py deleted file mode 100644 index 5fffb0c..0000000 --- a/pecan/tests/test_templating.py +++ /dev/null @@ -1,50 +0,0 @@ -import tempfile - -from six import b as b_ - -from pecan.templating import RendererFactory, format_line_context -from pecan.tests import PecanTestCase - - -class TestTemplate(PecanTestCase): - def setUp(self): - super(TestTemplate, self).setUp() - self.rf = RendererFactory() - - def test_available(self): - self.assertTrue(self.rf.available('json')) - self.assertFalse(self.rf.available('badrenderer')) - - def test_create_bad(self): - self.assertEqual(self.rf.get('doesnotexist', '/'), None) - - def test_extra_vars(self): - extra_vars = self.rf.extra_vars - self.assertEqual(extra_vars.make_ns({}), {}) - - extra_vars.update({'foo': 1}) - self.assertEqual(extra_vars.make_ns({}), {'foo': 1}) - - def test_update_extra_vars(self): - extra_vars = self.rf.extra_vars - extra_vars.update({'foo': 1}) - - self.assertEqual(extra_vars.make_ns({'bar': 2}), {'foo': 1, 'bar': 2}) - self.assertEqual(extra_vars.make_ns({'foo': 2}), {'foo': 2}) - - -class TestTemplateLineFormat(PecanTestCase): - - def setUp(self): - super(TestTemplateLineFormat, self).setUp() - self.f = tempfile.NamedTemporaryFile() - - def tearDown(self): - del self.f - - def test_format_line_context(self): - for i in range(11): - self.f.write(b_('Testing Line %d\n' % i)) - self.f.flush() - - assert format_line_context(self.f.name, 0).count('Testing Line') == 10 diff --git a/pecan/tests/test_util.py b/pecan/tests/test_util.py deleted file mode 100644 index 00e81f5..0000000 --- a/pecan/tests/test_util.py +++ /dev/null @@ -1,95 +0,0 @@ -import functools -import inspect -import unittest - -from pecan import expose -from pecan import util - - -class TestArgSpec(unittest.TestCase): - - @property - def controller(self): - - class RootController(object): - - @expose() - def index(self, a, b, c=1, *args, **kwargs): - return 'Hello, World!' - - @staticmethod - @expose() - def static_index(a, b, c=1, *args, **kwargs): - return 'Hello, World!' - - return RootController() - - def test_no_decorator(self): - expected = inspect.getargspec(self.controller.index.__func__) - actual = util.getargspec(self.controller.index.__func__) - assert expected == actual - - expected = inspect.getargspec(self.controller.static_index) - actual = util.getargspec(self.controller.static_index) - assert expected == actual - - def test_simple_decorator(self): - def dec(f): - return f - - expected = inspect.getargspec(self.controller.index.__func__) - actual = util.getargspec(dec(self.controller.index.__func__)) - assert expected == actual - - expected = inspect.getargspec(self.controller.static_index) - actual = util.getargspec(dec(self.controller.static_index)) - assert expected == actual - - def test_simple_wrapper(self): - def dec(f): - @functools.wraps(f) - def wrapped(*a, **kw): - return f(*a, **kw) - return wrapped - - expected = inspect.getargspec(self.controller.index.__func__) - actual = util.getargspec(dec(self.controller.index.__func__)) - assert expected == actual - - expected = inspect.getargspec(self.controller.static_index) - actual = util.getargspec(dec(self.controller.static_index)) - assert expected == actual - - def test_multiple_decorators(self): - def dec(f): - @functools.wraps(f) - def wrapped(*a, **kw): - return f(*a, **kw) - return wrapped - - expected = inspect.getargspec(self.controller.index.__func__) - actual = util.getargspec(dec(dec(dec(self.controller.index.__func__)))) - assert expected == actual - - expected = inspect.getargspec(self.controller.static_index) - actual = util.getargspec(dec(dec(dec( - self.controller.static_index)))) - assert expected == actual - - def test_decorator_with_args(self): - def dec(flag): - def inner(f): - @functools.wraps(f) - def wrapped(*a, **kw): - return f(*a, **kw) - return wrapped - return inner - - expected = inspect.getargspec(self.controller.index.__func__) - actual = util.getargspec(dec(True)(self.controller.index.__func__)) - assert expected == actual - - expected = inspect.getargspec(self.controller.static_index) - actual = util.getargspec(dec(True)( - self.controller.static_index)) - assert expected == actual |