diff --git a/applications/admin/controllers/appadmin.py b/applications/admin/controllers/appadmin.py
index 2f780749..3060945c 100644
--- a/applications/admin/controllers/appadmin.py
+++ b/applications/admin/controllers/appadmin.py
@@ -10,6 +10,7 @@ import datetime
import copy
import gluon.contenttype
import gluon.fileutils
+from gluon._compat import iteritems
try:
import pygraphviz as pgv
@@ -267,7 +268,7 @@ def select():
else:
rows = db(query, ignore_common_filters=True).select(
*fields, limitby=(start, stop))
- except Exception, e:
+ except Exception as e:
import traceback
tb = traceback.format_exc()
(rows, nrows) = ([], 0)
@@ -286,7 +287,7 @@ def select():
import_csv(db[request.vars.table],
request.vars.csvfile.file)
response.flash = T('data uploaded')
- except Exception, e:
+ except Exception as e:
response.flash = DIV(T('unable to parse csv file'), PRE(str(e)))
# end handle upload csv
@@ -454,7 +455,7 @@ def ccache():
except (KeyError, ZeroDivisionError):
ram['ratio'] = 0
- for key, value in cache.ram.storage.iteritems():
+ for key, value in iteritems(cache.ram.storage):
if hp:
ram['bytes'] += hp.iso(value[1]).size
ram['objects'] += hp.iso(value[1]).count
diff --git a/applications/admin/controllers/default.py b/applications/admin/controllers/default.py
index fea3c3f7..b28c7626 100644
--- a/applications/admin/controllers/default.py
+++ b/applications/admin/controllers/default.py
@@ -15,6 +15,7 @@ from gluon.utils import web2py_uuid
from gluon.tools import Config
from gluon.compileapp import find_exposed_functions
from glob import glob
+from gluon._compat import iteritems, PY2
import shutil
import platform
@@ -81,7 +82,10 @@ def safe_open(a, b):
def close(self):
pass
return tmp()
- return open(a, b)
+ if PY2 or 'b' in b:
+ return open(a, b)
+ else:
+ return open(a, b, encoding="utf8")
def safe_read(a, b='r'):
@@ -314,7 +318,7 @@ def site():
if FILTER_APPS:
apps = [f for f in apps if f in FILTER_APPS]
- apps = sorted(apps, lambda a, b: cmp(a.upper(), b.upper()))
+ apps = sorted(apps, key=lambda a: a.upper())
myplatform = platform.python_version()
return dict(app=None, apps=apps, myversion=myversion, myplatform=myplatform,
form_create=form_create, form_update=form_update)
@@ -1152,7 +1156,7 @@ def design():
# Get all languages
langpath = os.path.join(apath(app, r=request), 'languages')
languages = dict([(lang, info) for lang, info
- in read_possible_languages(langpath).iteritems()
+ in iteritems(read_possible_languages(langpath))
if info[2] != 0]) # info[2] is langfile_mtime:
# get only existed files
@@ -1288,7 +1292,7 @@ def plugin():
# Get all languages
languages = sorted([lang + '.py' for lang, info in
- T.get_possible_languages_info().iteritems()
+ iteritems(T.get_possible_languages_info())
if info[2] != 0]) # info[2] is langfile_mtime:
# get only existed files
diff --git a/applications/admin/views/default/ticket.html b/applications/admin/views/default/ticket.html
index 2b9a73b1..eb26c849 100644
--- a/applications/admin/views/default/ticket.html
+++ b/applications/admin/views/default/ticket.html
@@ -122,7 +122,7 @@
{{=XML(snapshot.get('response','no response available in snapshot'))}}
-{{except Exception, e:}}
+{{except Exception as e:}}
{{import traceback;tb=traceback.format_exc().replace("\n","\\n") }}
diff --git a/applications/admin/views/default/ticket.load b/applications/admin/views/default/ticket.load
index 381eee1d..9a42bba3 100644
--- a/applications/admin/views/default/ticket.load
+++ b/applications/admin/views/default/ticket.load
@@ -117,7 +117,7 @@
session
{{=BEAUTIFY(snapshot['session'])}}
response
{{=BEAUTIFY(snapshot['response'])}}
-{{except Exception, e:}}
+{{except Exception as e:}}
{{import traceback;tb=traceback.format_exc().replace("\n","\\n") }}
diff --git a/applications/admin/views/layout.html b/applications/admin/views/layout.html
index 748f8f6e..5203dfc6 100644
--- a/applications/admin/views/layout.html
+++ b/applications/admin/views/layout.html
@@ -61,7 +61,7 @@
{{if hasattr(T,'get_possible_languages_info'):}}
- {{=T('Admin language')}}
diff --git a/applications/examples/controllers/appadmin.py b/applications/examples/controllers/appadmin.py
index 2f780749..3060945c 100644
--- a/applications/examples/controllers/appadmin.py
+++ b/applications/examples/controllers/appadmin.py
@@ -10,6 +10,7 @@ import datetime
import copy
import gluon.contenttype
import gluon.fileutils
+from gluon._compat import iteritems
try:
import pygraphviz as pgv
@@ -267,7 +268,7 @@ def select():
else:
rows = db(query, ignore_common_filters=True).select(
*fields, limitby=(start, stop))
- except Exception, e:
+ except Exception as e:
import traceback
tb = traceback.format_exc()
(rows, nrows) = ([], 0)
@@ -286,7 +287,7 @@ def select():
import_csv(db[request.vars.table],
request.vars.csvfile.file)
response.flash = T('data uploaded')
- except Exception, e:
+ except Exception as e:
response.flash = DIV(T('unable to parse csv file'), PRE(str(e)))
# end handle upload csv
@@ -454,7 +455,7 @@ def ccache():
except (KeyError, ZeroDivisionError):
ram['ratio'] = 0
- for key, value in cache.ram.storage.iteritems():
+ for key, value in iteritems(cache.ram.storage):
if hp:
ram['bytes'] += hp.iso(value[1]).size
ram['objects'] += hp.iso(value[1]).count
diff --git a/applications/examples/controllers/soap_examples.py b/applications/examples/controllers/soap_examples.py
index 7840105e..2d091e80 100644
--- a/applications/examples/controllers/soap_examples.py
+++ b/applications/examples/controllers/soap_examples.py
@@ -44,7 +44,7 @@ def test_soap_sub():
try:
ret = client.SubIntegers(a=3, b=2)
result = ret['SubResult']
- except SoapFault, sf:
+ except SoapFault as sf:
result = sf
response.view = "soap_examples/generic.html"
return dict(xml_request=client.xml_request,
diff --git a/applications/examples/models/markmin.py b/applications/examples/models/markmin.py
index 3376bac6..0370df95 100644
--- a/applications/examples/models/markmin.py
+++ b/applications/examples/models/markmin.py
@@ -28,7 +28,7 @@ def get_content(b=None,
try:
openedfile = openfile()
- except Exception, IOError:
+ except (Exception, IOError):
l = 'en'
openedfile = openfile()
diff --git a/applications/welcome/controllers/appadmin.py b/applications/welcome/controllers/appadmin.py
index ddb02548..3060945c 100644
--- a/applications/welcome/controllers/appadmin.py
+++ b/applications/welcome/controllers/appadmin.py
@@ -10,6 +10,7 @@ import datetime
import copy
import gluon.contenttype
import gluon.fileutils
+from gluon._compat import iteritems
try:
import pygraphviz as pgv
@@ -454,7 +455,7 @@ def ccache():
except (KeyError, ZeroDivisionError):
ram['ratio'] = 0
- for key, value in cache.ram.storage.iteritems():
+ for key, value in iteritems(cache.ram.storage):
if hp:
ram['bytes'] += hp.iso(value[1]).size
ram['objects'] += hp.iso(value[1]).count
diff --git a/gluon/compileapp.py b/gluon/compileapp.py
index b6bbda79..1a55c3bc 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, basestring
+from gluon._compat import builtin, PY2, unicodeT, to_native, to_bytes, iteritems, basestring
from gluon.storage import Storage, List
from gluon.template import parse_template
from gluon.restricted import restricted, compile2
@@ -395,6 +395,11 @@ _base_environment_['SQLField'] = Field # for backward compatibility
_base_environment_['SQLFORM'] = SQLFORM
_base_environment_['SQLTABLE'] = SQLTABLE
_base_environment_['LOAD'] = LOAD
+# For an easier PY3 migration
+_base_environment_['PY2'] = PY2
+_base_environment_['to_native'] = to_native
+_base_environment_['to_bytes'] = to_bytes
+_base_environment_['iteritems'] = iteritems
def build_environment(request, response, session, store_current=True):
"""
diff --git a/gluon/http.py b/gluon/http.py
index a0273866..e34fb8f0 100644
--- a/gluon/http.py
+++ b/gluon/http.py
@@ -110,7 +110,7 @@ class HTTP(Exception):
if status[:1] == '4':
if not body:
body = status
- if isinstance(body, str):
+ if isinstance(body, (str, bytes, bytearray)):
headers['Content-Length'] = len(body)
rheaders = []
for k, v in iteritems(headers):
@@ -121,7 +121,7 @@ class HTTP(Exception):
responder(status, rheaders)
if env.get('request_method', '') == 'HEAD':
return ['']
- elif isinstance(body, str):
+ elif isinstance(body, (str, bytes, bytearray)):
return [body]
elif hasattr(body, '__iter__'):
return body