diff --git a/gluon/compileapp.py b/gluon/compileapp.py index 7c28fcbb..b6bbda79 100644 --- a/gluon/compileapp.py +++ b/gluon/compileapp.py @@ -18,7 +18,7 @@ import fnmatch import os import copy import random -from gluon._compat import builtin, PY2, unicodeT, to_native +from gluon._compat import builtin, PY2, unicodeT, to_native, basestring from gluon.storage import Storage, List from gluon.template import parse_template from gluon.restricted import restricted, compile2 @@ -151,7 +151,7 @@ def LOAD(c=None, f='index', args=None, vars=None, "infinity" or "continuous" are accepted to reload indefinitely the component """ - from html import TAG, DIV, URL, SCRIPT, XML + from gluon.html import TAG, DIV, URL, SCRIPT, XML if args is None: args = [] vars = Storage(vars or {}) @@ -430,7 +430,7 @@ def build_environment(request, response, session, store_current=True): __builtins__ = mybuiltin() elif is_pypy: # apply the same hack to pypy too __builtins__ = mybuiltin() - else: + elif PY2: __builtins__['__import__'] = builtin.__import__ # WHY? environment['request'] = request environment['response'] = response diff --git a/gluon/contrib/markmin/markmin2html.py b/gluon/contrib/markmin/markmin2html.py index cae5ff18..0752e063 100755 --- a/gluon/contrib/markmin/markmin2html.py +++ b/gluon/contrib/markmin/markmin2html.py @@ -6,15 +6,10 @@ from __future__ import print_function import re import urllib -from cgi import escape -from gluon._compat import maketrans, urllib_quote, unicodeT, _local_html_escape, to_bytes +from gluon._compat import maketrans, urllib_quote, unicodeT, _local_html_escape, to_bytes, to_native, _local_html_escape as escape +from ast import parse as ast_parse +import ast -try: - from ast import parse as ast_parse - import ast -except ImportError: # python 2.5 - from compiler import parse - import compiler.ast as ast """ TODO: next version should use MathJax @@ -950,12 +945,11 @@ def render(text, if protolinks == "default": protolinks = protolinks_simple pp = '\n' if pretty_print else '' - if isinstance(text, unicodeT): - text = text.encode('utf8') - text = str(text or '') + text = to_native(text) + if not (isinstance(text, str)): + text = str(text or '') text = regex_backslash.sub(lambda m: m.group(1).translate(ttab_in), text) text = text.replace('\x05', '').replace('\r\n', '\n') # concatenate strings separeted by \\n - if URL is not None: text = replace_at_urls(text, URL) diff --git a/gluon/custom_import.py b/gluon/custom_import.py index ad055153..8e848626 100644 --- a/gluon/custom_import.py +++ b/gluon/custom_import.py @@ -104,6 +104,9 @@ def custom_importer(name, globals=None, locals=None, fromlist=None, level=-1): finally: if import_tb: import_tb = None + elif not(PY2) and level < 0: + # FIXME PY3 why level is < 0? + level = 0 return NATIVE_IMPORTER(name, globals, locals, fromlist, level) diff --git a/gluon/html.py b/gluon/html.py index 642f097c..f2fb7b9b 100644 --- a/gluon/html.py +++ b/gluon/html.py @@ -974,7 +974,8 @@ class DIV(XmlComponent): """ str(COMPONENT) returns COMPONENT.xml() """ - return self.xml() + # In PY3 __str__ cannot return bytes (TypeError: __str__ returned non-string (type bytes)) + return to_native(self.xml()) def flatten(self, render=None): """ diff --git a/gluon/languages.py b/gluon/languages.py index b40cabd3..6b4748d8 100644 --- a/gluon/languages.py +++ b/gluon/languages.py @@ -27,9 +27,7 @@ from gluon.utf8 import Utf8 from gluon.fileutils import listdir from gluon.cfs import getcfs from gluon.html import XML, xmlescape -if PY2: - # FIXME PY3 - from gluon.contrib.markmin.markmin2html import render, markmin_escape +from gluon.contrib.markmin.markmin2html import render, markmin_escape __all__ = ['translator', 'findT', 'update_all_languages'] @@ -761,10 +759,10 @@ class translator(object): symbols = (symbols,) symbols = tuple( value if isinstance(value, NUMBERS) - else xmlescape(value).translate(ttab_in) + else to_native(xmlescape(value)).translate(ttab_in) for value in symbols) message = self.params_substitution(message, symbols) - return XML(message.translate(ttab_out)) + return to_native(XML(message.translate(ttab_out)).xml()) def M(self, message, symbols={}, language=None, lazy=None, filter=None, ftag=None, ns=None): diff --git a/gluon/main.py b/gluon/main.py index d7a977c9..e438f4ba 100644 --- a/gluon/main.py +++ b/gluon/main.py @@ -298,6 +298,7 @@ def wsgibase(environ, responder): env.web2py_version = web2py_version #env.update(global_settings) static_file = False + http_response = None try: try: try: @@ -439,8 +440,8 @@ def wsgibase(environ, responder): gluon.debug.dbg.do_debug(mainpyfile=request.folder) serve_controller(request, response, session) - - except HTTP as http_response: + except HTTP as hr: + http_response = hr if static_file: return http_response.to(responder, env=env) diff --git a/gluon/rocket.py b/gluon/rocket.py index 51460532..199f1004 100644 --- a/gluon/rocket.py +++ b/gluon/rocket.py @@ -11,7 +11,7 @@ import errno import socket import logging import platform -from gluon._compat import iteritems +from gluon._compat import iteritems, to_bytes # Define Constants VERSION = '1.2.6' @@ -1772,7 +1772,7 @@ class WSGIWorker(Worker): if self.chunked: self.conn.sendall(b('%x\r\n%s\r\n' % (len(data), data))) else: - self.conn.sendall(data) + self.conn.sendall(to_bytes(data)) except socket.timeout: self.closeConnection = True except socket.error: diff --git a/gluon/streamer.py b/gluon/streamer.py index 1095b592..dd7b78b2 100644 --- a/gluon/streamer.py +++ b/gluon/streamer.py @@ -17,6 +17,7 @@ import re import errno from gluon.http import HTTP from gluon.contenttype import contenttype +from gluon._compat import PY2 regex_start_range = re.compile('\d+(?=\-)') @@ -53,8 +54,11 @@ def stream_file_or_304_or_206( # if error_message is None: # error_message = rewrite.THREAD_LOCAL.routes.error_message % 'invalid request' try: - open = file # this makes no sense but without it GAE cannot open files - fp = open(static_file,'rb') + if PY2: + open_f = file # this makes no sense but without it GAE cannot open files + else: + open_f = open + fp = open_f(static_file,'rb') except IOError as e: if e[0] == errno.EISDIR: raise HTTP(403, error_message, web2py_error='file is a directory') diff --git a/gluon/tests/__init__.py b/gluon/tests/__init__.py index 8a43f01c..4c879ad3 100644 --- a/gluon/tests/__init__.py +++ b/gluon/tests/__init__.py @@ -19,10 +19,10 @@ from .test_utils import * from .test_serializers import * from .test_languages import * from .test_compileapp import * +from .test_appadmin import * if sys.version[:3] == '2.7': from .test_is_url import * - from .test_appadmin import * from .test_scheduler import * from .test_web import * from .test_old_doctests import * diff --git a/gluon/tests/test_languages.py b/gluon/tests/test_languages.py index 0df6f21b..acc621ea 100644 --- a/gluon/tests/test_languages.py +++ b/gluon/tests/test_languages.py @@ -106,10 +106,8 @@ class TestTranslations(unittest.TestCase): '1 quark') self.assertEqual(str(T('%s %%{quark[0]}', 2)), '2 quarks') - if PY2: - # FIXME PY3 markmin is not supported yet - self.assertEqual(str(T.M('**Hello World**')), - 'Hello World') + self.assertEqual(str(T.M('**Hello World**')), + 'Hello World') T.force('it') self.assertEqual(str(T('Hello World')), 'Salve Mondo')