Merge branch 'master' of ssh://github.com/web2py/web2py

This commit is contained in:
Michele Comitini
2013-07-21 16:37:55 +02:00
14 changed files with 843 additions and 783 deletions
+1 -1
View File
@@ -1 +1 @@
Version 2.6.0-development+timestamp.2013.07.17.17.18.40 Version 2.6.0-development+timestamp.2013.07.20.12.59.52
+10 -1
View File
@@ -42,7 +42,7 @@ input[type="file"] { margin-bottom:9px; }
.form-inline input[type="file"] { margin-bottom:0px; } .form-inline input[type="file"] { margin-bottom:0px; }
input + .help-block { margin-top:-5px; margin-bottom:4px; } input + .help-block { margin-top:-10px; margin-bottom:4px; }
#confirm_form input.btn, .generatedbyw2p input { margin-right:4px; } #confirm_form input.btn, .generatedbyw2p input { margin-right:4px; }
@@ -467,6 +467,9 @@ EDIT PAGE SLIDING FILES MENU
} }
/*-----------------------------------
miscellaneous
-------------------------------------*/
h4.editableapp, h4.currentapp { padding: 5px 0 5px 54px; display: inline; } h4.editableapp, h4.currentapp { padding: 5px 0 5px 54px; display: inline; }
h4.editableapp { background: #fff url(../images/folder.png) no-repeat; } h4.editableapp { background: #fff url(../images/folder.png) no-repeat; }
@@ -474,7 +477,13 @@ h4.editableapp { background: #fff url(../images/folder.png) no-repeat; }
h4.currentapp { background: #fff url(../images/folder_locked.png) no-repeat; } h4.currentapp { background: #fff url(../images/folder_locked.png) no-repeat; }
.flash { position:fixed; width:50%; top:49px; left:25%; right:25%; cursor:default; text-align:center; z-index:5620; } .flash { position:fixed; width:50%; top:49px; left:25%; right:25%; cursor:default; text-align:center; z-index:5620; }
span#closeflash {position:absolute; top:1px; right:-1px; font-size:150%; border:1px solid black; border-color: transparent transparent #fbeed5 #fbeed5; border-radius: 0 0 0 4px; width:22px; }
span#closeflash:hover {font-weight:bold; cursor:pointer; }
table.twitter{ background-color: transparent; } table.twitter{ background-color: transparent; }
table.twitter tr td {vertical-align: top; padding: 5px; } table.twitter tr td {vertical-align: top; padding: 5px; }
table.twitter tr { border-bottom: 1px solid #a0a0a0; } table.twitter tr { border-bottom: 1px solid #a0a0a0; }
div.error_wrapper {margin-top:-10px; margin-bottom:8px; padding-left:2px; color:#d62e2b; }
.twitter-timeline >iframe{padding: 1em 0;}
@@ -145,6 +145,10 @@ div>input[type="radio"],div>input[type="checkbox"]{margin:0;}
/* bootstrap has button instead of input */ /* bootstrap has button instead of input */
input[type="button"], input[type="submit"]{margin-right:8px;} input[type="button"], input[type="submit"]{margin-right:8px;}
/* web2py radio widget adjustment */
.generic-widget input[type='radio'] {margin:-1px 0 0 0; vertical-align: middle;}
.generic-widget input[type='radio'] + label {display:inline-block; margin:0 0 0 6px; vertical-align: middle;}
/*============================================================= /*=============================================================
RULES FOR SOLVING CONFLICTS BETWEEN WEB2PY.CSS AND BOOTSTRAP.CSS RULES FOR SOLVING CONFLICTS BETWEEN WEB2PY.CSS AND BOOTSTRAP.CSS
==============================================================*/ ==============================================================*/
@@ -233,10 +237,11 @@ div.controls .error {
@media only screen and (max-width:979px){ @media only screen and (max-width:979px){
body{padding-top:0px;} body{padding-top:0px;}
#navbar{top:5px;} #navbar{/*top:5px;*/}
div.flash{right:5px;} div.flash{right:5px;}
.dropdown-menu ul{visibility:visible;} .dropdown-menu ul{visibility:visible;}
} }
@media only screen and (max-width:479px){ @media only screen and (max-width:479px){
body{ body{
padding-left:10px; padding-left:10px;
@@ -250,3 +255,10 @@ div.controls .error {
width:95%; width:95%;
} }
} }
@media (max-width: 767px) {
.navbar {
margin-right: -20px;
margin-left: -20px;
}
}
+3 -1
View File
@@ -72,6 +72,7 @@
var date_format = (typeof w2p_ajax_date_format != 'undefined') ? w2p_ajax_date_format : "%Y-%m-%d"; var date_format = (typeof w2p_ajax_date_format != 'undefined') ? w2p_ajax_date_format : "%Y-%m-%d";
var datetime_format = (typeof w2p_ajax_datetime_format != 'undefined') ? w2p_ajax_datetime_format : "%Y-%m-%d %H:%M:%S"; var datetime_format = (typeof w2p_ajax_datetime_format != 'undefined') ? w2p_ajax_datetime_format : "%Y-%m-%d %H:%M:%S";
$("input.date", target).each(function () { $("input.date", target).each(function () {
$(this).attr('autocomplete','off');
Calendar.setup({ Calendar.setup({
inputField: this, inputField: this,
ifFormat: date_format, ifFormat: date_format,
@@ -79,6 +80,7 @@
}); });
}); });
$("input.datetime", target).each(function () { $("input.datetime", target).each(function () {
$(this).attr('autocomplete','off');
Calendar.setup({ Calendar.setup({
inputField: this, inputField: this,
ifFormat: datetime_format, ifFormat: datetime_format,
@@ -87,7 +89,7 @@
}); });
}); });
$("input.time", target).each(function () { $("input.time", target).each(function () {
$(this).timeEntry(); $(this).timeEntry().attr('autocomplete','off');
}); });
/*adds btn class to buttons*/ /*adds btn class to buttons*/
$('button', target).addClass('btn'); $('button', target).addClass('btn');
+7 -2
View File
@@ -65,10 +65,15 @@ jQuery(document).on('click', '#filesTab button[class="close"]', function (e) {
} }
if (close) { if (close) {
if (tab_header.hasClass('active') === true) { //Set active an other tab if (tab_header.hasClass('active') === true) { //Set active an other tab
jQuery(tab_header).prev().children('a[data-toggle="tab"]').tab('show'); // Select first tab var $prev = jQuery(tab_header).prev();
if ($prev.length) {
$prev.children('a[data-toggle="tab"]').tab('show'); // select previous tab
} else {
jQuery(tab_header).next().children('a[data-toggle="tab"]').tab('show'); // select next tab
}
} }
tab_header.remove(); //remove li of tab tab_header.remove(); //remove li of tab
tab_body.remove(); //remove li of tab tab_body.remove(); //remove tab content (div)
} }
}); });
+5 -2
View File
@@ -145,8 +145,11 @@
<p>{{=button(URL('wizard','index'), T('Start wizard'))}}<br/> <p>{{=button(URL('wizard','index'), T('Start wizard'))}}<br/>
{{=T("(requires internet access, experimental)")}}</p> {{=T("(requires internet access, experimental)")}}</p>
</div> <!-- /APP WIZARD --> </div> <!-- /APP WIZARD -->
<a class="twitter-timeline" href="https://twitter.com/web2py" data-widget-id="340456915207327745">Tweets by @web2py</a> <!-- TWITTER TIMELINE -->
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+"://platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script> <div class="box twitter-timeline">
<a class="twitter-timeline" href="https://twitter.com/web2py" data-widget-id="340456915207327745">Tweets by @web2py</a>
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+"://platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
</div><!-- /TWITTER TIMELINE -->
</div> </div>
</div> <!-- /sidebar --> </div> <!-- /sidebar -->
</div> <!-- /row-fluid </div> <!-- /row-fluid
@@ -145,6 +145,10 @@ div>input[type="radio"],div>input[type="checkbox"]{margin:0;}
/* bootstrap has button instead of input */ /* bootstrap has button instead of input */
input[type="button"], input[type="submit"]{margin-right:8px;} input[type="button"], input[type="submit"]{margin-right:8px;}
/* web2py radio widget adjustment */
.generic-widget input[type='radio'] {margin:-1px 0 0 0; vertical-align: middle;}
.generic-widget input[type='radio'] + label {display:inline-block; margin:0 0 0 6px; vertical-align: middle;}
/*============================================================= /*=============================================================
RULES FOR SOLVING CONFLICTS BETWEEN WEB2PY.CSS AND BOOTSTRAP.CSS RULES FOR SOLVING CONFLICTS BETWEEN WEB2PY.CSS AND BOOTSTRAP.CSS
==============================================================*/ ==============================================================*/
@@ -233,10 +237,11 @@ div.controls .error {
@media only screen and (max-width:979px){ @media only screen and (max-width:979px){
body{padding-top:0px;} body{padding-top:0px;}
#navbar{top:5px;} #navbar{/*top:5px;*/}
div.flash{right:5px;} div.flash{right:5px;}
.dropdown-menu ul{visibility:visible;} .dropdown-menu ul{visibility:visible;}
} }
@media only screen and (max-width:479px){ @media only screen and (max-width:479px){
body{ body{
padding-left:10px; padding-left:10px;
@@ -250,3 +255,10 @@ div.controls .error {
width:95%; width:95%;
} }
} }
@media (max-width: 767px) {
.navbar {
margin-right: -20px;
margin-left: -20px;
}
}
+3 -1
View File
@@ -72,6 +72,7 @@
var date_format = (typeof w2p_ajax_date_format != 'undefined') ? w2p_ajax_date_format : "%Y-%m-%d"; var date_format = (typeof w2p_ajax_date_format != 'undefined') ? w2p_ajax_date_format : "%Y-%m-%d";
var datetime_format = (typeof w2p_ajax_datetime_format != 'undefined') ? w2p_ajax_datetime_format : "%Y-%m-%d %H:%M:%S"; var datetime_format = (typeof w2p_ajax_datetime_format != 'undefined') ? w2p_ajax_datetime_format : "%Y-%m-%d %H:%M:%S";
$("input.date", target).each(function () { $("input.date", target).each(function () {
$(this).attr('autocomplete','off');
Calendar.setup({ Calendar.setup({
inputField: this, inputField: this,
ifFormat: date_format, ifFormat: date_format,
@@ -79,6 +80,7 @@
}); });
}); });
$("input.datetime", target).each(function () { $("input.datetime", target).each(function () {
$(this).attr('autocomplete','off');
Calendar.setup({ Calendar.setup({
inputField: this, inputField: this,
ifFormat: datetime_format, ifFormat: datetime_format,
@@ -87,7 +89,7 @@
}); });
}); });
$("input.time", target).each(function () { $("input.time", target).each(function () {
$(this).timeEntry(); $(this).timeEntry().attr('autocomplete','off');
}); });
/*adds btn class to buttons*/ /*adds btn class to buttons*/
$('button', target).addClass('btn'); $('button', target).addClass('btn');
@@ -145,6 +145,10 @@ div>input[type="radio"],div>input[type="checkbox"]{margin:0;}
/* bootstrap has button instead of input */ /* bootstrap has button instead of input */
input[type="button"], input[type="submit"]{margin-right:8px;} input[type="button"], input[type="submit"]{margin-right:8px;}
/* web2py radio widget adjustment */
.generic-widget input[type='radio'] {margin:-1px 0 0 0; vertical-align: middle;}
.generic-widget input[type='radio'] + label {display:inline-block; margin:0 0 0 6px; vertical-align: middle;}
/*============================================================= /*=============================================================
RULES FOR SOLVING CONFLICTS BETWEEN WEB2PY.CSS AND BOOTSTRAP.CSS RULES FOR SOLVING CONFLICTS BETWEEN WEB2PY.CSS AND BOOTSTRAP.CSS
==============================================================*/ ==============================================================*/
+3 -1
View File
@@ -72,6 +72,7 @@
var date_format = (typeof w2p_ajax_date_format != 'undefined') ? w2p_ajax_date_format : "%Y-%m-%d"; var date_format = (typeof w2p_ajax_date_format != 'undefined') ? w2p_ajax_date_format : "%Y-%m-%d";
var datetime_format = (typeof w2p_ajax_datetime_format != 'undefined') ? w2p_ajax_datetime_format : "%Y-%m-%d %H:%M:%S"; var datetime_format = (typeof w2p_ajax_datetime_format != 'undefined') ? w2p_ajax_datetime_format : "%Y-%m-%d %H:%M:%S";
$("input.date", target).each(function () { $("input.date", target).each(function () {
$(this).attr('autocomplete','off');
Calendar.setup({ Calendar.setup({
inputField: this, inputField: this,
ifFormat: date_format, ifFormat: date_format,
@@ -79,6 +80,7 @@
}); });
}); });
$("input.datetime", target).each(function () { $("input.datetime", target).each(function () {
$(this).attr('autocomplete','off');
Calendar.setup({ Calendar.setup({
inputField: this, inputField: this,
ifFormat: datetime_format, ifFormat: datetime_format,
@@ -87,7 +89,7 @@
}); });
}); });
$("input.time", target).each(function () { $("input.time", target).each(function () {
$(this).timeEntry(); $(this).timeEntry().attr('autocomplete','off');
}); });
/*adds btn class to buttons*/ /*adds btn class to buttons*/
$('button', target).addClass('btn'); $('button', target).addClass('btn');
+9 -5
View File
@@ -710,6 +710,7 @@ class BaseAdapter(ConnectionPool):
os.unlink(filename) os.unlink(filename)
def find_driver(self,adapter_args,uri=None): def find_driver(self,adapter_args,uri=None):
self.adapter_args = adapter_args
if getattr(self,'driver',None) != None: if getattr(self,'driver',None) != None:
return return
drivers_available = [driver for driver in self.drivers drivers_available = [driver for driver in self.drivers
@@ -950,7 +951,8 @@ class BaseAdapter(ConnectionPool):
dbpath, '%s_%s.table' % (table._db._uri_hash, tablename)) dbpath, '%s_%s.table' % (table._db._uri_hash, tablename))
if table._dbt: if table._dbt:
table._loggername = pjoin(dbpath, 'sql.log') logfilename = self.adapter_args.get('logfile','sql.log')
table._loggername = pjoin(dbpath, logfilename)
logfile = self.file_open(table._loggername, 'a') logfile = self.file_open(table._loggername, 'a')
else: else:
logfile = None logfile = None
@@ -2108,8 +2110,8 @@ class BaseAdapter(ConnectionPool):
new_rows.append(new_row) new_rows.append(new_row)
rowsobj = Rows(db, new_rows, colnames, rawrows=rows) rowsobj = Rows(db, new_rows, colnames, rawrows=rows)
for tablename in virtualtables: for tablename in virtualtables:
### new style virtual fields
table = db[tablename] table = db[tablename]
fields_virtual = [(f,v) for (f,v) in table.iteritems() fields_virtual = [(f,v) for (f,v) in table.iteritems()
if isinstance(v,FieldVirtual)] if isinstance(v,FieldVirtual)]
@@ -2569,6 +2571,8 @@ class PostgreSQLAdapter(BaseAdapter):
} }
QUOTE_TEMPLATE = '%s'
def varquote(self,name): def varquote(self,name):
return varquote_aux(name,'"%s"') return varquote_aux(name,'"%s"')
@@ -4242,15 +4246,15 @@ class DatabaseStoredFile:
return self.db._adapter.escape(obj) return self.db._adapter.escape(obj)
def __init__(self,db,filename,mode): def __init__(self,db,filename,mode):
if not db._adapter.dbengine in ('mysql', 'postgres'): if not db._adapter.dbengine in ('mysql', 'postgres', 'sqlite'):
raise RuntimeError("only MySQL/Postgres can store metadata .table files in database for now") raise RuntimeError("only MySQL/Postgres/SQLite can store metadata .table files in database for now")
self.db = db self.db = db
self.filename = filename self.filename = filename
self.mode = mode self.mode = mode
if not self.web2py_filesystem: if not self.web2py_filesystem:
if db._adapter.dbengine == 'mysql': if db._adapter.dbengine == 'mysql':
sql = "CREATE TABLE IF NOT EXISTS web2py_filesystem (path VARCHAR(255), content LONGTEXT, PRIMARY KEY(path) ) ENGINE=InnoDB;" sql = "CREATE TABLE IF NOT EXISTS web2py_filesystem (path VARCHAR(255), content LONGTEXT, PRIMARY KEY(path) ) ENGINE=InnoDB;"
elif db._adapter.dbengine == 'postgres': elif db._adapter.dbengine in ('postgres', 'sqlite'):
sql = "CREATE TABLE IF NOT EXISTS web2py_filesystem (path VARCHAR(255), content TEXT, PRIMARY KEY(path));" sql = "CREATE TABLE IF NOT EXISTS web2py_filesystem (path VARCHAR(255), content TEXT, PRIMARY KEY(path));"
self.db.executesql(sql) self.db.executesql(sql)
DatabaseStoredFile.web2py_filesystem = True DatabaseStoredFile.web2py_filesystem = True
+3 -1
View File
@@ -1928,6 +1928,7 @@ class SQLFORM(FORM):
if isinstance(f,Field.Virtual) and f.readable: if isinstance(f,Field.Virtual) and f.readable:
f.tablename = table._tablename f.tablename = table._tablename
columns.append(f) columns.append(f)
fields.append(f)
if not field_id: if not field_id:
field_id = tables[0]._id field_id = tables[0]._id
if not any(str(f)==str(field_id) for f in fields): if not any(str(f)==str(field_id) for f in fields):
@@ -2239,7 +2240,7 @@ class SQLFORM(FORM):
limitby = None limitby = None
try: try:
table_fields = [f for f in fields if f.tablename in tablenames] table_fields = filter(lambda f: f.tablename in tablenames, fields)
if dbset._db._adapter.dbengine=='google:datastore': if dbset._db._adapter.dbengine=='google:datastore':
rows = dbset.select(left=left,orderby=orderby, rows = dbset.select(left=left,orderby=orderby,
groupby=groupby,limitby=limitby, groupby=groupby,limitby=limitby,
@@ -2247,6 +2248,7 @@ class SQLFORM(FORM):
cacheable=True,*table_fields) cacheable=True,*table_fields)
next_cursor = dbset._db.get('_lastcursor', None) next_cursor = dbset._db.get('_lastcursor', None)
else: else:
# print('table_fields: %s' %([f_.name for f_ in table_fields],))
rows = dbset.select(left=left,orderby=orderby, rows = dbset.select(left=left,orderby=orderby,
groupby=groupby,limitby=limitby, groupby=groupby,limitby=limitby,
cacheable=True,*table_fields) cacheable=True,*table_fields)
+3 -1
View File
@@ -1500,7 +1500,7 @@ class Auth(object):
label=T('Modified By'), ondelete=ondelete)) label=T('Modified By'), ondelete=ondelete))
def define_tables(self, username=None, signature=None, def define_tables(self, username=None, signature=None,
migrate=True, fake_migrate=False): migrate=None, fake_migrate=None):
""" """
to be called unless tables are defined manually to be called unless tables are defined manually
@@ -1516,6 +1516,8 @@ class Auth(object):
""" """
db = self.db db = self.db
if migrate is None: migrate = db._migrate
if fake_migrate is None: fake_migrate = db._fake_migrate
settings = self.settings settings = self.settings
if username is None: if username is None:
username = settings.use_username username = settings.use_username
+3 -2
View File
@@ -79,8 +79,9 @@ def mysql(database_name, username, password):
if 'CREATE' in sql_create_stmnt: # check if the table exists if 'CREATE' in sql_create_stmnt: # check if the table exists
#remove garbage lines from sql statement #remove garbage lines from sql statement
sql_lines = sql_create_stmnt.split('\n') sql_lines = sql_create_stmnt.split('\n')
sql_lines = [x for x in sql_lines if not( sql_lines = filter(
x.startswith('--') or x.startswith('/*') or x == '')] lambda x: not(x in ('','\r') or x[:2] in ('--','/*')),
sql_lines)
#generate the web2py code from the create statement #generate the web2py code from the create statement
web2py_table_code = '' web2py_table_code = ''
table_name = re.search( table_name = re.search(