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')