From 2861dc4215ae97f65b6f7bc78177aba5f5c35cf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonel=20C=C3=A2mara?= Date: Tue, 5 Sep 2017 15:46:31 +0100 Subject: [PATCH 01/12] Fixes #1753 --- gluon/compileapp.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gluon/compileapp.py b/gluon/compileapp.py index ac9cc491..dc0dae79 100644 --- a/gluon/compileapp.py +++ b/gluon/compileapp.py @@ -205,7 +205,7 @@ def LOAD(c=None, f='index', args=None, vars=None, other_response = Response() other_request.env.path_info = '/' + \ '/'.join([request.application, c, f] + - map(str, other_request.args)) + [str(a) for a in other_request.args]) other_request.env.query_string = \ vars and URL(vars=vars).split('?')[1] or '' other_request.env.http_web2py_component_location = \ @@ -288,7 +288,7 @@ class LoadFactory(object): other_response = globals.Response() other_request.env.path_info = '/' + \ '/'.join([request.application, c, f] + - map(str, other_request.args)) + [str(a) for a in other_request.args]) other_request.env.query_string = \ vars and html.URL(vars=vars).split('?')[1] or '' other_request.env.http_web2py_component_location = \ @@ -678,7 +678,7 @@ def run_view_in(environment): layer = None scode = None if patterns: - regex = re_compile('|'.join(map(fnmatch.translate, patterns))) + regex = re_compile('|'.join(fnmatch.translate(p) for p in patterns)) short_action = '%(controller)s/%(function)s.%(extension)s' % request allow_generic = regex.search(short_action) else: From 4aefb93ab44e0555d134603da88137cd73e534b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonel=20C=C3=A2mara?= Date: Wed, 6 Sep 2017 15:28:39 +0100 Subject: [PATCH 02/12] Fixes #1752 --- gluon/_compat.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gluon/_compat.py b/gluon/_compat.py index f7562b12..1a68163d 100644 --- a/gluon/_compat.py +++ b/gluon/_compat.py @@ -151,7 +151,7 @@ def with_metaclass(meta, *bases): def to_unicode(obj, charset='utf-8', errors='strict'): if obj is None: return None - if not isinstance(obj, bytes): + if not hasattr(obj, 'decode') and not isinstance(obj, bytes): return text_type(obj) return obj.decode(charset, errors) From a6044068cd043a89db6b643a221dca7b1344d840 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonel=20C=C3=A2mara?= Date: Wed, 6 Sep 2017 15:31:30 +0100 Subject: [PATCH 03/12] Fixes #1751 --- gluon/_compat.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gluon/_compat.py b/gluon/_compat.py index 1a68163d..5b7ec948 100644 --- a/gluon/_compat.py +++ b/gluon/_compat.py @@ -63,7 +63,7 @@ if PY2: return None if isinstance(obj, (bytes, bytearray, buffer)): return bytes(obj) - if isinstance(obj, unicode): + if hasattr(obj, 'encode'): return obj.encode(charset, errors) raise TypeError('Expected bytes') From 83f90165284a25a2852db0c50e7fc81380be0087 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonel=20C=C3=A2mara?= Date: Wed, 6 Sep 2017 15:33:47 +0100 Subject: [PATCH 04/12] fix in py3 too --- gluon/_compat.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gluon/_compat.py b/gluon/_compat.py index 5b7ec948..e5fcbdd8 100644 --- a/gluon/_compat.py +++ b/gluon/_compat.py @@ -122,7 +122,7 @@ else: return None if isinstance(obj, (bytes, bytearray, memoryview)): return bytes(obj) - if isinstance(obj, str): + if hasattr(obj, 'encode'): return obj.encode(charset, errors) raise TypeError('Expected bytes') From 4b38186b518244ebbd91bf53073d273f32d70ae6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonel=20C=C3=A2mara?= Date: Wed, 6 Sep 2017 15:37:51 +0100 Subject: [PATCH 05/12] simplify condition if you ain't got decode you ain't bytes --- gluon/_compat.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gluon/_compat.py b/gluon/_compat.py index e5fcbdd8..a61ddc51 100644 --- a/gluon/_compat.py +++ b/gluon/_compat.py @@ -151,7 +151,7 @@ def with_metaclass(meta, *bases): def to_unicode(obj, charset='utf-8', errors='strict'): if obj is None: return None - if not hasattr(obj, 'decode') and not isinstance(obj, bytes): + if not hasattr(obj, 'decode'): return text_type(obj) return obj.decode(charset, errors) From 912c22d593375d491e83dcb65ee12a2bec03f02c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonel=20C=C3=A2mara?= Date: Wed, 6 Sep 2017 16:22:50 +0100 Subject: [PATCH 06/12] Don't use gluon.utf8.Utf8 with py3 there's no need for it and it breaks stuff --- gluon/languages.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/gluon/languages.py b/gluon/languages.py index b626457c..aff3db14 100644 --- a/gluon/languages.py +++ b/gluon/languages.py @@ -18,10 +18,11 @@ import pkgutil import logging from cgi import escape from threading import RLock -from gluon.utf8 import Utf8 + from gluon.utils import local_html_escape from gluon._compat import copyreg, PY2, maketrans, iterkeys, unicodeT, to_unicode, to_bytes, iteritems, to_native, pjoin + from pydal.contrib.portalocker import read_locked, LockedFile from gluon.fileutils import listdir @@ -49,8 +50,10 @@ DEFAULT_CONSTRUCT_PLURAL_FORM = lambda word, plural_id: word if PY2: NUMBERS = (int, long, float) + from gluon.utf8 import Utf8 else: NUMBERS = (int, float) + Utf8 = str # pattern to find T(blah blah blah) expressions PY_STRING_LITERAL_RE = r'(?<=[^\w]T\()(?P'\ From 3ecdd1c11b05b805bc1a5d82bb3e28344a9b8f3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonel=20C=C3=A2mara?= Date: Thu, 7 Sep 2017 10:18:41 +0100 Subject: [PATCH 07/12] Fix #1757 --- gluon/globals.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gluon/globals.py b/gluon/globals.py index f9f5013b..cb52d331 100644 --- a/gluon/globals.py +++ b/gluon/globals.py @@ -331,7 +331,7 @@ class Request(Storage): user_agent = session._user_agent if user_agent: return user_agent - http_user_agent = self.env.http_user_agent + http_user_agent = self.env.http_user_agent or '' user_agent = user_agent_parser.detect(http_user_agent) for key, value in user_agent.items(): if isinstance(value, dict): From 8eda21ca8685ab5dcde4efcec85009806f3be327 Mon Sep 17 00:00:00 2001 From: abastardi Date: Wed, 13 Sep 2017 11:48:25 -0400 Subject: [PATCH 08/12] Fix bug with compiled views in compiled-only apps Compiled views were not being executed in apps containing only compiled files (i.e., generated via the admin "Pack compiled" functionality), resulting in "Invalid view" errors for all pages. --- gluon/compileapp.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/gluon/compileapp.py b/gluon/compileapp.py index ac9cc491..1ec547d5 100644 --- a/gluon/compileapp.py +++ b/gluon/compileapp.py @@ -709,23 +709,22 @@ def run_view_in(environment): ccode = getcfs(compiled, compiled, lambda: read_pyc(compiled)) layer = compiled break - if not os.path.exists(filename) and allow_generic: - view = 'generic.' + request.extension - filename = pjoin(folder, 'views', view) - if not os.path.exists(filename): - raise HTTP(404, - rewrite.THREAD_LOCAL.routes.error_message % badv, - web2py_error=badv) - # if the view is not compiled if not layer: + if not os.path.exists(filename) and allow_generic: + view = 'generic.' + request.extension + filename = pjoin(folder, 'views', view) + if not os.path.exists(filename): + raise HTTP(404, + rewrite.THREAD_LOCAL.routes.error_message % badv, + web2py_error=badv) # Parse template scode = parse_template(view, pjoin(folder, 'views'), context=environment) # Compile template ccode = compile2(scode, filename) - layer = filename + layer = filename restricted(ccode, environment, layer=layer, scode=scode) # parse_template saves everything in response body return environment['response'].body.getvalue() From a605e43fa6d2e0d15626429411cf074c0609c982 Mon Sep 17 00:00:00 2001 From: abastardi Date: Thu, 14 Sep 2017 18:49:31 -0400 Subject: [PATCH 09/12] Fix grid TSV export bug --- gluon/sqlhtml.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gluon/sqlhtml.py b/gluon/sqlhtml.py index 0653c4c7..555123e9 100644 --- a/gluon/sqlhtml.py +++ b/gluon/sqlhtml.py @@ -3570,7 +3570,9 @@ class ExportClass(object): if not self.rows.db._adapter.REGEX_TABLE_DOT_FIELD.match(col): row.append(record._extra[col]) else: - (t, f) = col.split('.') + # The grid code modifies rows.colnames, adding double quotes + # around the table and field names -- so they must be removed here. + (t, f) = [name.strip('"') for name in col.split('.')] field = self.rows.db[t][f] if isinstance(record.get(t, None), (Row, dict)): value = record[t][f] From 4a347a4f783d9cd0b5d3550b161208ccecc12f0a Mon Sep 17 00:00:00 2001 From: "tiago.bar" Date: Fri, 22 Sep 2017 13:04:47 -0300 Subject: [PATCH 10/12] Enhances/fixes validators/is_empty() for Python 3 compatibility, fix #1764 --- gluon/validators.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gluon/validators.py b/gluon/validators.py index 1d9dddcf..21de1ce2 100644 --- a/gluon/validators.py +++ b/gluon/validators.py @@ -996,7 +996,7 @@ def is_empty(value, empty_regex=None): value = value.strip() if empty_regex is not None and empty_regex.match(value): value = '' - if value is None or value == '' or value == []: + if value is None or value == '' or value == b'' or value == []: return (_value, True) return (_value, False) From 511245a68c4abcce3c721bbd3d0d48d614f55f3b Mon Sep 17 00:00:00 2001 From: "tiago.bar" Date: Sat, 23 Sep 2017 20:21:14 -0300 Subject: [PATCH 11/12] Unit test for #1764 fix --- gluon/tests/test_validators.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gluon/tests/test_validators.py b/gluon/tests/test_validators.py index e534fbd8..36bf454e 100644 --- a/gluon/tests/test_validators.py +++ b/gluon/tests/test_validators.py @@ -444,6 +444,8 @@ class TestValidators(unittest.TestCase): self.assertEqual(rtn, (None, 'Enter a value')) rtn = IS_NOT_EMPTY()('') self.assertEqual(rtn, ('', 'Enter a value')) + rtn = IS_NOT_EMPTY()(b'') + self.assertEqual(rtn, (b'', 'Enter a value')) rtn = IS_NOT_EMPTY()(' ') self.assertEqual(rtn, (' ', 'Enter a value')) rtn = IS_NOT_EMPTY()(' \n\t') From 2e6f529dfdfcf60e6fde1d31bb411f2d391697fe Mon Sep 17 00:00:00 2001 From: Tim Nyborg Date: Thu, 12 Oct 2017 17:18:06 +0100 Subject: [PATCH 12/12] Fix setting 'ac' in request.vars --- gluon/sqlhtml.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gluon/sqlhtml.py b/gluon/sqlhtml.py index 555123e9..c4095e44 100644 --- a/gluon/sqlhtml.py +++ b/gluon/sqlhtml.py @@ -17,6 +17,7 @@ Holds: import datetime import urllib import re +import copy import os from gluon._compat import StringIO, unichr, urllib_quote, iteritems, basestring, long, unicodeT, to_native, to_unicode @@ -682,7 +683,7 @@ class AutocompleteWidget(object): else: self.is_reference = False if hasattr(request, 'application'): - urlvars = request.vars + urlvars = copy.copy(request.vars) urlvars[default_var] = 1 self.url = URL(args=request.args, vars=urlvars, user_signature=user_signature, hash_vars=hash_vars)