From 54dcf2ead915add6dc01e973d264124aef8b1ceb Mon Sep 17 00:00:00 2001 From: mdipierro Date: Mon, 1 Oct 2012 17:07:06 -0500 Subject: [PATCH 01/10] more customizaiton of booleans --- VERSION | 2 +- gluon/dal.py | 25 +++++++++++++------------ 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/VERSION b/VERSION index fc99cdc6..ae05d6ee 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Version 2.0.9 (2012-10-01 15:54:19) dev +Version 2.0.9 (2012-10-01 17:06:56) dev diff --git a/gluon/dal.py b/gluon/dal.py index 1a50c2d2..bafe2af0 100644 --- a/gluon/dal.py +++ b/gluon/dal.py @@ -594,7 +594,8 @@ class BaseAdapter(ConnectionPool): support_distributed_transaction = False uploads_in_blob = False can_select_for_update = True - + TRUE = 'T' + FALSE = 'F' types = { 'boolean': 'CHAR(1)', 'string': 'CHAR(%(length)s)', @@ -623,6 +624,11 @@ class BaseAdapter(ConnectionPool): def adapt(self, obj): return "'%s'" % obj.replace("'", "''") + def smart_adapt(self, obj): + if isinstance(obj,(int,float)): + return str(obj) + return self.adapt(str(obj)) + def integrity_error(self): return self.driver.IntegrityError @@ -1703,10 +1709,10 @@ class BaseAdapter(ConnectionPool): if not r is None: return r if fieldtype == 'boolean': - if obj and not str(obj)[:1].upper() in ['F', '0']: - return "'T'" + if obj and not str(obj)[:1].upper() in '0F': + return self.smart_adapt(self.TRUE) else: - return "'F'" + return self.smart_adapt(self.FALSE) if fieldtype == 'id' or fieldtype == 'integer': return str(int(obj)) if field_is_type('decimal'): @@ -2946,13 +2952,8 @@ class MSSQLAdapter(BaseAdapter): sql_s += ' TOP %i' % lmax return 'SELECT %s %s FROM %s%s%s;' % (sql_s, sql_f, sql_t, sql_w, sql_o) - def represent_exceptions(self, obj, fieldtype): - if fieldtype == 'boolean': - if obj and not str(obj)[0].upper() == 'F': - return '1' - else: - return '0' - return None + TRUE = 1 + FALSE = 0 REGEX_DSN = re.compile('^(?P.+)$') REGEX_URI = re.compile('^(?P[^:@]+)(\:(?P[^@]*))?@(?P[^\:/]+)(\:(?P[0-9]+))?/(?P[^\?]+)(\?(?P.*))?$') @@ -4089,7 +4090,7 @@ class NoSQLAdapter(BaseAdapter): obj = obj['id'] obj = long(obj) elif fieldtype == 'boolean': - if obj and not str(obj)[0].upper() == 'F': + if obj and not str(obj)[0].upper() in '0F': obj = True else: obj = False From fc1e4ad62077da66492214f0b4c460cb8f8290ff Mon Sep 17 00:00:00 2001 From: mdipierro Date: Mon, 1 Oct 2012 19:15:37 -0500 Subject: [PATCH 02/10] fixed DAL.__new__ and SQLFORM.factory --- VERSION | 2 +- gluon/dal.py | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/VERSION b/VERSION index ae05d6ee..7aa13c43 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Version 2.0.9 (2012-10-01 17:06:56) dev +Version 2.0.9 (2012-10-01 19:15:30) dev diff --git a/gluon/dal.py b/gluon/dal.py index bafe2af0..8062dac4 100644 --- a/gluon/dal.py +++ b/gluon/dal.py @@ -6572,7 +6572,10 @@ class DAL(object): Field('fieldname2')) """ - def __new__(cls, uri='sqlite://dummy.db', *args, **kwargs): + def __new__(cls, uri='sqlite://dummy.db', *args, **kwargs): + if uri==None and not 'singleton_code' in kwargs: + # this deal with the special case of Dummy DAL for SQLFORM.factory + return super(DAL, cls).__new__(cls, uri, *args, **kwargs) if not hasattr(THREAD_LOCAL,'db_instances'): THREAD_LOCAL.db_instances = {} if 'singleton_code' in kwargs: From 606daabdd34170c8e2b0e81ec42afde99b4616c5 Mon Sep 17 00:00:00 2001 From: mdipierro Date: Mon, 1 Oct 2012 20:52:02 -0500 Subject: [PATCH 03/10] possibly fixed 1020 --- VERSION | 2 +- gluon/dal.py | 21 ++++++++++++++------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/VERSION b/VERSION index 7aa13c43..6c39fd27 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Version 2.0.9 (2012-10-01 19:15:30) dev +Version 2.0.9 (2012-10-01 20:51:51) dev diff --git a/gluon/dal.py b/gluon/dal.py index 8062dac4..77255abd 100644 --- a/gluon/dal.py +++ b/gluon/dal.py @@ -594,6 +594,7 @@ class BaseAdapter(ConnectionPool): support_distributed_transaction = False uploads_in_blob = False can_select_for_update = True + TRUE = 'T' FALSE = 'F' types = { @@ -621,6 +622,9 @@ class BaseAdapter(ConnectionPool): 'big-reference': 'BIGINT REFERENCES %(foreign_key)s ON DELETE %(on_delete_action)s', } + def id_query(self, table): + return table._id != None + def adapt(self, obj): return "'%s'" % obj.replace("'", "''") @@ -4057,6 +4061,9 @@ class NoSQLAdapter(BaseAdapter): return unicode(obj) return obj + def id_query(self, table): + return table._id > 0 + def represent(self, obj, fieldtype): field_is_type = fieldtype.startswith if isinstance(obj, CALLABLETYPES): @@ -4407,7 +4414,7 @@ class GoogleDatastoreAdapter(NoSQLAdapter): return self.expand(first) def truncate(self,table,mode): - self.db(table._id > 0).delete() + self.db(table._id).delete() def select_raw(self,query,fields=None,attributes=None): db = self.db @@ -4425,7 +4432,7 @@ class GoogleDatastoreAdapter(NoSQLAdapter): tablename = self.get_table(query) elif fields: tablename = fields[0].tablename - query = fields[0].table._id != None + query = db._adapter.id_query(fields[0].table) else: raise SyntaxError, "Unable to determine a tablename" @@ -7123,7 +7130,7 @@ def index(): def __call__(self, query=None, ignore_common_filters=None): if isinstance(query,Table): - query = query._id != None + query = self._adapter.id_query(query) elif isinstance(query,Field): query = query!=None return Set(self, query, ignore_common_filters=ignore_common_filters) @@ -7240,7 +7247,7 @@ def index(): kwargs.get("write_colnames", True) for table in self.tables: ofile.write('TABLE %s\r\n' % table) - query = self[table]._id > 0 + query = self._adapter.id_query(self[table]) nrows = self(query).count() kwargs['write_colnames'] = write_colnames for k in range(0,nrows,step): @@ -8670,7 +8677,7 @@ class Set(object): def __call__(self, query, ignore_common_filters=False): if isinstance(query,Table): - query = query._id != None + query = self.db._adapter.id_query(query) elif isinstance(query,str): query = Expression(self.db,query) elif isinstance(query,Field): @@ -9448,10 +9455,10 @@ def test_all(): Example of expressions >>> mynumber = db.define_table('mynumber', Field('x', 'integer')) - >>> db(mynumber.id>0).delete() + >>> db(mynumber).delete() 0 >>> for i in range(10): tmp = mynumber.insert(x=i) - >>> db(mynumber.id>0).select(mynumber.x.sum())[0](mynumber.x.sum()) + >>> db(mynumber).select(mynumber.x.sum())[0](mynumber.x.sum()) 45 >>> db(mynumber.x+2==5).select(mynumber.x + 2)[0](mynumber.x + 2) From f79660dd2a183beba3d6f70b6f9f3472e13e5d32 Mon Sep 17 00:00:00 2001 From: mdipierro Date: Mon, 1 Oct 2012 21:11:45 -0500 Subject: [PATCH 04/10] attempt to fix issue 981 --- VERSION | 2 +- gluon/globals.py | 3 ++- gluon/streamer.py | 52 +++++++++++++++++++++++++---------------------- 3 files changed, 31 insertions(+), 26 deletions(-) diff --git a/VERSION b/VERSION index 6c39fd27..6c894fea 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Version 2.0.9 (2012-10-01 20:51:51) dev +Version 2.0.9 (2012-10-01 21:11:37) dev diff --git a/gluon/globals.py b/gluon/globals.py index c40918fb..3d075b8c 100644 --- a/gluon/globals.py +++ b/gluon/globals.py @@ -329,7 +329,8 @@ class Response(Storage): stream_file_or_304_or_206(stream, chunk_size=chunk_size, request=request, - headers=headers) + headers=headers, + status=self.status) # ## the following is for backward compatibility if hasattr(stream, 'name'): diff --git a/gluon/streamer.py b/gluon/streamer.py index cf165646..5ab2b8c8 100644 --- a/gluon/streamer.py +++ b/gluon/streamer.py @@ -43,6 +43,7 @@ def stream_file_or_304_or_206( chunk_size = DEFAULT_CHUNK_SIZE, request = None, headers = {}, + status = 200, error_message = None, ): if error_message is None: @@ -67,30 +68,33 @@ def stream_file_or_304_or_206( headers.setdefault('Pragma', 'cache') headers.setdefault('Cache-Control', 'private') - if request and request.env.http_if_modified_since == mtime: - raise HTTP(304, **{'Content-Type': headers['Content-Type']}) + # if this is a normal response and not a respnse to an error page + if status == 200: + if request and request.env.http_if_modified_since == mtime: + raise HTTP(304, **{'Content-Type': headers['Content-Type']}) - elif request and request.env.http_range: - start_items = regex_start_range.findall(request.env.http_range) - if not start_items: - start_items = [0] - stop_items = regex_stop_range.findall(request.env.http_range) - if not stop_items or int(stop_items[0]) > fsize - 1: - stop_items = [fsize - 1] - part = (int(start_items[0]), int(stop_items[0]), fsize) - bytes = part[1] - part[0] + 1 - try: - stream = open(static_file, 'rb') - except IOError, e: - if e[0] in (errno.EISDIR, errno.EACCES): - raise HTTP(403) - else: - raise HTTP(404) - stream.seek(part[0]) - headers['Content-Range'] = 'bytes %i-%i/%i' % part - headers['Content-Length'] = '%i' % bytes - status = 206 - else: + elif request and request.env.http_range: + start_items = regex_start_range.findall(request.env.http_range) + if not start_items: + start_items = [0] + stop_items = regex_stop_range.findall(request.env.http_range) + if not stop_items or int(stop_items[0]) > fsize - 1: + stop_items = [fsize - 1] + part = (int(start_items[0]), int(stop_items[0]), fsize) + bytes = part[1] - part[0] + 1 + try: + stream = open(static_file, 'rb') + except IOError, e: + if e[0] in (errno.EISDIR, errno.EACCES): + raise HTTP(403) + else: + raise HTTP(404) + stream.seek(part[0]) + headers['Content-Range'] = 'bytes %i-%i/%i' % part + headers['Content-Length'] = '%i' % bytes + status = 206 + # in all the other cases (not 304, not 206, but 200 or error page) + if status != 206: if 'gzip' in request.env.http_accept_encoding and\ not 'Content-Encoding' in headers: gzipped = static_file + '.gz' @@ -102,13 +106,13 @@ def stream_file_or_304_or_206( try: stream = open(static_file, 'rb') except IOError, e: + # this better does not happer when returning an error page ;-) if e[0] in (errno.EISDIR, errno.EACCES): raise HTTP(403) else: raise HTTP(404) headers['Content-Length'] = fsize bytes = None - status = 200 if request and request.env.web2py_use_wsgi_file_wrapper: wrapped = request.env.wsgi_file_wrapper(stream, chunk_size) else: From efa5ceb6deecfed6ea81668ce44827e684c27cc7 Mon Sep 17 00:00:00 2001 From: mdipierro Date: Mon, 1 Oct 2012 21:16:42 -0500 Subject: [PATCH 05/10] fixed issue 738 --- VERSION | 2 +- gluon/dal.py | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/VERSION b/VERSION index 6c894fea..9ba4d665 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Version 2.0.9 (2012-10-01 21:11:37) dev +Version 2.0.9 (2012-10-01 21:16:35) dev diff --git a/gluon/dal.py b/gluon/dal.py index 77255abd..bd6ecf31 100644 --- a/gluon/dal.py +++ b/gluon/dal.py @@ -7871,8 +7871,11 @@ class Table(object): value = bar_decode_string(value) elif field.type.startswith(list_reference_s): ref_table = field.type[len(list_reference_s):].strip() - value = [id_map[ref_table][int(v)] \ + if id_map is not None: + value = [id_map[ref_table][int(v)] \ for v in bar_decode_string(value)] + else: + value = [v for v in bar_decode_string(value)] elif field.type.startswith('list:'): value = bar_decode_integer(value) elif id_map and field.type.startswith('reference'): From b20e74c899e3735c46684c01138c0eccd0335d46 Mon Sep 17 00:00:00 2001 From: Massimo Date: Tue, 2 Oct 2012 14:50:16 -0500 Subject: [PATCH 06/10] wiki uses contains instead of startswith, thanks David --- VERSION | 2 +- gluon/dal.py | 4 +++- gluon/tools.py | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/VERSION b/VERSION index 9ba4d665..90a3f2e3 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Version 2.0.9 (2012-10-01 21:16:35) dev +Version 2.0.9 (2012-10-02 14:50:06) dev diff --git a/gluon/dal.py b/gluon/dal.py index bd6ecf31..b98394cc 100644 --- a/gluon/dal.py +++ b/gluon/dal.py @@ -3267,7 +3267,9 @@ class FireBirdAdapter(BaseAdapter): return 'SUBSTRING(%s from %s for %s)' % (self.expand(field), parameters[0], parameters[1]) def CONTAINS(self, first, second): - if first.type.startswith('list:'): + if first.type in ('string','text'): + key = str(second).replace('%','%%') + elif first.type.startswith('list:'): key = '|'+str(second).replace('|','||').replace('%','%%')+'|' return '(%s CONTAINING %s)' % (self.expand(first), self.expand(key,'string')) diff --git a/gluon/tools.py b/gluon/tools.py index 3d4141c1..34cfdd3d 100644 --- a/gluon/tools.py +++ b/gluon/tools.py @@ -4921,7 +4921,7 @@ class Wiki(object): if query is None: query = (db.wiki_page.id==db.wiki_tag.wiki_page)&\ (db.wiki_tag.name.belongs(tags)) - query = query|db.wiki_page.title.startswith(request.vars.q) + query = query|db.wiki_page.title.contains(request.vars.q) if self.restrict_search and not self.manage(): query = query&(db.wiki_page.created_by==self.auth.user_id) pages = db(query).select(count, From bacff3453baff950bc60318fb515687e9b89ccde Mon Sep 17 00:00:00 2001 From: Massimo Date: Tue, 2 Oct 2012 14:55:56 -0500 Subject: [PATCH 07/10] fised issue 1063 --- VERSION | 2 +- gluon/streamer.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/VERSION b/VERSION index 90a3f2e3..c364805d 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Version 2.0.9 (2012-10-02 14:50:06) dev +Version 2.0.9 (2012-10-02 14:55:51) dev diff --git a/gluon/streamer.py b/gluon/streamer.py index 5ab2b8c8..c5b5142b 100644 --- a/gluon/streamer.py +++ b/gluon/streamer.py @@ -95,8 +95,8 @@ def stream_file_or_304_or_206( status = 206 # in all the other cases (not 304, not 206, but 200 or error page) if status != 206: - if 'gzip' in request.env.http_accept_encoding and\ - not 'Content-Encoding' in headers: + enc = request.env.http_accept_encoding + if enc and 'gzip' in enc and not 'Content-Encoding' in headers: gzipped = static_file + '.gz' if os.path.isfile(gzipped) and os.path.getmtime(gzipped)>modified: static_file = gzipped From 433a02537c8730e23998855fb000e6c7797eeca8 Mon Sep 17 00:00:00 2001 From: Massimo Date: Wed, 3 Oct 2012 11:54:03 -0500 Subject: [PATCH 08/10] fixed issue 1064 --- VERSION | 2 +- applications/admin/controllers/appadmin.py | 4 ++++ applications/admin/views/appadmin.html | 6 ++++++ applications/examples/controllers/appadmin.py | 4 ++++ applications/examples/views/appadmin.html | 6 ++++++ applications/welcome/controllers/appadmin.py | 4 ++++ applications/welcome/views/appadmin.html | 6 ++++++ 7 files changed, 31 insertions(+), 1 deletion(-) diff --git a/VERSION b/VERSION index c364805d..2a886d26 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Version 2.0.9 (2012-10-02 14:55:51) dev +Version 2.0.9 (2012-10-03 11:53:40) dev diff --git a/applications/admin/controllers/appadmin.py b/applications/admin/controllers/appadmin.py index fa264bae..b37afc70 100644 --- a/applications/admin/controllers/appadmin.py +++ b/applications/admin/controllers/appadmin.py @@ -207,6 +207,7 @@ def select(): if match: table = match.group('table') try: + tb = None nrows = db(query).count() if form.vars.update_check and form.vars.update_fields: db(query).update(**eval_in_global_env('dict(%s)' @@ -221,6 +222,8 @@ def select(): else: rows = db(query,ignore_common_filters=True).select(limitby=(start, stop)) except Exception, e: + import traceback + tb = traceback.format_exc() (rows, nrows) = ([], 0) response.flash = DIV(T('Invalid Query'),PRE(str(e))) # begin handle upload csv @@ -250,6 +253,7 @@ def select(): rows=rows, query=request.vars.query, formcsv = formcsv, + tb = tb, ) diff --git a/applications/admin/views/appadmin.html b/applications/admin/views/appadmin.html index 72dfc00c..6a933679 100644 --- a/applications/admin/views/appadmin.html +++ b/applications/admin/views/appadmin.html @@ -44,6 +44,12 @@ {{elif request.function=='select':}}

{{=XML(str(T("Database %s select"))%A(request.args[0],_href=URL('index'))) }}

+ {{if tb:}} +

{{=T('Traceback')}}

+
+    {{=tb}}
+  
+ {{pass}} {{if table:}} {{=A(str(T('New Record')),_href=URL('insert',args=[request.args[0],table]),_class="btn")}}

{{=T("Rows in Table")}}


diff --git a/applications/examples/controllers/appadmin.py b/applications/examples/controllers/appadmin.py index fa264bae..b37afc70 100644 --- a/applications/examples/controllers/appadmin.py +++ b/applications/examples/controllers/appadmin.py @@ -207,6 +207,7 @@ def select(): if match: table = match.group('table') try: + tb = None nrows = db(query).count() if form.vars.update_check and form.vars.update_fields: db(query).update(**eval_in_global_env('dict(%s)' @@ -221,6 +222,8 @@ def select(): else: rows = db(query,ignore_common_filters=True).select(limitby=(start, stop)) except Exception, e: + import traceback + tb = traceback.format_exc() (rows, nrows) = ([], 0) response.flash = DIV(T('Invalid Query'),PRE(str(e))) # begin handle upload csv @@ -250,6 +253,7 @@ def select(): rows=rows, query=request.vars.query, formcsv = formcsv, + tb = tb, ) diff --git a/applications/examples/views/appadmin.html b/applications/examples/views/appadmin.html index 72dfc00c..6a933679 100644 --- a/applications/examples/views/appadmin.html +++ b/applications/examples/views/appadmin.html @@ -44,6 +44,12 @@ {{elif request.function=='select':}}

{{=XML(str(T("Database %s select"))%A(request.args[0],_href=URL('index'))) }}

+ {{if tb:}} +

{{=T('Traceback')}}

+
+    {{=tb}}
+  
+ {{pass}} {{if table:}} {{=A(str(T('New Record')),_href=URL('insert',args=[request.args[0],table]),_class="btn")}}

{{=T("Rows in Table")}}


diff --git a/applications/welcome/controllers/appadmin.py b/applications/welcome/controllers/appadmin.py index fa264bae..b37afc70 100644 --- a/applications/welcome/controllers/appadmin.py +++ b/applications/welcome/controllers/appadmin.py @@ -207,6 +207,7 @@ def select(): if match: table = match.group('table') try: + tb = None nrows = db(query).count() if form.vars.update_check and form.vars.update_fields: db(query).update(**eval_in_global_env('dict(%s)' @@ -221,6 +222,8 @@ def select(): else: rows = db(query,ignore_common_filters=True).select(limitby=(start, stop)) except Exception, e: + import traceback + tb = traceback.format_exc() (rows, nrows) = ([], 0) response.flash = DIV(T('Invalid Query'),PRE(str(e))) # begin handle upload csv @@ -250,6 +253,7 @@ def select(): rows=rows, query=request.vars.query, formcsv = formcsv, + tb = tb, ) diff --git a/applications/welcome/views/appadmin.html b/applications/welcome/views/appadmin.html index 72dfc00c..6a933679 100644 --- a/applications/welcome/views/appadmin.html +++ b/applications/welcome/views/appadmin.html @@ -44,6 +44,12 @@ {{elif request.function=='select':}}

{{=XML(str(T("Database %s select"))%A(request.args[0],_href=URL('index'))) }}

+ {{if tb:}} +

{{=T('Traceback')}}

+
+    {{=tb}}
+  
+ {{pass}} {{if table:}} {{=A(str(T('New Record')),_href=URL('insert',args=[request.args[0],table]),_class="btn")}}

{{=T("Rows in Table")}}


From 96247eda51756bf224b7f20220162a773f70cf3a Mon Sep 17 00:00:00 2001 From: Massimo Date: Wed, 3 Oct 2012 11:58:50 -0500 Subject: [PATCH 09/10] fixed some problem with grid --- VERSION | 2 +- gluon/sqlhtml.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/VERSION b/VERSION index 2a886d26..3a85b362 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Version 2.0.9 (2012-10-03 11:53:40) dev +Version 2.0.9 (2012-10-03 11:58:23) dev diff --git a/gluon/sqlhtml.py b/gluon/sqlhtml.py index 47b3c823..59cb6f6a 100644 --- a/gluon/sqlhtml.py +++ b/gluon/sqlhtml.py @@ -1888,7 +1888,7 @@ class SQLFORM(FORM): rows = dbset.select(cacheable=True) else: rows = dbset.select(left=left,orderby=orderby, - cacheable=True*columns) + cacheable=True,*columns) if export_type in exportManager: value = exportManager[export_type] @@ -2039,7 +2039,7 @@ class SQLFORM(FORM): table_fields = [f for f in fields if f._tablename in tablenames] rows = dbset.select(left=left,orderby=orderby, groupby=groupby,limitby=limitby, - cacheable=True,*table_fields) + *table_fields) except SyntaxError: rows = None error = T("Query Not Supported") From c80a6db604a4abc31e101f6a42429e017daa448e Mon Sep 17 00:00:00 2001 From: Massimo Date: Wed, 3 Oct 2012 12:32:12 -0500 Subject: [PATCH 10/10] better request.requires_https, thanks Yarin and Niphlod --- VERSION | 2 +- gluon/globals.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 3a85b362..a3303341 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Version 2.0.9 (2012-10-03 11:58:23) dev +Version 2.0.9 (2012-10-03 12:32:01) dev diff --git a/gluon/globals.py b/gluon/globals.py index 3d075b8c..8bf69150 100644 --- a/gluon/globals.py +++ b/gluon/globals.py @@ -128,6 +128,7 @@ class Request(Storage): and secure the session. """ if not global_settings.cronjob and not self.is_https: + session.forget() redirect(URL(scheme='https', args=self.args, vars=self.vars)) current.session.secure()