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)
|
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__':
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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 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:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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))
|
.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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
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__':
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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'
|
'c697356ad4b37dfaefc5913972e4d3bd'
|
||||||
'61c29f254a943366cc831d3a74e8cb'.decode('hex')
|
'61c29f254a943366cc831d3a74e8cb'.decode('hex')
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
return thumb
|
||||||
else:
|
else:
|
||||||
return image
|
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__':
|
if __name__ == '__main__':
|
||||||
test()
|
test()
|
||||||
|
|
||||||
|
|||||||
@@ -170,3 +170,4 @@ if __name__ == '__main__':
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -963,3 +963,4 @@ if __name__ == '__main__':
|
|||||||
qdb.main(**kwargs)
|
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)
|
print client.add(1, 2)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -115,3 +115,4 @@ def sms_email(number,provider):
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
# You can turn off ordering of results
|
||||||
print(t.getReportText(orderByCost=False))
|
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()
|
>>> 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__':
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -191,3 +191,4 @@ import gluon.main
|
|||||||
gluon.main.global_settings.debugging = True
|
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.gluon_parent, path)
|
||||||
return os.path.join(global_settings.applications_parent, path)
|
return os.path.join(global_settings.applications_parent, path)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+10
-9
@@ -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):
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -347,3 +347,4 @@ if __name__ == '__main__':
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+5
-4
@@ -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
@@ -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):
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -112,3 +112,4 @@ for module in base_modules + contributed_modules:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -938,3 +938,4 @@ if __name__ == '__main__':
|
|||||||
import doctest
|
import doctest
|
||||||
doctest.testmod()
|
doctest.testmod()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -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):
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|
||||||
|
|||||||
@@ -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()
|
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
|
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()
|
||||||
|
|
||||||
|
|||||||
@@ -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 \
|
hasattr(sys, 'JYTHON_JAR') or \
|
||||||
str(sys.copyright).find('Jython') > 0
|
str(sys.copyright).find('Jython') > 0
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+4
-3
@@ -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__':
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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:
|
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
@@ -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__':
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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:
|
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()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -653,3 +653,4 @@ if __name__ == '__main__':
|
|||||||
|
|
||||||
doctests()
|
doctests()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+5
-4
@@ -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
@@ -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__':
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1183,3 +1183,4 @@ end tell
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -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__':
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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()
|
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