removed unwanted whitespaces

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