From f0691a64eac284e5241919ef2d62fa358f8e91ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonel=20C=C3=A2mara?= Date: Fri, 1 Aug 2014 15:46:29 +0100 Subject: [PATCH 1/7] typo in a comment --- gluon/dal.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gluon/dal.py b/gluon/dal.py index 2677b723..b9301a44 100644 --- a/gluon/dal.py +++ b/gluon/dal.py @@ -11237,8 +11237,8 @@ class Rows(object): """ returns the data as list of trees. - :param parent_name: the name of the field to holding the reference to - the parent (default parent_id). + :param parent_name: the name of the field holding the reference to the + parent (default parent_id). :param children_name: the name where the children of each row will be stored as a list (default children). :param render: whether we will render the fields using their represent From 444a09b0b265ec7779176bad478a4559140be8b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonel=20C=C3=A2mara?= Date: Sat, 2 Aug 2014 10:52:47 +0100 Subject: [PATCH 2/7] Refactored BaseAdapter delete method - Special case code for sqlite and spatialite should not be in the BaseAdapter it should be in SQLiteAdapter, this should also provide a negligible performance boost in delete operations for most adapters including SQLiteAdapter. --- gluon/dal.py | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/gluon/dal.py b/gluon/dal.py index b9301a44..ab80bcc9 100644 --- a/gluon/dal.py +++ b/gluon/dal.py @@ -1638,24 +1638,11 @@ class BaseAdapter(ConnectionPool): def delete(self, tablename, query): sql = self._delete(tablename, query) - ### special code to handle CASCADE in SQLite & SpatiaLite - db = self.db - table = db[tablename] - if self.dbengine in ('sqlite', 'spatialite') and table._referenced_by: - deleted = [x[table._id.name] for x in db(query).select(table._id)] - ### end special code to handle CASCADE in SQLite & SpatiaLite self.execute(sql) try: counter = self.cursor.rowcount except: counter = None - ### special code to handle CASCADE in SQLite & SpatiaLite - if self.dbengine in ('sqlite', 'spatialite') and counter: - for field in table._referenced_by: - if field.type == 'reference '+table._tablename \ - and field.ondelete == 'CASCADE': - db(field.belongs(deleted)).delete() - ### end special code to handle CASCADE in SQLite & SpatiaLite return counter def get_table(self, query): @@ -2451,6 +2438,27 @@ class SQLiteAdapter(BaseAdapter): return '(%s REGEXP %s)' % (self.expand(first), self.expand(second, 'string')) + def delete(self, tablename, query): + sql = self._delete(tablename, query) + ### Special code to Handle CASCADE in SQLite & SpatiaLite + db = self.db + table = db[tablename] + deleted = [x[table._id.name] for x in db(query).select(table._id)] + ### end special code to handle CASCADE in SQLite & SpatiaLite + self.execute(sql) + try: + counter = self.cursor.rowcount + except: + counter = None + ### special code to handle CASCADE in SQLite & SpatiaLite + if counter: + for field in table._referenced_by: + if field.type == 'reference '+table._tablename \ + and field.ondelete == 'CASCADE': + db(field.belongs(deleted)).delete() + ### end special code to handle CASCADE in SQLite & SpatiaLite + return counter + def select(self, query, fields, attributes): """ Simulate `SELECT ... FOR UPDATE` with `BEGIN IMMEDIATE TRANSACTION`. From b788e8b493f0b700438f212ad46be6a3fde767be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonel=20C=C3=A2mara?= Date: Sat, 2 Aug 2014 10:57:02 +0100 Subject: [PATCH 3/7] minor - Slight optimization use tablename directly instead of table._tablename --- gluon/dal.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gluon/dal.py b/gluon/dal.py index ab80bcc9..f1eb604d 100644 --- a/gluon/dal.py +++ b/gluon/dal.py @@ -2453,7 +2453,7 @@ class SQLiteAdapter(BaseAdapter): ### special code to handle CASCADE in SQLite & SpatiaLite if counter: for field in table._referenced_by: - if field.type == 'reference '+table._tablename \ + if field.type == 'reference '+ tablename \ and field.ondelete == 'CASCADE': db(field.belongs(deleted)).delete() ### end special code to handle CASCADE in SQLite & SpatiaLite From 5c0693b175a6cdd0697c6810dec50730219df28d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonel=20C=C3=A2mara?= Date: Tue, 5 Aug 2014 10:53:40 +0100 Subject: [PATCH 4/7] Further refactored SQLiteAdapter calling the super method instead of duplicating the code --- gluon/dal.py | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/gluon/dal.py b/gluon/dal.py index f1eb604d..3a4fcee4 100644 --- a/gluon/dal.py +++ b/gluon/dal.py @@ -2439,24 +2439,19 @@ class SQLiteAdapter(BaseAdapter): self.expand(second, 'string')) def delete(self, tablename, query): - sql = self._delete(tablename, query) - ### Special code to Handle CASCADE in SQLite & SpatiaLite + # SQLite requires its own delete to handle CASCADE db = self.db table = db[tablename] deleted = [x[table._id.name] for x in db(query).select(table._id)] - ### end special code to handle CASCADE in SQLite & SpatiaLite - self.execute(sql) - try: - counter = self.cursor.rowcount - except: - counter = None - ### special code to handle CASCADE in SQLite & SpatiaLite + + counter = super(SQLiteAdapter, self).delete(tablename, query) + if counter: for field in table._referenced_by: if field.type == 'reference '+ tablename \ and field.ondelete == 'CASCADE': db(field.belongs(deleted)).delete() - ### end special code to handle CASCADE in SQLite & SpatiaLite + return counter def select(self, query, fields, attributes): From 0f55d43a11584b47463b46776c46ba5efd721b45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonel=20C=C3=A2mara?= Date: Tue, 5 Aug 2014 15:37:10 +0100 Subject: [PATCH 5/7] Removed unecessary dict call in get_workers --- gluon/scheduler.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/gluon/scheduler.py b/gluon/scheduler.py index ca48556e..d27e2b8e 100644 --- a/gluon/scheduler.py +++ b/gluon/scheduler.py @@ -1382,8 +1382,8 @@ class Scheduler(MetaScheduler): def get_workers(self, only_ticker=False): """ Returns a dict holding worker_name : {**columns} representing all "registered" workers - only_ticker returns only the worker running as a TICKER, - if there is any + only_ticker returns only the workers running as a TICKER, + if there are any """ db = self.db if only_ticker: @@ -1392,14 +1392,13 @@ class Scheduler(MetaScheduler): workers = db(db.scheduler_worker.id > 0).select() all_workers = {} for row in workers: - all_workers[row.worker_name] = Storage(dict( + all_workers[row.worker_name] = Storage( status=row.status, first_heartbeat=row.first_heartbeat, last_heartbeat=row.last_heartbeat, group_names=row.group_names, is_ticker=row.is_ticker, worker_stats=row.worker_stats - ) ) return all_workers From c9c054e72bc3ed60731d3d48780e209292195974 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonel=20C=C3=A2mara?= Date: Tue, 5 Aug 2014 18:30:20 +0100 Subject: [PATCH 6/7] refactored backward compatibility on formstyles to use try except instead of inspecting arguments, should make the new style faster as it never raises the exception --- gluon/sqlhtml.py | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/gluon/sqlhtml.py b/gluon/sqlhtml.py index cb85158d..fc84e7c6 100644 --- a/gluon/sqlhtml.py +++ b/gluon/sqlhtml.py @@ -35,7 +35,6 @@ import re import cStringIO from gluon.globals import current from gluon.http import redirect -from gluon.utils import get_callable_argspec try: import gluon.settings as settings @@ -1288,9 +1287,13 @@ class SQLFORM(FORM): raise RuntimeError('formstyle not found') if callable(formstyle): - # backward compatibility, 4 argument function is the old style - args, varargs, keywords, defaults = get_callable_argspec(formstyle) - if defaults and len(args) - len(defaults) == 4 or len(args) == 4: + try: + table = formstyle(self, xfields) + for id, a, b, c in xfields: + self.field_parent[id] = getattr(b, 'parent', None) \ + if isinstance(b, XmlComponent) else None + except TypeError: + # backward compatibility, 4 argument function is the old style table = TABLE() for id, a, b, c in xfields: newrows = formstyle(id, a, b, c) @@ -1300,11 +1303,6 @@ class SQLFORM(FORM): newrows = [newrows] for newrow in newrows: table.append(newrow) - else: - table = formstyle(self, xfields) - for id, a, b, c in xfields: - self.field_parent[id] = getattr(b, 'parent', None) \ - if isinstance(b, XmlComponent) else None else: raise RuntimeError('formstyle not supported') return table From 59bbe7cddded745e8b7575aeb97a8d0c7ce63581 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonel=20C=C3=A2mara?= Date: Tue, 5 Aug 2014 18:32:32 +0100 Subject: [PATCH 7/7] minor - removed unnecessary dict calls --- gluon/sqlhtml.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gluon/sqlhtml.py b/gluon/sqlhtml.py index fc84e7c6..3388f1e1 100644 --- a/gluon/sqlhtml.py +++ b/gluon/sqlhtml.py @@ -939,7 +939,7 @@ class SQLFORM(FORM): # - add translatable label for record ID # - add third column to right of fields, populated from the col3 dict - widgets = Storage(dict( + widgets = Storage( string=StringWidget, text=TextWidget, json=JSONWidget, @@ -959,9 +959,9 @@ class SQLFORM(FORM): checkboxes=CheckboxesWidget, autocomplete=AutocompleteWidget, list=ListWidget, - )) + ) - formstyles = Storage(dict( + formstyles = Storage( table3cols=formstyle_table3cols, table2cols=formstyle_table2cols, divs=formstyle_divs, @@ -969,7 +969,7 @@ class SQLFORM(FORM): bootstrap=formstyle_bootstrap, bootstrap3=formstyle_bootstrap3, inline=formstyle_inline, - )) + ) FIELDNAME_REQUEST_DELETE = 'delete_this_record' FIELDKEY_DELETE_RECORD = 'delete_record'