From 5a0ebb7d8c36efec5dcc2c9182cfc9056993f0dd Mon Sep 17 00:00:00 2001 From: mdipierro Date: Sun, 14 Oct 2012 14:16:43 -0500 Subject: [PATCH 1/9] faster better web2py_uuid, thanks Michele --- VERSION | 2 +- gluon/utils.py | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/VERSION b/VERSION index 35d8d2f4..15e51e7f 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Version 2.1.0 (2012-10-13 14:36:14) dev +Version 2.1.0 (2012-10-14 14:16:37) dev diff --git a/gluon/utils.py b/gluon/utils.py index e10fb7a4..13314c5e 100644 --- a/gluon/utils.py +++ b/gluon/utils.py @@ -161,8 +161,7 @@ def web2py_uuid(ctokens=UNPACKED_CTOKENS): It works like uuid.uuid4 except that tries to use os.urandom() if possible and it XORs the output with the tokens uniquely associated with this machine. """ - rand_longs = struct.unpack('=QQ', string.join( - (chr(random.randrange(256)) for i in xrange(16)),'')) + rand_longs = (random.getrandbits(64),random.getrandbits(64)) if HAVE_URANDOM: urand_longs = struct.unpack('=QQ', fast_urandom16()) byte_s = struct.pack('=QQ', From 648cb296e6cbc063ae8ea53f243c8f91943481ef Mon Sep 17 00:00:00 2001 From: mdipierro Date: Sun, 14 Oct 2012 14:20:12 -0500 Subject: [PATCH 2/9] bettere errors in custom_import, thanks Michele --- VERSION | 2 +- gluon/custom_import.py | 40 ++++++++++++++++++++++++---------------- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/VERSION b/VERSION index 15e51e7f..42bb24cb 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Version 2.1.0 (2012-10-14 14:16:37) dev +Version 2.1.0 (2012-10-14 14:20:09) dev diff --git a/gluon/custom_import.py b/gluon/custom_import.py index 4ba79f26..b924ae83 100644 --- a/gluon/custom_import.py +++ b/gluon/custom_import.py @@ -9,11 +9,11 @@ import threading import traceback from gluon import current -NAIVE_IMPORTER = __builtin__.__import__ +NATIVE_IMPORTER = __builtin__.__import__ TRACK_CHANGES = False INVALID_MODULES = set(sys.modules.keys()).union(('','gluon','applications','custom_import')) -# backward compatibility API +# backward compatibility API def custom_import_install(): __builtin__.__import__ = custom_importer @@ -22,14 +22,17 @@ def track_changes(track=True): global TRACK_CHANGES TRACK_CHANGES = track -def is_tracking_changes(): +def is_tracking_changes(): return TRACK_CHANGES +class CustomImportException(ImportError): + pass + def custom_importer(name, globals=None, locals=None, fromlist=None, level=-1): """ The web2py custom importer. Like the standard Python importer but it tries to transform import statements as something like - "import applications.app_name.modules.x". + "import applications.app_name.modules.x". If the import failed, fall back on naive_importer """ @@ -37,13 +40,14 @@ def custom_importer(name, globals=None, locals=None, fromlist=None, level=-1): locals = locals or {} fromlist = fromlist or [] - base_importer = TRACK_IMPORTER if TRACK_CHANGES else NAIVE_IMPORTER + base_importer = TRACK_IMPORTER if TRACK_CHANGES else NATIVE_IMPORTER # if not relative and not from applications: if hasattr(current,'request') \ and level<=0 \ and not name.split('.')[0] in INVALID_MODULES \ - and isinstance(globals, dict): + and isinstance(globals, dict): + import_tb = None try: items = current.request.folder.split(os.path.sep) if not items[-1]: items = items[:-1] @@ -52,23 +56,27 @@ def custom_importer(name, globals=None, locals=None, fromlist=None, level=-1): # import like "import x" or "import x.y" result = None for itemname in name.split("."): - new_mod = base_importer( - modules_prefix, globals,locals, [itemname], level) - try: - result = result or new_mod.__dict__[itemname] - except KeyError, e: - raise ImportError, 'Cannot import module %s' % str(e) modules_prefix += "." + itemname + base_importer( + modules_prefix, globals,locals, [], level) return result else: # import like "from x import a, b, ..." pname = modules_prefix + "." + name return base_importer(pname, globals, locals, fromlist, level) except ImportError, e1: - pass # the module does not exist + import_tb = sys.exc_info()[2] + try: + return NATIVE_IMPORTER(name,globals,locals,fromlist,level) + except ImportError, e3: + raise ImportError, e1, import_tb.tb_next # there an import error in the module except Exception, e2: raise e2 # there is an error in the module - return NAIVE_IMPORTER(name,globals,locals,fromlist,level) + finally: + if import_tb: + import_tb = None + + return NATIVE_IMPORTER(name,globals,locals,fromlist,level) class TrackImporter(object): @@ -96,7 +104,7 @@ class TrackImporter(object): # Check the date and reload if needed: self._update_dates(name, globals, locals, fromlist, level) # Try to load the module and update the dates if it works: - result = NAIVE_IMPORTER(name, globals, locals, fromlist, level) + result = NATIVE_IMPORTER(name, globals, locals, fromlist, level) # Module maybe loaded for the 1st time so we need to set the date self._update_dates(name, globals, locals, fromlist, level) return result @@ -152,7 +160,7 @@ class TrackImporter(object): mod_name = module.__name__ del sys.modules[mod_name] # Delete the module # Reload the module: - NAIVE_IMPORTER(mod_name, globals, locals, [], level) + NATIVE_IMPORTER(mod_name, globals, locals, [], level) else: reload(module) self.THREAD_LOCAL._modules_loaded.add(module) From cac9741cb7becb3ec0707055e036ca02eab5e0af Mon Sep 17 00:00:00 2001 From: mdipierro Date: Sun, 14 Oct 2012 14:28:17 -0500 Subject: [PATCH 3/9] wiki preview patch, thanks Niphlod --- VERSION | 2 +- gluon/tools.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/VERSION b/VERSION index 42bb24cb..e5ff8014 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Version 2.1.0 (2012-10-14 14:20:09) dev +Version 2.1.0 (2012-10-14 14:28:13) dev diff --git a/gluon/tools.py b/gluon/tools.py index 03838bcd..49097d6a 100644 --- a/gluon/tools.py +++ b/gluon/tools.py @@ -4789,15 +4789,16 @@ class Wiki(object): $(function() { if (!$('#wiki_page_body').length) return; var pagecontent = $('#wiki_page_body'); + pagecontent.css('font-family', 'Monaco,Menlo,Consolas,"Courier New",monospace'); var prevbutton = $(''); var preview = $('
').hide(); var table = $('form'); prevbutton.insertBefore(table); + preview.insertBefore(table); prevbutton.on('click', function(e) { e.preventDefault(); if (prevbutton.hasClass('nopreview')) { prevbutton.addClass('preview').removeClass('nopreview').html('Edit Source'); - preview.insertBefore(table); web2py_ajax_page('post', '%(url)s', {body : $('#wiki_page_body').val()}, 'preview'); table.fadeOut('medium', function() {preview.fadeIn()}); } else { From e2234a877191b4d09989d8791c406baaa7a4b0ba Mon Sep 17 00:00:00 2001 From: mdipierro Date: Sun, 14 Oct 2012 14:41:28 -0500 Subject: [PATCH 4/9] added storage of length, notnull, unique in .table files --- VERSION | 2 +- gluon/dal.py | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/VERSION b/VERSION index e5ff8014..1ac25a89 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Version 2.1.0 (2012-10-14 14:28:13) dev +Version 2.1.0 (2012-10-14 14:41:24) dev diff --git a/gluon/dal.py b/gluon/dal.py index 27f428f6..702e8c2e 100644 --- a/gluon/dal.py +++ b/gluon/dal.py @@ -835,6 +835,9 @@ class BaseAdapter(ConnectionPool): # add to list of fields sql_fields[field_name] = dict( + length=field.length, + unique=field.unique, + notnull=field.notnull, sortable=sortable, type=str(field_type), sql=ftype) From 39c5341dbc5e435a0de5bf8178ea798b183154e0 Mon Sep 17 00:00:00 2001 From: mdipierro Date: Sun, 14 Oct 2012 14:44:37 -0500 Subject: [PATCH 5/9] auth_wiki extra fields, thanks Alan --- VERSION | 2 +- gluon/tools.py | 13 +++++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/VERSION b/VERSION index 1ac25a89..504ba611 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Version 2.1.0 (2012-10-14 14:41:24) dev +Version 2.1.0 (2012-10-14 14:44:33) dev diff --git a/gluon/tools.py b/gluon/tools.py index 49097d6a..dfbca930 100644 --- a/gluon/tools.py +++ b/gluon/tools.py @@ -4603,7 +4603,7 @@ class Wiki(object): Field('can_edit', 'list:string', writable=perms,readable=perms, default=[Wiki.everybody]), - Field('changelog'), + Field('changelog'), Field('html','text',compute=render, readable=False, writable=False), auth.signature], @@ -4625,8 +4625,17 @@ class Wiki(object): # define only non-existent tables for key, value in table_definitions: + args = [] if not key in db.tables(): - db.define_table(key, *value['args'], **value['vars']) + # look for wiki_ extra fields in auth.settings + extra_fields = auth.settings.extra_fields + if extra_fields: + if key in extra_fields: + if extra_fields[key]: + for field in extra_fields[key]: + args.append(field) + args += value['args'] + db.define_table(key, *args, **value['vars']) def update_tags_insert(page,id,db=db): for tag in page.tags or []: From 6cf05edf63b1db90cd2d728839ca4168ae3f9299 Mon Sep 17 00:00:00 2001 From: mdipierro Date: Sun, 14 Oct 2012 15:08:25 -0500 Subject: [PATCH 6/9] DAL(...,do_connect=False,migrate_enabled=False) --- VERSION | 2 +- gluon/dal.py | 77 ++++++++++++++++++++++++++++------------------------ 2 files changed, 43 insertions(+), 36 deletions(-) diff --git a/VERSION b/VERSION index 504ba611..b253c64f 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Version 2.1.0 (2012-10-14 14:44:33) dev +Version 2.1.0 (2012-10-14 15:08:21) dev diff --git a/gluon/dal.py b/gluon/dal.py index 702e8c2e..3b802192 100644 --- a/gluon/dal.py +++ b/gluon/dal.py @@ -1648,25 +1648,25 @@ class BaseAdapter(ConnectionPool): return list(tables) def commit(self): - return self.connection.commit() + if self.connection: return self.connection.commit() def rollback(self): - return self.connection.rollback() + if self.connection: return self.connection.rollback() def close_connection(self): - return self.connection.close() + if self.connection: return self.connection.close() def distributed_transaction_begin(self, key): return def prepare(self, key): - self.connection.prepare() - + if self.connection: self.connection.prepare() + def commit_prepared(self, key): - self.connection.commit() + if self.connection: self.connection.commit() def rollback_prepared(self, key): - self.connection.rollback() + if self.connection: self.connection.rollback() def concat_add(self, table): return ', ADD ' @@ -1678,6 +1678,7 @@ class BaseAdapter(ConnectionPool): self.execute(query) def log_execute(self, *a, **b): + if not self.connection: return None command = a[0] if self.db._debug: LOGGER.debug('SQL: %s' % command) @@ -2074,7 +2075,7 @@ class SQLiteAdapter(BaseAdapter): self.db = db self.dbengine = "sqlite" self.uri = uri - self.find_driver(adapter_args) + if do_connect: self.find_driver(adapter_args) self.pool_size = 0 self.folder = folder self.db_codec = db_codec @@ -2133,11 +2134,11 @@ class SpatiaLiteAdapter(SQLiteAdapter): def __init__(self, db, uri, pool_size=0, folder=None, db_codec ='UTF-8', credential_decoder=IDENTITY, driver_args={}, - adapter_args={}, srid=4326): + adapter_args={}, do_connect=True, srid=4326): self.db = db self.dbengine = "spatialite" self.uri = uri - self.find_driver(adapter_args) + if do_connect: self.find_driver(adapter_args) self.pool_size = 0 self.folder = folder self.db_codec = db_codec @@ -2242,7 +2243,7 @@ class JDBCSQLiteAdapter(SQLiteAdapter): self.db = db self.dbengine = "sqlite" self.uri = uri - self.find_driver(adapter_args) + if do_connect: self.find_driver(adapter_args) self.pool_size = pool_size self.folder = folder self.db_codec = db_codec @@ -2344,7 +2345,7 @@ class MySQLAdapter(BaseAdapter): self.db = db self.dbengine = "mysql" self.uri = uri - self.find_driver(adapter_args,uri) + if do_connect: self.find_driver(adapter_args,uri) self.pool_size = pool_size self.folder = folder self.db_codec = db_codec @@ -2470,7 +2471,7 @@ class PostgreSQLAdapter(BaseAdapter): self.db = db self.dbengine = "postgres" self.uri = uri - self.find_driver(adapter_args,uri) + if do_connect: self.find_driver(adapter_args,uri) self.pool_size = pool_size self.folder = folder self.db_codec = db_codec @@ -2696,7 +2697,7 @@ class JDBCPostgreSQLAdapter(PostgreSQLAdapter): self.db = db self.dbengine = "postgres" self.uri = uri - self.find_driver(adapter_args,uri) + if do_connect: self.find_driver(adapter_args,uri) self.pool_size = pool_size self.folder = folder self.db_codec = db_codec @@ -2821,7 +2822,7 @@ class OracleAdapter(BaseAdapter): self.db = db self.dbengine = "oracle" self.uri = uri - self.find_driver(adapter_args,uri) + if do_connect: self.find_driver(adapter_args,uri) self.pool_size = pool_size self.folder = folder self.db_codec = db_codec @@ -2977,7 +2978,7 @@ class MSSQLAdapter(BaseAdapter): self.db = db self.dbengine = "mssql" self.uri = uri - self.find_driver(adapter_args,uri) + if do_connect: self.find_driver(adapter_args,uri) self.pool_size = pool_size self.folder = folder self.db_codec = db_codec @@ -3174,7 +3175,7 @@ class SybaseAdapter(MSSQLAdapter): self.db = db self.dbengine = "sybase" self.uri = uri - self.find_driver(adapter_args,uri) + if do_connect: self.find_driver(adapter_args,uri) self.pool_size = pool_size self.folder = folder self.db_codec = db_codec @@ -3304,7 +3305,7 @@ class FireBirdAdapter(BaseAdapter): self.db = db self.dbengine = "firebird" self.uri = uri - self.find_driver(adapter_args,uri) + if do_connect: self.find_driver(adapter_args,uri) self.pool_size = pool_size self.folder = folder self.db_codec = db_codec @@ -3363,7 +3364,7 @@ class FireBirdEmbeddedAdapter(FireBirdAdapter): self.db = db self.dbengine = "firebird" self.uri = uri - self.find_driver(adapter_args,uri) + if do_connect: self.find_driver(adapter_args,uri) self.pool_size = pool_size self.folder = folder self.db_codec = db_codec @@ -3470,7 +3471,7 @@ class InformixAdapter(BaseAdapter): self.db = db self.dbengine = "informix" self.uri = uri - self.find_driver(adapter_args,uri) + if do_connect: self.find_driver(adapter_args,uri) self.pool_size = pool_size self.folder = folder self.db_codec = db_codec @@ -3572,7 +3573,7 @@ class DB2Adapter(BaseAdapter): self.db = db self.dbengine = "db2" self.uri = uri - self.find_driver(adapter_args,uri) + if do_connect: self.find_driver(adapter_args,uri) self.pool_size = pool_size self.folder = folder self.db_codec = db_codec @@ -3635,7 +3636,7 @@ class TeradataAdapter(BaseAdapter): self.db = db self.dbengine = "teradata" self.uri = uri - self.find_driver(adapter_args,uri) + if do_connect: self.find_driver(adapter_args,uri) self.pool_size = pool_size self.folder = folder self.db_codec = db_codec @@ -3716,7 +3717,7 @@ class IngresAdapter(BaseAdapter): self.db = db self.dbengine = "ingres" self.uri = uri - self.find_driver(adapter_args,uri) + if do_connect: self.find_driver(adapter_args,uri) self.pool_size = pool_size self.folder = folder self.db_codec = db_codec @@ -3852,7 +3853,7 @@ class SAPDBAdapter(BaseAdapter): self.db = db self.dbengine = "sapdb" self.uri = uri - self.find_driver(adapter_args,uri) + if do_connect: self.find_driver(adapter_args,uri) self.pool_size = pool_size self.folder = folder self.db_codec = db_codec @@ -3895,7 +3896,7 @@ class CubridAdapter(MySQLAdapter): self.db = db self.dbengine = "cubrid" self.uri = uri - self.find_driver(adapter_args,uri) + if do_connect: self.find_driver(adapter_args,uri) self.pool_size = pool_size self.folder = folder self.db_codec = db_codec @@ -4700,7 +4701,7 @@ class CouchDBAdapter(NoSQLAdapter): adapter_args={}, do_connect=True): self.db = db self.uri = uri - self.find_driver(adapter_args) + if do_connect: self.find_driver(adapter_args) self.dbengine = 'couchdb' self.folder = folder db['_lastsql'] = '' @@ -4861,7 +4862,7 @@ class MongoDBAdapter(NoSQLAdapter): adapter_args={}, do_connect=True): self.db = db self.uri = uri - self.find_driver(adapter_args) + if do_connect: self.find_driver(adapter_args) m=None try: @@ -5468,7 +5469,7 @@ class IMAPAdapter(NoSQLAdapter): self.db = db self.uri = uri - self.find_driver(adapter_args) + if do_connect: self.find_driver(adapter_args) self.pool_size=pool_size self.folder = folder self.db_codec = db_codec @@ -6676,7 +6677,7 @@ class DAL(object): decode_credentials=False, driver_args=None, adapter_args=None, attempts=5, auto_import=False, bigint_id=False,debug=False,lazy_tables=False, - db_uid=None): + db_uid=None, do_connect=True): """ Creates a new Database Abstraction Layer instance. @@ -6742,10 +6743,15 @@ class DAL(object): raise SyntaxError, "Error in URI '%s' or database not supported" % self._dbname # notice that driver args or {} else driver_args # defaults to {} global, not correct - args = (self,uri,pool_size,folder, - db_codec, credential_decoder, - driver_args or {}, adapter_args or {}) - self._adapter = ADAPTERS[self._dbname](*args) + kwargs = dict(db=self,uri=uri, + pool_size=pool_size, + folder=folder, + db_codec=db_codec, + credential_decoder=credential_decoder, + driver_args=driver_args or {}, + adapter_args=adapter_args or {}, + do_connect=do_connect) + self._adapter = ADAPTERS[self._dbname](**kwargs) if bigint_id: types = ADAPTERS[self._dbname].types self._adapter.types = copy.copy(types) # copy so multiple DAL() possible @@ -6766,8 +6772,9 @@ class DAL(object): if not connected: raise RuntimeError, "Failure to connect, tried %d times:\n%s" % (attempts, tb) else: - args = (self,'None',0,folder,db_codec) - self._adapter = BaseAdapter(*args) + self._adapter = BaseAdapter(db=self,pool_size=0, + uri='None',folder=folder, + db_codec=db_codec) migrate = fake_migrate = False adapter = self._adapter self._uri_hash = hashlib.md5(adapter.uri).hexdigest() From 71ec500fde099290fb61c355942fe77fc54e14b9 Mon Sep 17 00:00:00 2001 From: mdipierro Date: Sun, 14 Oct 2012 15:32:33 -0500 Subject: [PATCH 7/9] changed default driver for sqlite, thanks Niphlod --- VERSION | 2 +- gluon/dal.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/VERSION b/VERSION index b253c64f..160c221c 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Version 2.1.0 (2012-10-14 15:08:21) dev +Version 2.1.0 (2012-10-14 15:32:29) dev diff --git a/gluon/dal.py b/gluon/dal.py index 3b802192..a0c38767 100644 --- a/gluon/dal.py +++ b/gluon/dal.py @@ -2039,7 +2039,7 @@ class BaseAdapter(ConnectionPool): ################################################################################### class SQLiteAdapter(BaseAdapter): - drivers = ('sqlite3','sqlite2') + drivers = ('sqlite2','sqlite3') can_select_for_update = None # support ourselves with BEGIN TRANSACTION From c6b5ad817943ffb8038e170138d31859476ec68d Mon Sep 17 00:00:00 2001 From: mdipierro Date: Sun, 14 Oct 2012 15:55:45 -0500 Subject: [PATCH 8/9] auth = Auth(db).define_tables() in one line --- VERSION | 2 +- gluon/tools.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 160c221c..513a6ef6 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Version 2.1.0 (2012-10-14 15:32:29) dev +Version 2.1.0 (2012-10-14 15:55:41) dev diff --git a/gluon/tools.py b/gluon/tools.py index dfbca930..8023171b 100644 --- a/gluon/tools.py +++ b/gluon/tools.py @@ -1627,6 +1627,7 @@ class Auth(object): urlbase = settings.cas_provider, actions=actions, maps=maps) + return self def log_event(self, description, vars=None, origin='auth'): """ From df7d6847e626f3a9762fc2ed315de1f212e84e51 Mon Sep 17 00:00:00 2001 From: mdipierro Date: Sun, 14 Oct 2012 16:40:49 -0500 Subject: [PATCH 9/9] fixed issue 1088 --- VERSION | 2 +- gluon/dal.py | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/VERSION b/VERSION index 513a6ef6..968fa96d 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Version 2.1.0 (2012-10-14 15:55:41) dev +Version 2.1.0 (2012-10-14 16:40:34) dev diff --git a/gluon/dal.py b/gluon/dal.py index a0c38767..31e068c6 100644 --- a/gluon/dal.py +++ b/gluon/dal.py @@ -6801,7 +6801,12 @@ class DAL(object): try: sql_fields = cPickle.load(tfile) name = filename[len(pattern)-7:-6] - mf = [(value['sortable'],Field(key,type=value['type'])) \ + mf = [(value['sortable'], + Field(key, + type=value['type'], + length=value.get('length',None), + notnull=value.get('notnull',False), + unique=value.get('unique',False))) \ for key, value in sql_fields.iteritems()] mf.sort(lambda a,b: cmp(a[0],b[0])) self.define_table(name,*[item[1] for item in mf],