From dc0f5f5821ce62713a653da05c4df341b7e2d252 Mon Sep 17 00:00:00 2001 From: Massimo DiPierro Date: Wed, 16 May 2012 16:45:10 -0500 Subject: [PATCH 01/16] Sybase Adapter --- VERSION | 2 +- gluon/dal.py | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 5132036b..15d23283 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Version 2.00.0 (2012-05-16 11:15:52) dev +Version 2.00.0 (2012-05-16 16:45:06) dev diff --git a/gluon/dal.py b/gluon/dal.py index 1ed4b799..797c593f 100644 --- a/gluon/dal.py +++ b/gluon/dal.py @@ -283,6 +283,12 @@ if not 'google' in drivers: except ImportError: logger.debug('no MSSQL/DB2/Teradata driver') + try: + import Sybase + drivers.append('Sybase') + except ImportError: + logger.debug('no Sybase driver') + try: import kinterbasdb drivers.append('Interbase') @@ -2747,6 +2753,101 @@ class MSSQL2Adapter(MSSQLAdapter): def execute(self,a): return self.log_execute(a.decode('utf8')) +class SybaseAdapter(MSSQLAdapter): + + driver = globals().get('Sybase',None) + + types = { + 'boolean': 'BIT', + 'string': 'CHAR VARYING(%(length)s)', + 'text': 'TEXT', + 'password': 'CHAR VARYING(%(length)s)', + 'blob': 'IMAGE', + 'upload': 'CHAR VARYING(%(length)s)', + 'integer': 'INT', + 'bigint': 'BIGINT', + 'float': 'FLOAT', + 'double': 'FLOAT', + 'decimal': 'NUMERIC(%(precision)s,%(scale)s)', + 'date': 'DATETIME', + 'time': 'CHAR(8)', + 'datetime': 'DATETIME', + 'id': 'INT IDENTITY PRIMARY KEY', + 'reference': 'INT NULL, CONSTRAINT %(constraint_name)s FOREIGN KEY (%(field_name)s) REFERENCES %(foreign_key)s ON DELETE %(on_delete_action)s', + 'list:integer': 'TEXT', + 'list:string': 'TEXT', + 'list:reference': 'TEXT', + 'geometry': 'geometry', + 'geography': 'geography', + 'big-id': 'BIGINT IDENTITY PRIMARY KEY', + 'big-reference': 'BIGINT NULL, CONSTRAINT %(constraint_name)s FOREIGN KEY (%(field_name)s) REFERENCES %(foreign_key)s ON DELETE %(on_delete_action)s', + 'reference FK': ', CONSTRAINT FK_%(constraint_name)s FOREIGN KEY (%(field_name)s) REFERENCES %(foreign_key)s ON DELETE %(on_delete_action)s', + 'reference TFK': ' CONSTRAINT FK_%(foreign_table)s_PK FOREIGN KEY (%(field_name)s) REFERENCES %(foreign_table)s (%(foreign_key)s) ON DELETE %(on_delete_action)s', + } + + + def __init__(self,db,uri,pool_size=0,folder=None,db_codec ='UTF-8', + credential_decoder=lambda x:x, driver_args={}, + adapter_args={}, fake_connect=False, srid=4326): + ### Fix this for sybase + if not self.driver: + raise RuntimeError, "Unable to import driver" + self.db = db + self.dbengine = "sybase" + self.uri = uri + self.pool_size = pool_size + self.folder = folder + self.db_codec = db_codec + self.srid = srid + self.find_or_make_work_folder() + # ## read: http://bytes.com/groups/python/460325-cx_oracle-utf8 + uri = uri.split('://')[1] + if '@' not in uri: + try: + m = re.compile('^(?P.+)$').match(uri) + if not m: + raise SyntaxError, \ + 'Parsing uri string(%s) has no result' % self.uri + dsn = m.group('dsn') + if not dsn: + raise SyntaxError, 'DSN required' + except SyntaxError, e: + logger.error('NdGpatch error') + raise e + else: + m = re.compile('^(?P[^:@]+)(\:(?P[^@]*))?@(?P[^\:/]+)(\:(?P[0-9]+))?/(?P[^\?]+)(\?(?P.*))?$').match(uri) + if not m: + raise SyntaxError, \ + "Invalid URI string in DAL: %s" % uri + user = credential_decoder(m.group('user')) + if not user: + raise SyntaxError, 'User required' + password = credential_decoder(m.group('password')) + if not password: + password = '' + host = m.group('host') + if not host: + raise SyntaxError, 'Host name required' + db = m.group('db') + if not db: + raise SyntaxError, 'Database name required' + port = m.group('port') or '1433' + + dsn = 'sybase:host=%s:%s;dbname=%s' % (host,port,db) + + driver_args.update(dict(user = credential_decoder(user), + password = credential_decoder(password), + locale = charset)) + + def connect(dsn=dsn,driver_args=driver_args): + return self.driver.connect(dsn,**driver_args) + if not fake_connect: + self.pool_connection(connect) + self.after_connection() + + def integrity_error_class(self): + return RuntimeError # FIX THIS + class FireBirdAdapter(BaseAdapter): @@ -5760,6 +5861,7 @@ ADAPTERS = { 'oracle': OracleAdapter, 'mssql': MSSQLAdapter, 'mssql2': MSSQL2Adapter, + 'sybase': SybaseAdapter, 'db2': DB2Adapter, 'teradata': TeradataAdapter, 'informix': InformixAdapter, From 0be064442439a7ed2f01e69d447c2865a2b37191 Mon Sep 17 00:00:00 2001 From: Massimo DiPierro Date: Wed, 16 May 2012 16:52:09 -0500 Subject: [PATCH 02/16] fixed issue 799, thanks hi21alt --- VERSION | 2 +- gluon/dal.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/VERSION b/VERSION index 15d23283..d35eebd7 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Version 2.00.0 (2012-05-16 16:45:06) dev +Version 2.00.0 (2012-05-16 16:52:05) dev diff --git a/gluon/dal.py b/gluon/dal.py index 797c593f..354384f2 100644 --- a/gluon/dal.py +++ b/gluon/dal.py @@ -6164,7 +6164,8 @@ def smart_query(fields,text): value = constants[item[1:]] else: value = item - if op == '=': op = 'like' + if field.type in ('text','string'): + if op == '=': op = 'like' if op == '=': new_query = field==value elif op == '<': new_query = field': new_query = field>value From a2cc167d6857d5ff684cc361bdf35ab587673953 Mon Sep 17 00:00:00 2001 From: Massimo DiPierro Date: Wed, 16 May 2012 18:23:18 -0500 Subject: [PATCH 03/16] disabled copied of logging.conf again, problem with python 2.5 --- VERSION | 2 +- gluon/widget.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/VERSION b/VERSION index d35eebd7..54906232 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Version 2.00.0 (2012-05-16 16:52:05) dev +Version 2.00.0 (2012-05-16 18:23:15) dev diff --git a/gluon/widget.py b/gluon/widget.py index 2cab034e..8542b056 100644 --- a/gluon/widget.py +++ b/gluon/widget.py @@ -896,7 +896,7 @@ def start(cron=True): if hasattr(options,key): setattr(options,key,getattr(options2,key)) - if not os.path.exists('logging.conf') and \ + if False and not os.path.exists('logging.conf') and \ os.path.exists('logging.example.conf'): import shutil sys.stdout.write("Copying logging.conf.example to logging.conf ... ") From 92d4aa33625bb5761b7abdd8c47e72711941c948 Mon Sep 17 00:00:00 2001 From: Massimo Di Pierro Date: Thu, 17 May 2012 09:55:50 -0500 Subject: [PATCH 04/16] no more class='' but class=None, thanks Jonathan --- VERSION | 2 +- gluon/sqlhtml.py | 32 ++++++++++++++++---------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/VERSION b/VERSION index 54906232..8ef9b363 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Version 2.00.0 (2012-05-16 18:23:15) dev +Version 2.00.0 (2012-05-17 09:55:01) dev diff --git a/gluon/sqlhtml.py b/gluon/sqlhtml.py index 55fd6f7e..981f0167 100644 --- a/gluon/sqlhtml.py +++ b/gluon/sqlhtml.py @@ -1546,27 +1546,27 @@ class SQLFORM(FORM): buttonurl=url(args=[]),callback=None,delete=None,trap=True): if showbuttontext: if callback: - return A(SPAN(_class=ui.get(buttonclass,'')), + return A(SPAN(_class=ui.get(buttonclass)), SPAN(T(buttontext),_title=buttontext, - _class=ui.get('buttontext','')), + _class=ui.get('buttontext')), callback=callback,delete=delete, - _class=trap_class(ui.get('button',''),trap)) + _class=trap_class(ui.get('button'),trap)) else: - return A(SPAN(_class=ui.get(buttonclass,'')), + return A(SPAN(_class=ui.get(buttonclass)), SPAN(T(buttontext),_title=buttontext, - _class=ui.get('buttontext','')), + _class=ui.get('buttontext')), _href=buttonurl, - _class=trap_class(ui.get('button',''),trap)) + _class=trap_class(ui.get('button'),trap)) else: if callback: - return A(SPAN(_class=ui.get(buttonclass,'')), + return A(SPAN(_class=ui.get(buttonclass)), callback=callback,delete=delete, _title=buttontext, - _class=trap_class(ui.get('buttontext',''),trap)) + _class=trap_class(ui.get('buttontext'),trap)) else: - return A(SPAN(_class=ui.get(buttonclass,'')), + return A(SPAN(_class=ui.get(buttonclass)), _href=buttonurl,_title=buttontext, - _class=trap_class(ui.get('buttontext',''),trap)) + _class=trap_class(ui.get('buttontext'),trap)) dbset = db(query) tablenames = db._adapter.tables(dbset.query) if left!=None: tablenames+=db._adapter.tables(left) @@ -1772,9 +1772,9 @@ class SQLFORM(FORM): else: orderby = (order[:1]=='~' and ~sort_field) or sort_field - head = TR(_class=ui.get('header','')) + head = TR(_class=ui.get('header')) if selectable: - head.append(TH(_class=ui.get('default',''))) + head.append(TH(_class=ui.get('default'))) for field in fields: if columns and not str(field) in columns: continue if not field.readable: continue @@ -1791,19 +1791,19 @@ class SQLFORM(FORM): header = A(header,marker,_href=url(vars=dict( keywords=request.vars.keywords or '', order=key)),_class=trap_class()) - head.append(TH(header, _class=ui.get('default',''))) + head.append(TH(header, _class=ui.get('default'))) if links and links_in_grid: for link in links: if isinstance(link,dict): - head.append(TH(link['header'], _class=ui.get('default',''))) + head.append(TH(link['header'], _class=ui.get('default'))) # Include extra column for buttons if needed. include_buttons_column = (details or editable or deletable or (links and links_in_grid and not all([isinstance(link, dict) for link in links]))) if include_buttons_column: - head.append(TH(_class=ui.get('default',''))) + head.append(TH(_class=ui.get('default'))) paginator = UL() if paginate and paginate Date: Thu, 17 May 2012 10:54:17 -0500 Subject: [PATCH 05/16] mail.settings.login can be None,False,0,'' --- VERSION | 2 +- gluon/tools.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/VERSION b/VERSION index 8ef9b363..98aed456 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Version 2.00.0 (2012-05-17 09:55:01) dev +Version 2.00.0 (2012-05-17 10:53:49) dev diff --git a/gluon/tools.py b/gluon/tools.py index 4d8c4188..6cd652bd 100644 --- a/gluon/tools.py +++ b/gluon/tools.py @@ -646,7 +646,7 @@ class Mail(object): server.ehlo() server.starttls() server.ehlo() - if not self.settings.login is None: + if not self.settings.login: server.login(*self.settings.login.split(':',1)) result = server.sendmail(self.settings.sender, to, payload.as_string()) server.quit() From 05ee1e90cacf37026e5188694c51d84ca81975b9 Mon Sep 17 00:00:00 2001 From: Massimo Di Pierro Date: Thu, 17 May 2012 15:56:19 -0500 Subject: [PATCH 06/16] get or create key now defaults to sha512 asn should have all along, thanks Harkirat --- VERSION | 2 +- gluon/tools.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/VERSION b/VERSION index 98aed456..75b1b7cd 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Version 2.00.0 (2012-05-17 10:53:49) dev +Version 2.00.0 (2012-05-17 15:55:39) dev diff --git a/gluon/tools.py b/gluon/tools.py index 6cd652bd..153300a1 100644 --- a/gluon/tools.py +++ b/gluon/tools.py @@ -861,14 +861,14 @@ class Auth(object): """ @staticmethod - def get_or_create_key(filename=None): + def get_or_create_key(filename=None, alg='sha512'): request = current.request if not filename: filename = os.path.join(request.folder,'private','auth.key') if os.path.exists(filename): key = open(filename,'r').read().strip() else: - key = web2py_uuid() + key = alg+web2py_uuid() open(filename,'w').write(key) return key From b6a415a37c5c05dcb737b990662fd879713316ee Mon Sep 17 00:00:00 2001 From: Massimo Di Pierro Date: Thu, 17 May 2012 17:52:27 -0500 Subject: [PATCH 07/16] fixed bug in last commit, thanks Harkirat --- VERSION | 2 +- gluon/tools.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/VERSION b/VERSION index 75b1b7cd..8abd600f 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Version 2.00.0 (2012-05-17 15:55:39) dev +Version 2.00.0 (2012-05-17 17:51:51) dev diff --git a/gluon/tools.py b/gluon/tools.py index 153300a1..e746c393 100644 --- a/gluon/tools.py +++ b/gluon/tools.py @@ -868,7 +868,7 @@ class Auth(object): if os.path.exists(filename): key = open(filename,'r').read().strip() else: - key = alg+web2py_uuid() + key = alg+':'+web2py_uuid() open(filename,'w').write(key) return key From 2d48af247d9e0b0423881cde27e44becbef71b67 Mon Sep 17 00:00:00 2001 From: Massimo Di Pierro Date: Thu, 17 May 2012 18:14:19 -0500 Subject: [PATCH 08/16] db.table.field.avg(), issue 803, thanks Ato --- VERSION | 2 +- gluon/dal.py | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 8abd600f..77c5d028 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Version 2.00.0 (2012-05-17 17:51:51) dev +Version 2.00.0 (2012-05-17 18:13:53) dev diff --git a/gluon/dal.py b/gluon/dal.py index 354384f2..9023cc88 100644 --- a/gluon/dal.py +++ b/gluon/dal.py @@ -7479,6 +7479,9 @@ class Expression(object): def len(self): return Expression(self.db, self.db._adapter.AGGREGATE, self, 'LENGTH', 'integer') + def avg(self): + return Expression(self.db, self.db._adapter.AGGREGATE, self, 'AVG', self.type) + def lower(self): return Expression(self.db, self.db._adapter.LOWER, self, None, self.type) From 6775f89c2ed5038fd57f83f143154e78acd45e2f Mon Sep 17 00:00:00 2001 From: Massimo DiPierro Date: Sat, 19 May 2012 10:07:56 -0500 Subject: [PATCH 09/16] fixed logging issue (807), thanks Marc --- VERSION | 2 +- gluon/main.py | 7 +++++++ gluon/rewrite.py | 5 ++++- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/VERSION b/VERSION index 77c5d028..23782032 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Version 2.00.0 (2012-05-17 18:13:53) dev +Version 2.00.0 (2012-05-19 10:07:52) dev diff --git a/gluon/main.py b/gluon/main.py index 57bf6476..2f69c6ba 100644 --- a/gluon/main.py +++ b/gluon/main.py @@ -68,6 +68,13 @@ create_missing_folders() # set up logging for subsequent imports import logging import logging.config + +# This needed to prevent exception on Python 2.5: +# NameError: name 'gluon' is not defined +# See http://bugs.python.org/issue1436 +import gluon.messageboxhandler +logging.gluon = gluon + logpath = abspath("logging.conf") if os.path.exists(logpath): logging.config.fileConfig(abspath("logging.conf")) diff --git a/gluon/rewrite.py b/gluon/rewrite.py index 1e76acbb..b6ee5f6a 100644 --- a/gluon/rewrite.py +++ b/gluon/rewrite.py @@ -1016,13 +1016,16 @@ class MapUrlIn(object): self.request.args = self.args if self.language: self.request.uri_language = self.language - uri = '/%s/%s/%s' % (self.application, self.controller, self.function) + uri = '/%s/%s' % (self.controller, self.function) + app = self.application if self.map_hyphen: uri = uri.replace('_', '-') + app = app.replace('_', '-') if self.extension != 'html': uri += '.' + self.extension if self.language: uri = '/%s%s' % (self.language, uri) + uri = '/%s%s' % (app, uri) uri += self.args and urllib.quote('/' + '/'.join([str(x) for x in self.args])) or '' uri += (self.query and ('?' + self.query) or '') self.env['REQUEST_URI'] = uri From 6d70560c69f6a7df5839c715e4d5b0010d268e8f Mon Sep 17 00:00:00 2001 From: Massimo DiPierro Date: Sat, 19 May 2012 10:09:38 -0500 Subject: [PATCH 10/16] use applescript to force slash screen on to, thanks Marc --- VERSION | 2 +- gluon/widget.py | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 23782032..8e3f204b 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Version 2.00.0 (2012-05-19 10:07:52) dev +Version 2.00.0 (2012-05-19 10:09:36) dev diff --git a/gluon/widget.py b/gluon/widget.py index 8542b056..185a1af6 100644 --- a/gluon/widget.py +++ b/gluon/widget.py @@ -983,6 +983,17 @@ def start(cron=True): if root: root.focus_force() + + # Mac OS X - make the GUI window rise to the top + if os.path.exists("/usr/bin/osascript"): + applescript = """ +tell application "System Events" + set proc to first process whose unix id is %d + set frontmost of proc to true +end tell +""" % (os.getpid()) + os.system("/usr/bin/osascript -e '%s'" % applescript) + if not options.quiet: presentation(root) master = web2pyDialog(root, options) From cb485d320a11e089f26b4d78c391813dd2228e9e Mon Sep 17 00:00:00 2001 From: Massimo DiPierro Date: Sat, 19 May 2012 10:11:55 -0500 Subject: [PATCH 11/16] fixed 5th parameter of menu does not work on mobiles, issue 805, thanks mweissen --- VERSION | 2 +- gluon/html.py | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/VERSION b/VERSION index 8e3f204b..f2cbe091 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Version 2.00.0 (2012-05-19 10:09:36) dev +Version 2.00.0 (2012-05-19 10:11:52) dev diff --git a/gluon/html.py b/gluon/html.py index 4d513e95..a42bd8e1 100644 --- a/gluon/html.py +++ b/gluon/html.py @@ -2150,10 +2150,11 @@ class MENU(DIV): if not select: select = SELECT(**self.attributes) for item in data: - if item[2]: - select.append(OPTION(CAT(prefix, item[0]), _value=item[2], _selected=item[1])) - if len(item)>3 and len(item[3]): - self.serialize_mobile(item[3], select, prefix = CAT(prefix, item[0], '/')) + if len(item) <= 4 or item[4] == True: + if item[2]: + select.append(OPTION(CAT(prefix, item[0]), _value=item[2], _selected=item[1])) + if len(item)>3 and len(item[3]): + self.serialize_mobile(item[3], select, prefix = CAT(prefix, item[0], '/')) select['_onchange'] = 'window.location=this.value' return select From 1173f292fa5570bbab2389188febdbd67b472f0a Mon Sep 17 00:00:00 2001 From: Massimo Di Pierro Date: Sat, 19 May 2012 22:35:12 -0500 Subject: [PATCH 12/16] {{super}} equals '' if no parent --- VERSION | 2 +- gluon/template.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/VERSION b/VERSION index f2cbe091..cf2dc60b 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Version 2.00.0 (2012-05-19 10:11:52) dev +Version 2.00.0 (2012-05-19 22:34:21) dev diff --git a/gluon/template.py b/gluon/template.py index 073f7199..8cdc8706 100644 --- a/gluon/template.py +++ b/gluon/template.py @@ -47,8 +47,8 @@ class SuperNode(Node): if self.value: return str(self.value) else: - raise SyntaxError("Undefined parent block ``%s``. \n" % self.name + \ -"You must define a block before referencing it.\nMake sure you have not left out an ``{{end}}`` tag." ) + # raise SyntaxError("Undefined parent block ``%s``. \n" % self.name + "You must define a block before referencing it.\nMake sure you have not left out an ``{{end}}`` tag." ) + return '' def __repr__(self): return "%s->%s" % (self.name, self.value) From 5522e8d9ea96d76fbb504c8486fc427f47714307 Mon Sep 17 00:00:00 2001 From: Massimo Di Pierro Date: Sun, 20 May 2012 10:09:41 -0500 Subject: [PATCH 13/16] parse_as_rest returns count, thaks Joseph Piron --- VERSION | 2 +- gluon/dal.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/VERSION b/VERSION index cf2dc60b..3643f23d 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Version 2.00.0 (2012-05-19 22:34:21) dev +Version 2.00.0 (2012-05-20 10:09:09) dev diff --git a/gluon/dal.py b/gluon/dal.py index 9023cc88..0a030aab 100644 --- a/gluon/dal.py +++ b/gluon/dal.py @@ -6615,7 +6615,8 @@ def index(): except ValueError: return Row({'status':400,'pattern':pattern, 'error':'invalid path','response':None}) - return Row({'status':200,'response':response,'pattern':pattern}) + return Row({'status':200,'response':response, + 'pattern':pattern,'count':count}) return Row({'status':400,'error':'no matching pattern','response':None}) From 0e0c655355d972e4d349da4eda7f7ff412f2a07f Mon Sep 17 00:00:00 2001 From: Massimo DiPierro Date: Mon, 21 May 2012 09:55:05 -0500 Subject: [PATCH 14/16] db(db.a)._update(name=db(db.b.a==db.a.id).nested_select(db.b.id)) --- VERSION | 2 +- gluon/dal.py | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/VERSION b/VERSION index 3643f23d..1c80a83d 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Version 2.00.0 (2012-05-20 10:09:09) dev +Version 2.00.0 (2012-05-21 09:55:00) dev diff --git a/gluon/dal.py b/gluon/dal.py index 0a030aab..d4378eb9 100644 --- a/gluon/dal.py +++ b/gluon/dal.py @@ -1130,7 +1130,9 @@ class BaseAdapter(ConnectionPool): elif not isinstance(expression.op, str): return expression.op() else: - return '(%s)' % expression.op + op = expression.op + if op.endswith(';'): op=op[:-1] + return '(%s)' % op elif field_type: return str(self.represent(expression,field_type)) elif isinstance(expression,(list,tuple)): @@ -7981,8 +7983,6 @@ class Field(Expression): return '.%s' % self.name -def raw(s): return Expression(None,s) - class Query(object): """ @@ -8071,7 +8071,7 @@ class Set(object): if isinstance(query,Table): query = query._id>0 elif isinstance(query,str): - query = raw(query) + query = Expression(self.db,query) elif isinstance(query,Field): query = query!=None if self.query: @@ -8109,6 +8109,9 @@ class Set(object): fields = adapter.expand_all(fields, adapter.tables(self.query)) return adapter.select(self.query,fields,attributes) + def nested_select(self,*fields,**attributes): + return Expression(self.db,self._select(*fields,**attributes)) + def delete(self): tablename=self.db._adapter.get_table(self.query) table = self.db[tablename] From 3f18d032e97c5cc613048f19a69ff265bca57f57 Mon Sep 17 00:00:00 2001 From: Massimo DiPierro Date: Mon, 21 May 2012 10:08:44 -0500 Subject: [PATCH 15/16] fixed bug in smartdict, thanks Jonathan --- VERSION | 2 +- gluon/sqlhtml.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/VERSION b/VERSION index 1c80a83d..2d4db54a 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Version 2.00.0 (2012-05-21 09:55:00) dev +Version 2.00.0 (2012-05-21 10:08:41) dev diff --git a/gluon/sqlhtml.py b/gluon/sqlhtml.py index 981f0167..78942d11 100644 --- a/gluon/sqlhtml.py +++ b/gluon/sqlhtml.py @@ -1323,7 +1323,7 @@ class SQLFORM(FORM): def smartdictform(session,name,filename=None,query=None,**kwargs): import os if query: - session[name] = db(query).select().first().as_dict() + session[name] = query.db(query).select().first().as_dict() elif os.path.exists(filename): env = {'datetime':datetime} session[name] = eval(open(filename).read(),{},env) @@ -1331,7 +1331,7 @@ class SQLFORM(FORM): if form.process().accepted: session[name].update(form.vars) if query: - db(query).update(**form.vars) + query.db(query).update(**form.vars) else: open(filename,'w').write(repr(session[name])) return form From ba6ba5342a91ac375296df99dd082d8a258eda1f Mon Sep 17 00:00:00 2001 From: Massimo DiPierro Date: Mon, 21 May 2012 16:50:03 -0500 Subject: [PATCH 16/16] better setup-web2py-nginx-uwsgi-ubuntu.sh, issue 816, thanks Orsomannaro --- VERSION | 2 +- scripts/setup-web2py-nginx-uwsgi-ubuntu.sh | 160 ++++++++++----------- 2 files changed, 80 insertions(+), 82 deletions(-) diff --git a/VERSION b/VERSION index 2d4db54a..ec33540d 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Version 2.00.0 (2012-05-21 10:08:41) dev +Version 2.00.0 (2012-05-21 16:49:59) dev diff --git a/scripts/setup-web2py-nginx-uwsgi-ubuntu.sh b/scripts/setup-web2py-nginx-uwsgi-ubuntu.sh index 67a20db8..1d50f6ad 100644 --- a/scripts/setup-web2py-nginx-uwsgi-ubuntu.sh +++ b/scripts/setup-web2py-nginx-uwsgi-ubuntu.sh @@ -1,81 +1,79 @@ -#!/bin/bash - -echo 'setup-web2py-nginx-uwsgi-ubuntu.sh' -echo 'Requires Ubuntu 10.04 (LTS) and installs Nginx + uWSGI + Web2py' - -# Get Web2py Admin Password -echo -e "Web2py Admin Password: \c " -read PW - -# Upgrade and install needed software -apt-get update -apt-get -y upgrade -apt-get install python-software-properties -add-apt-repository ppa:nginx/stable -add-apt-repository ppa:uwsgi/release -apt-get update -apt-get -y install nginx-full -apt-get -y install uwsgi-python - -# Create configuration file /etc/nginx/sites-available/web2py -echo 'server { - listen 80; - server_name $hostname; - location ~* /(\w+)/static/ { - root /home/www-data/web2py/applications/; - } - location / { - uwsgi_pass 127.0.0.1:9001; - include uwsgi_params; - uwsgi_param UWSGI_SCHEME $scheme; - uwsgi_param SERVER_SOFTWARE nginx/$nginx_version; - } -} - -server { - listen 443; - server_name $hostname; - ssl on; - ssl_certificate /etc/nginx/ssl/web2py.crt; - ssl_certificate_key /etc/nginx/ssl/web2py.key; - location / { - uwsgi_pass 127.0.0.1:9001; - include uwsgi_params; - uwsgi_param UWSGI_SCHEME $scheme; - uwsgi_param SERVER_SOFTWARE nginx/$nginx_version; - } - -}' >/etc/nginx/sites-available/web2py - -ln -s /etc/nginx/sites-available/web2py /etc/nginx/sites-enabled/web2py -rm /etc/nginx/sites-enabled/default -rm /etc/nginx/sites-available/default -mkdir /etc/nginx/ssl -cd /etc/nginx/ssl -openssl genrsa -out web2py.key 1024 -openssl req -batch -new -key web2py.key -out web2py.csr -openssl x509 -req -days 1780 -in web2py.csr -signkey web2py.key -out web2py.crt - -# Create configuration file /etc/uwsgi-python/apps-available/web2py.xml -echo ' - 127.0.0.1:9001 - /home/www-data/web2py/ - - - -' >/etc/uwsgi-python/apps-available/web2py.xml -ln -s /etc/uwsgi-python/apps-available/web2py.xml /etc/uwsgi-python/apps-enabled/web2py.xml - -# Install Web2py -apt-get -y install unzip -cd /home -mkdir www-data -cd www-data -wget http://web2py.com/examples/static/web2py_src.zip -unzip web2py_src.zip -rm web2py_src.zip -chown -R www-data:www-data web2py -cd /home/www-data/web2py -sudo -u www-data python -c "from gluon.main import save_password; save_password('$PW',443)" -/etc/init.d/uwsgi-python restart -/etc/init.d/nginx restart +#!/bin/bash + +echo 'setup-web2py-nginx-uwsgi-ubuntu-precise.sh' +echo 'Requires Ubuntu 12.04 and installs Nginx + uWSGI + Web2py' + +# Get Web2py Admin Password +echo -e "Web2py Admin Password: \c " +read PW + +# Upgrade and install needed software +apt-get update +apt-get -y upgrade +apt-get -y dist-upgrade +apt-get autoremove +apt-get autoclean +apt-get -y install nginx-full +apt-get -y install uwsgi uwsgi-plugin-python + +# Create configuration file /etc/nginx/sites-available/web2py +echo 'server { + listen 80; + server_name $hostname; + location ~* /(\w+)/static/ { + root /home/www-data/web2py/applications/; + } + location / { + uwsgi_pass 127.0.0.1:9001; + include uwsgi_params; + uwsgi_param UWSGI_SCHEME $scheme; + uwsgi_param SERVER_SOFTWARE nginx/$nginx_version; + } +} + +server { + listen 443; + server_name $hostname; + ssl on; + ssl_certificate /etc/nginx/ssl/web2py.crt; + ssl_certificate_key /etc/nginx/ssl/web2py.key; + location / { + uwsgi_pass 127.0.0.1:9001; + include uwsgi_params; + uwsgi_param UWSGI_SCHEME $scheme; + uwsgi_param SERVER_SOFTWARE nginx/$nginx_version; + } + +}' >/etc/nginx/sites-available/web2py + +ln -s /etc/nginx/sites-available/web2py /etc/nginx/sites-enabled/web2py +rm /etc/nginx/sites-enabled/default +mkdir /etc/nginx/ssl +cd /etc/nginx/ssl +openssl genrsa -out web2py.key 1024 +openssl req -batch -new -key web2py.key -out web2py.csr +openssl x509 -req -days 1780 -in web2py.csr -signkey web2py.key -out web2py.crt + +# Create configuration file /etc/uwsgi/apps-available/web2py.xml +echo ' + python + 127.0.0.1:9001 + /home/www-data/web2py/ + + + +' >/etc/uwsgi/apps-available/web2py.xml +ln -s /etc/uwsgi/apps-available/web2py.xml /etc/uwsgi/apps-enabled/web2py.xml + +# Install Web2py +apt-get -y install unzip +mkdir /home/www-data +cd /home/www-data +wget http://web2py.com/examples/static/web2py_src.zip +unzip web2py_src.zip +rm web2py_src.zip +chown -R www-data:www-data web2py +cd /home/www-data/web2py +sudo -u www-data python -c "from gluon.main import save_password; save_password('$PW',443)" +/etc/init.d/uwsgi restart +/etc/init.d/nginx restart