removed unwanted whitespaces
This commit is contained in:
@@ -1 +1 @@
|
||||
Version 2.00.0 (2012-08-16 11:06:01) dev
|
||||
Version 2.00.0 (2012-08-16 11:56:03) dev
|
||||
|
||||
@@ -4,3 +4,5 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+3
-2
@@ -130,12 +130,12 @@ class Servers:
|
||||
config.update(options)
|
||||
sys.argv = ['anyserver.py']
|
||||
class GunicornApplication(Application):
|
||||
def init(self, parser, opts, args):
|
||||
def init(self, parser, opts, args):
|
||||
return config
|
||||
def load(self):
|
||||
return app
|
||||
g = GunicornApplication()
|
||||
g.run()
|
||||
g.run()
|
||||
|
||||
@staticmethod
|
||||
def eventlet(app,address, **options):
|
||||
@@ -308,3 +308,4 @@ if __name__=='__main__':
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -5,3 +5,4 @@ def webapp_add_wsgi_middleware(app):
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -64,3 +64,4 @@ wsgiref.handlers.CGIHandler().run(gluon.main.wsgibase)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -54,3 +54,4 @@ fcgi.WSGIServer(application, bindAddress='/tmp/fcgi.sock').run()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -102,3 +102,4 @@ if __name__ == '__main__':
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+4
-2
@@ -26,14 +26,14 @@ if 0:
|
||||
from cache import Cache
|
||||
from languages import translator
|
||||
from tools import Auth, Crud, Mail, Service, PluginManager
|
||||
|
||||
|
||||
# API objects
|
||||
request = Request()
|
||||
response = Response()
|
||||
session = Session()
|
||||
cache = Cache(request)
|
||||
T = translator(request)
|
||||
|
||||
|
||||
# Objects commonly defined in application model files
|
||||
# (names are conventions only -- not part of API)
|
||||
db = DAL()
|
||||
@@ -50,3 +50,5 @@ if 0:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -464,3 +464,4 @@ def create_missing_app_folders(request):
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+3
-2
@@ -398,9 +398,9 @@ class CacheAction(object):
|
||||
.replace('%(args)s',str(a)).replace('%(vars)s',str(b))
|
||||
cache_model = self.cache_model
|
||||
if not cache_model or isinstance(cache_model,str):
|
||||
cache_model = getattr(self.cache,cache_model or 'ram')
|
||||
cache_model = getattr(self.cache,cache_model or 'ram')
|
||||
return cache_model(key2,
|
||||
lambda a=a,b=b:self.func(*a,**b),
|
||||
lambda a=a,b=b:self.func(*a,**b),
|
||||
self.time_expire)
|
||||
|
||||
|
||||
@@ -497,3 +497,4 @@ def lazy_cache(key=None,time_expire=None,cache_model='ram'):
|
||||
return g
|
||||
return decorator
|
||||
|
||||
|
||||
|
||||
@@ -55,3 +55,4 @@ def getcfs(key, filename, filter=None):
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+2
-1
@@ -358,7 +358,7 @@ def build_environment(request, response, session, store_current=True):
|
||||
"""
|
||||
Build the environment dictionary into which web2py files are executed.
|
||||
"""
|
||||
|
||||
|
||||
environment = {}
|
||||
for key in html.__all__:
|
||||
environment[key] = getattr(html, key)
|
||||
@@ -690,3 +690,4 @@ if __name__ == '__main__':
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -722,3 +722,4 @@ def contenttype(filename, default='text/plain'):
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -262,3 +262,4 @@ if __name__=='__main__':
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -242,3 +242,4 @@ if __name__=='__main__':
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,3 +4,4 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -500,3 +500,4 @@ aes_Rcon = array('B',
|
||||
'c697356ad4b37dfaefc5913972e4d3bd'
|
||||
'61c29f254a943366cc831d3a74e8cb'.decode('hex')
|
||||
)
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ Released under the web2py license (LGPL)
|
||||
|
||||
What does it do?
|
||||
|
||||
if html is a variable containing HTML text and urls in the text, when you call
|
||||
if html is a variable containing HTML text and urls in the text, when you call
|
||||
|
||||
html = expend_html(html)
|
||||
|
||||
@@ -63,7 +63,7 @@ EMBED_MAPS = [
|
||||
'http://www.hulu.com/api/oembed.json'),
|
||||
(re.compile('http://vimeo.com/\S*'),
|
||||
'http://vimeo.com/api/oembed.json'),
|
||||
(re.compile('http://www.slideshare.net/[^\/]+/\S*'),
|
||||
(re.compile('http://www.slideshare.net/[^\/]+/\S*'),
|
||||
'http://www.slideshare.net/api/oembed/2'),
|
||||
(re.compile('http://qik.com/\S*'),
|
||||
'http://qik.com/api/oembed.json'),
|
||||
@@ -128,8 +128,8 @@ EXTENSION_MAPS = {
|
||||
|
||||
def oembed(url):
|
||||
for k,v in EMBED_MAPS:
|
||||
if k.match(url):
|
||||
oembed = v+'?format=json&url='+cgi.escape(url)
|
||||
if k.match(url):
|
||||
oembed = v+'?format=json&url='+cgi.escape(url)
|
||||
try:
|
||||
return loads(urllib.urlopen(oembed).read())
|
||||
except:
|
||||
@@ -196,3 +196,4 @@ if __name__=="__main__":
|
||||
print expand_html(open(sys.argv[1]).read())
|
||||
else:
|
||||
print test()
|
||||
|
||||
|
||||
@@ -193,3 +193,4 @@ if __name__ == "__main__":
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -3909,3 +3909,4 @@ def parse(url_file_stream_or_string, etag=None, modified=None, agent=None, refer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -54,3 +54,4 @@ class MemcacheClient(Client):
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -89,3 +89,4 @@ def autoretry_datastore_timeouts(attempts=5.0, interval=0.1, exponent=2.0):
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -66,3 +66,4 @@ def pdf_from_html(html):
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -18,3 +18,4 @@ def button(merchant_id="123456789012345",
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -8,3 +8,4 @@ from gluon.dal import DAL, Field, Table, Query, Set, Expression, Row, Rows, driv
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -57,3 +57,4 @@ def THUMB(image, nx=120, ny=120, gae=False, name='thumb'):
|
||||
return thumb
|
||||
else:
|
||||
return image
|
||||
|
||||
|
||||
@@ -910,3 +910,4 @@ if __name__ == '__main__':
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -126,3 +126,4 @@ if __name__ == "__main__":
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -128,3 +128,4 @@ def test():
|
||||
|
||||
if __name__ == '__main__':
|
||||
test()
|
||||
|
||||
|
||||
@@ -170,3 +170,4 @@ if __name__ == '__main__':
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -963,3 +963,4 @@ if __name__ == '__main__':
|
||||
qdb.main(**kwargs)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -166,3 +166,4 @@ class RedisClient(object):
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -591,3 +591,4 @@ if __name__ == '__main__':
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -269,3 +269,4 @@ if __name__=='__main__':
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -150,3 +150,4 @@ if __name__ == "__main__":
|
||||
print client.add(1, 2)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -115,3 +115,4 @@ def sms_email(number,provider):
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ class Node:
|
||||
self.onchange = onchange
|
||||
self.size = 4
|
||||
self.locked = False
|
||||
|
||||
|
||||
def xml(self):
|
||||
return """<input name="%s" id="%s" value="%s" size="%s"
|
||||
onkeyup="ajax('%s/keyup',['%s'], ':eval');"
|
||||
@@ -44,7 +44,7 @@ class Node:
|
||||
class Sheet:
|
||||
"""
|
||||
Basic class for creating web spreadsheets
|
||||
|
||||
|
||||
New features:
|
||||
|
||||
-dal spreadsheets:
|
||||
@@ -105,32 +105,32 @@ class Sheet:
|
||||
more details)
|
||||
|
||||
client JavaScript objects:
|
||||
|
||||
|
||||
-var w2p_spreadsheet_data
|
||||
Stores cell updates by key and
|
||||
Used for updated cells control
|
||||
|
||||
|
||||
-var w2p_spreadsheet_update_button
|
||||
Stores the id of the update command
|
||||
Used for event binding (update click)
|
||||
|
||||
|
||||
var w2p_spreadsheet_update_result
|
||||
object attributes:
|
||||
modified - n updated records
|
||||
errors - n errors
|
||||
message - a message for feedback and errors
|
||||
|
||||
|
||||
Stores the ajax db update call returned stats
|
||||
and the db_callback string js
|
||||
Used after calling w2p_spreadsheet_update_db()
|
||||
|
||||
|
||||
-function w2p_spreadsheet_update_cell(a)
|
||||
Used for responding to normal cell events
|
||||
(encapsulates old behavior)
|
||||
|
||||
|
||||
-function w2p_spreadsheet_update_db_callback(result)
|
||||
Called after a background db update
|
||||
|
||||
|
||||
-function w2p_spreadsheet_update_db()
|
||||
Called for updating the database with
|
||||
client data
|
||||
@@ -182,7 +182,7 @@ class Sheet:
|
||||
Second method: Sending data updates with .ajax()
|
||||
|
||||
-spreadsheet page's view:
|
||||
|
||||
|
||||
{{
|
||||
=INPUT(_type="button", _value="update data",
|
||||
_id="w2p_spreadsheet_update_data")
|
||||
@@ -223,9 +223,9 @@ class Sheet:
|
||||
# -Delete checkbox columns for each table and default
|
||||
# -Deletable=True option for showing/hiding delete checkboxes
|
||||
# -process() method support for db I/O
|
||||
|
||||
|
||||
"""
|
||||
|
||||
|
||||
regex = re.compile('(?<!\w)[a-zA-Z_]\w*')
|
||||
pregex = re.compile('\d+')
|
||||
re_strings = re.compile(r'(?P<name>'
|
||||
@@ -315,7 +315,7 @@ class Sheet:
|
||||
changes[tablename][row_id][fieldname] = value
|
||||
|
||||
return changes
|
||||
|
||||
|
||||
|
||||
def process(self, request, db=None, db_callback=None):
|
||||
"""
|
||||
@@ -429,7 +429,7 @@ class Sheet:
|
||||
self.readonly = readonly
|
||||
|
||||
self.update_button = update_button
|
||||
|
||||
|
||||
self.client = {
|
||||
"columns": {},
|
||||
"colnames": {},
|
||||
@@ -439,14 +439,14 @@ class Sheet:
|
||||
"modified": {},
|
||||
"headers": headers
|
||||
}
|
||||
|
||||
|
||||
# if db and query:
|
||||
if self.data is not None:
|
||||
# retrieve row columns length
|
||||
self.rows = len(self.data)
|
||||
# retrieve rows length
|
||||
self.cols = len(self.data.colnames)
|
||||
|
||||
|
||||
# map row data to rncn values
|
||||
for x, colname in enumerate(self.data.colnames):
|
||||
self.client["columns"][colname] = x
|
||||
@@ -557,7 +557,7 @@ class Sheet:
|
||||
# one column example:
|
||||
# {"0": {"value":1.0, "readonly":False, "active":True, "onchange":None}}
|
||||
# value: common value for all cells
|
||||
|
||||
|
||||
attributes = self.get_attributes(kwarg)
|
||||
if attributes is not None:
|
||||
self.tr_attributes[str(row)] = attributes
|
||||
@@ -593,10 +593,10 @@ class Sheet:
|
||||
# arg: value pairs
|
||||
# one row example:
|
||||
# {"0": {"value":1.0, "readonly":False, "active":True, "onchange":None}}
|
||||
# value: common value for all cells
|
||||
# value: common value for all cells
|
||||
"""
|
||||
attributes = self.get_attributes(kwarg)
|
||||
|
||||
|
||||
if isinstance(cells, dict):
|
||||
for row, data in cells.iteritems():
|
||||
key = "r%sc%s" % (row, col)
|
||||
@@ -610,7 +610,7 @@ class Sheet:
|
||||
onchange=onchange, **attributes)
|
||||
else:
|
||||
active, onchange, readonly, all_value = \
|
||||
self.get_cell_arguments(kwarg)
|
||||
self.get_cell_arguments(kwarg)
|
||||
for row, cell_value in enumerate(cells):
|
||||
key = "r%sc%s" % (row, col)
|
||||
if value is None:
|
||||
@@ -626,7 +626,7 @@ class Sheet:
|
||||
Insert a n x n matrix or a set of cells
|
||||
# starts: upper left cell
|
||||
# ends: lower right cell
|
||||
|
||||
|
||||
# cells: a sequence of value sequences
|
||||
# or a dict with "rncn" keys
|
||||
# Example 1 cells:
|
||||
@@ -637,7 +637,7 @@ class Sheet:
|
||||
# value: common value for all cells
|
||||
"""
|
||||
attributes = self.get_attributes(kwarg)
|
||||
|
||||
|
||||
starts_r, starts_c = self.position(starts)
|
||||
ends_r, ends_c = None, None
|
||||
if ends is not None:
|
||||
@@ -832,7 +832,7 @@ class Sheet:
|
||||
jQuery(function(){
|
||||
jQuery(".%(name)s input").change(w2p_spreadsheet_update_cell);
|
||||
});
|
||||
|
||||
|
||||
if (w2p_spreadsheet_update_button != ""){
|
||||
jQuery(function(){
|
||||
jQuery("#" + w2p_spreadsheet_update_button).click(w2p_spreadsheet_update_db);
|
||||
@@ -855,7 +855,7 @@ class Sheet:
|
||||
|
||||
sorted_headers = [TH(),] + \
|
||||
[TH(header[1]) for header in sorted(unsorted_headers)]
|
||||
table.insert(0, TR(*sorted_headers,
|
||||
table.insert(0, TR(*sorted_headers,
|
||||
**{_class:"%s_fieldnames" % \
|
||||
attributes["_class"]}))
|
||||
else:
|
||||
@@ -878,3 +878,4 @@ if __name__ == '__main__':
|
||||
s.cell('c', value="=cos(a)**2+b*b")
|
||||
print s['c'].computed_value
|
||||
|
||||
|
||||
|
||||
@@ -65,3 +65,4 @@ if __name__=='__main__':
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -246,3 +246,4 @@ class TaskBarIcon:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -94,3 +94,4 @@ if __name__=='__main__':
|
||||
# You can turn off ordering of results
|
||||
print(t.getReportText(orderByCost=False))
|
||||
|
||||
|
||||
|
||||
@@ -519,3 +519,4 @@ class mobilize(object):
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -328,3 +328,4 @@ class _Web2pyDateTrackerImporter(_Web2pyImporter, _DateTrackerImporter):
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+44
-43
@@ -91,7 +91,7 @@ Example of usage:
|
||||
>>> person.drop()
|
||||
|
||||
Supported field types:
|
||||
id string text boolean integer double decimal password upload
|
||||
id string text boolean integer double decimal password upload
|
||||
blob time date datetime
|
||||
|
||||
Supported DAL URI strings:
|
||||
@@ -507,7 +507,7 @@ class ConnectionPool(object):
|
||||
|
||||
def pool_connection(self, f, cursor=True):
|
||||
"""
|
||||
this function defines: self.connection and self.cursor
|
||||
this function defines: self.connection and self.cursor
|
||||
(iff cursor is True)
|
||||
if self.pool_size>0 it will try pull the connection from the pool
|
||||
if the connection is not active (closed by db server) it will loop
|
||||
@@ -691,7 +691,7 @@ class BaseAdapter(ConnectionPool):
|
||||
# make a guess here for circular references
|
||||
id_fieldname = referenced in table._db \
|
||||
and table._db[referenced]._id.name or 'id'
|
||||
ftype = self.types[field.type[:9]] % dict(
|
||||
ftype = self.types[field.type[:9]] % dict(
|
||||
index_name = field.name+'__idx',
|
||||
field_name = field.name,
|
||||
constraint_name = constraint_name,
|
||||
@@ -749,11 +749,11 @@ class BaseAdapter(ConnectionPool):
|
||||
sql=ftype)
|
||||
|
||||
if isinstance(field.default,(str,int,float)):
|
||||
# Caveat: sql_fields and sql_fields_aux
|
||||
# Caveat: sql_fields and sql_fields_aux
|
||||
# differ for default values.
|
||||
# sql_fields is used to trigger migrations and sql_fields_aux
|
||||
# is used for create tables.
|
||||
# The reason is that we do not want to trigger
|
||||
# The reason is that we do not want to trigger
|
||||
# a migration simply because a default value changes.
|
||||
not_null = self.NOT_NULL(field.default, field.type)
|
||||
ftype = ftype.replace('NOT NULL', not_null)
|
||||
@@ -785,7 +785,7 @@ class BaseAdapter(ConnectionPool):
|
||||
|
||||
if hasattr(table,'_primarykey'):
|
||||
query = "CREATE TABLE %s(\n %s,\n %s) %s" % \
|
||||
(tablename, fields,
|
||||
(tablename, fields,
|
||||
self.PRIMARY_KEY(', '.join(table._primarykey)),other)
|
||||
else:
|
||||
query = "CREATE TABLE %s(\n %s\n)%s" % \
|
||||
@@ -823,7 +823,7 @@ class BaseAdapter(ConnectionPool):
|
||||
if not fake_migrate:
|
||||
self.create_sequence_and_triggers(query,table)
|
||||
table._db.commit()
|
||||
# Postgres geom fields are added now,
|
||||
# Postgres geom fields are added now,
|
||||
# after the table has been created
|
||||
for query in postcreation_fields:
|
||||
self.execute(query)
|
||||
@@ -911,7 +911,7 @@ class BaseAdapter(ConnectionPool):
|
||||
schema = parms.split(',')[0]
|
||||
query = [ "SELECT DropGeometryColumn ('%(schema)s', '%(table)s', '%(field)s');" % dict(schema=schema, table=tablename, field=key,) ]
|
||||
elif not self.dbengine in ('firebird',):
|
||||
query = ['ALTER TABLE %s DROP COLUMN %s;'
|
||||
query = ['ALTER TABLE %s DROP COLUMN %s;'
|
||||
% (tablename, key)]
|
||||
else:
|
||||
query = ['ALTER TABLE %s DROP %s;' % (tablename, key)]
|
||||
@@ -1097,11 +1097,11 @@ class BaseAdapter(ConnectionPool):
|
||||
self.expand(second, 'string'))
|
||||
|
||||
def STARTSWITH(self, first, second):
|
||||
return '(%s LIKE %s)' % (self.expand(first),
|
||||
return '(%s LIKE %s)' % (self.expand(first),
|
||||
self.expand(second+'%', 'string'))
|
||||
|
||||
def ENDSWITH(self, first, second):
|
||||
return '(%s LIKE %s)' % (self.expand(first),
|
||||
return '(%s LIKE %s)' % (self.expand(first),
|
||||
self.expand('%'+second, 'string'))
|
||||
|
||||
def CONTAINS(self, first, second):
|
||||
@@ -1114,13 +1114,13 @@ class BaseAdapter(ConnectionPool):
|
||||
def EQ(self, first, second=None):
|
||||
if second is None:
|
||||
return '(%s IS NULL)' % self.expand(first)
|
||||
return '(%s = %s)' % (self.expand(first),
|
||||
return '(%s = %s)' % (self.expand(first),
|
||||
self.expand(second, first.type))
|
||||
|
||||
def NE(self, first, second=None):
|
||||
if second is None:
|
||||
return '(%s IS NOT NULL)' % self.expand(first)
|
||||
return '(%s <> %s)' % (self.expand(first),
|
||||
return '(%s <> %s)' % (self.expand(first),
|
||||
self.expand(second, first.type))
|
||||
|
||||
def LT(self,first,second=None):
|
||||
@@ -1156,7 +1156,7 @@ class BaseAdapter(ConnectionPool):
|
||||
self.expand(second, first.type))
|
||||
|
||||
def MUL(self, first, second):
|
||||
return '(%s * %s)' % (self.expand(first),
|
||||
return '(%s * %s)' % (self.expand(first),
|
||||
self.expand(second, first.type))
|
||||
|
||||
def DIV(self, first, second):
|
||||
@@ -1179,7 +1179,7 @@ class BaseAdapter(ConnectionPool):
|
||||
def COMMA(self, first, second):
|
||||
return '%s, %s' % (self.expand(first), self.expand(second))
|
||||
|
||||
def expand(self, expression, field_type=None):
|
||||
def expand(self, expression, field_type=None):
|
||||
if isinstance(expression, Field):
|
||||
return '%s.%s' % (expression.tablename, expression.name)
|
||||
elif isinstance(expression, (Expression, Query)):
|
||||
@@ -1375,24 +1375,24 @@ class BaseAdapter(ConnectionPool):
|
||||
icommand = self.JOIN()
|
||||
if not isinstance(inner_join, (tuple, list)):
|
||||
inner_join = [inner_join]
|
||||
ijoint = [t._tablename for t in inner_join
|
||||
ijoint = [t._tablename for t in inner_join
|
||||
if not isinstance(t,Expression)]
|
||||
ijoinon = [t for t in inner_join if isinstance(t, Expression)]
|
||||
itables_to_merge={} #issue 490
|
||||
[itables_to_merge.update(
|
||||
dict.fromkeys(self.tables(t))) for t in ijoinon]
|
||||
ijoinont = [t.first._tablename for t in ijoinon]
|
||||
[itables_to_merge.pop(t) for t in ijoinont
|
||||
[itables_to_merge.pop(t) for t in ijoinont
|
||||
if t in itables_to_merge] #issue 490
|
||||
iimportant_tablenames = ijoint + ijoinont + itables_to_merge.keys()
|
||||
iexcluded = [t for t in tablenames
|
||||
iexcluded = [t for t in tablenames
|
||||
if not t in iimportant_tablenames]
|
||||
if left:
|
||||
join = attributes['left']
|
||||
command = self.LEFT_JOIN()
|
||||
if not isinstance(join, (tuple, list)):
|
||||
join = [join]
|
||||
joint = [t._tablename for t in join
|
||||
joint = [t._tablename for t in join
|
||||
if not isinstance(t, Expression)]
|
||||
joinon = [t for t in join if isinstance(t, Expression)]
|
||||
#patch join+left patch (solves problem with ordering in left joins)
|
||||
@@ -1402,7 +1402,7 @@ class BaseAdapter(ConnectionPool):
|
||||
joinont = [t.first._tablename for t in joinon]
|
||||
[tables_to_merge.pop(t) for t in joinont if t in tables_to_merge]
|
||||
important_tablenames = joint + joinont + tables_to_merge.keys()
|
||||
excluded = [t for t in tablenames
|
||||
excluded = [t for t in tablenames
|
||||
if not t in important_tablenames ]
|
||||
def alias(t):
|
||||
return str(self.db[t])
|
||||
@@ -1809,10 +1809,10 @@ class BaseAdapter(ConnectionPool):
|
||||
else:
|
||||
id = value
|
||||
colset.update_record = (
|
||||
lambda _ = (colset, table, id), **a:
|
||||
lambda _ = (colset, table, id), **a:
|
||||
update_record(_, a))
|
||||
colset.delete_record = (
|
||||
lambda t = table, i = id:
|
||||
lambda t = table, i = id:
|
||||
t._db(t._id==i).delete())
|
||||
for (referee_table, referee_name) in table._referenced_by:
|
||||
s = db[referee_table][referee_name]
|
||||
@@ -1826,9 +1826,9 @@ class BaseAdapter(ConnectionPool):
|
||||
for tablename in virtualtables:
|
||||
### new style virtual fields
|
||||
table = db[tablename]
|
||||
fields_virtual = [(f,v) for (f,v) in table.items()
|
||||
fields_virtual = [(f,v) for (f,v) in table.items()
|
||||
if isinstance(v,FieldVirtual)]
|
||||
fields_lazy = [(f,v) for (f,v) in table.items()
|
||||
fields_lazy = [(f,v) for (f,v) in table.items()
|
||||
if isinstance(v,FieldLazy)]
|
||||
if fields_virtual or fields_lazy:
|
||||
for row in rowsobj.records:
|
||||
@@ -2101,7 +2101,7 @@ class JDBCSQLiteAdapter(SQLiteAdapter):
|
||||
|
||||
def after_connection(self):
|
||||
# FIXME http://www.zentus.com/sqlitejdbc/custom_functions.html for UDFs
|
||||
self.connection.create_function('web2py_extract', 2,
|
||||
self.connection.create_function('web2py_extract', 2,
|
||||
SQLiteAdapter.web2py_extract)
|
||||
|
||||
def execute(self, a):
|
||||
@@ -2257,7 +2257,7 @@ class PostgreSQLAdapter(BaseAdapter):
|
||||
|
||||
def adapt(self,obj):
|
||||
#if self.driver == self.drivers.get('pg8000'):
|
||||
# obj = str(obj).replace('%','%%')
|
||||
# obj = str(obj).replace('%','%%')
|
||||
return psycopg2_adapt(obj).getquoted()
|
||||
|
||||
def sequence_name(self,table):
|
||||
@@ -2519,7 +2519,7 @@ class NewPostgreSQLAdapter(PostgreSQLAdapter):
|
||||
if fieldtype.startswith('list:string'):
|
||||
obj = [str(item) for item in obj]
|
||||
else:
|
||||
obj = [int(item) for item in obj]
|
||||
obj = [int(item) for item in obj]
|
||||
return 'ARRAY[%s]' % ','.join(repr(item) for item in obj)
|
||||
return BaseAdapter.represent(self, obj, fieldtype)
|
||||
|
||||
@@ -4100,7 +4100,7 @@ class GoogleDatastoreAdapter(NoSQLAdapter):
|
||||
|
||||
def parse_id(self, value, field_type):
|
||||
return value
|
||||
|
||||
|
||||
def create_table(self,table,migrate=True,fake_migrate=False, polymodel=None):
|
||||
myfields = {}
|
||||
for k in table.fields:
|
||||
@@ -4300,7 +4300,7 @@ class GoogleDatastoreAdapter(NoSQLAdapter):
|
||||
if isinstance(attributes.get('reusecursor'), str):
|
||||
cursor = attributes.get('reusecursor')
|
||||
items = gae.Query(tableobj, projection=query_projection, cursor=cursor)
|
||||
|
||||
|
||||
for filter in filters:
|
||||
if attributes.get('projection') == True and \
|
||||
filter.name in query_projection and \
|
||||
@@ -4375,7 +4375,7 @@ class GoogleDatastoreAdapter(NoSQLAdapter):
|
||||
requests, and the filters must be identical. It is up to the user
|
||||
to follow google's limitations: https://developers.google.com/appengine/docs/python/datastore/queries#Query_Cursors
|
||||
"""
|
||||
|
||||
|
||||
(items, tablename, fields) = self.select_raw(query,fields,attributes)
|
||||
# self.db['_lastsql'] = self._select(query,fields,attributes)
|
||||
rows = [[(t==self.db[tablename]._id.name and item) or \
|
||||
@@ -5266,7 +5266,7 @@ class IMAPAdapter(NoSQLAdapter):
|
||||
|
||||
.define_tables() returns a dictionary mapping dal tablenames
|
||||
to the server mailbox names with the following structure:
|
||||
|
||||
|
||||
{<tablename>: str <server mailbox name>}
|
||||
|
||||
Here is a list of supported fields:
|
||||
@@ -5434,7 +5434,7 @@ class IMAPAdapter(NoSQLAdapter):
|
||||
self.imap4 = self.driver.IMAP4
|
||||
connection = self.imap4(driver_args["host"], driver_args["port"])
|
||||
data = connection.login(driver_args["user"], driver_args["password"])
|
||||
|
||||
|
||||
# static mailbox list
|
||||
connection.mailbox_names = None
|
||||
|
||||
@@ -5649,7 +5649,7 @@ class IMAPAdapter(NoSQLAdapter):
|
||||
Field("email", "string", writable=False, readable=False),
|
||||
Field("attachments", "list:string", writable=False, readable=False),
|
||||
)
|
||||
|
||||
|
||||
return self.connection.mailbox_names
|
||||
|
||||
def create_table(self, *args, **kwargs):
|
||||
@@ -5893,7 +5893,7 @@ class IMAPAdapter(NoSQLAdapter):
|
||||
self.connection.mailbox_names[tablename])
|
||||
string_query = "(%s)" % query
|
||||
result, data = self.connection.search(None, string_query)
|
||||
store_list = [item.strip() for item in data[0].split()
|
||||
store_list = [item.strip() for item in data[0].split()
|
||||
if item.strip().isdigit()]
|
||||
# change marked flags
|
||||
for number in store_list:
|
||||
@@ -6346,7 +6346,7 @@ copy_reg.pickle(Row, Row_pickler, Row_unpickler)
|
||||
|
||||
|
||||
################################################################################
|
||||
# Everything below should be independent of the specifics of the database
|
||||
# Everything below should be independent of the specifics of the database
|
||||
# and should work for RDBMs and some NoSQL databases
|
||||
################################################################################
|
||||
|
||||
@@ -6440,7 +6440,7 @@ def smart_query(fields,text):
|
||||
value = constants[item[1:]]
|
||||
else:
|
||||
value = item
|
||||
if field.type in ('text','string'):
|
||||
if field.type in ('text','string'):
|
||||
if op == '=': op = 'like'
|
||||
if op == '=': new_query = field==value
|
||||
elif op == '<': new_query = field<value
|
||||
@@ -7324,7 +7324,7 @@ class Table(dict):
|
||||
archive_name = archive_name % dict(tablename=self._tablename)
|
||||
if archive_name in archive_db.tables():
|
||||
return # do not try define the archive if already exists
|
||||
fieldnames = self.fields()
|
||||
fieldnames = self.fields()
|
||||
field_type = self if archive_db is self._db else 'bigint'
|
||||
archive_table = archive_db.define_table(
|
||||
archive_name,
|
||||
@@ -7607,18 +7607,18 @@ class Table(dict):
|
||||
*args, **kwargs
|
||||
):
|
||||
"""
|
||||
Import records from csv file.
|
||||
Column headers must have same names as table fields.
|
||||
Import records from csv file.
|
||||
Column headers must have same names as table fields.
|
||||
Field 'id' is ignored.
|
||||
If column names read 'table.file' the 'table.' prefix is ignored.
|
||||
'unique' argument is a field which must be unique
|
||||
'unique' argument is a field which must be unique
|
||||
(typically a uuid field)
|
||||
'restore' argument is default False;
|
||||
if set True will remove old values in table first.
|
||||
'id_map' ff set to None will not map ids.
|
||||
The import will keep the id numbers in the restored table.
|
||||
The import will keep the id numbers in the restored table.
|
||||
This assumes that there is an field of type id that
|
||||
is integer and in incrementing order.
|
||||
is integer and in incrementing order.
|
||||
Will keep the id numbers in restored table.
|
||||
"""
|
||||
|
||||
@@ -7703,7 +7703,7 @@ class Table(dict):
|
||||
curr_id = self.insert(**dict(items))
|
||||
if first:
|
||||
first = False
|
||||
# First curr_id is bigger than csv_id,
|
||||
# First curr_id is bigger than csv_id,
|
||||
# then we are not restoring but
|
||||
# extending db table with csv db table
|
||||
if curr_id>csv_id:
|
||||
@@ -8442,7 +8442,7 @@ class Set(object):
|
||||
def count(self,distinct=None):
|
||||
return self.db._adapter.count(self.query,distinct)
|
||||
|
||||
def select(self, *fields, **attributes):
|
||||
def select(self, *fields, **attributes):
|
||||
if self.query is None:# and fields[0]._table._common_filter != None:
|
||||
return self(fields[0]._table).select(*fields,**attributes)
|
||||
adapter = self.db._adapter
|
||||
@@ -9120,3 +9120,4 @@ if __name__ == '__main__':
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -191,3 +191,4 @@ import gluon.main
|
||||
gluon.main.global_settings.debugging = True
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -77,3 +77,4 @@ def decoder(buffer):
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -397,3 +397,4 @@ def abspath(*relpath, **base):
|
||||
return os.path.join(global_settings.gluon_parent, path)
|
||||
return os.path.join(global_settings.applications_parent, path)
|
||||
|
||||
|
||||
|
||||
+10
-9
@@ -428,9 +428,9 @@ class Session(Storage):
|
||||
if not masterapp:
|
||||
masterapp = request.application
|
||||
response.session_id_name = 'session_id_%s' % masterapp.lower()
|
||||
|
||||
|
||||
# Load session data from cookie
|
||||
|
||||
|
||||
if cookie_key:
|
||||
response.session_cookie_key = cookie_key
|
||||
response.session_cookie_key2 = hashlib.md5(cookie_key).digest()
|
||||
@@ -523,25 +523,25 @@ class Session(Storage):
|
||||
migrate=table_migrate,
|
||||
)
|
||||
try:
|
||||
|
||||
# Get session data out of the database
|
||||
|
||||
# Key comes from the cookie
|
||||
|
||||
# Get session data out of the database
|
||||
|
||||
# Key comes from the cookie
|
||||
key = request.cookies[response.session_id_name].value
|
||||
(record_id, unique_key) = key.split(':')
|
||||
if record_id == '0':
|
||||
raise Exception, 'record_id == 0'
|
||||
# Select from database.
|
||||
# Select from database.
|
||||
rows = db(table.id == record_id).select()
|
||||
|
||||
# Make sure the session data exists in the database
|
||||
# Make sure the session data exists in the database
|
||||
if len(rows) == 0 or rows[0].unique_key != unique_key:
|
||||
raise Exception, 'No record'
|
||||
|
||||
# rows[0].update_record(locked=True)
|
||||
|
||||
|
||||
# Unpickle the data
|
||||
# Unpickle the data
|
||||
session_data = cPickle.loads(rows[0].session_data)
|
||||
self.update(session_data)
|
||||
except Exception:
|
||||
@@ -668,3 +668,4 @@ class Session(Storage):
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -347,3 +347,4 @@ if __name__ == '__main__':
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+5
-4
@@ -2034,11 +2034,11 @@ class FORM(DIV):
|
||||
return self
|
||||
|
||||
REDIRECT_JS = "window.location='%s';return false"
|
||||
|
||||
|
||||
def add_button(self,value,url,_class=None):
|
||||
self[0][-1][1].append(INPUT(_type="button",_value=value,_class=_class,
|
||||
_onclick=self.REDIRECT_JS % url))
|
||||
|
||||
|
||||
|
||||
|
||||
@staticmethod
|
||||
@@ -2052,7 +2052,7 @@ class FORM(DIV):
|
||||
inputs += [INPUT(_type='hidden',
|
||||
_name=name,
|
||||
_value=value)
|
||||
for name,value in hidden.items()]
|
||||
for name,value in hidden.items()]
|
||||
form = FORM(INPUT(_type='submit',_value=text),*inputs)
|
||||
form.process()
|
||||
return form
|
||||
@@ -2385,7 +2385,7 @@ class MARKMIN(XmlComponent):
|
||||
autolinks='default',
|
||||
protolinks='default',
|
||||
class_prefix='',
|
||||
id_prefix='markmin_'):
|
||||
id_prefix='markmin_'):
|
||||
self.text = text
|
||||
self.extra = extra or {}
|
||||
self.allowed = allowed or {}
|
||||
@@ -2434,3 +2434,4 @@ if __name__ == '__main__':
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+2
-1
@@ -128,7 +128,7 @@ class HTTP(BaseException):
|
||||
|
||||
def redirect(location, how=303, client_side=False):
|
||||
if location:
|
||||
from gluon import current
|
||||
from gluon import current
|
||||
loc = location.replace('\r', '%0D').replace('\n', '%0A')
|
||||
if client_side and current.request.ajax:
|
||||
raise HTTP(200, **{'web2py-redirect-location': loc})
|
||||
@@ -141,3 +141,4 @@ def redirect(location, how=303, client_side=False):
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -112,3 +112,4 @@ for module in base_modules + contributed_modules:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -938,3 +938,4 @@ if __name__ == '__main__':
|
||||
import doctest
|
||||
doctest.testmod()
|
||||
|
||||
|
||||
|
||||
+2
-1
@@ -562,7 +562,7 @@ def wsgibase(environ, responder):
|
||||
del response.cookies[response.session_id_name]
|
||||
elif session._secure:
|
||||
response.cookies[response.session_id_name]['secure'] = True
|
||||
|
||||
|
||||
http_response.cookies2headers(response.cookies)
|
||||
ticket=None
|
||||
|
||||
@@ -851,3 +851,4 @@ class HttpServer(object):
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -13,3 +13,4 @@ class MessageBoxHandler(logging.Handler):
|
||||
if tkMessageBox:
|
||||
msg = self.format(record)
|
||||
tkMessageBox.showinfo('info1', msg)
|
||||
|
||||
|
||||
@@ -31,3 +31,4 @@ regex_extend = re.compile(\
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -342,3 +342,4 @@ def crondance(applications_parent, ctype='soft', startup=False, apps=None):
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -150,3 +150,4 @@ if __name__=='__main__':
|
||||
f.close()
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1716,3 +1716,4 @@ ADAPTERS['all'] = reduce(lambda a,b:a.union(b),(x for x in ADAPTERS.values()))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -306,3 +306,4 @@ def snapshot(info=None, context=5, code=None, environment=None):
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1316,3 +1316,4 @@ def get_effective_router(appname):
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2084,3 +2084,4 @@ if __name__=='__main__':
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -227,3 +227,4 @@ def sanitize(text, permitted_tags=[
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+2
-1
@@ -108,7 +108,7 @@ SECONDS = 1
|
||||
HEARTBEAT = 3*SECONDS
|
||||
MAXHIBERNATION = 10
|
||||
|
||||
CALLABLETYPES = (types.LambdaType, types.FunctionType,
|
||||
CALLABLETYPES = (types.LambdaType, types.FunctionType,
|
||||
types.BuiltinFunctionType,
|
||||
types.MethodType, types.BuiltinMethodType)
|
||||
|
||||
@@ -801,3 +801,4 @@ def main():
|
||||
|
||||
if __name__=='__main__':
|
||||
main()
|
||||
|
||||
|
||||
@@ -116,3 +116,4 @@ def rss(feed):
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -33,3 +33,4 @@ global_settings.is_jython = 'java' in sys.platform.lower() or \
|
||||
hasattr(sys, 'JYTHON_JAR') or \
|
||||
str(sys.copyright).find('Jython') > 0
|
||||
|
||||
|
||||
|
||||
+4
-3
@@ -61,7 +61,7 @@ def exec_environment(
|
||||
appname = mo.group('appname')
|
||||
request.folder = os.path.join('applications', appname)
|
||||
else:
|
||||
request.folder = ''
|
||||
request.folder = ''
|
||||
env = build_environment(request, response, session, store_current=False)
|
||||
if pyfile:
|
||||
pycfile = pyfile + 'c'
|
||||
@@ -123,7 +123,7 @@ def env(
|
||||
return True
|
||||
|
||||
fileutils.check_credentials = check_credentials
|
||||
|
||||
|
||||
environment = build_environment(request, response, session)
|
||||
|
||||
if import_models:
|
||||
@@ -178,7 +178,7 @@ def run(
|
||||
logging.warn('application does not exist and will not be created')
|
||||
return
|
||||
if c.lower() in ['y', 'yes']:
|
||||
|
||||
|
||||
os.mkdir(adir)
|
||||
w2p_unpack('welcome.w2p', adir)
|
||||
for subfolder in ['models','views','controllers', 'databases',
|
||||
@@ -430,3 +430,4 @@ if __name__ == '__main__':
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -8,3 +8,4 @@ from dal import DAL, Field, Table, Query, Set, Expression, Row, Rows, drivers, B
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+8
-7
@@ -414,9 +414,9 @@ class CheckboxesWidget(OptionsWidget):
|
||||
|
||||
|
||||
if opts:
|
||||
opts.append(INPUT(_class="hidden", requires=attr.get('requires', None),
|
||||
opts.append(INPUT(_class="hidden", requires=attr.get('requires', None),
|
||||
_disabled="disabled", _name=field.name,
|
||||
hideerror=False))
|
||||
hideerror=False))
|
||||
return parent(*opts, **attr)
|
||||
|
||||
|
||||
@@ -1298,14 +1298,14 @@ class SQLFORM(FORM):
|
||||
f = os.path.join(current.request.folder,
|
||||
os.path.normpath(f))
|
||||
source_file = open(f, 'rb')
|
||||
original_filename = os.path.split(f)[1]
|
||||
original_filename = os.path.split(f)[1]
|
||||
elif hasattr(f, 'file'):
|
||||
(source_file, original_filename) = (f.file, f.filename)
|
||||
elif isinstance(f, (str, unicode)):
|
||||
### do not know why this happens, it should not
|
||||
(source_file, original_filename) = \
|
||||
(cStringIO.StringIO(f), 'file.txt')
|
||||
newfilename = field.store(source_file, original_filename,
|
||||
(source_file, original_filename) = \
|
||||
(cStringIO.StringIO(f), 'file.txt')
|
||||
newfilename = field.store(source_file, original_filename,
|
||||
field.uploadfolder)
|
||||
# this line was for backward compatibility but problematic
|
||||
# self.vars['%s_newfilename' % fieldname] = newfilename
|
||||
@@ -1890,7 +1890,7 @@ class SQLFORM(FORM):
|
||||
label = k
|
||||
options.append(OPTION(T(label),_value=k))
|
||||
items = url2().split('?', 1)
|
||||
myurl = items[0]
|
||||
myurl = items[0]
|
||||
if len(items)>1:
|
||||
mysignature = psq(items[1]).get('_signature', [None])[-1]
|
||||
else:
|
||||
@@ -2637,3 +2637,4 @@ class ExporterHtml(ExportClass):
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+2
-1
@@ -25,7 +25,7 @@ class List(list):
|
||||
instead of IndexOutOfBounds
|
||||
"""
|
||||
|
||||
def __call__(self, i, default=None, cast=None, url_onerror=None):
|
||||
def __call__(self, i, default=None, cast=None, url_onerror=None):
|
||||
n = len(self)
|
||||
if 0<=i<n or -n<=i<0:
|
||||
value = self[i]
|
||||
@@ -244,3 +244,4 @@ if __name__ == '__main__':
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -111,3 +111,4 @@ def stream_file_or_304_or_206(
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -947,3 +947,4 @@ if __name__ == '__main__':
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+33
-32
@@ -676,8 +676,8 @@ class Recaptcha(DIV):
|
||||
Usage:
|
||||
|
||||
form = FORM(Recaptcha(public_key='...',private_key='...'))
|
||||
|
||||
or
|
||||
|
||||
or
|
||||
|
||||
form = SQLFORM(...)
|
||||
form.append(Recaptcha(public_key='...',private_key='...'))
|
||||
@@ -1152,7 +1152,7 @@ class Auth(object):
|
||||
|
||||
# for "remember me" option
|
||||
response = current.response
|
||||
if auth and auth.remember:
|
||||
if auth and auth.remember:
|
||||
# when user wants to be logged in for longer
|
||||
response.cookies[response.session_id_name]["expires"] = \
|
||||
auth.expiration
|
||||
@@ -1223,12 +1223,12 @@ class Auth(object):
|
||||
if URL() == action:
|
||||
next = ''
|
||||
else:
|
||||
next = '?_next=' + urllib.quote(URL(args=request.args,
|
||||
next = '?_next=' + urllib.quote(URL(args=request.args,
|
||||
vars=request.get_vars))
|
||||
|
||||
|
||||
href = lambda function: '%s/%s%s' % (action, function,
|
||||
next if referrer_actions is DEFAULT or function in referrer_actions else '')
|
||||
|
||||
|
||||
if self.user_id:
|
||||
if user_identifier is DEFAULT:
|
||||
user_identifier = '%(first_name)s'
|
||||
@@ -1279,7 +1279,7 @@ class Auth(object):
|
||||
else:
|
||||
return True
|
||||
|
||||
def enable_record_versioning(self,
|
||||
def enable_record_versioning(self,
|
||||
tables,
|
||||
archive_db = None,
|
||||
archive_names='%(tablename)s_archive',
|
||||
@@ -1295,13 +1295,13 @@ class Auth(object):
|
||||
|
||||
tables can be the db (all table) or a list of tables.
|
||||
only tables with modified_by and modified_on fiels (as created
|
||||
by auth.signature) will have versioning. Old record versions will be
|
||||
by auth.signature) will have versioning. Old record versions will be
|
||||
in table 'mything_archive' automatically defined.
|
||||
|
||||
|
||||
when you enable enable_record_versioning, records are never
|
||||
deleted but marked with is_active=False.
|
||||
|
||||
enable_record_versioning enables a common_filter for
|
||||
enable_record_versioning enables a common_filter for
|
||||
every table that filters out records with is_active = False
|
||||
|
||||
Important: If you use auth.enable_record_versioning,
|
||||
@@ -1311,7 +1311,7 @@ class Auth(object):
|
||||
|
||||
"""
|
||||
tables = [table for table in tables]
|
||||
for table in tables:
|
||||
for table in tables:
|
||||
if 'modified_on' in table.fields():
|
||||
table._enable_record_versioning(
|
||||
archive_db = archive_db,
|
||||
@@ -1355,7 +1355,7 @@ class Auth(object):
|
||||
label=T('Modified By')))
|
||||
|
||||
|
||||
def define_tables(self, username=False, signature=None,
|
||||
def define_tables(self, username=False, signature=None,
|
||||
migrate=True, fake_migrate=False):
|
||||
"""
|
||||
to be called unless tables are defined manually
|
||||
@@ -2021,7 +2021,7 @@ class Auth(object):
|
||||
cas_user = cas.get_user()
|
||||
if cas_user:
|
||||
next = cas.logout_url(next)
|
||||
|
||||
|
||||
current.session.auth = None
|
||||
current.session.flash = self.messages.logged_out
|
||||
redirect(next)
|
||||
@@ -2061,7 +2061,7 @@ class Auth(object):
|
||||
username = 'username'
|
||||
else:
|
||||
username = 'email'
|
||||
|
||||
|
||||
# Ensure the username field is unique.
|
||||
unique_validator = IS_NOT_IN_DB(self.db, table_user[username])
|
||||
if not table_user[username].requires:
|
||||
@@ -2076,7 +2076,7 @@ class Auth(object):
|
||||
elif not isinstance(table_user[username].requires, IS_NOT_IN_DB):
|
||||
table_user[username].requires = [table_user[username].requires,
|
||||
unique_validator]
|
||||
|
||||
|
||||
passfield = self.settings.password_field
|
||||
formstyle = self.settings.formstyle
|
||||
form = SQLFORM(table_user,
|
||||
@@ -2639,7 +2639,7 @@ class Auth(object):
|
||||
redirect(next)
|
||||
return form
|
||||
|
||||
def is_impersonating(self):
|
||||
def is_impersonating(self):
|
||||
return current.session.auth and \
|
||||
'impersonator' in current.session.auth
|
||||
|
||||
@@ -2851,8 +2851,8 @@ class Auth(object):
|
||||
else:
|
||||
user = self.user
|
||||
return self.settings.create_user_groups % user
|
||||
|
||||
|
||||
|
||||
|
||||
def has_membership(self, group_id=None, user_id=None, role=None):
|
||||
"""
|
||||
checks if user is member of group_id or role
|
||||
@@ -2935,7 +2935,7 @@ class Auth(object):
|
||||
self.has_permission(
|
||||
name,table_name,record_id,user_id=None,
|
||||
group_id=self.settings.everybody_group_id): return True
|
||||
|
||||
|
||||
if not user_id and not group_id and self.user:
|
||||
user_id = self.user.id
|
||||
if user_id:
|
||||
@@ -4453,7 +4453,7 @@ class Wiki(object):
|
||||
everybody = 'everybody'
|
||||
rows_page = 25
|
||||
regex_redirect = re.compile('redirect\s+(\w+\://\S+)\s*')
|
||||
def markmin_render(self,page):
|
||||
def markmin_render(self,page):
|
||||
return MARKMIN(page.body,url=True,environment=self.env,
|
||||
autolinks=lambda link: expand_one(link,{})).xml()
|
||||
def __init__(self,auth,env=None,automenu=True,render='markmin',
|
||||
@@ -4501,7 +4501,7 @@ class Wiki(object):
|
||||
if tag: db.wiki_tag.insert(name=tag,wiki_page=id)
|
||||
def update_tags_update(dbset,page,db=db):
|
||||
page = dbset.select().first()
|
||||
db(db.wiki_tag.wiki_page==page.id).delete()
|
||||
db(db.wiki_tag.wiki_page==page.id).delete()
|
||||
for tag in page.tags or []:
|
||||
tag = tag.strip().lower()
|
||||
if tag: db.wiki_tag.insert(name=tag,wiki_page=page.id)
|
||||
@@ -4515,7 +4515,7 @@ class Wiki(object):
|
||||
return True
|
||||
elif self.auth.user:
|
||||
groups = self.auth.user_groups.values()
|
||||
if ('wiki_editor' in groups or
|
||||
if ('wiki_editor' in groups or
|
||||
set(groups).intersection(set(page.can_read+page.can_edit)) or
|
||||
page.created_by==self.auth.user.id): return True
|
||||
return False
|
||||
@@ -4525,7 +4525,7 @@ class Wiki(object):
|
||||
return ('wiki_editor' in groups or
|
||||
(page is None and 'wiki_author' in groups) or
|
||||
not page is None and (
|
||||
set(groups).intersection(set(page.can_edit)) or
|
||||
set(groups).intersection(set(page.can_edit)) or
|
||||
page.created_by==self.auth.user.id))
|
||||
def can_manage(self):
|
||||
if not self.auth.user: redirect(self.auth.settings.login_url)
|
||||
@@ -4564,7 +4564,7 @@ class Wiki(object):
|
||||
)
|
||||
elif zero=='_cloud':
|
||||
return self.cloud()
|
||||
|
||||
|
||||
|
||||
def first_paragraph(self,page):
|
||||
if not self.can_read(page):
|
||||
@@ -4582,13 +4582,13 @@ class Wiki(object):
|
||||
redirect(URL(args=('_create',slug)))
|
||||
if not self.can_read(page): return self.not_authorized(page)
|
||||
if current.request.extension == 'html':
|
||||
if not page:
|
||||
if not page:
|
||||
url = URL(args=('_edit',slug))
|
||||
return dict(content=A('Create page "%s"' % slug,_href=url,_class="btn"))
|
||||
else:
|
||||
match = self.regex_redirect.match(page.body)
|
||||
if match: redirect(match.group(1))
|
||||
return dict(content=XML(page.html))
|
||||
return dict(content=XML(page.html))
|
||||
elif current.request.extension == 'load':
|
||||
return page.html if page else ''
|
||||
else:
|
||||
@@ -4607,7 +4607,7 @@ class Wiki(object):
|
||||
redirect(self.auth.settings.login_url)
|
||||
elif not self.auth.has_membership(role):
|
||||
if not act: return False
|
||||
raise HTTP(401, "Not Authorized")
|
||||
raise HTTP(401, "Not Authorized")
|
||||
return True
|
||||
def edit(self,slug):
|
||||
auth = self.auth
|
||||
@@ -4729,7 +4729,7 @@ class Wiki(object):
|
||||
if mode in (1,2):
|
||||
submenu.append((current.T('Edit Page Media'),None,
|
||||
URL(controller,function,args=('_editmedia',slug))))
|
||||
|
||||
|
||||
submenu.append((current.T('Create New Page'),None,
|
||||
URL(controller,function,args=('_create'))))
|
||||
# if self.can_manage():
|
||||
@@ -4740,7 +4740,7 @@ class Wiki(object):
|
||||
URL(controller,function,args=('_search'))))
|
||||
return menu
|
||||
def search(self,tags=None,query=None,cloud=True,preview=True,
|
||||
limitby=(0,100),orderby=None):
|
||||
limitby=(0,100),orderby=None):
|
||||
if not self.can_search(): return self.not_authorized()
|
||||
request = current.request
|
||||
content = CAT()
|
||||
@@ -4766,7 +4766,7 @@ class Wiki(object):
|
||||
pages = db(query).select(
|
||||
*fields,**dict(orderby=orderby or ~count,
|
||||
groupby=db.wiki_page.id,
|
||||
limitby=limitby))
|
||||
limitby=limitby))
|
||||
if request.extension in ('html','load'):
|
||||
if not pages:
|
||||
content.append(DIV(T("No results",_class='w2p_wiki_form')))
|
||||
@@ -4784,7 +4784,7 @@ class Wiki(object):
|
||||
cloud=False
|
||||
content = [p.as_dict() for p in pages]
|
||||
elif cloud:
|
||||
content.append(self.cloud()['content'])
|
||||
content.append(self.cloud()['content'])
|
||||
if request.extension=='load':
|
||||
return content
|
||||
return dict(content=content)
|
||||
@@ -4806,10 +4806,11 @@ class Wiki(object):
|
||||
vars=dict(tags=item.wiki_tag.name)))
|
||||
for item in ids]
|
||||
return dict(content=DIV(_class='w2p_cloud',*items))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import doctest
|
||||
doctest.testmod()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -653,3 +653,4 @@ if __name__ == '__main__':
|
||||
|
||||
doctests()
|
||||
|
||||
|
||||
|
||||
+5
-4
@@ -47,7 +47,7 @@ def simple_hash(text, key='', salt = '', digest_alg = 'md5'):
|
||||
elif digest_alg.startswith('pbkdf2'): # latest and coolest!
|
||||
iterations, keylen, alg = digest_alg[7:-1].split(',')
|
||||
return pbkdf2_hex(text, salt, int(iterations),
|
||||
int(keylen),get_digest(alg))
|
||||
int(keylen),get_digest(alg))
|
||||
elif key: # use hmac
|
||||
digest_alg = get_digest(digest_alg)
|
||||
h = hmac.new(key+salt,text,digest_alg)
|
||||
@@ -154,7 +154,7 @@ def is_valid_ip_address(address):
|
||||
True
|
||||
>>> is_valid_ip_address('2001:660::1')
|
||||
True
|
||||
"""
|
||||
"""
|
||||
# deal with special cases
|
||||
if address.lower() in ('127.0.0.1','localhost','::1','::ffff:127.0.0.1'):
|
||||
return True
|
||||
@@ -166,7 +166,7 @@ def is_valid_ip_address(address):
|
||||
addr = socket.inet_aton(address)
|
||||
return True
|
||||
except socket.error: # invalid address
|
||||
return False
|
||||
return False
|
||||
else: # try validate using Regex
|
||||
match = REGEX_IPv4.match(address)
|
||||
if match and all(0<=int(math.group(i))<256 for i in (1,2,3,4)):
|
||||
@@ -177,7 +177,7 @@ def is_valid_ip_address(address):
|
||||
addr = socket.inet_pton(socket.AF_INET6, address)
|
||||
return True
|
||||
except socket.error: # invalid address
|
||||
return False
|
||||
return False
|
||||
else: # do not know what to do? assume it is a valid address
|
||||
return True
|
||||
|
||||
@@ -185,3 +185,4 @@ def is_valid_ip_address(address):
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+20
-19
@@ -266,7 +266,7 @@ class IS_LENGTH(Validator):
|
||||
if value is None:
|
||||
length = 0
|
||||
if self.minsize <= length <= self.maxsize:
|
||||
return (value, None)
|
||||
return (value, None)
|
||||
elif isinstance(value, cgi.FieldStorage):
|
||||
if value.file:
|
||||
value.file.seek(0, os.SEEK_END)
|
||||
@@ -460,7 +460,7 @@ class IS_IN_DB(Validator):
|
||||
orderby = self.orderby or reduce(lambda a,b:a|b,fields)
|
||||
groupby = self.groupby
|
||||
distinct = self.distinct
|
||||
dd = dict(orderby=orderby, groupby=groupby,
|
||||
dd = dict(orderby=orderby, groupby=groupby,
|
||||
distinct=distinct, cache=self.cache)
|
||||
records = self.dbset(table).select(*fields, **dd)
|
||||
else:
|
||||
@@ -2560,7 +2560,7 @@ class LazyCrypt(object):
|
||||
key = 'pbkdf2(1000,64,sha512):uuid' 1000 iterations and 64 chars length
|
||||
"""
|
||||
if self.crypted:
|
||||
return self.crypted
|
||||
return self.crypted
|
||||
if self.crypt.key:
|
||||
if ':' in self.crypt.key:
|
||||
digest_alg, key = self.crypt.key.split(':',1)
|
||||
@@ -2569,7 +2569,7 @@ class LazyCrypt(object):
|
||||
else:
|
||||
digest_alg, key = self.crypt.digest_alg, ''
|
||||
if self.crypt.salt:
|
||||
if self.crypt.salt == True:
|
||||
if self.crypt.salt == True:
|
||||
salt = str(web2py_uuid()).replace('-','')[-16:]
|
||||
else:
|
||||
salt = self.crypt.salt
|
||||
@@ -2579,13 +2579,13 @@ class LazyCrypt(object):
|
||||
self.crypted = '%s$%s$%s' % (digest_alg, salt, hashed)
|
||||
return self.crypted
|
||||
|
||||
def __eq__(self, stored_password):
|
||||
def __eq__(self, stored_password):
|
||||
"""
|
||||
compares the current lazy crypted password with a stored password
|
||||
"""
|
||||
if self.crypt.key:
|
||||
if ':' in self.crypt.key:
|
||||
key = self.crypt.key.split(':')[1]
|
||||
key = self.crypt.key.split(':')[1]
|
||||
else:
|
||||
key = self.crypt.key
|
||||
else:
|
||||
@@ -2593,16 +2593,16 @@ class LazyCrypt(object):
|
||||
if stored_password.count('$')==2:
|
||||
(digest_alg, salt, hash) = stored_password.split('$')
|
||||
h = simple_hash(self.password, key, salt, digest_alg)
|
||||
temp_pass = '%s$%s$%s' % (digest_alg, salt, h)
|
||||
temp_pass = '%s$%s$%s' % (digest_alg, salt, h)
|
||||
else: # no salting
|
||||
# guess digest_alg
|
||||
digest_alg = DIGEST_ALG_BY_SIZE.get(len(stored_password),None)
|
||||
if not digest_alg:
|
||||
if not digest_alg:
|
||||
return False
|
||||
else:
|
||||
temp_pass = simple_hash(self.password, key, '', digest_alg)
|
||||
return temp_pass == stored_password
|
||||
|
||||
|
||||
|
||||
class CRYPT(object):
|
||||
"""
|
||||
@@ -2624,23 +2624,23 @@ class CRYPT(object):
|
||||
Notice that an empty password is accepted but invalid. It will not allow login back.
|
||||
Stores junk as hashed password.
|
||||
|
||||
Specify an algorithm or by default we will use sha512.
|
||||
Specify an algorithm or by default we will use sha512.
|
||||
|
||||
Typical available algorithms:
|
||||
md5, sha1, sha224, sha256, sha384, sha512
|
||||
Typical available algorithms:
|
||||
md5, sha1, sha224, sha256, sha384, sha512
|
||||
|
||||
If salt, it hashes a password with a salt.
|
||||
If salt is True, this method will automatically generate one.
|
||||
If salt is True, this method will automatically generate one.
|
||||
Either case it returns an encrypted password string in the following format:
|
||||
|
||||
<algorithm>$<salt>$<hash>
|
||||
<algorithm>$<salt>$<hash>
|
||||
|
||||
Important: hashed password is returned as a LazyCrypt object and computed only if needed.
|
||||
The LasyCrypt object also knows how to compare itself with an existing salted password
|
||||
|
||||
Supports standard algorithms
|
||||
|
||||
>>> for alg in ('md5','sha1','sha256','sha384','sha512'):
|
||||
>>> for alg in ('md5','sha1','sha256','sha384','sha512'):
|
||||
... print str(CRYPT(digest_alg=alg,salt=True)('test')[0])
|
||||
md5$...$...
|
||||
sha1$...$...
|
||||
@@ -2682,17 +2682,17 @@ class CRYPT(object):
|
||||
True
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
key=None,
|
||||
def __init__(self,
|
||||
key=None,
|
||||
digest_alg='pbkdf2(1000,20,sha512)',
|
||||
min_length=0,
|
||||
min_length=0,
|
||||
error_message='too short', salt=True):
|
||||
"""
|
||||
important, digest_alg='md5' is not the default hashing algorithm for
|
||||
web2py. This is only an example of usage of this function.
|
||||
|
||||
The actual hash algorithm is determined from the key which is
|
||||
generated by web2py in tools.py. This defaults to hmac+sha512.
|
||||
generated by web2py in tools.py. This defaults to hmac+sha512.
|
||||
"""
|
||||
self.key = key
|
||||
self.digest_alg = digest_alg
|
||||
@@ -3151,3 +3151,4 @@ if __name__ == '__main__':
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1183,3 +1183,4 @@ end tell
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+2
-1
@@ -90,7 +90,7 @@ class Web2pyService(Service):
|
||||
cls = _winreg.QueryValue(h, 'PythonClass')
|
||||
finally:
|
||||
_winreg.CloseKey(h)
|
||||
dir = os.path.dirname(cls)
|
||||
dir = os.path.dirname(cls)
|
||||
os.chdir(dir)
|
||||
from gluon.settings import global_settings
|
||||
global_settings.gluon_parent = dir
|
||||
@@ -171,3 +171,4 @@ if __name__ == '__main__':
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -24,3 +24,4 @@ def handler(request, response, methods):
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -36,3 +36,4 @@ if __name__=='__main__':
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -225,3 +225,4 @@ def handler(req):
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -34,3 +34,4 @@ nocron = None
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -212,3 +212,4 @@ if __name__ == '__main__':
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -173,3 +173,4 @@ if __name__ == '__main__':
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -74,3 +74,4 @@ if SOFTCRON:
|
||||
SCGIServer(application, port=4000).enable_sighandler().run()
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -55,3 +55,4 @@ setup(app=['web2py.py'],
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -185,3 +185,4 @@ print "Enjoy web2py " +web2py_version_line
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -167,3 +167,4 @@ print "Enjoy web2py " +web2py_version_line
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -45,3 +45,4 @@ if SOFTCRON:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user