fixing merge issue

This commit is contained in:
mdipierro
2016-05-04 09:29:30 -05:00
2 changed files with 311 additions and 241 deletions
+124 -105
View File
@@ -32,15 +32,15 @@ from gluon.languages import (read_possible_languages, read_dict, write_dict,
if DEMO_MODE and request.function in ['change_password', 'pack', if DEMO_MODE and request.function in ['change_password', 'pack',
'pack_custom','pack_plugin', 'upgrade_web2py', 'uninstall', 'pack_custom', 'pack_plugin', 'upgrade_web2py', 'uninstall',
'cleanup', 'compile_app', 'remove_compiled_app', 'delete', 'cleanup', 'compile_app', 'remove_compiled_app', 'delete',
'delete_plugin', 'create_file', 'upload_file', 'update_languages', 'delete_plugin', 'create_file', 'upload_file', 'update_languages',
'reload_routes', 'git_push', 'git_pull', 'install_plugin']: 'reload_routes', 'git_push', 'git_pull', 'install_plugin']:
session.flash = T('disabled in demo mode') session.flash = T('disabled in demo mode')
redirect(URL('site')) redirect(URL('site'))
if is_gae and request.function in ('edit', 'edit_language', if is_gae and request.function in ('edit', 'edit_language',
'edit_plurals', 'update_languages', 'create_file', 'install_plugin'): 'edit_plurals', 'update_languages', 'create_file', 'install_plugin'):
session.flash = T('disabled in GAE mode') session.flash = T('disabled in GAE mode')
redirect(URL('site')) redirect(URL('site'))
@@ -74,8 +74,10 @@ def log_progress(app, mode='EDIT', filename=None, progress=0):
def safe_open(a, b): def safe_open(a, b):
if (DEMO_MODE or is_gae) and ('w' in b or 'a' in b): if (DEMO_MODE or is_gae) and ('w' in b or 'a' in b):
class tmp: class tmp:
def write(self, data): def write(self, data):
pass pass
def close(self): def close(self):
pass pass
return tmp() return tmp()
@@ -208,6 +210,7 @@ def site():
file_or_appurl = 'file' in request.vars or 'appurl' in request.vars file_or_appurl = 'file' in request.vars or 'appurl' in request.vars
class IS_VALID_APPNAME(object): class IS_VALID_APPNAME(object):
def __call__(self, value): def __call__(self, value):
if not re.compile('^\w+$').match(value): if not re.compile('^\w+$').match(value):
return (value, T('Invalid application name')) return (value, T('Invalid application name'))
@@ -325,7 +328,7 @@ def report_progress(app):
if not m: if not m:
continue continue
days = -(request.now - datetime.datetime.strptime(m[0], days = -(request.now - datetime.datetime.strptime(m[0],
'%Y-%m-%d %H:%M:%S')).days '%Y-%m-%d %H:%M:%S')).days
counter += int(m[1]) counter += int(m[1])
events.append([days, counter]) events.append([days, counter])
return events return events
@@ -353,6 +356,7 @@ def pack():
session.flash = T('internal error: %s', e) session.flash = T('internal error: %s', e)
redirect(URL('site')) redirect(URL('site'))
def pack_plugin(): def pack_plugin():
app = get_app() app = get_app()
if len(request.args) == 2: if len(request.args) == 2:
@@ -368,7 +372,6 @@ def pack_plugin():
redirect(URL('plugin', args=request.args)) redirect(URL('plugin', args=request.args))
def pack_exe(app, base, filenames=None): def pack_exe(app, base, filenames=None):
import urllib import urllib
import zipfile import zipfile
@@ -397,10 +400,20 @@ def pack_exe(app, base, filenames=None):
def pack_custom(): def pack_custom():
app = get_app() app = get_app()
base = apath(app, r=request) base = apath(app, r=request)
def ignore(fs):
return [f for f in fs if not (
f[:1] in '#' or f.endswith('~') or f.endswith('.bak'))]
files = {}
for (r, d, f) in os.walk(base):
files[r] = {'folders': ignore(d), 'files': ignore(f)}
if request.post_vars.file: if request.post_vars.file:
valid_set = set(os.path.relpath(os.path.join(r, f), base) for r in files for f in files[r]['files'])
files = request.post_vars.file files = request.post_vars.file
files = [files] if not isinstance(files,list) else files files = [files] if not isinstance(files, list) else files
files = [file for file in files if file in valid_set]
if request.post_vars.doexe is None: if request.post_vars.doexe is None:
fname = 'web2py.app.%s.w2p' % app fname = 'web2py.app.%s.w2p' % app
try: try:
@@ -417,12 +430,7 @@ def pack_custom():
redirect(URL(args=request.args)) redirect(URL(args=request.args))
else: else:
return pack_exe(app, base, files) return pack_exe(app, base, files)
def ignore(fs):
return [f for f in fs if not (
f[:1] in '#' or f.endswith('~') or f.endswith('.bak'))]
files = {}
for (r,d,f) in os.walk(base):
files[r] = {'folders':ignore(d),'files':ignore(f)}
return locals() return locals()
@@ -485,14 +493,14 @@ def cleanup():
def compile_app(): def compile_app():
app = get_app() app = get_app()
c = app_compile(app, request, c = app_compile(app, request,
skip_failed_views = (request.args(1) == 'skip_failed_views')) skip_failed_views=(request.args(1) == 'skip_failed_views'))
if not c: if not c:
session.flash = T('application compiled') session.flash = T('application compiled')
elif isinstance(c, list): elif isinstance(c, list):
session.flash = DIV(*[T('application compiled'), BR(), BR(), session.flash = DIV(*[T('application compiled'), BR(), BR(),
T('WARNING: The following views could not be compiled:'), BR()] + T('WARNING: The following views could not be compiled:'), BR()] +
[CAT(BR(), view) for view in c] + [CAT(BR(), view) for view in c] +
[BR(), BR(), T('DO NOT use the "Pack compiled" feature.')]) [BR(), BR(), T('DO NOT use the "Pack compiled" feature.')])
else: else:
session.flash = DIV(T('Cannot compile: there are errors in your app:'), session.flash = DIV(T('Cannot compile: there are errors in your app:'),
CODE(c)) CODE(c))
@@ -546,6 +554,7 @@ def enable():
safe_open(filename, 'wb').write('disabled: True\ntime-disabled: %s' % request.now) safe_open(filename, 'wb').write('disabled: True\ntime-disabled: %s' % request.now)
return SPAN(T('Enable'), _style='color:red') return SPAN(T('Enable'), _style='color:red')
def peek(): def peek():
""" Visualize object code """ """ Visualize object code """
app = get_app(request.vars.app) app = get_app(request.vars.app)
@@ -609,7 +618,7 @@ def edit():
# Load json only if it is ajax edited... # Load json only if it is ajax edited...
app = get_app(request.vars.app) app = get_app(request.vars.app)
app_path = apath(app, r=request) app_path = apath(app, r=request)
preferences={'theme':'web2py', 'editor': 'default', 'closetag': 'true', 'codefolding': 'false', 'tabwidth':'4', 'indentwithtabs':'false', 'linenumbers':'true', 'highlightline':'true'} preferences = {'theme': 'web2py', 'editor': 'default', 'closetag': 'true', 'codefolding': 'false', 'tabwidth': '4', 'indentwithtabs': 'false', 'linenumbers': 'true', 'highlightline': 'true'}
config = Config(os.path.join(request.folder, 'settings.cfg'), config = Config(os.path.join(request.folder, 'settings.cfg'),
section='editor', default_values={}) section='editor', default_values={})
preferences.update(config.read()) preferences.update(config.read())
@@ -617,14 +626,14 @@ def edit():
if not(request.ajax) and not(is_mobile): if not(request.ajax) and not(is_mobile):
# return the scaffolding, the rest will be through ajax requests # return the scaffolding, the rest will be through ajax requests
response.title = T('Editing %s') % app response.title = T('Editing %s') % app
return response.render ('default/edit.html', dict(app=app, editor_settings=preferences)) return response.render('default/edit.html', dict(app=app, editor_settings=preferences))
# show settings tab and save prefernces # show settings tab and save prefernces
if 'settings' in request.vars: if 'settings' in request.vars:
if request.post_vars: #save new preferences if request.post_vars: # save new preferences
post_vars = request.post_vars.items() post_vars = request.post_vars.items()
# Since unchecked checkbox are not serialized, we must set them as false by hand to store the correct preference in the settings # Since unchecked checkbox are not serialized, we must set them as false by hand to store the correct preference in the settings
post_vars+= [(opt, 'false') for opt in preferences if opt not in request.post_vars ] post_vars += [(opt, 'false') for opt in preferences if opt not in request.post_vars]
if config.save(post_vars): if config.save(post_vars):
response.headers["web2py-component-flash"] = T('Preferences saved correctly') response.headers["web2py-component-flash"] = T('Preferences saved correctly')
else: else:
@@ -632,8 +641,8 @@ def edit():
response.headers["web2py-component-command"] = "update_editor(%s);$('a[href=#editor_settings] button.close').click();" % response.json(config.read()) response.headers["web2py-component-command"] = "update_editor(%s);$('a[href=#editor_settings] button.close').click();" % response.json(config.read())
return return
else: else:
details = {'realfilename':'settings', 'filename':'settings', 'id':'editor_settings', 'force': False} details = {'realfilename': 'settings', 'filename': 'settings', 'id': 'editor_settings', 'force': False}
details['plain_html'] = response.render('default/editor_settings.html', {'editor_settings':preferences}) details['plain_html'] = response.render('default/editor_settings.html', {'editor_settings': preferences})
return response.json(details) return response.json(details)
""" File edit handler """ """ File edit handler """
@@ -764,8 +773,8 @@ def edit():
view = request.args[3].replace('.html', '') view = request.args[3].replace('.html', '')
view_link = URL(request.args[0], request.args[2], view) view_link = URL(request.args[0], request.args[2], view)
elif filetype == 'python' and request.args[1] == 'controllers': elif filetype == 'python' and request.args[1] == 'controllers':
## it's a controller file. # it's a controller file.
## Create links to all of the associated view files. # Create links to all of the associated view files.
app = get_app() app = get_app()
viewname = os.path.splitext(request.args[2])[0] viewname = os.path.splitext(request.args[2])[0]
viewpath = os.path.join(app, 'views', viewname) viewpath = os.path.join(app, 'views', viewname)
@@ -796,22 +805,22 @@ def edit():
return response.json({'file_hash': file_hash, 'saved_on': saved_on, 'functions': functions, 'controller': controller, 'application': request.args[0], 'highlight': highlight}) return response.json({'file_hash': file_hash, 'saved_on': saved_on, 'functions': functions, 'controller': controller, 'application': request.args[0], 'highlight': highlight})
else: else:
file_details = dict(app=request.args[0], file_details = dict(app=request.args[0],
lineno=request.vars.lineno or 1, lineno=request.vars.lineno or 1,
editor_settings=preferences, editor_settings=preferences,
filename=filename, filename=filename,
realfilename=realfilename, realfilename=realfilename,
filetype=filetype, filetype=filetype,
data=data, data=data,
edit_controller=edit_controller, edit_controller=edit_controller,
file_hash=file_hash, file_hash=file_hash,
saved_on=saved_on, saved_on=saved_on,
controller=controller, controller=controller,
functions=functions, functions=functions,
view_link=view_link, view_link=view_link,
editviewlinks=editviewlinks, editviewlinks=editviewlinks,
id=IS_SLUG()(filename)[0], id=IS_SLUG()(filename)[0],
force= True if (request.vars.restore or force=True if (request.vars.restore or
request.vars.revert) else False) request.vars.revert) else False)
plain_html = response.render('default/edit_js.html', file_details) plain_html = response.render('default/edit_js.html', file_details)
file_details['plain_html'] = plain_html file_details['plain_html'] = plain_html
if is_mobile: if is_mobile:
@@ -820,14 +829,16 @@ def edit():
else: else:
return response.json(file_details) return response.json(file_details)
def todolist(): def todolist():
""" Returns all TODO of the requested app """ Returns all TODO of the requested app
""" """
app = request.vars.app or '' app = request.vars.app or ''
app_path = apath('%(app)s' % {'app':app}, r=request) app_path = apath('%(app)s' % {'app': app}, r=request)
dirs=['models', 'controllers', 'modules', 'private' ] dirs = ['models', 'controllers', 'modules', 'private']
def listfiles(app, dir, regexp='.*\.py$'): def listfiles(app, dir, regexp='.*\.py$'):
files = sorted( listdir(apath('%(app)s/%(dir)s/' % {'app':app, 'dir':dir}, r=request), regexp)) files = sorted(listdir(apath('%(app)s/%(dir)s/' % {'app': app, 'dir': dir}, r=request), regexp))
files = [x.replace(os.path.sep, '/') for x in files if not x.endswith('.bak')] files = [x.replace(os.path.sep, '/') for x in files if not x.endswith('.bak')]
return files return files
@@ -838,17 +849,18 @@ def todolist():
for d in dirs: for d in dirs:
for f in listfiles(app, d): for f in listfiles(app, d):
matches = [] matches = []
filename= apath(os.path.join(app, d, f), r=request) filename = apath(os.path.join(app, d, f), r=request)
with open(filename, 'r') as f_s: with open(filename, 'r') as f_s:
src = f_s.read() src = f_s.read()
for m in regex.finditer(src): for m in regex.finditer(src):
start = m.start() start = m.start()
lineno = src.count('\n', 0, start) + 1 lineno = src.count('\n', 0, start) + 1
matches.append({'text':m.group(0), 'lineno':lineno}) matches.append({'text': m.group(0), 'lineno': lineno})
if len(matches) != 0: if len(matches) != 0:
output.append({'filename':f,'matches':matches, 'dir':d}) output.append({'filename': f, 'matches': matches, 'dir': d})
return {'todo': output, 'app': app}
return {'todo':output, 'app': app}
def editor_sessions(): def editor_sessions():
config = Config(os.path.join(request.folder, 'settings.cfg'), config = Config(os.path.join(request.folder, 'settings.cfg'),
@@ -858,13 +870,14 @@ def editor_sessions():
if request.vars.session_name and request.vars.files: if request.vars.session_name and request.vars.files:
session_name = request.vars.session_name session_name = request.vars.session_name
files = request.vars.files files = request.vars.files
preferences.update({session_name:','.join(files)}) preferences.update({session_name: ','.join(files)})
if config.save(preferences.items()): if config.save(preferences.items()):
response.headers["web2py-component-flash"] = T('Session saved correctly') response.headers["web2py-component-flash"] = T('Session saved correctly')
else: else:
response.headers["web2py-component-flash"] = T('Session saved on session only') response.headers["web2py-component-flash"] = T('Session saved on session only')
return response.render('default/editor_sessions.html', {'editor_sessions':preferences}) return response.render('default/editor_sessions.html', {'editor_sessions': preferences})
def resolve(): def resolve():
""" """
@@ -901,8 +914,8 @@ def resolve():
def getclass(item): def getclass(item):
""" Determine item class """ """ Determine item class """
operators = {' ':'normal', '+':'plus', '-':'minus'} operators = {' ': 'normal', '+': 'plus', '-': 'minus'}
return operators[item[0]] return operators[item[0]]
if request.vars: if request.vars:
@@ -921,7 +934,7 @@ def resolve():
diff = TABLE(*[TR(TD(gen_data(i, item)), diff = TABLE(*[TR(TD(gen_data(i, item)),
TD(item[0]), TD(item[0]),
TD(leading(item[2:]), TD(leading(item[2:]),
TT(item[2:].rstrip())), TT(item[2:].rstrip())),
_class=getclass(item)) _class=getclass(item))
for (i, item) in enumerate(d) if item[0] != '?']) for (i, item) in enumerate(d) if item[0] != '?'])
@@ -968,11 +981,11 @@ def edit_language():
new_row = DIV(LABEL(prefix, k, _style="font-weight:normal;"), new_row = DIV(LABEL(prefix, k, _style="font-weight:normal;"),
CAT(elem, '\n', TAG.BUTTON( CAT(elem, '\n', TAG.BUTTON(
T('delete'), T('delete'),
_onclick='return delkey("%s")' % name, _onclick='return delkey("%s")' % name,
_class='btn')), _id=name, _class='span6 well well-small') _class='btn')), _id=name, _class='span6 well well-small')
rows.append(DIV(new_row,_class="row-fluid")) rows.append(DIV(new_row, _class="row-fluid"))
rows.append(DIV(INPUT(_type='submit', _value=T('update'), _class="btn btn-primary"), _class='controls')) rows.append(DIV(INPUT(_type='submit', _value=T('update'), _class="btn btn-primary"), _class='controls'))
form = FORM(*rows) form = FORM(*rows)
if form.accepts(request.vars, keepvalues=True): if form.accepts(request.vars, keepvalues=True):
@@ -1128,18 +1141,18 @@ def design():
# Get all static files # Get all static files
statics = listdir(apath('%s/static/' % app, r=request), '[^\.#].*', statics = listdir(apath('%s/static/' % app, r=request), '[^\.#].*',
maxnum = MAXNFILES) maxnum=MAXNFILES)
statics = [x.replace(os.path.sep, '/') for x in statics] statics = [x.replace(os.path.sep, '/') for x in statics]
statics.sort() statics.sort()
# Get all languages # Get all languages
langpath = os.path.join(apath(app, r=request),'languages') langpath = os.path.join(apath(app, r=request), 'languages')
languages = dict([(lang, info) for lang, info languages = dict([(lang, info) for lang, info
in read_possible_languages(langpath).iteritems() in read_possible_languages(langpath).iteritems()
if info[2] != 0]) # info[2] is langfile_mtime: if info[2] != 0]) # info[2] is langfile_mtime:
# get only existed files # get only existed files
#Get crontab # Get crontab
cronfolder = apath('%s/cron' % app, r=request) cronfolder = apath('%s/cron' % app, r=request)
crontab = apath('%s/cron/crontab' % app, r=request) crontab = apath('%s/cron/crontab' % app, r=request)
if not is_gae: if not is_gae:
@@ -1265,7 +1278,7 @@ def plugin():
# Get all static files # Get all static files
statics = listdir(apath('%s/static/' % app, r=request), '[^\.#].*', statics = listdir(apath('%s/static/' % app, r=request), '[^\.#].*',
maxnum = MAXNFILES) maxnum=MAXNFILES)
statics = [x.replace(os.path.sep, '/') for x in statics] statics = [x.replace(os.path.sep, '/') for x in statics]
statics.sort() statics.sort()
@@ -1273,9 +1286,9 @@ def plugin():
languages = sorted([lang + '.py' for lang, info in languages = sorted([lang + '.py' for lang, info in
T.get_possible_languages_info().iteritems() T.get_possible_languages_info().iteritems()
if info[2] != 0]) # info[2] is langfile_mtime: if info[2] != 0]) # info[2] is langfile_mtime:
# get only existed files # get only existed files
#Get crontab # Get crontab
crontab = apath('%s/cron/crontab' % app, r=request) crontab = apath('%s/cron/crontab' % app, r=request)
if not os.path.exists(crontab): if not os.path.exists(crontab):
safe_write(crontab, '#crontab') safe_write(crontab, '#crontab')
@@ -1298,6 +1311,7 @@ def plugin():
languages=languages, languages=languages,
crontab=crontab) crontab=crontab)
def create_file(): def create_file():
""" Create files handler """ """ Create files handler """
if request.vars and not request.vars.token == session.token: if request.vars and not request.vars.token == session.token:
@@ -1309,7 +1323,7 @@ def create_file():
path = abspath(request.vars.location) path = abspath(request.vars.location)
else: else:
if request.vars.dir: if request.vars.dir:
request.vars.location += request.vars.dir + '/' request.vars.location += request.vars.dir + '/'
app = get_app(name=request.vars.location.split('/')[0]) app = get_app(name=request.vars.location.split('/')[0])
path = apath(request.vars.location, r=request) path = apath(request.vars.location, r=request)
filename = re.sub('[^\w./-]+', '_', request.vars.filename) filename = re.sub('[^\w./-]+', '_', request.vars.filename)
@@ -1419,7 +1433,7 @@ def create_file():
elif (path[-8:] == '/static/') or (path[-9:] == '/private/'): elif (path[-8:] == '/static/') or (path[-9:] == '/private/'):
if (request.vars.plugin and if (request.vars.plugin and
not filename.startswith('plugin_%s/' % request.vars.plugin)): not filename.startswith('plugin_%s/' % request.vars.plugin)):
filename = 'plugin_%s/%s' % (request.vars.plugin, filename) filename = 'plugin_%s/%s' % (request.vars.plugin, filename)
text = '' text = ''
@@ -1439,17 +1453,17 @@ def create_file():
log_progress(app, 'CREATE', filename) log_progress(app, 'CREATE', filename)
if request.vars.dir: if request.vars.dir:
result = T('file "%(filename)s" created', result = T('file "%(filename)s" created',
dict(filename=full_filename[len(path):])) dict(filename=full_filename[len(path):]))
else: else:
session.flash = T('file "%(filename)s" created', session.flash = T('file "%(filename)s" created',
dict(filename=full_filename[len(path):])) dict(filename=full_filename[len(path):]))
vars = {} vars = {}
if request.vars.id: if request.vars.id:
vars['id'] = request.vars.id vars['id'] = request.vars.id
if request.vars.app: if request.vars.app:
vars['app'] = request.vars.app vars['app'] = request.vars.app
redirect(URL('edit', redirect(URL('edit',
args=[os.path.join(request.vars.location, filename)], vars=vars)) args=[os.path.join(request.vars.location, filename)], vars=vars))
except Exception, e: except Exception, e:
if not isinstance(e, HTTP): if not isinstance(e, HTTP):
@@ -1460,7 +1474,7 @@ def create_file():
response.headers['web2py-component-content'] = 'append' response.headers['web2py-component-content'] = 'append'
response.headers['web2py-component-command'] = "%s %s %s" % ( response.headers['web2py-component-command'] = "%s %s %s" % (
"$.web2py.invalidate('#files_menu');", "$.web2py.invalidate('#files_menu');",
"load_file('%s');" % URL('edit', args=[app,request.vars.dir,filename]), "load_file('%s');" % URL('edit', args=[app, request.vars.dir, filename]),
"$.web2py.enableElement($('#form form').find($.web2py.formInputClickSelector));") "$.web2py.enableElement($('#form form').find($.web2py.formInputClickSelector));")
return '' return ''
else: else:
@@ -1468,32 +1482,35 @@ def create_file():
def listfiles(app, dir, regexp='.*\.py$'): def listfiles(app, dir, regexp='.*\.py$'):
files = sorted( files = sorted(
listdir(apath('%(app)s/%(dir)s/' % {'app':app, 'dir':dir}, r=request), regexp)) listdir(apath('%(app)s/%(dir)s/' % {'app': app, 'dir': dir}, r=request), regexp))
files = [x.replace('\\', '/') for x in files if not x.endswith('.bak')] files = [x.replace('\\', '/') for x in files if not x.endswith('.bak')]
return files return files
def editfile(path, file, vars={}, app=None):
args = (path, file) if 'app' in vars else (app, path, file)
url = URL('edit', args=args, vars=vars)
return A(file, _class='editor_filelink', _href=url, _style='word-wrap: nowrap;')
def editfile(path,file,vars={}, app = None):
args=(path,file) if 'app' in vars else (app,path,file)
url = URL('edit', args=args, vars=vars)
return A(file, _class='editor_filelink', _href=url, _style='word-wrap: nowrap;')
def files_menu(): def files_menu():
app = request.vars.app or 'welcome' app = request.vars.app or 'welcome'
dirs=[{'name':'models', 'reg':'.*\.py$'}, dirs = [{'name': 'models', 'reg': '.*\.py$'},
{'name':'controllers', 'reg':'.*\.py$'}, {'name': 'controllers', 'reg': '.*\.py$'},
{'name':'views', 'reg':'[\w/\-]+(\.\w+)+$'}, {'name': 'views', 'reg': '[\w/\-]+(\.\w+)+$'},
{'name':'modules', 'reg':'.*\.py$'}, {'name': 'modules', 'reg': '.*\.py$'},
{'name':'static', 'reg': '[^\.#].*'}, {'name': 'static', 'reg': '[^\.#].*'},
{'name':'private', 'reg':'.*\.py$'}] {'name': 'private', 'reg': '.*\.py$'}]
result_files = [] result_files = []
for dir in dirs: for dir in dirs:
result_files.append(TAG[''](LI(dir['name'], _class="nav-header component", _onclick="collapse('" + dir['name'] + "_files');"), result_files.append(TAG[''](LI(dir['name'], _class="nav-header component", _onclick="collapse('" + dir['name'] + "_files');"),
LI(UL(*[LI(editfile(dir['name'], f, dict(id=dir['name'] + f.replace('.','__')), app), _style="overflow:hidden", _id=dir['name']+"__"+f.replace('.','__')) LI(UL(*[LI(editfile(dir['name'], f, dict(id=dir['name'] + f.replace('.', '__')), app), _style="overflow:hidden", _id=dir['name'] + "__" + f.replace('.', '__'))
for f in listfiles(app, dir['name'], regexp=dir['reg'])], for f in listfiles(app, dir['name'], regexp=dir['reg'])],
_class="nav nav-list small-font"), _class="nav nav-list small-font"),
_id=dir['name'] + '_files', _style="display: none;"))) _id=dir['name'] + '_files', _style="display: none;")))
return dict(result_files = result_files) return dict(result_files=result_files)
def upload_file(): def upload_file():
""" File uploading handler """ """ File uploading handler """
@@ -1556,7 +1573,7 @@ def errors():
app = get_app() app = get_app()
if is_gae: if is_gae:
method = 'dbold' if ('old' in method = 'dbold' if ('old' in
(request.args(1) or '')) else 'dbnew' (request.args(1) or '')) else 'dbnew'
else: else:
method = request.args(1) or 'new' method = request.args(1) or 'new'
db_ready = {} db_ready = {}
@@ -1599,7 +1616,7 @@ def errors():
hash2error[hash]['count'] += 1 hash2error[hash]['count'] += 1
except KeyError: except KeyError:
error_lines = error['traceback'].split("\n") error_lines = error['traceback'].split("\n")
last_line = error_lines[-2] if len(error_lines)>1 else 'unknown' last_line = error_lines[-2] if len(error_lines) > 1 else 'unknown'
error_causer = os.path.split(error['layer'])[1] error_causer = os.path.split(error['layer'])[1]
hash2error[hash] = dict(count=1, pickel=error, hash2error[hash] = dict(count=1, pickel=error,
causer=error_causer, causer=error_causer,
@@ -1638,9 +1655,9 @@ def errors():
last_line = error_lines[-2] last_line = error_lines[-2]
error_causer = os.path.split(error['layer'])[1] error_causer = os.path.split(error['layer'])[1]
hash2error[hash] = dict(count=1, hash2error[hash] = dict(count=1,
pickel=error, causer=error_causer, pickel=error, causer=error_causer,
last_line=last_line, hash=hash, last_line=last_line, hash=hash,
ticket=fn.ticket_id) ticket=fn.ticket_id)
except AttributeError, e: except AttributeError, e:
tk_db(tk_table.id == fn.id).delete() tk_db(tk_table.id == fn.id).delete()
tk_db.commit() tk_db.commit()
@@ -1657,11 +1674,11 @@ def errors():
tk_db(tk_table.ticket_id == item[7:]).delete() tk_db(tk_table.ticket_id == item[7:]).delete()
tk_db.commit() tk_db.commit()
tickets_ = tk_db(tk_table.id > 0).select(tk_table.ticket_id, tickets_ = tk_db(tk_table.id > 0).select(tk_table.ticket_id,
tk_table.created_datetime, tk_table.created_datetime,
orderby=~tk_table.created_datetime) orderby=~tk_table.created_datetime)
tickets = [row.ticket_id for row in tickets_] tickets = [row.ticket_id for row in tickets_]
times = dict([(row.ticket_id, row.created_datetime) for times = dict([(row.ticket_id, row.created_datetime) for
row in tickets_]) row in tickets_])
return dict(app=app, tickets=tickets, method=method, return dict(app=app, tickets=tickets, method=method,
times=times, db_ready=db_ready) times=times, db_ready=db_ready)
@@ -1721,7 +1738,7 @@ def make_link(path):
if ext.lower() == editable[key] and check_extension: if ext.lower() == editable[key] and check_extension:
return A('"' + tryFile + '"', return A('"' + tryFile + '"',
_href=URL(r=request, _href=URL(r=request,
f='edit/%s/%s/%s' % (app, key, filename))).xml() f='edit/%s/%s/%s' % (app, key, filename))).xml()
return '' return ''
@@ -1867,7 +1884,7 @@ def bulk_register():
redirect(URL('site')) redirect(URL('site'))
return locals() return locals()
### Begin experimental stuff need fixes: # Begin experimental stuff need fixes:
# 1) should run in its own process - cannot os.chdir # 1) should run in its own process - cannot os.chdir
# 2) should not prompt user at console # 2) should not prompt user at console
# 3) should give option to force commit and not reuqire manual merge # 3) should give option to force commit and not reuqire manual merge
@@ -1934,6 +1951,7 @@ def git_push():
redirect(URL('site')) redirect(URL('site'))
return dict(app=app, form=form) return dict(app=app, form=form)
def plugins(): def plugins():
app = request.args(0) app = request.args(0)
from serializers import loads_json from serializers import loads_json
@@ -1948,6 +1966,7 @@ def plugins():
session.plugins = [] session.plugins = []
return dict(plugins=session.plugins["results"], app=request.args(0)) return dict(plugins=session.plugins["results"], app=request.args(0))
def install_plugin(): def install_plugin():
app = request.args(0) app = request.args(0)
source = request.vars.source source = request.vars.source
@@ -1972,5 +1991,5 @@ def install_plugin():
else: else:
session.flash = \ session.flash = \
T('unable to install plugin "%s"', filename) T('unable to install plugin "%s"', filename)
redirect(URL(f="plugins", args=[app,])) redirect(URL(f="plugins", args=[app, ]))
return dict(form=form, app=app, plugin=plugin, source=source) return dict(form=form, app=app, plugin=plugin, source=source)
+187 -136
View File
@@ -178,9 +178,9 @@ class TestValidators(unittest.TestCase):
self.assertEqual(rtn, (('max', 'john'), None)) self.assertEqual(rtn, (('max', 'john'), None))
rtn = IS_IN_SET(['max', 'john'], multiple=True)(('bill', 'john')) rtn = IS_IN_SET(['max', 'john'], multiple=True)(('bill', 'john'))
self.assertEqual(rtn, (('bill', 'john'), 'Value not allowed')) self.assertEqual(rtn, (('bill', 'john'), 'Value not allowed'))
rtn = IS_IN_SET(('id1','id2'), ['first label','second label'])('id1') # Traditional way rtn = IS_IN_SET(('id1', 'id2'), ['first label', 'second label'])('id1') # Traditional way
self.assertEqual(rtn, ('id1', None)) self.assertEqual(rtn, ('id1', None))
rtn = IS_IN_SET({'id1':'first label', 'id2':'second label'})('id1') rtn = IS_IN_SET({'id1': 'first label', 'id2': 'second label'})('id1')
self.assertEqual(rtn, ('id1', None)) self.assertEqual(rtn, ('id1', None))
rtn = IS_IN_SET(['id1', 'id2'], error_message='oops', multiple=True)(None) rtn = IS_IN_SET(['id1', 'id2'], error_message='oops', multiple=True)(None)
self.assertEqual(rtn, ([], None)) self.assertEqual(rtn, ([], None))
@@ -188,14 +188,14 @@ class TestValidators(unittest.TestCase):
self.assertEqual(rtn, ([], None)) self.assertEqual(rtn, ([], None))
rtn = IS_IN_SET(['id1', 'id2'], error_message='oops', multiple=True)('id1') rtn = IS_IN_SET(['id1', 'id2'], error_message='oops', multiple=True)('id1')
self.assertEqual(rtn, (['id1'], None)) self.assertEqual(rtn, (['id1'], None))
rtn = IS_IN_SET(['id1', 'id2'], error_message='oops', multiple=(1,2))(None) rtn = IS_IN_SET(['id1', 'id2'], error_message='oops', multiple=(1, 2))(None)
self.assertEqual(rtn, ([], 'oops')) self.assertEqual(rtn, ([], 'oops'))
import itertools import itertools
rtn = IS_IN_SET(itertools.chain(['1','3','5'],['2','4','6']))('1') rtn = IS_IN_SET(itertools.chain(['1', '3', '5'], ['2', '4', '6']))('1')
self.assertEqual(rtn, ('1', None)) self.assertEqual(rtn, ('1', None))
rtn = IS_IN_SET([('id1','first label'), ('id2','second label')])('id1') # Redundant way rtn = IS_IN_SET([('id1', 'first label'), ('id2', 'second label')])('id1') # Redundant way
self.assertEqual(rtn, ('id1', None)) self.assertEqual(rtn, ('id1', None))
rtn = IS_IN_SET([('id1','first label'), ('id2','second label')]).options(zero=False) rtn = IS_IN_SET([('id1', 'first label'), ('id2', 'second label')]).options(zero=False)
self.assertEqual(rtn, [('id1', 'first label'), ('id2', 'second label')]) self.assertEqual(rtn, [('id1', 'first label'), ('id2', 'second label')])
rtn = IS_IN_SET(['id1', 'id2']).options(zero=False) rtn = IS_IN_SET(['id1', 'id2']).options(zero=False)
self.assertEqual(rtn, [('id1', 'id1'), ('id2', 'id2')]) self.assertEqual(rtn, [('id1', 'id1'), ('id2', 'id2')])
@@ -210,47 +210,79 @@ class TestValidators(unittest.TestCase):
costanza_id = db.person.insert(name='costanza') costanza_id = db.person.insert(name='costanza')
rtn = IS_IN_DB(db, 'person.id', '%(name)s')(george_id) rtn = IS_IN_DB(db, 'person.id', '%(name)s')(george_id)
self.assertEqual(rtn, (george_id, None)) self.assertEqual(rtn, (george_id, None))
rtn = IS_IN_DB(db, 'person.name', '%(name)s')('george')
self.assertEqual(rtn, ('george', None))
rtn = IS_IN_DB(db, db.person, '%(name)s')(george_id) rtn = IS_IN_DB(db, db.person, '%(name)s')(george_id)
self.assertEqual(rtn, (george_id, None)) self.assertEqual(rtn, (george_id, None))
rtn = IS_IN_DB(db(db.person.id > 0), db.person, '%(name)s')(george_id) rtn = IS_IN_DB(db(db.person.id > 0), db.person, '%(name)s')(george_id)
self.assertEqual(rtn, (george_id, None)) self.assertEqual(rtn, (george_id, None))
rtn = IS_IN_DB(db, 'person.id', '%(name)s', error_message='oops')(george_id+costanza_id) rtn = IS_IN_DB(db, 'person.id', '%(name)s', error_message='oops')(george_id + costanza_id)
self.assertEqual(rtn, (george_id+costanza_id, 'oops')) self.assertEqual(rtn, (george_id + costanza_id, 'oops'))
rtn = IS_IN_DB(db, db.person.id, '%(name)s')(george_id) rtn = IS_IN_DB(db, db.person.id, '%(name)s')(george_id)
self.assertEqual(rtn, (george_id, None)) self.assertEqual(rtn, (george_id, None))
rtn = IS_IN_DB(db, db.person.id, '%(name)s', error_message='oops')(george_id+costanza_id) rtn = IS_IN_DB(db, db.person.id, '%(name)s', error_message='oops')(george_id + costanza_id)
self.assertEqual(rtn, (george_id+costanza_id, 'oops')) self.assertEqual(rtn, (george_id + costanza_id, 'oops'))
rtn = IS_IN_DB(db, 'person.id', '%(name)s', multiple=True)([george_id,costanza_id]) rtn = IS_IN_DB(db, 'person.id', '%(name)s', multiple=True)([george_id, costanza_id])
self.assertEqual(rtn, ([george_id,costanza_id], None)) self.assertEqual(rtn, ([george_id, costanza_id], None))
rtn = IS_IN_DB(db, 'person.id', '%(name)s', multiple=True, error_message='oops')("I'm not even an id")
self.assertEqual(rtn, (["I'm not even an id"], 'oops'))
rtn = IS_IN_DB(db, 'person.id', '%(name)s', multiple=True, delimiter=',')('%d,%d' % (george_id, costanza_id)) rtn = IS_IN_DB(db, 'person.id', '%(name)s', multiple=True, delimiter=',')('%d,%d' % (george_id, costanza_id))
self.assertEqual(rtn, ( ('%d,%d' % (george_id, costanza_id)).split(','), None)) self.assertEqual(rtn, (('%d,%d' % (george_id, costanza_id)).split(','), None))
rtn = IS_IN_DB(db, 'person.id', '%(name)s', multiple=(1,3), delimiter=',')('%d,%d' % (george_id, costanza_id)) rtn = IS_IN_DB(db, 'person.id', '%(name)s', multiple=(1, 3), delimiter=',')('%d,%d' % (george_id, costanza_id))
self.assertEqual(rtn, ( ('%d,%d' % (george_id, costanza_id)).split(','), None)) self.assertEqual(rtn, (('%d,%d' % (george_id, costanza_id)).split(','), None))
rtn = IS_IN_DB(db, 'person.id', '%(name)s', multiple=(1,2), delimiter=',', error_message='oops')('%d,%d' % (george_id, costanza_id)) rtn = IS_IN_DB(db, 'person.id', '%(name)s', multiple=(1, 2), delimiter=',', error_message='oops')('%d,%d' % (george_id, costanza_id))
self.assertEqual(rtn, ( ('%d,%d' % (george_id, costanza_id)).split(','), 'oops')) self.assertEqual(rtn, (('%d,%d' % (george_id, costanza_id)).split(','), 'oops'))
rtn = IS_IN_DB(db, db.person.id, '%(name)s', error_message='oops').options(zero=False) rtn = IS_IN_DB(db, db.person.id, '%(name)s', error_message='oops').options(zero=False)
self.assertEqual(sorted(rtn), [('%d' % george_id, 'george'), ('%d' % costanza_id, 'costanza')]) self.assertEqual(sorted(rtn), [('%d' % george_id, 'george'), ('%d' % costanza_id, 'costanza')])
rtn = IS_IN_DB(db, db.person.id, db.person.name, error_message='oops', sort=True).options(zero=True) rtn = IS_IN_DB(db, db.person.id, db.person.name, error_message='oops', sort=True).options(zero=True)
self.assertEqual(rtn, [('', ''), ('%d' % costanza_id, 'costanza'), ('%d' % george_id, 'george')]) self.assertEqual(rtn, [('', ''), ('%d' % costanza_id, 'costanza'), ('%d' % george_id, 'george')])
# Test using the set it made for options
vldtr = IS_IN_DB(db, 'person.name', '%(name)s', error_message='oops')
vldtr.options()
rtn = vldtr('george')
self.assertEqual(rtn, ('george', None))
rtn = vldtr('jerry')
self.assertEqual(rtn, ('jerry', 'oops'))
vldtr = IS_IN_DB(db, 'person.name', '%(name)s', error_message='oops', multiple=True)
vldtr.options()
rtn = vldtr(['george', 'costanza'])
self.assertEqual(rtn, (['george', 'costanza'], None))
# Test it works with self reference # Test it works with self reference
db.define_table('category', db.define_table('category',
Field('parent_id', 'reference category', requires=IS_EMPTY_OR(IS_IN_DB(db, 'category.id', '%(name)s'))), Field('parent_id', 'reference category', requires=IS_EMPTY_OR(IS_IN_DB(db, 'category.id', '%(name)s'))),
Field('name') Field('name')
) )
ret = db.category.validate_and_insert(name='seinfeld') ret = db.category.validate_and_insert(name='seinfeld')
self.assertFalse(list(ret.errors)) self.assertFalse(list(ret.errors))
ret = db.category.validate_and_insert(name='characters', parent_id=ret.id) ret = db.category.validate_and_insert(name='characters', parent_id=ret.id)
self.assertFalse(list(ret.errors)) self.assertFalse(list(ret.errors))
rtn = IS_IN_DB(db, 'category.id', '%(name)s')(ret.id) rtn = IS_IN_DB(db, 'category.id', '%(name)s')(ret.id)
self.assertEqual(rtn, (ret.id, None)) self.assertEqual(rtn, (ret.id, None))
# Test _and
vldtr = IS_IN_DB(db, 'person.name', '%(name)s', error_message='oops', _and=IS_LENGTH(maxsize=7, error_message='bad'))
rtn = vldtr('george')
self.assertEqual(rtn, ('george', None))
rtn = vldtr('costanza')
self.assertEqual(rtn, ('costanza', 'bad'))
rtn = vldtr('jerry')
self.assertEqual(rtn, ('jerry', 'oops'))
vldtr.options() # test theset with _and
rtn = vldtr('jerry')
self.assertEqual(rtn, ('jerry', 'oops'))
# Test auto_add
rtn = IS_IN_DB(db, 'person.id', '%(name)s', error_message='oops')('jerry')
self.assertEqual(rtn, ('jerry', 'oops'))
rtn = IS_IN_DB(db, 'person.id', '%(name)s', auto_add=True)('jerry')
self.assertEqual(rtn, (3, None))
db.person.drop() db.person.drop()
db.category.drop() db.category.drop()
def test_IS_NOT_IN_DB(self): def test_IS_NOT_IN_DB(self):
from gluon.dal import DAL, Field from gluon.dal import DAL, Field
db = DAL('sqlite:memory') db = DAL('sqlite:memory')
db.define_table('person', Field('name')) db.define_table('person', Field('name'), Field('nickname'))
db.person.insert(name='george') db.person.insert(name='george')
db.person.insert(name='costanza', nickname='T Bone')
rtn = IS_NOT_IN_DB(db, 'person.name', error_message='oops')('george') rtn = IS_NOT_IN_DB(db, 'person.name', error_message='oops')('george')
self.assertEqual(rtn, ('george', 'oops')) self.assertEqual(rtn, ('george', 'oops'))
rtn = IS_NOT_IN_DB(db, 'person.name', error_message='oops', allowed_override=['george'])('george') rtn = IS_NOT_IN_DB(db, 'person.name', error_message='oops', allowed_override=['george'])('george')
@@ -261,6 +293,17 @@ class TestValidators(unittest.TestCase):
self.assertEqual(rtn, ('jerry', None)) self.assertEqual(rtn, ('jerry', None))
rtn = IS_NOT_IN_DB(db, 'person.name')(u'jerry') rtn = IS_NOT_IN_DB(db, 'person.name')(u'jerry')
self.assertEqual(rtn, ('jerry', None)) self.assertEqual(rtn, ('jerry', None))
rtn = IS_NOT_IN_DB(db(db.person.id > 0), 'person.name')(u'jerry')
self.assertEqual(rtn, ('jerry', None))
rtn = IS_NOT_IN_DB(db, db.person, error_message='oops')(1)
self.assertEqual(rtn, ('1', 'oops'))
vldtr = IS_NOT_IN_DB(db, 'person.name', error_message='oops')
vldtr.set_self_id({'name': 'costanza', 'nickname': 'T Bone'})
rtn = vldtr('george')
self.assertEqual(rtn, ('george', 'oops'))
rtn = vldtr('costanza')
self.assertEqual(rtn, ('costanza', None))
db.person.drop() db.person.drop()
def test_IS_INT_IN_RANGE(self): def test_IS_INT_IN_RANGE(self):
@@ -413,7 +456,7 @@ class TestValidators(unittest.TestCase):
def test_IS_ALPHANUMERIC(self): def test_IS_ALPHANUMERIC(self):
rtn = IS_ALPHANUMERIC()('1') rtn = IS_ALPHANUMERIC()('1')
self.assertEqual(rtn, ('1', None)) self.assertEqual(rtn, ('1', None))
rtn = IS_ALPHANUMERIC()('') rtn = IS_ALPHANUMERIC()('')
self.assertEqual(rtn, ('', None)) self.assertEqual(rtn, ('', None))
rtn = IS_ALPHANUMERIC()('A_a') rtn = IS_ALPHANUMERIC()('A_a')
self.assertEqual(rtn, ('A_a', None)) self.assertEqual(rtn, ('A_a', None))
@@ -421,62 +464,62 @@ class TestValidators(unittest.TestCase):
self.assertEqual(rtn, ('!', 'Enter only letters, numbers, and underscore')) self.assertEqual(rtn, ('!', 'Enter only letters, numbers, and underscore'))
def test_IS_EMAIL(self): def test_IS_EMAIL(self):
rtn = IS_EMAIL()('a@b.com') rtn = IS_EMAIL()('a@b.com')
self.assertEqual(rtn, ('a@b.com', None)) self.assertEqual(rtn, ('a@b.com', None))
rtn = IS_EMAIL()('abc@def.com') rtn = IS_EMAIL()('abc@def.com')
self.assertEqual(rtn, ('abc@def.com', None)) self.assertEqual(rtn, ('abc@def.com', None))
rtn = IS_EMAIL()('abc@3def.com') rtn = IS_EMAIL()('abc@3def.com')
self.assertEqual(rtn, ('abc@3def.com', None)) self.assertEqual(rtn, ('abc@3def.com', None))
rtn = IS_EMAIL()('abc@def.us') rtn = IS_EMAIL()('abc@def.us')
self.assertEqual(rtn, ('abc@def.us', None)) self.assertEqual(rtn, ('abc@def.us', None))
rtn = IS_EMAIL()('abc@d_-f.us') rtn = IS_EMAIL()('abc@d_-f.us')
self.assertEqual(rtn, ('abc@d_-f.us', None)) self.assertEqual(rtn, ('abc@d_-f.us', None))
rtn = IS_EMAIL()('@def.com') # missing name rtn = IS_EMAIL()('@def.com') # missing name
self.assertEqual(rtn, ('@def.com', 'Enter a valid email address')) self.assertEqual(rtn, ('@def.com', 'Enter a valid email address'))
rtn = IS_EMAIL()('"abc@def".com') # quoted name rtn = IS_EMAIL()('"abc@def".com') # quoted name
self.assertEqual(rtn, ('"abc@def".com', 'Enter a valid email address')) self.assertEqual(rtn, ('"abc@def".com', 'Enter a valid email address'))
rtn = IS_EMAIL()('abc+def.com') # no @ rtn = IS_EMAIL()('abc+def.com') # no @
self.assertEqual(rtn, ('abc+def.com', 'Enter a valid email address')) self.assertEqual(rtn, ('abc+def.com', 'Enter a valid email address'))
rtn = IS_EMAIL()('abc@def.x') # one-char TLD rtn = IS_EMAIL()('abc@def.x') # one-char TLD
self.assertEqual(rtn, ('abc@def.x', 'Enter a valid email address')) self.assertEqual(rtn, ('abc@def.x', 'Enter a valid email address'))
rtn = IS_EMAIL()('abc@def.12') # numeric TLD rtn = IS_EMAIL()('abc@def.12') # numeric TLD
self.assertEqual(rtn, ('abc@def.12', 'Enter a valid email address')) self.assertEqual(rtn, ('abc@def.12', 'Enter a valid email address'))
rtn = IS_EMAIL()('abc@def..com') # double-dot in domain rtn = IS_EMAIL()('abc@def..com') # double-dot in domain
self.assertEqual(rtn, ('abc@def..com', 'Enter a valid email address')) self.assertEqual(rtn, ('abc@def..com', 'Enter a valid email address'))
rtn = IS_EMAIL()('abc@.def.com') # dot starts domain rtn = IS_EMAIL()('abc@.def.com') # dot starts domain
self.assertEqual(rtn, ('abc@.def.com', 'Enter a valid email address')) self.assertEqual(rtn, ('abc@.def.com', 'Enter a valid email address'))
rtn = IS_EMAIL()('abc@def.c_m') # underscore in TLD rtn = IS_EMAIL()('abc@def.c_m') # underscore in TLD
self.assertEqual(rtn, ('abc@def.c_m', 'Enter a valid email address')) self.assertEqual(rtn, ('abc@def.c_m', 'Enter a valid email address'))
rtn = IS_EMAIL()('NotAnEmail') # missing @ rtn = IS_EMAIL()('NotAnEmail') # missing @
self.assertEqual(rtn, ('NotAnEmail', 'Enter a valid email address')) self.assertEqual(rtn, ('NotAnEmail', 'Enter a valid email address'))
rtn = IS_EMAIL()('abc@NotAnEmail') # missing TLD rtn = IS_EMAIL()('abc@NotAnEmail') # missing TLD
self.assertEqual(rtn, ('abc@NotAnEmail', 'Enter a valid email address')) self.assertEqual(rtn, ('abc@NotAnEmail', 'Enter a valid email address'))
rtn = IS_EMAIL()('customer/department@example.com') rtn = IS_EMAIL()('customer/department@example.com')
self.assertEqual(rtn, ('customer/department@example.com', None)) self.assertEqual(rtn, ('customer/department@example.com', None))
rtn = IS_EMAIL()('$A12345@example.com') rtn = IS_EMAIL()('$A12345@example.com')
self.assertEqual(rtn, ('$A12345@example.com', None)) self.assertEqual(rtn, ('$A12345@example.com', None))
rtn = IS_EMAIL()('!def!xyz%abc@example.com') rtn = IS_EMAIL()('!def!xyz%abc@example.com')
self.assertEqual(rtn, ('!def!xyz%abc@example.com', None)) self.assertEqual(rtn, ('!def!xyz%abc@example.com', None))
rtn = IS_EMAIL()('_Yosemite.Sam@example.com') rtn = IS_EMAIL()('_Yosemite.Sam@example.com')
self.assertEqual(rtn, ('_Yosemite.Sam@example.com', None)) self.assertEqual(rtn, ('_Yosemite.Sam@example.com', None))
rtn = IS_EMAIL()('~@example.com') rtn = IS_EMAIL()('~@example.com')
self.assertEqual(rtn, ('~@example.com', None)) self.assertEqual(rtn, ('~@example.com', None))
rtn = IS_EMAIL()('.wooly@example.com') # dot starts name rtn = IS_EMAIL()('.wooly@example.com') # dot starts name
self.assertEqual(rtn, ('.wooly@example.com', 'Enter a valid email address')) self.assertEqual(rtn, ('.wooly@example.com', 'Enter a valid email address'))
rtn = IS_EMAIL()('wo..oly@example.com') # adjacent dots in name rtn = IS_EMAIL()('wo..oly@example.com') # adjacent dots in name
self.assertEqual(rtn, ('wo..oly@example.com', 'Enter a valid email address')) self.assertEqual(rtn, ('wo..oly@example.com', 'Enter a valid email address'))
rtn = IS_EMAIL()('pootietang.@example.com') # dot ends name rtn = IS_EMAIL()('pootietang.@example.com') # dot ends name
self.assertEqual(rtn, ('pootietang.@example.com', 'Enter a valid email address')) self.assertEqual(rtn, ('pootietang.@example.com', 'Enter a valid email address'))
rtn = IS_EMAIL()('.@example.com') # name is bare dot rtn = IS_EMAIL()('.@example.com') # name is bare dot
self.assertEqual(rtn, ('.@example.com', 'Enter a valid email address')) self.assertEqual(rtn, ('.@example.com', 'Enter a valid email address'))
rtn = IS_EMAIL()('Ima.Fool@example.com') rtn = IS_EMAIL()('Ima.Fool@example.com')
self.assertEqual(rtn, ('Ima.Fool@example.com', None)) self.assertEqual(rtn, ('Ima.Fool@example.com', None))
rtn = IS_EMAIL()('Ima Fool@example.com') # space in name rtn = IS_EMAIL()('Ima Fool@example.com') # space in name
self.assertEqual(rtn, ('Ima Fool@example.com', 'Enter a valid email address')) self.assertEqual(rtn, ('Ima Fool@example.com', 'Enter a valid email address'))
rtn = IS_EMAIL()('localguy@localhost') # localhost as domain rtn = IS_EMAIL()('localguy@localhost') # localhost as domain
self.assertEqual(rtn, ('localguy@localhost', None)) self.assertEqual(rtn, ('localguy@localhost', None))
# test for banned # test for banned
rtn = IS_EMAIL(banned='^.*\.com(|\..*)$')('localguy@localhost') # localhost as domain rtn = IS_EMAIL(banned='^.*\.com(|\..*)$')('localguy@localhost') # localhost as domain
self.assertEqual(rtn, ('localguy@localhost', None)) self.assertEqual(rtn, ('localguy@localhost', None))
rtn = IS_EMAIL(banned='^.*\.com(|\..*)$')('abc@example.com') rtn = IS_EMAIL(banned='^.*\.com(|\..*)$')('abc@example.com')
self.assertEqual(rtn, ('abc@example.com', 'Enter a valid email address')) self.assertEqual(rtn, ('abc@example.com', 'Enter a valid email address'))
@@ -485,6 +528,9 @@ class TestValidators(unittest.TestCase):
self.assertEqual(rtn, ('localguy@localhost', 'Enter a valid email address')) self.assertEqual(rtn, ('localguy@localhost', 'Enter a valid email address'))
rtn = IS_EMAIL(forced='^.*\.edu(|\..*)$')('localguy@example.edu') rtn = IS_EMAIL(forced='^.*\.edu(|\..*)$')('localguy@example.edu')
self.assertEqual(rtn, ('localguy@example.edu', None)) self.assertEqual(rtn, ('localguy@example.edu', None))
# test for not a string at all
rtn = IS_EMAIL(error_message='oops')(42)
self.assertEqual(rtn, (42, 'oops'))
def test_IS_LIST_OF_EMAILS(self): def test_IS_LIST_OF_EMAILS(self):
emails = ['localguy@localhost', '_Yosemite.Sam@example.com'] emails = ['localguy@localhost', '_Yosemite.Sam@example.com']
@@ -543,16 +589,16 @@ class TestValidators(unittest.TestCase):
self.assertEqual(rtn, ('', 'Enter time as hh:mm:ss (seconds, am, pm optional)')) self.assertEqual(rtn, ('', 'Enter time as hh:mm:ss (seconds, am, pm optional)'))
def test_IS_DATE(self): def test_IS_DATE(self):
v = IS_DATE(format="%m/%d/%Y",error_message="oops") v = IS_DATE(format="%m/%d/%Y", error_message="oops")
rtn = v('03/03/2008') rtn = v('03/03/2008')
self.assertEqual(rtn, (datetime.date(2008, 3, 3), None)) self.assertEqual(rtn, (datetime.date(2008, 3, 3), None))
rtn = v('31/03/2008') rtn = v('31/03/2008')
self.assertEqual(rtn, ('31/03/2008', 'oops')) self.assertEqual(rtn, ('31/03/2008', 'oops'))
rtn = IS_DATE(format="%m/%d/%Y",error_message="oops").formatter(datetime.date(1834, 12, 14)) rtn = IS_DATE(format="%m/%d/%Y", error_message="oops").formatter(datetime.date(1834, 12, 14))
self.assertEqual(rtn, '12/14/1834') self.assertEqual(rtn, '12/14/1834')
def test_IS_DATETIME(self): def test_IS_DATETIME(self):
v = IS_DATETIME(format="%m/%d/%Y %H:%M",error_message="oops") v = IS_DATETIME(format="%m/%d/%Y %H:%M", error_message="oops")
rtn = v('03/03/2008 12:40') rtn = v('03/03/2008 12:40')
self.assertEqual(rtn, (datetime.datetime(2008, 3, 3, 12, 40), None)) self.assertEqual(rtn, (datetime.datetime(2008, 3, 3, 12, 40), None))
rtn = v('31/03/2008 29:40') rtn = v('31/03/2008 29:40')
@@ -560,16 +606,20 @@ class TestValidators(unittest.TestCase):
# Test timezone is removed and value is properly converted # Test timezone is removed and value is properly converted
# #
# https://github.com/web2py/web2py/issues/1094 # https://github.com/web2py/web2py/issues/1094
class DummyTimezone(datetime.tzinfo): class DummyTimezone(datetime.tzinfo):
ONE = datetime.timedelta(hours=1) ONE = datetime.timedelta(hours=1)
def utcoffset(self, dt): def utcoffset(self, dt):
return DummyTimezone.ONE return DummyTimezone.ONE
def tzname(self, dt): def tzname(self, dt):
return "UTC+1" return "UTC+1"
def dst(self, dt): def dst(self, dt):
return DummyTimezone.ONE return DummyTimezone.ONE
def localize(self, dt, is_dst=False): def localize(self, dt, is_dst=False):
return dt.replace(tzinfo=self) return dt.replace(tzinfo=self)
v = IS_DATETIME(format="%Y-%m-%d %H:%M", error_message="oops", timezone=DummyTimezone()) v = IS_DATETIME(format="%Y-%m-%d %H:%M", error_message="oops", timezone=DummyTimezone())
@@ -577,65 +627,65 @@ class TestValidators(unittest.TestCase):
self.assertEqual(rtn, (datetime.datetime(1982, 12, 14, 7, 0), None)) self.assertEqual(rtn, (datetime.datetime(1982, 12, 14, 7, 0), None))
def test_IS_DATE_IN_RANGE(self): def test_IS_DATE_IN_RANGE(self):
v = IS_DATE_IN_RANGE(minimum=datetime.date(2008,1,1), v = IS_DATE_IN_RANGE(minimum=datetime.date(2008, 1, 1),
maximum=datetime.date(2009,12,31), maximum=datetime.date(2009, 12, 31),
format="%m/%d/%Y",error_message="oops") format="%m/%d/%Y", error_message="oops")
rtn = v('03/03/2008') rtn = v('03/03/2008')
self.assertEqual(rtn, (datetime.date(2008, 3, 3), None)) self.assertEqual(rtn, (datetime.date(2008, 3, 3), None))
rtn = v('03/03/2010') rtn = v('03/03/2010')
self.assertEqual(rtn, ('03/03/2010', 'oops')) self.assertEqual(rtn, ('03/03/2010', 'oops'))
rtn = v(datetime.date(2008,3,3)) rtn = v(datetime.date(2008, 3, 3))
self.assertEqual(rtn, (datetime.date(2008, 3, 3), None)) self.assertEqual(rtn, (datetime.date(2008, 3, 3), None))
rtn = v(datetime.date(2010,3,3)) rtn = v(datetime.date(2010, 3, 3))
self.assertEqual(rtn, (datetime.date(2010, 3, 3), 'oops')) self.assertEqual(rtn, (datetime.date(2010, 3, 3), 'oops'))
v = IS_DATE_IN_RANGE(maximum=datetime.date(2009,12,31), v = IS_DATE_IN_RANGE(maximum=datetime.date(2009, 12, 31),
format="%m/%d/%Y") format="%m/%d/%Y")
rtn = v('03/03/2010') rtn = v('03/03/2010')
self.assertEqual(rtn, ('03/03/2010', 'Enter date on or before 12/31/2009')) self.assertEqual(rtn, ('03/03/2010', 'Enter date on or before 12/31/2009'))
v = IS_DATE_IN_RANGE(minimum=datetime.date(2008,1,1), v = IS_DATE_IN_RANGE(minimum=datetime.date(2008, 1, 1),
format="%m/%d/%Y") format="%m/%d/%Y")
rtn = v('03/03/2007') rtn = v('03/03/2007')
self.assertEqual(rtn, ('03/03/2007', 'Enter date on or after 01/01/2008')) self.assertEqual(rtn, ('03/03/2007', 'Enter date on or after 01/01/2008'))
v = IS_DATE_IN_RANGE(minimum=datetime.date(2008,1,1), v = IS_DATE_IN_RANGE(minimum=datetime.date(2008, 1, 1),
maximum=datetime.date(2009,12,31), maximum=datetime.date(2009, 12, 31),
format="%m/%d/%Y") format="%m/%d/%Y")
rtn = v('03/03/2007') rtn = v('03/03/2007')
self.assertEqual(rtn, ('03/03/2007', 'Enter date in range 01/01/2008 12/31/2009')) self.assertEqual(rtn, ('03/03/2007', 'Enter date in range 01/01/2008 12/31/2009'))
def test_IS_DATETIME_IN_RANGE(self): def test_IS_DATETIME_IN_RANGE(self):
v = IS_DATETIME_IN_RANGE( v = IS_DATETIME_IN_RANGE(
minimum=datetime.datetime(2008,1,1,12,20), minimum=datetime.datetime(2008, 1, 1, 12, 20),
maximum=datetime.datetime(2009,12,31,12,20), maximum=datetime.datetime(2009, 12, 31, 12, 20),
format="%m/%d/%Y %H:%M",error_message="oops") format="%m/%d/%Y %H:%M", error_message="oops")
rtn = v('03/03/2008 12:40') rtn = v('03/03/2008 12:40')
self.assertEqual(rtn, (datetime.datetime(2008, 3, 3, 12, 40), None)) self.assertEqual(rtn, (datetime.datetime(2008, 3, 3, 12, 40), None))
rtn = v('03/03/2010 10:34') rtn = v('03/03/2010 10:34')
self.assertEqual(rtn, ('03/03/2010 10:34', 'oops')) self.assertEqual(rtn, ('03/03/2010 10:34', 'oops'))
rtn = v(datetime.datetime(2008,3,3,0,0)) rtn = v(datetime.datetime(2008, 3, 3, 0, 0))
self.assertEqual(rtn, (datetime.datetime(2008, 3, 3, 0, 0), None)) self.assertEqual(rtn, (datetime.datetime(2008, 3, 3, 0, 0), None))
rtn = v(datetime.datetime(2010,3,3,0,0)) rtn = v(datetime.datetime(2010, 3, 3, 0, 0))
self.assertEqual(rtn, (datetime.datetime(2010, 3, 3, 0, 0), 'oops')) self.assertEqual(rtn, (datetime.datetime(2010, 3, 3, 0, 0), 'oops'))
v = IS_DATETIME_IN_RANGE(maximum=datetime.datetime(2009,12,31,12,20), v = IS_DATETIME_IN_RANGE(maximum=datetime.datetime(2009, 12, 31, 12, 20),
format='%m/%d/%Y %H:%M:%S') format='%m/%d/%Y %H:%M:%S')
rtn = v('03/03/2010 12:20:00') rtn = v('03/03/2010 12:20:00')
self.assertEqual(rtn, ('03/03/2010 12:20:00', 'Enter date and time on or before 12/31/2009 12:20:00')) self.assertEqual(rtn, ('03/03/2010 12:20:00', 'Enter date and time on or before 12/31/2009 12:20:00'))
v = IS_DATETIME_IN_RANGE(minimum=datetime.datetime(2008,1,1,12,20), v = IS_DATETIME_IN_RANGE(minimum=datetime.datetime(2008, 1, 1, 12, 20),
format='%m/%d/%Y %H:%M:%S') format='%m/%d/%Y %H:%M:%S')
rtn = v('03/03/2007 12:20:00') rtn = v('03/03/2007 12:20:00')
self.assertEqual(rtn, ('03/03/2007 12:20:00', 'Enter date and time on or after 01/01/2008 12:20:00')) self.assertEqual(rtn, ('03/03/2007 12:20:00', 'Enter date and time on or after 01/01/2008 12:20:00'))
v = IS_DATETIME_IN_RANGE(minimum=datetime.datetime(2008,1,1,12,20), v = IS_DATETIME_IN_RANGE(minimum=datetime.datetime(2008, 1, 1, 12, 20),
maximum=datetime.datetime(2009,12,31,12,20), maximum=datetime.datetime(2009, 12, 31, 12, 20),
format='%m/%d/%Y %H:%M:%S') format='%m/%d/%Y %H:%M:%S')
rtn = v('03/03/2007 12:20:00') rtn = v('03/03/2007 12:20:00')
self.assertEqual(rtn, ('03/03/2007 12:20:00', 'Enter date and time in range 01/01/2008 12:20:00 12/31/2009 12:20:00')) self.assertEqual(rtn, ('03/03/2007 12:20:00', 'Enter date and time in range 01/01/2008 12:20:00 12/31/2009 12:20:00'))
v = IS_DATETIME_IN_RANGE(maximum=datetime.datetime(2009,12,31,12,20), v = IS_DATETIME_IN_RANGE(maximum=datetime.datetime(2009, 12, 31, 12, 20),
format='%Y-%m-%d %H:%M:%S', error_message='oops') format='%Y-%m-%d %H:%M:%S', error_message='oops')
rtn = v('clearly not a date') rtn = v('clearly not a date')
self.assertEqual(rtn, ('clearly not a date', 'oops')) self.assertEqual(rtn, ('clearly not a date', 'oops'))
def test_IS_LIST_OF(self): def test_IS_LIST_OF(self):
values = [0,1,2,3,4] values = [0, 1, 2, 3, 4]
rtn = IS_LIST_OF(IS_INT_IN_RANGE(0, 10))(values) rtn = IS_LIST_OF(IS_INT_IN_RANGE(0, 10))(values)
self.assertEqual(rtn, (values, None)) self.assertEqual(rtn, (values, None))
values.append(11) values.append(11)
@@ -643,9 +693,9 @@ class TestValidators(unittest.TestCase):
self.assertEqual(rtn, (values, 'Enter an integer between 0 and 9')) self.assertEqual(rtn, (values, 'Enter an integer between 0 and 9'))
rtn = IS_LIST_OF(IS_INT_IN_RANGE(0, 10))(1) rtn = IS_LIST_OF(IS_INT_IN_RANGE(0, 10))(1)
self.assertEqual(rtn, ([1], None)) self.assertEqual(rtn, ([1], None))
rtn = IS_LIST_OF(IS_INT_IN_RANGE(0, 10), minimum=10)([1,2]) rtn = IS_LIST_OF(IS_INT_IN_RANGE(0, 10), minimum=10)([1, 2])
self.assertEqual(rtn, ([1, 2], 'Enter between 10 and 100 values')) self.assertEqual(rtn, ([1, 2], 'Enter between 10 and 100 values'))
rtn = IS_LIST_OF(IS_INT_IN_RANGE(0, 10), maximum=2)([1,2,3]) rtn = IS_LIST_OF(IS_INT_IN_RANGE(0, 10), maximum=2)([1, 2, 3])
self.assertEqual(rtn, ([1, 2, 3], 'Enter between 0 and 2 values')) self.assertEqual(rtn, ([1, 2, 3], 'Enter between 0 and 2 values'))
# regression test for issue 742 # regression test for issue 742
rtn = IS_LIST_OF(minimum=1)('') rtn = IS_LIST_OF(minimum=1)('')
@@ -704,69 +754,69 @@ class TestValidators(unittest.TestCase):
self.assertEqual(rtn, ('a bc', 'Must be slug')) self.assertEqual(rtn, ('a bc', 'Must be slug'))
def test_ANY_OF(self): def test_ANY_OF(self):
rtn = ANY_OF([IS_EMAIL(),IS_ALPHANUMERIC()])('a@b.co') rtn = ANY_OF([IS_EMAIL(), IS_ALPHANUMERIC()])('a@b.co')
self.assertEqual(rtn, ('a@b.co', None)) self.assertEqual(rtn, ('a@b.co', None))
rtn = ANY_OF([IS_EMAIL(),IS_ALPHANUMERIC()])('abco') rtn = ANY_OF([IS_EMAIL(), IS_ALPHANUMERIC()])('abco')
self.assertEqual(rtn, ('abco', None)) self.assertEqual(rtn, ('abco', None))
rtn = ANY_OF([IS_EMAIL(),IS_ALPHANUMERIC()])('@ab.co') rtn = ANY_OF([IS_EMAIL(), IS_ALPHANUMERIC()])('@ab.co')
self.assertEqual(rtn, ('@ab.co', 'Enter only letters, numbers, and underscore')) self.assertEqual(rtn, ('@ab.co', 'Enter only letters, numbers, and underscore'))
rtn = ANY_OF([IS_ALPHANUMERIC(),IS_EMAIL()])('@ab.co') rtn = ANY_OF([IS_ALPHANUMERIC(), IS_EMAIL()])('@ab.co')
self.assertEqual(rtn, ('@ab.co', 'Enter a valid email address')) self.assertEqual(rtn, ('@ab.co', 'Enter a valid email address'))
rtn = ANY_OF([IS_DATE(),IS_EMAIL()])('a@b.co') rtn = ANY_OF([IS_DATE(), IS_EMAIL()])('a@b.co')
self.assertEqual(rtn, ('a@b.co', None)) self.assertEqual(rtn, ('a@b.co', None))
rtn = ANY_OF([IS_DATE(),IS_EMAIL()])('1982-12-14') rtn = ANY_OF([IS_DATE(), IS_EMAIL()])('1982-12-14')
self.assertEqual(rtn, (datetime.date(1982, 12, 14), None)) self.assertEqual(rtn, (datetime.date(1982, 12, 14), None))
rtn = ANY_OF([IS_DATE(format='%m/%d/%Y'),IS_EMAIL()]).formatter(datetime.date(1834, 12, 14)) rtn = ANY_OF([IS_DATE(format='%m/%d/%Y'), IS_EMAIL()]).formatter(datetime.date(1834, 12, 14))
self.assertEqual(rtn, '12/14/1834') self.assertEqual(rtn, '12/14/1834')
def test_IS_EMPTY_OR(self): def test_IS_EMPTY_OR(self):
rtn = IS_EMPTY_OR(IS_EMAIL())('abc@def.com') rtn = IS_EMPTY_OR(IS_EMAIL())('abc@def.com')
self.assertEqual(rtn, ('abc@def.com', None)) self.assertEqual(rtn, ('abc@def.com', None))
rtn = IS_EMPTY_OR(IS_EMAIL())(' ') rtn = IS_EMPTY_OR(IS_EMAIL())(' ')
self.assertEqual(rtn, (None, None)) self.assertEqual(rtn, (None, None))
rtn = IS_EMPTY_OR(IS_EMAIL(), null='abc')(' ') rtn = IS_EMPTY_OR(IS_EMAIL(), null='abc')(' ')
self.assertEqual(rtn, ('abc', None)) self.assertEqual(rtn, ('abc', None))
rtn = IS_EMPTY_OR(IS_EMAIL(), null='abc', empty_regex='def')('def') rtn = IS_EMPTY_OR(IS_EMAIL(), null='abc', empty_regex='def')('def')
self.assertEqual(rtn, ('abc', None)) self.assertEqual(rtn, ('abc', None))
rtn = IS_EMPTY_OR(IS_EMAIL())('abc') rtn = IS_EMPTY_OR(IS_EMAIL())('abc')
self.assertEqual(rtn, ('abc', 'Enter a valid email address')) self.assertEqual(rtn, ('abc', 'Enter a valid email address'))
rtn = IS_EMPTY_OR(IS_EMAIL())(' abc ') rtn = IS_EMPTY_OR(IS_EMAIL())(' abc ')
self.assertEqual(rtn, ('abc', 'Enter a valid email address')) self.assertEqual(rtn, ('abc', 'Enter a valid email address'))
rtn = IS_EMPTY_OR(IS_IN_SET([('id1','first label'), ('id2','second label')], zero='zero')).options(zero=False) rtn = IS_EMPTY_OR(IS_IN_SET([('id1', 'first label'), ('id2', 'second label')], zero='zero')).options(zero=False)
self.assertEqual(rtn, [('', ''),('id1', 'first label'), ('id2', 'second label')]) self.assertEqual(rtn, [('', ''), ('id1', 'first label'), ('id2', 'second label')])
rtn = IS_EMPTY_OR(IS_IN_SET([('id1','first label'), ('id2','second label')], zero='zero')).options() rtn = IS_EMPTY_OR(IS_IN_SET([('id1', 'first label'), ('id2', 'second label')], zero='zero')).options()
self.assertEqual(rtn, [('', 'zero'),('id1', 'first label'), ('id2', 'second label')]) self.assertEqual(rtn, [('', 'zero'), ('id1', 'first label'), ('id2', 'second label')])
def test_CLEANUP(self): def test_CLEANUP(self):
rtn = CLEANUP()('helloò') rtn = CLEANUP()('helloò')
self.assertEqual(rtn, ('hello', None)) self.assertEqual(rtn, ('hello', None))
def test_CRYPT(self): def test_CRYPT(self):
rtn = str(CRYPT(digest_alg='md5',salt=True)('test')[0]) rtn = str(CRYPT(digest_alg='md5', salt=True)('test')[0])
self.assertRegexpMatches(rtn, r'^md5\$.{16}\$.{32}$') self.assertRegexpMatches(rtn, r'^md5\$.{16}\$.{32}$')
rtn = str(CRYPT(digest_alg='sha1',salt=True)('test')[0]) rtn = str(CRYPT(digest_alg='sha1', salt=True)('test')[0])
self.assertRegexpMatches(rtn, r'^sha1\$.{16}\$.{40}$') self.assertRegexpMatches(rtn, r'^sha1\$.{16}\$.{40}$')
rtn = str(CRYPT(digest_alg='sha256',salt=True)('test')[0]) rtn = str(CRYPT(digest_alg='sha256', salt=True)('test')[0])
self.assertRegexpMatches(rtn, r'^sha256\$.{16}\$.{64}$') self.assertRegexpMatches(rtn, r'^sha256\$.{16}\$.{64}$')
rtn = str(CRYPT(digest_alg='sha384',salt=True)('test')[0]) rtn = str(CRYPT(digest_alg='sha384', salt=True)('test')[0])
self.assertRegexpMatches(rtn, r'^sha384\$.{16}\$.{96}$') self.assertRegexpMatches(rtn, r'^sha384\$.{16}\$.{96}$')
rtn = str(CRYPT(digest_alg='sha512',salt=True)('test')[0]) rtn = str(CRYPT(digest_alg='sha512', salt=True)('test')[0])
self.assertRegexpMatches(rtn, r'^sha512\$.{16}\$.{128}$') self.assertRegexpMatches(rtn, r'^sha512\$.{16}\$.{128}$')
alg = 'pbkdf2(1000,20,sha512)' alg = 'pbkdf2(1000,20,sha512)'
rtn = str(CRYPT(digest_alg=alg,salt=True)('test')[0]) rtn = str(CRYPT(digest_alg=alg, salt=True)('test')[0])
self.assertRegexpMatches(rtn, r'^pbkdf2\(1000,20,sha512\)\$.{16}\$.{40}$') self.assertRegexpMatches(rtn, r'^pbkdf2\(1000,20,sha512\)\$.{16}\$.{40}$')
rtn = str(CRYPT(digest_alg='md5',key='mykey',salt=True)('test')[0]) rtn = str(CRYPT(digest_alg='md5', key='mykey', salt=True)('test')[0])
self.assertRegexpMatches(rtn, r'^md5\$.{16}\$.{32}$') self.assertRegexpMatches(rtn, r'^md5\$.{16}\$.{32}$')
a = str(CRYPT(digest_alg='sha1',salt=False)('test')[0]) a = str(CRYPT(digest_alg='sha1', salt=False)('test')[0])
self.assertEqual(CRYPT(digest_alg='sha1',salt=False)('test')[0], a) self.assertEqual(CRYPT(digest_alg='sha1', salt=False)('test')[0], a)
self.assertEqual(CRYPT(digest_alg='sha1',salt=False)('test')[0], a[6:]) self.assertEqual(CRYPT(digest_alg='sha1', salt=False)('test')[0], a[6:])
self.assertEqual(CRYPT(digest_alg='md5',salt=False)('test')[0], a) self.assertEqual(CRYPT(digest_alg='md5', salt=False)('test')[0], a)
self.assertEqual(CRYPT(digest_alg='md5',salt=False)('test')[0], a[6:]) self.assertEqual(CRYPT(digest_alg='md5', salt=False)('test')[0], a[6:])
def test_IS_STRONG(self): def test_IS_STRONG(self):
rtn = IS_STRONG(es=True)('Abcd1234') rtn = IS_STRONG(es=True)('Abcd1234')
self.assertEqual(rtn, ('Abcd1234', self.assertEqual(rtn, ('Abcd1234',
'Must include at least 1 of the following: ~!@#$%^&*()_+-=?<>,.:;{}[]|')) 'Must include at least 1 of the following: ~!@#$%^&*()_+-=?<>,.:;{}[]|'))
rtn = IS_STRONG(es=True)('Abcd1234!') rtn = IS_STRONG(es=True)('Abcd1234!')
self.assertEqual(rtn, ('Abcd1234!', None)) self.assertEqual(rtn, ('Abcd1234!', None))
rtn = IS_STRONG(es=True, entropy=1)('a') rtn = IS_STRONG(es=True, entropy=1)('a')
@@ -787,33 +837,34 @@ class TestValidators(unittest.TestCase):
self.assertEqual(rtn, ('********', None)) self.assertEqual(rtn, ('********', None))
rtn = IS_STRONG(es=True, max=4)('abcde') rtn = IS_STRONG(es=True, max=4)('abcde')
self.assertEqual(rtn, self.assertEqual(rtn,
('abcde', ('abcde',
'|'.join(['Minimum length is 8', '|'.join(['Minimum length is 8',
'Maximum length is 4', 'Maximum length is 4',
'Must include at least 1 of the following: ~!@#$%^&*()_+-=?<>,.:;{}[]|', 'Must include at least 1 of the following: ~!@#$%^&*()_+-=?<>,.:;{}[]|',
'Must include at least 1 upper case', 'Must include at least 1 upper case',
'Must include at least 1 number'])) 'Must include at least 1 number']))
) )
rtn = IS_STRONG(es=True)('abcde') rtn = IS_STRONG(es=True)('abcde')
self.assertEqual(rtn, self.assertEqual(rtn,
('abcde', ('abcde',
'|'.join(['Minimum length is 8', '|'.join(['Minimum length is 8',
'Must include at least 1 of the following: ~!@#$%^&*()_+-=?<>,.:;{}[]|', 'Must include at least 1 of the following: ~!@#$%^&*()_+-=?<>,.:;{}[]|',
'Must include at least 1 upper case', 'Must include at least 1 upper case',
'Must include at least 1 number'])) 'Must include at least 1 number']))
) )
rtn = IS_STRONG(upper=0, lower=0, number=0, es=True)('Abcde1') rtn = IS_STRONG(upper=0, lower=0, number=0, es=True)('Abcde1')
self.assertEqual(rtn, self.assertEqual(rtn,
('Abcde1', ('Abcde1',
'|'.join(['Minimum length is 8', '|'.join(['Minimum length is 8',
'Must include at least 1 of the following: ~!@#$%^&*()_+-=?<>,.:;{}[]|', 'Must include at least 1 of the following: ~!@#$%^&*()_+-=?<>,.:;{}[]|',
'May not include any upper case letters', 'May not include any upper case letters',
'May not include any lower case letters', 'May not include any lower case letters',
'May not include any numbers'])) 'May not include any numbers']))
) )
def test_IS_IMAGE(self): def test_IS_IMAGE(self):
class DummyImageFile(object): class DummyImageFile(object):
def __init__(self, filename, ext, width, height): def __init__(self, filename, ext, width, height):
from StringIO import StringIO from StringIO import StringIO
import struct import struct
@@ -821,7 +872,7 @@ class TestValidators(unittest.TestCase):
self.file = StringIO() self.file = StringIO()
if ext == 'bmp': if ext == 'bmp':
self.file.write(b'BM') self.file.write(b'BM')
self.file.write(b' '*16) self.file.write(b' ' * 16)
self.file.write(struct.pack('<LL', width, height)) self.file.write(struct.pack('<LL', width, height))
elif ext == 'gif': elif ext == 'gif':
self.file.write(b'GIF87a') self.file.write(b'GIF87a')
@@ -832,7 +883,7 @@ class TestValidators(unittest.TestCase):
self.file.write(struct.pack('!xHH', height, width)) self.file.write(struct.pack('!xHH', height, width))
elif ext == 'png': elif ext == 'png':
self.file.write(b'\211PNG\r\n\032\n') self.file.write(b'\211PNG\r\n\032\n')
self.file.write(b' '*4) self.file.write(b' ' * 4)
self.file.write(b'IHDR') self.file.write(b'IHDR')
self.file.write(struct.pack('!LL', width, height)) self.file.write(struct.pack('!LL', width, height))
self.file.seek(0) self.file.seek(0)
@@ -873,10 +924,10 @@ class TestValidators(unittest.TestCase):
rtn = IS_IMAGE(error_message='oops')(img) rtn = IS_IMAGE(error_message='oops')(img)
self.assertEqual(rtn, (img, 'oops')) self.assertEqual(rtn, (img, 'oops'))
def test_IS_UPLOAD_FILENAME(self): def test_IS_UPLOAD_FILENAME(self):
import cgi import cgi
from StringIO import StringIO from StringIO import StringIO
def gen_fake(filename): def gen_fake(filename):
formdata_file_data = """ formdata_file_data = """
---123 ---123
@@ -984,7 +1035,7 @@ this is the content of the fake file
self.assertEqual(rtn, ('2001::8ffa:fe22:b3af', None)) self.assertEqual(rtn, ('2001::8ffa:fe22:b3af', None))
rtn = IS_IPV6(subnets='fb00::/8')('2001::8ffa:fe22:b3af') rtn = IS_IPV6(subnets='fb00::/8')('2001::8ffa:fe22:b3af')
self.assertEqual(rtn, ('2001::8ffa:fe22:b3af', 'Enter valid IPv6 address')) self.assertEqual(rtn, ('2001::8ffa:fe22:b3af', 'Enter valid IPv6 address'))
rtn = IS_IPV6(subnets=['fc00::/8','2001::/32'])('2001::8ffa:fe22:b3af') rtn = IS_IPV6(subnets=['fc00::/8', '2001::/32'])('2001::8ffa:fe22:b3af')
self.assertEqual(rtn, ('2001::8ffa:fe22:b3af', None)) self.assertEqual(rtn, ('2001::8ffa:fe22:b3af', None))
rtn = IS_IPV6(subnets='invalidsubnet')('2001::8ffa:fe22:b3af') rtn = IS_IPV6(subnets='invalidsubnet')('2001::8ffa:fe22:b3af')
self.assertEqual(rtn, ('2001::8ffa:fe22:b3af', 'invalid subnet provided')) self.assertEqual(rtn, ('2001::8ffa:fe22:b3af', 'invalid subnet provided'))
@@ -1059,7 +1110,7 @@ this is the content of the fake file
self.assertEqual(rtn, ('2001::8ffa:fe22:b3af', None)) self.assertEqual(rtn, ('2001::8ffa:fe22:b3af', None))
rtn = IS_IPADDRESS(subnets='fb00::/8')('2001::8ffa:fe22:b3af') rtn = IS_IPADDRESS(subnets='fb00::/8')('2001::8ffa:fe22:b3af')
self.assertEqual(rtn, ('2001::8ffa:fe22:b3af', 'Enter valid IP address')) self.assertEqual(rtn, ('2001::8ffa:fe22:b3af', 'Enter valid IP address'))
rtn = IS_IPADDRESS(subnets=['fc00::/8','2001::/32'])('2001::8ffa:fe22:b3af') rtn = IS_IPADDRESS(subnets=['fc00::/8', '2001::/32'])('2001::8ffa:fe22:b3af')
self.assertEqual(rtn, ('2001::8ffa:fe22:b3af', None)) self.assertEqual(rtn, ('2001::8ffa:fe22:b3af', None))
rtn = IS_IPADDRESS(subnets='invalidsubnet')('2001::8ffa:fe22:b3af') rtn = IS_IPADDRESS(subnets='invalidsubnet')('2001::8ffa:fe22:b3af')
self.assertEqual(rtn, ('2001::8ffa:fe22:b3af', 'invalid subnet provided')) self.assertEqual(rtn, ('2001::8ffa:fe22:b3af', 'invalid subnet provided'))