diff --git a/pecan/commands/base.py b/pecan/commands/base.py index 5b6d7ee..85f40d4 100644 --- a/pecan/commands/base.py +++ b/pecan/commands/base.py @@ -102,7 +102,14 @@ class CommandRunner(object): return self.manager.commands -class BaseCommand(object): +class BaseCommandMeta(type): + + @property + def summary(cls): + return cls.__doc__.strip().splitlines()[0].rstrip('.') + + +class BaseCommandParent(object): """ A base interface for Pecan commands. @@ -130,11 +137,6 @@ class BaseCommand(object): print(args.extra_arg) """ - class __metaclass__(type): - @property - def summary(cls): - return cls.__doc__.strip().splitlines()[0].rstrip('.') - arguments = ({ 'name': 'config_file', 'help': 'a Pecan configuration file', @@ -148,3 +150,5 @@ class BaseCommand(object): def load_app(self): from pecan import load_app return load_app(self.args.config_file) + +BaseCommand = BaseCommandMeta('BaseCommand', (BaseCommandParent,), {}) diff --git a/pecan/core.py b/pecan/core.py index 8cd768b..864fed8 100644 --- a/pecan/core.py +++ b/pecan/core.py @@ -336,7 +336,7 @@ class Pecan(object): valid_args = valid_args[len(args):] # handle wildcard arguments - if filter(None, remainder): + if [i for i in remainder if i]: if not argspec[1]: abort(404) args.extend(remainder) @@ -422,7 +422,7 @@ class Pecan(object): # handle generic controllers im_self = None if cfg.get('generic'): - im_self = controller.im_self + im_self = six.get_method_self(controller) handlers = cfg['generic_handlers'] controller = handlers.get(req.method, handlers['DEFAULT']) cfg = _cfg(controller) @@ -533,8 +533,14 @@ class Pecan(object): testing_variables['controller_output'] = result # set the body content - if isinstance(result, unicode): - resp.unicode_body = result + if six.PY3: + resp.text = result if isinstance(result, str) else str( + result, + 'utf-8', + 'strict' + ) + elif isinstance(result, six.text_type): + resp.text = result else: resp.body = result diff --git a/pecan/middleware/errordocument.py b/pecan/middleware/errordocument.py index 2559c9c..82b2590 100644 --- a/pecan/middleware/errordocument.py +++ b/pecan/middleware/errordocument.py @@ -1,5 +1,6 @@ import sys +from pecan.compat import bytes_ from .recursive import ForwardRequestException, RecursionLoop @@ -31,9 +32,9 @@ class StatusPersist(object): [('Content-type', 'text/plain')], sys.exc_info() ) - return [ + return [bytes_( 'Error: %s. (Error page could not be fetched)' % self.status - ] + )] class ErrorDocumentMiddleware(object): diff --git a/pecan/middleware/static.py b/pecan/middleware/static.py index c68bce7..a05a7f8 100644 --- a/pecan/middleware/static.py +++ b/pecan/middleware/static.py @@ -10,6 +10,8 @@ import mimetypes from datetime import datetime from time import gmtime +import six + class FileWrapper(object): """This class can be used to convert a :class:`file`-like object into @@ -42,6 +44,10 @@ class FileWrapper(object): raise StopIteration() +if six.PY3: + FileWrapper.__next__ = FileWrapper.next + + def wrap_file(environ, file, buffer_size=8192): """Wraps a file. This uses the WSGI server's file wrapper if available or otherwise the generic :class:`FileWrapper`. @@ -64,7 +70,7 @@ def _dump_date(d, delim): d = gmtime() elif isinstance(d, datetime): d = d.utctimetuple() - elif isinstance(d, (int, long, float)): + elif isinstance(d, (int, float)): d = gmtime(d) return '%s, %02d%s%s%s%s %02d:%02d:%02d GMT' % ( ('Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun')[d.tm_wday], diff --git a/pecan/tests/test_scaffolds.py b/pecan/tests/test_scaffolds.py index 23d6e81..669aa7d 100644 --- a/pecan/tests/test_scaffolds.py +++ b/pecan/tests/test_scaffolds.py @@ -95,7 +95,6 @@ class TestScaffoldUtils(PecanTestCase): def test_destination_directory_already_exists(self): from pecan.scaffolds import copy_dir - from cStringIO import StringIO f = StringIO() copy_dir( (