fixed pep8 in apps

This commit is contained in:
mdipierro committed 2012-10-19 14:13:37 -05:00
1 parent c7943b8977
commit d053900032
28 files changed
+510 -217

No files matched your search

+1 -1
View File
@@ -1 +1 @@
Version 2.1.1 (2012-10-19 12:59:55) dev Version 2.1.1 (2012-10-19 14:13:30) dev
+34 -16
View File
@@ -102,17 +102,16 @@ def query_by_table_type(tablename,db,request=request):
cond = '>0' cond = '>0'
if firstkey.type in ['string', 'text']: if firstkey.type in ['string', 'text']:
cond = '!=""' cond = '!=""'
qry = '%s.%s.%s%s' % (request.args[0], request.args[1], firstkey.name, cond) qry = '%s.%s.%s%s' % (
request.args[0], request.args[1], firstkey.name, cond)
else: else:
qry = '%s.%s.id>0' % tuple(request.args[:2]) qry = '%s.%s.id>0' % tuple(request.args[:2])
return qry return qry
# ########################################################## # ##########################################################
# ## list all databases and tables # ## list all databases and tables
# ########################################################### # ###########################################################
def index(): def index():
return dict(databases=databases) return dict(databases=databases)
@@ -140,6 +139,7 @@ def download():
db = get_database(request) db = get_database(request)
return response.download(request, db) return response.download(request, db)
def csv(): def csv():
import gluon.contenttype import gluon.contenttype
response.headers['Content-Type'] = \ response.headers['Content-Type'] = \
@@ -156,6 +156,7 @@ def csv():
def import_csv(table, file): def import_csv(table, file):
table.import_from_csv_file(file) table.import_from_csv_file(file)
def select(): def select():
import re import re
db = get_database(request) db = get_database(request)
@@ -192,7 +193,8 @@ def select():
session.last_query = request.vars.query session.last_query = request.vars.query
form = FORM(TABLE(TR(T('Query:'), '', INPUT(_style='width:400px', form = FORM(TABLE(TR(T('Query:'), '', INPUT(_style='width:400px',
_name='query', _value=request.vars.query or '', _name='query', _value=request.vars.query or '',
requires=IS_NOT_EMPTY(error_message=T("Cannot be empty")))), TR(T('Update:'), requires=IS_NOT_EMPTY(
error_message=T("Cannot be empty")))), TR(T('Update:'),
INPUT(_name='update_check', _type='checkbox', INPUT(_name='update_check', _type='checkbox',
value=False), INPUT(_style='width:400px', value=False), INPUT(_style='width:400px',
_name='update_fields', _value=request.vars.update_fields _name='update_fields', _value=request.vars.update_fields
@@ -218,9 +220,11 @@ def select():
response.flash = T('%s %%{row} deleted', nrows) response.flash = T('%s %%{row} deleted', nrows)
nrows = db(query).count() nrows = db(query).count()
if orderby: if orderby:
rows = db(query,ignore_common_filters=True).select(limitby=(start, stop), orderby=eval_in_global_env(orderby)) rows = db(query, ignore_common_filters=True).select(limitby=(
start, stop), orderby=eval_in_global_env(orderby))
else: else:
rows = db(query,ignore_common_filters=True).select(limitby=(start, stop)) rows = db(query, ignore_common_filters=True).select(
limitby=(start, stop))
except Exception, e: except Exception, e:
import traceback import traceback
tb = traceback.format_exc() tb = traceback.format_exc()
@@ -269,9 +273,11 @@ def update():
if keyed: if keyed:
key = [f for f in request.vars if f in db[table]._primarykey] key = [f for f in request.vars if f in db[table]._primarykey]
if key: if key:
record = db(db[table][key[0]] == request.vars[key[0]], ignore_common_filters=True).select().first() record = db(db[table][key[0]] == request.vars[key[
0]], ignore_common_filters=True).select().first()
else: else:
record = db(db[table].id == request.args(2),ignore_common_filters=True).select().first() record = db(db[table].id == request.args(
2), ignore_common_filters=True).select().first()
if not record: if not record:
qry = query_by_table_type(table, db) qry = query_by_table_type(table, db)
@@ -283,7 +289,8 @@ def update():
for k in db[table]._primarykey: for k in db[table]._primarykey:
db[table][k].writable = False db[table][k].writable = False
form = SQLFORM(db[table], record, deletable=True, delete_label=T('Check to delete'), form = SQLFORM(
db[table], record, deletable=True, delete_label=T('Check to delete'),
ignore_rw=ignore_rw and not keyed, ignore_rw=ignore_rw and not keyed,
linkto=URL('select', linkto=URL('select',
args=request.args[:1]), upload=URL(r=request, args=request.args[:1]), upload=URL(r=request,
@@ -305,11 +312,15 @@ def update():
def state(): def state():
return dict() return dict()
def ccache(): def ccache():
form = FORM( form = FORM(
P(TAG.BUTTON(T("Clear CACHE?"), _type="submit", _name="yes", _value="yes")), P(TAG.BUTTON(
P(TAG.BUTTON(T("Clear RAM"), _type="submit", _name="ram", _value="ram")), T("Clear CACHE?"), _type="submit", _name="yes", _value="yes")),
P(TAG.BUTTON(T("Clear DISK"), _type="submit", _name="disk", _value="disk")), P(TAG.BUTTON(
T("Clear RAM"), _type="submit", _name="ram", _value="ram")),
P(TAG.BUTTON(
T("Clear DISK"), _type="submit", _name="disk", _value="disk")),
) )
if form.accepts(request.vars, session): if form.accepts(request.vars, session):
@@ -333,11 +344,16 @@ def ccache():
redirect(URL(r=request)) redirect(URL(r=request))
try: try:
from guppy import hpy; hp=hpy() from guppy import hpy
hp = hpy()
except ImportError: except ImportError:
hp = False hp = False
import shelve, os, copy, time, math import shelve
import os
import copy
import time
import math
from gluon import portalocker from gluon import portalocker
ram = { ram = {
@@ -384,7 +400,8 @@ def ccache():
locker = open(os.path.join(request.folder, locker = open(os.path.join(request.folder,
'cache/cache.lock'), 'a') 'cache/cache.lock'), 'a')
portalocker.lock(locker, portalocker.LOCK_EX) portalocker.lock(locker, portalocker.LOCK_EX)
disk_storage = shelve.open(os.path.join(request.folder, 'cache/cache.shelve')) disk_storage = shelve.open(
os.path.join(request.folder, 'cache/cache.shelve'))
try: try:
for key, value in disk_storage.items(): for key, value in disk_storage.items():
if isinstance(value, dict): if isinstance(value, dict):
@@ -415,7 +432,8 @@ def ccache():
total['misses'] = ram['misses'] + disk['misses'] total['misses'] = ram['misses'] + disk['misses']
total['keys'] = ram['keys'] + disk['keys'] total['keys'] = ram['keys'] + disk['keys']
try: try:
total['ratio'] = total['hits'] * 100 / (total['hits'] + total['misses']) total['ratio'] = total['hits'] * 100 / (total['hits'] +
total['misses'])
except (KeyError, ZeroDivisionError): except (KeyError, ZeroDivisionError):
total['ratio'] = 0 total['ratio'] = 0
+11 -1
View File
@@ -5,7 +5,8 @@ import gluon.contrib.shell
import gluon.dal import gluon.dal
import gluon.html import gluon.html
import gluon.validators import gluon.validators
import code, thread import code
import thread
from gluon.debug import communicate, web_debugger, qdb_debugger from gluon.debug import communicate, web_debugger, qdb_debugger
import pydoc import pydoc
@@ -16,6 +17,7 @@ if DEMO_MODE or MULTI_USER_MODE:
FE = 10 ** 9 FE = 10 ** 9
def index(): def index():
app = request.args(0) or 'admin' app = request.args(0) or 'admin'
reset() reset()
@@ -23,6 +25,7 @@ def index():
data = communicate() data = communicate()
return dict(app=app, data=data) return dict(app=app, data=data)
def callback(): def callback():
app = request.args[0] app = request.args[0]
command = request.vars.statement command = request.vars.statement
@@ -31,6 +34,7 @@ def callback():
k = len(session['debug_commands:' + app]) - 1 k = len(session['debug_commands:' + app]) - 1
return '[%i] %s%s\n' % (k + 1, command, output) return '[%i] %s%s\n' % (k + 1, command, output)
def reset(): def reset():
app = request.args(0) or 'admin' app = request.args(0) or 'admin'
session['debug_commands:' + app] = [] session['debug_commands:' + app] = []
@@ -81,26 +85,32 @@ def interact():
f_globals=f_globals, f_locals=f_locals, f_globals=f_globals, f_locals=f_locals,
exception=web_debugger.exception_info) exception=web_debugger.exception_info)
def step(): def step():
web_debugger.do_step() web_debugger.do_step()
redirect(URL("interact")) redirect(URL("interact"))
def next(): def next():
web_debugger.do_next() web_debugger.do_next()
redirect(URL("interact")) redirect(URL("interact"))
def cont(): def cont():
web_debugger.do_continue() web_debugger.do_continue()
redirect(URL("interact")) redirect(URL("interact"))
def ret(): def ret():
web_debugger.do_return() web_debugger.do_return()
redirect(URL("interact")) redirect(URL("interact"))
def stop(): def stop():
web_debugger.do_quit() web_debugger.do_quit()
redirect(URL("interact")) redirect(URL("interact"))
def execute(): def execute():
app = request.args[0] app = request.args[0]
command = request.vars.statement command = request.vars.statement
+125 -51
View File
@@ -39,26 +39,33 @@ if FILTER_APPS and request.args(0) and not request.args(0) in FILTER_APPS:
redirect(URL('site')) redirect(URL('site'))
if not session.token: session.token = web2py_uuid() if not session.token:
session.token = web2py_uuid()
def count_lines(data): def count_lines(data):
return len([line for line in data.split('\n') if line.strip() and not line.startswith('#')]) return len([line for line in data.split('\n') if line.strip() and not line.startswith('#')])
def log_progress(app, mode='EDIT', filename=None, progress=0): def log_progress(app, mode='EDIT', filename=None, progress=0):
progress_file = os.path.join(apath(app, r=request), 'progress.log') progress_file = os.path.join(apath(app, r=request), 'progress.log')
now = str(request.now)[:19] now = str(request.now)[:19]
if not os.path.exists(progress_file): if not os.path.exists(progress_file):
safe_open(progress_file, 'w').write('[%s] START\n' % now) safe_open(progress_file, 'w').write('[%s] START\n' % now)
if filename: if filename:
safe_open(progress_file,'a').write('[%s] %s %s: %s\n' % (now,mode,filename,progress)) safe_open(progress_file, 'a').write(
'[%s] %s %s: %s\n' % (now, mode, filename, progress))
def safe_open(a, b): def safe_open(a, b):
if DEMO_MODE and ('w' in b or 'a' in b): if DEMO_MODE and ('w' in b or 'a' in b):
class tmp: class tmp:
def write(self,data): pass def write(self, data):
pass
return tmp() return tmp()
return open(a, b) return open(a, b)
def safe_read(a, b='r'): def safe_read(a, b='r'):
safe_file = safe_open(a, b) safe_file = safe_open(a, b)
try: try:
@@ -66,6 +73,7 @@ def safe_read(a, b='r'):
finally: finally:
safe_file.close() safe_file.close()
def safe_write(a, value, b='w'): def safe_write(a, value, b='w'):
safe_file = safe_open(a, b) safe_file = safe_open(a, b)
try: try:
@@ -73,14 +81,16 @@ def safe_write(a, value, b='w'):
finally: finally:
safe_file.close() safe_file.close()
def get_app(name=None): def get_app(name=None):
app = name or request.args(0) app = name or request.args(0)
if app and (not MULTI_USER_MODE or is_manager() or \ if app and (not MULTI_USER_MODE or is_manager() or
db(db.app.name == app)(db.app.owner == auth.user.id).count()): db(db.app.name == app)(db.app.owner == auth.user.id).count()):
return app return app
session.flash = T('App does not exist or your are not authorized') session.flash = T('App does not exist or your are not authorized')
redirect(URL('site')) redirect(URL('site'))
def index(): def index():
""" Index handler """ """ Index handler """
@@ -137,9 +147,10 @@ def check_version():
return SPAN('You should upgrade to version %s.%s.%s' % version_number[:3]) return SPAN('You should upgrade to version %s.%s.%s' % version_number[:3])
else: else:
return sp_button(URL('upgrade_web2py'), T('upgrade now')) \ return sp_button(URL('upgrade_web2py'), T('upgrade now')) \
+ XML(' <strong class="upgrade_version">%s.%s.%s</strong>' \ + XML(' <strong class="upgrade_version">%s.%s.%s</strong>'
% version_number[:3]) % version_number[:3])
def logout(): def logout():
""" Logout handler """ """ Logout handler """
session.authorized = None session.authorized = None
@@ -151,10 +162,12 @@ def logout():
def change_password(): def change_password():
if session.pam_user: if session.pam_user:
session.flash = T('PAM authenticated user, cannot change password here') session.flash = T(
'PAM authenticated user, cannot change password here')
redirect(URL('site')) redirect(URL('site'))
form = SQLFORM.factory(Field('current_admin_password', 'password'), form = SQLFORM.factory(Field('current_admin_password', 'password'),
Field('new_admin_password','password',requires=IS_STRONG()), Field('new_admin_password',
'password', requires=IS_STRONG()),
Field('new_admin_password_again', 'password')) Field('new_admin_password_again', 'password'))
if form.accepts(request.vars): if form.accepts(request.vars):
if not verify_password(request.vars.current_admin_password): if not verify_password(request.vars.current_admin_password):
@@ -163,7 +176,8 @@ def change_password():
form.errors.new_admin_password_again = T('no match') form.errors.new_admin_password_again = T('no match')
else: else:
path = abspath('parameters_%s.py' % request.env.server_port) path = abspath('parameters_%s.py' % request.env.server_port)
safe_write(path, 'password="%s"' % CRYPT()(request.vars.new_admin_password)[0]) safe_write(path, 'password="%s"' % CRYPT()(
request.vars.new_admin_password)[0])
session.flash = T('password changed') session.flash = T('password changed')
redirect(URL('site')) redirect(URL('site'))
return dict(form=form) return dict(form=form)
@@ -295,8 +309,10 @@ def report_progress(app):
matches = regex.findall(open(progress_file, 'r').read()) matches = regex.findall(open(progress_file, 'r').read())
events, counter = [], 0 events, counter = [], 0
for m in matches: for m in matches:
if not m: continue if not m:
days = -(request.now - datetime.datetime.strptime(m[0],'%Y-%m-%d %H:%M:%S')).days continue
days = -(request.now - datetime.datetime.strptime(m[0],
'%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
@@ -324,6 +340,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:
@@ -338,6 +355,7 @@ def pack_plugin():
session.flash = T('internal error') session.flash = T('internal error')
redirect(URL('plugin', args=request.args)) redirect(URL('plugin', args=request.args))
def upgrade_web2py(): def upgrade_web2py():
dialog = FORM.confirm(T('Upgrade'), dialog = FORM.confirm(T('Upgrade'),
{T('Cancel'): URL('site')}) {T('Cancel'): URL('site')})
@@ -350,6 +368,7 @@ def upgrade_web2py():
redirect(URL('site')) redirect(URL('site'))
return dict(dialog=dialog) return dict(dialog=dialog)
def uninstall(): def uninstall():
app = get_app() app = get_app()
@@ -407,6 +426,7 @@ def remove_compiled_app():
session.flash = T('compiled application removed') session.flash = T('compiled application removed')
redirect(URL('site')) redirect(URL('site'))
def delete(): def delete():
""" Object delete handler """ """ Object delete handler """
app = get_app() app = get_app()
@@ -432,6 +452,7 @@ def delete():
redirect(URL(sender, anchor=request.vars.id2)) redirect(URL(sender, anchor=request.vars.id2))
return dict(filename=filename, sender=sender) return dict(filename=filename, sender=sender)
def delete(): def delete():
""" Object delete handler """ """ Object delete handler """
app = get_app() app = get_app()
@@ -458,6 +479,7 @@ def delete():
redirect(URL(sender, anchor=request.vars.id2)) redirect(URL(sender, anchor=request.vars.id2))
return dict(dialog=dialog, filename=filename) return dict(dialog=dialog, filename=filename)
def enable(): def enable():
app = get_app() app = get_app()
filename = os.path.join(apath(app, r=request), 'DISABLED') filename = os.path.join(apath(app, r=request), 'DISABLED')
@@ -470,6 +492,7 @@ def enable():
safe_open(filename, 'wb').write(time.ctime()) safe_open(filename, 'wb').write(time.ctime())
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)
@@ -491,6 +514,7 @@ def peek():
data=data, data=data,
extension=extension) extension=extension)
def test(): def test():
""" Execute controller tests """ """ Execute controller tests """
app = get_app() app = get_app()
@@ -499,16 +523,20 @@ def test():
else: else:
file = '.*\.py' file = '.*\.py'
controllers = listdir(apath('%s/controllers/' % app, r=request), file + '$') controllers = listdir(
apath('%s/controllers/' % app, r=request), file + '$')
return dict(app=app, controllers=controllers) return dict(app=app, controllers=controllers)
def keepalive(): def keepalive():
return '' return ''
def search(): def search():
keywords = request.vars.keywords or '' keywords = request.vars.keywords or ''
app = get_app() app = get_app()
def match(filename, keywords): def match(filename, keywords):
filename = os.path.join(apath(app, r=request), filename) filename = os.path.join(apath(app, r=request), filename)
if keywords in read_file(filename, 'rb'): if keywords in read_file(filename, 'rb'):
@@ -518,9 +546,11 @@ def search():
files1 = glob(os.path.join(path, '*/*.py')) files1 = glob(os.path.join(path, '*/*.py'))
files2 = glob(os.path.join(path, '*/*.html')) files2 = glob(os.path.join(path, '*/*.html'))
files3 = glob(os.path.join(path, '*/*/*.html')) files3 = glob(os.path.join(path, '*/*/*.html'))
files=[x[len(path)+1:].replace('\\','/') for x in files1+files2+files3 if match(x,keywords)] files = [x[len(path) + 1:].replace(
'\\', '/') for x in files1 + files2 + files3 if match(x, keywords)]
return response.json(dict(files=files, message=T.M('Searching: **%s** %%{file}', len(files)))) return response.json(dict(files=files, message=T.M('Searching: **%s** %%{file}', len(files))))
def edit(): def edit():
""" File edit handler """ """ File edit handler """
# Load json only if it is ajax edited... # Load json only if it is ajax edited...
@@ -590,7 +620,8 @@ def edit():
data = request.vars.data.replace('\r\n', '\n').strip() + '\n' data = request.vars.data.replace('\r\n', '\n').strip() + '\n'
safe_write(path, data) safe_write(path, data)
lineno_new = count_lines(data) lineno_new = count_lines(data)
log_progress(app,'EDIT',filename,progress=lineno_new-lineno_old) log_progress(
app, 'EDIT', filename, progress=lineno_new - lineno_old)
file_hash = md5_hash(data) file_hash = md5_hash(data)
saved_on = time.ctime(os.stat(path)[stat.ST_MTIME]) saved_on = time.ctime(os.stat(path)[stat.ST_MTIME])
response.flash = T('file saved on %s', saved_on) response.flash = T('file saved on %s', saved_on)
@@ -609,28 +640,33 @@ def edit():
in enumerate(request.vars.data.split("\n")) in enumerate(request.vars.data.split("\n"))
if l < e.lineno - 1]) if l < e.lineno - 1])
if e.text and e.offset: if e.text and e.offset:
offset = e.offset - (len(e.text) - len(e.text.splitlines()[-1])) offset = e.offset - (len(e.text) - len(
e.text.splitlines()[-1]))
else: else:
offset = 0 offset = 0
highlight = {'start': start, 'end': start + offset + 1, 'lineno': e.lineno} highlight = {'start': start, 'end': start +
offset + 1, 'lineno': e.lineno}
try: try:
ex_name = e.__class__.__name__ ex_name = e.__class__.__name__
except: except:
ex_name = 'unknown exception!' ex_name = 'unknown exception!'
response.flash = DIV(T('failed to compile file because:'), BR(), response.flash = DIV(T('failed to compile file because:'), BR(),
B(ex_name), ' ' + T('at line %s', e.lineno), B(ex_name), ' ' + T('at line %s', e.lineno),
offset and ' '+T('at char %s', offset) or '', offset and ' ' +
T('at char %s', offset) or '',
PRE(str(e))) PRE(str(e)))
if data_or_revert and request.args[1] == 'modules': if data_or_revert and request.args[1] == 'modules':
# Lets try to reload the modules # Lets try to reload the modules
try: try:
mopath = '.'.join(request.args[2:])[:-3] mopath = '.'.join(request.args[2:])[:-3]
exec 'import applications.%s.modules.%s' % (request.args[0], mopath) exec 'import applications.%s.modules.%s' % (
request.args[0], mopath)
reload(sys.modules['applications.%s.modules.%s' reload(sys.modules['applications.%s.modules.%s'
% (request.args[0], mopath)]) % (request.args[0], mopath)])
except Exception, e: except Exception, e:
response.flash = DIV(T('failed to reload module because:'),PRE(str(e))) response.flash = DIV(
T('failed to reload module because:'), PRE(str(e)))
edit_controller = None edit_controller = None
editviewlinks = None editviewlinks = None
@@ -660,7 +696,7 @@ def edit():
for v in viewlist: for v in viewlist:
vf = os.path.split(v)[-1] vf = os.path.split(v)[-1]
vargs = "/".join([viewpath.replace(os.sep, "/"), vf]) vargs = "/".join([viewpath.replace(os.sep, "/"), vf])
editviewlinks.append(A(vf.split(".")[0],\ editviewlinks.append(A(vf.split(".")[0],
_href=URL('edit', args=[vargs]))) _href=URL('edit', args=[vargs])))
if len(request.args) > 2 and request.args[1] == 'controllers': if len(request.args) > 2 and request.args[1] == 'controllers':
@@ -680,7 +716,7 @@ def edit():
editarea_preferences['REPLACE_TAB_BY_SPACES'] = '4' editarea_preferences['REPLACE_TAB_BY_SPACES'] = '4'
editarea_preferences['DISPLAY'] = 'onload' editarea_preferences['DISPLAY'] = 'onload'
for key in editarea_preferences: for key in editarea_preferences:
if globals().has_key(key): if key in globals():
editarea_preferences[key] = globals()[key] editarea_preferences[key] = globals()[key]
return dict(app=request.args[0], return dict(app=request.args[0],
filename=filename, filename=filename,
@@ -695,6 +731,7 @@ def edit():
editarea_preferences=editarea_preferences, editarea_preferences=editarea_preferences,
editviewlinks=editviewlinks) editviewlinks=editviewlinks)
def resolve(): def resolve():
""" """
""" """
@@ -739,7 +776,7 @@ def resolve():
return 'minus' return 'minus'
if request.vars: if request.vars:
c = '\n'.join([item[2:].rstrip() for (i, item) in enumerate(d) if item[0] \ c = '\n'.join([item[2:].rstrip() for (i, item) in enumerate(d) if item[0]
== ' ' or 'line%i' % i in request.vars]) == ' ' or 'line%i' % i in request.vars])
safe_write(path, c) safe_write(path, c)
session.flash = 'files merged' session.flash = 'files merged'
@@ -770,7 +807,8 @@ def edit_language():
form = SPAN(strings['__corrupted__'], _class='error') form = SPAN(strings['__corrupted__'], _class='error')
return dict(filename=filename, form=form) return dict(filename=filename, form=form)
keys = sorted(strings.keys(),lambda x,y: cmp(unicode(x,'utf-8').lower(), unicode(y,'utf-8').lower())) keys = sorted(strings.keys(), lambda x, y: cmp(
unicode(x, 'utf-8').lower(), unicode(y, 'utf-8').lower()))
rows = [] rows = []
rows.append(H2(T('Original/Translation'))) rows.append(H2(T('Original/Translation')))
@@ -805,18 +843,21 @@ def edit_language():
strs = dict() strs = dict()
for key in keys: for key in keys:
name = md5_hash(key) name = md5_hash(key)
if form.vars[name]==chr(127): continue if form.vars[name] == chr(127):
continue
strs[key] = form.vars[name] strs[key] = form.vars[name]
write_dict(apath(filename, r=request), strs) write_dict(apath(filename, r=request), strs)
session.flash = T('file saved on %(time)s', dict(time=time.ctime())) session.flash = T('file saved on %(time)s', dict(time=time.ctime()))
redirect(URL(r=request, args=request.args)) redirect(URL(r=request, args=request.args))
return dict(app=request.args[0], filename=filename, form=form) return dict(app=request.args[0], filename=filename, form=form)
def edit_plurals(): def edit_plurals():
""" Edit plurals file """ """ Edit plurals file """
app = get_app() app = get_app()
filename = '/'.join(request.args) filename = '/'.join(request.args)
plurals = read_plural_dict(apath(filename, r=request)) # plural forms dictionary plurals = read_plural_dict(
apath(filename, r=request)) # plural forms dictionary
nplurals = int(request.vars.nplurals) - 1 # plural forms quantity nplurals = int(request.vars.nplurals) - 1 # plural forms quantity
xnplurals = xrange(nplurals) xnplurals = xrange(nplurals)
@@ -825,7 +866,8 @@ def edit_plurals():
form = SPAN(plurals['__corrupted__'], _class='error') form = SPAN(plurals['__corrupted__'], _class='error')
return dict(filename=filename, form=form) return dict(filename=filename, form=form)
keys = sorted(plurals.keys(),lambda x,y: cmp(unicode(x,'utf-8').lower(), unicode(y,'utf-8').lower())) keys = sorted(plurals.keys(), lambda x, y: cmp(
unicode(x, 'utf-8').lower(), unicode(y, 'utf-8').lower()))
rows = [] rows = []
row = [T("Singular Form")] row = [T("Singular Form")]
@@ -840,8 +882,10 @@ def edit_plurals():
forms.extend(None for i in xrange(nplurals - len(forms))) forms.extend(None for i in xrange(nplurals - len(forms)))
row = [B(key)] row = [B(key)]
row.extend([INPUT(_type='text', _name=name+'_'+str(n), value=forms[n], _size=20) for n in xnplurals]) row.extend([INPUT(_type='text', _name=name + '_' + str(n),
row.append(TD(TAG.BUTTON(T('delete'), _onclick='return delkey("%s")' % name))) value=forms[n], _size=20) for n in xnplurals])
row.append(TD(
TAG.BUTTON(T('delete'), _onclick='return delkey("%s")' % name)))
rows.append(TR(row, _id=name)) rows.append(TR(row, _id=name))
if rows: if rows:
table.append(TBODY(rows)) table.append(TBODY(rows))
@@ -851,11 +895,14 @@ def edit_plurals():
new_plurals = dict() new_plurals = dict()
for key in keys: for key in keys:
name = md5_hash(key) name = md5_hash(key)
if form.vars[name+'_0']==chr(127): continue if form.vars[name + '_0'] == chr(127):
new_plurals[key] = [form.vars[name+'_'+str(n)] for n in xnplurals] continue
new_plurals[key] = [form.vars[name + '_' + str(n)]
for n in xnplurals]
write_plural_dict(apath(filename, r=request), new_plurals) write_plural_dict(apath(filename, r=request), new_plurals)
session.flash = T('file saved on %(time)s', dict(time=time.ctime())) session.flash = T('file saved on %(time)s', dict(time=time.ctime()))
redirect(URL(r=request, args=request.args, vars=dict(nplurals=request.vars.nplurals))) redirect(URL(r=request, args=request.args, vars=dict(
nplurals=request.vars.nplurals)))
return dict(app=request.args[0], filename=filename, form=form) return dict(app=request.args[0], filename=filename, form=form)
@@ -879,7 +926,7 @@ def design():
if request.vars and not request.vars.token == session.token: if request.vars and not request.vars.token == session.token:
redirect(URL('logout')) redirect(URL('logout'))
if request.vars.pluginfile!=None and not isinstance(request.vars.pluginfile,str): if request.vars.pluginfile is not None and not isinstance(request.vars.pluginfile, str):
filename = os.path.basename(request.vars.pluginfile.filename) filename = os.path.basename(request.vars.pluginfile.filename)
if plugin_install(app, request.vars.pluginfile.file, if plugin_install(app, request.vars.pluginfile.file,
request, filename): request, filename):
@@ -893,7 +940,6 @@ def design():
session.flash = T('plugin not specified') session.flash = T('plugin not specified')
redirect(URL(r=request)) redirect(URL(r=request))
# If we have only pyc files it means that # If we have only pyc files it means that
# we cannot design # we cannot design
if os.path.exists(apath('%s/compiled' % app, r=request)): if os.path.exists(apath('%s/compiled' % app, r=request)):
@@ -911,7 +957,8 @@ def design():
defines[m].sort() defines[m].sort()
# Get all controllers # Get all controllers
controllers = sorted(listdir(apath('%s/controllers/' % app, r=request), '.*\.py$')) controllers = sorted(
listdir(apath('%s/controllers/' % app, r=request), '.*\.py$'))
controllers = [x.replace('\\', '/') for x in controllers] controllers = [x.replace('\\', '/') for x in controllers]
functions = {} functions = {}
for c in controllers: for c in controllers:
@@ -920,7 +967,8 @@ def design():
functions[c] = items functions[c] = items
# Get all views # Get all views
views = sorted(listdir(apath('%s/views/' % app, r=request), '[\w/\-]+(\.\w+)+$')) views = sorted(
listdir(apath('%s/views/' % app, r=request), '[\w/\-]+(\.\w+)+$'))
views = [x.replace('\\', '/') for x in views if not x.endswith('.bak')] views = [x.replace('\\', '/') for x in views if not x.endswith('.bak')]
extend = {} extend = {}
include = {} include = {}
@@ -958,14 +1006,17 @@ def design():
#Get crontab #Get crontab
cronfolder = apath('%s/cron' % app, r=request) cronfolder = apath('%s/cron' % app, r=request)
if not os.path.exists(cronfolder): os.mkdir(cronfolder) if not os.path.exists(cronfolder):
os.mkdir(cronfolder)
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')
plugins = [] plugins = []
def filter_plugins(items, plugins): def filter_plugins(items, plugins):
plugins+=[item[7:].split('/')[0].split('.')[0] for item in items if item.startswith('plugin_')] plugins += [item[7:].split('/')[0].split(
'.')[0] for item in items if item.startswith('plugin_')]
plugins[:] = list(set(plugins)) plugins[:] = list(set(plugins))
plugins.sort() plugins.sort()
return [item for item in items if not item.startswith('plugin_')] return [item for item in items if not item.startswith('plugin_')]
@@ -985,6 +1036,7 @@ def design():
crontab=crontab, crontab=crontab,
plugins=plugins) plugins=plugins)
def delete_plugin(): def delete_plugin():
""" Object delete handler """ """ Object delete handler """
app = request.args(0) app = request.args(0)
@@ -1014,6 +1066,7 @@ def delete_plugin():
redirect(URL('design', args=request.args(0), anchor=request.vars.id2)) redirect(URL('design', args=request.args(0), anchor=request.vars.id2))
return dict(dialog=dialog, plugin=plugin) return dict(dialog=dialog, plugin=plugin)
def plugin(): def plugin():
""" Application design handler """ """ Application design handler """
app = get_app() app = get_app()
@@ -1040,7 +1093,8 @@ def plugin():
defines[m].sort() defines[m].sort()
# Get all controllers # Get all controllers
controllers = sorted(listdir(apath('%s/controllers/' % app, r=request), '.*\.py$')) controllers = sorted(
listdir(apath('%s/controllers/' % app, r=request), '.*\.py$'))
controllers = [x.replace('\\', '/') for x in controllers] controllers = [x.replace('\\', '/') for x in controllers]
functions = {} functions = {}
for c in controllers: for c in controllers:
@@ -1049,7 +1103,8 @@ def plugin():
functions[c] = items functions[c] = items
# Get all views # Get all views
views = sorted(listdir(apath('%s/views/' % app, r=request), '[\w/\-]+\.\w+$')) views = sorted(
listdir(apath('%s/views/' % app, r=request), '[\w/\-]+\.\w+$'))
views = [x.replace('\\', '/') for x in views] views = [x.replace('\\', '/') for x in views]
extend = {} extend = {}
include = {} include = {}
@@ -1195,7 +1250,8 @@ def create_file():
if len(filename) == 5: if len(filename) == 5:
raise SyntaxError raise SyntaxError
msg = T('This is the %(filename)s template', dict(filename=filename)) msg = T(
'This is the %(filename)s template', dict(filename=filename))
if extension == 'html': if extension == 'html':
text = dedent(""" text = dedent("""
{{extend 'layout.html'}} {{extend 'layout.html'}}
@@ -1245,8 +1301,10 @@ def create_file():
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: vars['id']=request.vars.id if request.vars.id:
if request.vars.app: vars['app']=request.vars.app vars['id'] = request.vars.id
if 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:
@@ -1319,7 +1377,8 @@ def errors():
method = request.args(1) or 'new' method = request.args(1) or 'new'
db_ready = {} db_ready = {}
db_ready['status'] = get_ticket_storage(app) db_ready['status'] = get_ticket_storage(app)
db_ready['errmessage'] = T("No ticket_storage.txt found under /private folder") db_ready['errmessage'] = T(
"No ticket_storage.txt found under /private folder")
db_ready['errlink'] = "http://web2py.com/books/default/chapter/29/13#Collecting-tickets" db_ready['errlink'] = "http://web2py.com/books/default/chapter/29/13#Collecting-tickets"
if method == 'new': if method == 'new':
@@ -1334,7 +1393,8 @@ def errors():
for fn in listdir(errors_path, '^[a-fA-F0-9.\-]+$'): for fn in listdir(errors_path, '^[a-fA-F0-9.\-]+$'):
fullpath = os.path.join(errors_path, fn) fullpath = os.path.join(errors_path, fn)
if not os.path.isfile(fullpath): continue if not os.path.isfile(fullpath):
continue
try: try:
fullpath_file = open(fullpath, 'r') fullpath_file = open(fullpath, 'r')
try: try:
@@ -1367,7 +1427,6 @@ def errors():
return dict(errors=[x[1] for x in decorated], app=app, method=method, db_ready=db_ready) return dict(errors=[x[1] for x in decorated], app=app, method=method, db_ready=db_ready)
elif method == 'dbnew': elif method == 'dbnew':
errors_path = apath('%s/errors' % app, r=request) errors_path = apath('%s/errors' % app, r=request)
tk_db, tk_table = get_ticket_storage(app) tk_db, tk_table = get_ticket_storage(app)
@@ -1417,7 +1476,8 @@ def errors():
tk_db.commit() tk_db.commit()
tickets_ = tk_db(tk_table.id > 0).select(tk_table.ticket_id, tk_table.created_datetime, orderby=~tk_table.created_datetime) tickets_ = tk_db(tk_table.id > 0).select(tk_table.ticket_id, 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 row in tickets_]) times = dict(
[(row.ticket_id, row.created_datetime) for row in tickets_])
return dict(app=app, tickets=tickets, method=method, times=times) return dict(app=app, tickets=tickets, method=method, times=times)
@@ -1425,14 +1485,16 @@ def errors():
for item in request.vars: for item in request.vars:
if item[:7] == 'delete_': if item[:7] == 'delete_':
os.unlink(apath('%s/errors/%s' % (app, item[7:]), r=request)) os.unlink(apath('%s/errors/%s' % (app, item[7:]), r=request))
func = lambda p: os.stat(apath('%s/errors/%s' % \ func = lambda p: os.stat(apath('%s/errors/%s' %
(app, p), r=request)).st_mtime (app, p), r=request)).st_mtime
tickets = sorted(listdir(apath('%s/errors/' % app, r=request), '^\w.*'), tickets = sorted(
listdir(apath('%s/errors/' % app, r=request), '^\w.*'),
key=func, key=func,
reverse=True) reverse=True)
return dict(app=app, tickets=tickets, method=method, db_ready=db_ready) return dict(app=app, tickets=tickets, method=method, db_ready=db_ready)
def get_ticket_storage(app): def get_ticket_storage(app):
private_folder = apath('%s/private' % app, r=request) private_folder = apath('%s/private' % app, r=request)
ticket_file = os.path.join(private_folder, 'ticket_storage.txt') ticket_file = os.path.join(private_folder, 'ticket_storage.txt')
@@ -1454,6 +1516,7 @@ def get_ticket_storage(app):
) )
return ticketsdb, ticketsdb.get(tablename) return ticketsdb, ticketsdb.get(tablename)
def make_link(path): def make_link(path):
""" Create a link from a path """ """ Create a link from a path """
tryFile = path.replace('\\', '/') tryFile = path.replace('\\', '/')
@@ -1536,6 +1599,7 @@ def ticket():
layer=e.layer, layer=e.layer,
myversion=myversion) myversion=myversion)
def ticketdb(): def ticketdb():
""" Ticket handler """ """ Ticket handler """
@@ -1559,10 +1623,12 @@ def ticketdb():
layer=e.layer, layer=e.layer,
myversion=myversion) myversion=myversion)
def error(): def error():
""" Generate a ticket (for testing) """ """ Generate a ticket (for testing) """
raise RuntimeError('admin ticket generator at your service') raise RuntimeError('admin ticket generator at your service')
def update_languages(): def update_languages():
""" Update available languages """ """ Update available languages """
@@ -1600,12 +1666,14 @@ def user():
else: else:
return dict(form=T("Disabled")) return dict(form=T("Disabled"))
def reload_routes(): def reload_routes():
""" Reload routes.py """ """ Reload routes.py """
import gluon.rewrite import gluon.rewrite
gluon.rewrite.load() gluon.rewrite.load()
redirect(URL('site')) redirect(URL('site'))
def manage_students(): def manage_students():
if not (MULTI_USER_MODE and is_manager()): if not (MULTI_USER_MODE and is_manager()):
session.flash = T('Not Authorized') session.flash = T('Not Authorized')
@@ -1614,6 +1682,7 @@ def manage_students():
grid = SQLFORM.grid(db.auth_user) grid = SQLFORM.grid(db.auth_user)
return locals() return locals()
def bulk_register(): def bulk_register():
if not (MULTI_USER_MODE and is_manager()): if not (MULTI_USER_MODE and is_manager()):
session.flash = T('Not Authorized') session.flash = T('Not Authorized')
@@ -1634,6 +1703,7 @@ def bulk_register():
# 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
def git_pull(): def git_pull():
""" Git Pull handler """ """ Git Pull handler """
app = get_app() app = get_app()
@@ -1660,10 +1730,12 @@ def git_pull():
session.flash = T("Pull is not possible because you have unmerged files. Fix them up in the work tree, and then try again.") session.flash = T("Pull is not possible because you have unmerged files. Fix them up in the work tree, and then try again.")
redirect(URL('site')) redirect(URL('site'))
except GitCommandError, status: except GitCommandError, status:
session.flash = T("Pull failed, git exited abnormally. See logs for details.") session.flash = T(
"Pull failed, git exited abnormally. See logs for details.")
redirect(URL('site')) redirect(URL('site'))
except Exception, e: except Exception, e:
session.flash = T("Pull failed, git exited abnormally. See logs for details.") session.flash = T(
"Pull failed, git exited abnormally. See logs for details.")
redirect(URL('site')) redirect(URL('site'))
elif 'cancel' in request.vars: elif 'cancel' in request.vars:
redirect(URL('site')) redirect(URL('site'))
@@ -1688,12 +1760,14 @@ def git_push():
new_commit = index.commit(form.vars.changelog) new_commit = index.commit(form.vars.changelog)
origin = repo.remotes.origin origin = repo.remotes.origin
origin.push() origin.push()
session.flash = T("Git repo updated with latest application changes.") session.flash = T(
"Git repo updated with latest application changes.")
redirect(URL('site')) redirect(URL('site'))
except UnmergedEntriesError: except UnmergedEntriesError:
session.flash = T("Push failed, there are unmerged entries in the cache. Resolve merge issues manually and try again.") session.flash = T("Push failed, there are unmerged entries in the cache. Resolve merge issues manually and try again.")
redirect(URL('site')) redirect(URL('site'))
except Exception, e: except Exception, e:
session.flash = T("Push failed, git exited abnormally. See logs for details.") session.flash = T(
"Push failed, git exited abnormally. See logs for details.")
redirect(URL('site')) redirect(URL('site'))
return dict(app=app, form=form) return dict(app=app, form=form)
+16 -7
View File
@@ -18,28 +18,34 @@ if MULTI_USER_MODE and not is_manager():
forever = 10 ** 8 forever = 10 ** 8
def kill(): def kill():
p = cache.ram('gae_upload', lambda: None, forever) p = cache.ram('gae_upload', lambda: None, forever)
if not p or p.poll()!=None: if not p or p.poll() is not None:
return 'oops' return 'oops'
os.kill(p.pid, signal.SIGKILL) os.kill(p.pid, signal.SIGKILL)
cache.ram('gae_upload', lambda: None, -1) cache.ram('gae_upload', lambda: None, -1)
class EXISTS(object): class EXISTS(object):
def __init__(self, error_message='file not found'): def __init__(self, error_message='file not found'):
self.error_message = error_message self.error_message = error_message
def __call__(self, value): def __call__(self, value):
if os.path.exists(value): if os.path.exists(value):
return (value, None) return (value, None)
return (value, self.error_message) return (value, self.error_message)
def deploy(): def deploy():
regex = re.compile('^\w+$') regex = re.compile('^\w+$')
apps = sorted(file for file in os.listdir(apath(r=request)) if regex.match(file)) apps = sorted(
file for file in os.listdir(apath(r=request)) if regex.match(file))
form = SQLFORM.factory( form = SQLFORM.factory(
Field('appcfg', default=GAE_APPCFG, label=T('Path to appcfg.py'), Field('appcfg', default=GAE_APPCFG, label=T('Path to appcfg.py'),
requires=EXISTS(error_message=T('file not found'))), requires=EXISTS(error_message=T('file not found'))),
Field('google_application_id',requires=IS_MATCH('[\w\-]+'),label=T('Google Application Id')), Field('google_application_id', requires=IS_MATCH(
'[\w\-]+'), label=T('Google Application Id')),
Field('applications', 'list:string', Field('applications', 'list:string',
requires=IS_IN_SET(apps, multiple=True), requires=IS_IN_SET(apps, multiple=True),
label=T('web2py apps to deploy')), label=T('web2py apps to deploy')),
@@ -51,7 +57,7 @@ def deploy():
kill() kill()
except: except:
pass pass
ignore_apps = [item for item in apps \ ignore_apps = [item for item in apps
if not item in form.vars.applications] if not item in form.vars.applications]
regex = re.compile('\(applications/\(.*') regex = re.compile('\(applications/\(.*')
yaml = apath('../app.yaml', r=request) yaml = apath('../app.yaml', r=request)
@@ -59,8 +65,10 @@ def deploy():
example = apath('../app.example.yaml', r=request) example = apath('../app.example.yaml', r=request)
shutil.copyfile(example, yaml) shutil.copyfile(example, yaml)
data = read_file(yaml) data = read_file(yaml)
data = re.sub('application:.*','application: %s' % form.vars.google_application_id,data) data = re.sub('application:.*', 'application: %s' %
data = regex.sub('(applications/(%s)/.*)|' % '|'.join(ignore_apps),data) form.vars.google_application_id, data)
data = regex.sub(
'(applications/(%s)/.*)|' % '|'.join(ignore_apps), data)
write_file(yaml, data) write_file(yaml, data)
path = request.env.applications_parent path = request.env.applications_parent
@@ -76,9 +84,10 @@ def deploy():
fcntl.fcntl(p.stderr.fileno(), fcntl.F_SETFL, os.O_NONBLOCK) fcntl.fcntl(p.stderr.fileno(), fcntl.F_SETFL, os.O_NONBLOCK)
return dict(form=form, command=cmd) return dict(form=form, command=cmd)
def callback(): def callback():
p = cache.ram('gae_upload', lambda: None, forever) p = cache.ram('gae_upload', lambda: None, forever)
if not p or p.poll()!=None: if not p or p.poll() is not None:
return '<done/>' return '<done/>'
try: try:
output = p.stdout.read() output = p.stdout.read()
@@ -22,6 +22,7 @@ sessions/*
errors/* errors/*
""" """
def hg_repo(path): def hg_repo(path):
import os import os
uio = ui.ui() uio = ui.ui()
@@ -37,6 +38,7 @@ def hg_repo(path):
write_file(hgignore, _hgignore_content) write_file(hgignore, _hgignore_content)
return repo return repo
def commit(): def commit():
app = request.args(0) app = request.args(0)
path = apath(app, r=request) path = apath(app, r=request)
@@ -63,6 +65,7 @@ def commit():
changes = [] changes = []
return dict(form=form, files=files, changes=changes, repo=repo) return dict(form=form, files=files, changes=changes, repo=repo)
def revision(): def revision():
app = request.args(0) app = request.args(0)
path = apath(app, r=request) path = apath(app, r=request)
+7 -2
View File
@@ -10,10 +10,12 @@ except ImportError:
session.flash = T('requires python-git, but not installed') session.flash = T('requires python-git, but not installed')
redirect(URL('default', 'site')) redirect(URL('default', 'site'))
def deploy(): def deploy():
apps = sorted(file for file in os.listdir(apath(r=request))) apps = sorted(file for file in os.listdir(apath(r=request)))
form = SQLFORM.factory( form = SQLFORM.factory(
Field('osrepo',default='/tmp',label=T('Path to local openshift repo root.'), Field(
'osrepo', default='/tmp', label=T('Path to local openshift repo root.'),
requires=EXISTS(error_message=T('directory not found'))), requires=EXISTS(error_message=T('directory not found'))),
Field('osname', default='web2py', label=T('WSGI reference name')), Field('osname', default='web2py', label=T('WSGI reference name')),
Field('applications', 'list:string', Field('applications', 'list:string',
@@ -27,7 +29,8 @@ def deploy():
except: except:
pass pass
ignore_apps = [item for item in apps if not item in form.vars.applications] ignore_apps = [
item for item in apps if not item in form.vars.applications]
regex = re.compile('\(applications/\(.*') regex = re.compile('\(applications/\(.*')
w2p_origin = os.getcwd() w2p_origin = os.getcwd()
osrepo = form.vars.osrepo osrepo = form.vars.osrepo
@@ -51,9 +54,11 @@ def deploy():
#Git code ends here #Git code ends here
return dict(form=form, command=cmd) return dict(form=form, command=cmd)
class EXISTS(object): class EXISTS(object):
def __init__(self, error_message='file not found'): def __init__(self, error_message='file not found'):
self.error_message = error_message self.error_message = error_message
def __call__(self, value): def __call__(self, value):
if os.path.exists(value): if os.path.exists(value):
return (value, None) return (value, None)
@@ -1,8 +1,10 @@
response.files = response.files[:3] response.files = response.files[:3]
response.menu = [] response.menu = []
def index(): def index():
return locals() return locals()
def about(): def about():
return locals() return locals()
+7 -2
View File
@@ -1,7 +1,8 @@
import sys import sys
import cStringIO import cStringIO
import gluon.contrib.shell import gluon.contrib.shell
import code, thread import code
import thread
from gluon.shell import env from gluon.shell import env
if DEMO_MODE or MULTI_USER_MODE: if DEMO_MODE or MULTI_USER_MODE:
@@ -10,16 +11,19 @@ if DEMO_MODE or MULTI_USER_MODE:
FE = 10 ** 9 FE = 10 ** 9
def index(): def index():
app = request.args(0) or 'admin' app = request.args(0) or 'admin'
reset() reset()
return dict(app=app) return dict(app=app)
def callback(): def callback():
app = request.args[0] app = request.args[0]
command = request.vars.statement command = request.vars.statement
escape = command[:1] != '!' escape = command[:1] != '!'
history = session['history:'+app] = session.get('history:'+app,gluon.contrib.shell.History()) history = session['history:' + app] = session.get(
'history:' + app, gluon.contrib.shell.History())
if not escape: if not escape:
command = command[1:] command = command[1:]
if command == '%reset': if command == '%reset':
@@ -38,6 +42,7 @@ def callback():
#return TABLE(TR('In[%i]:'%k,PRE(command)),TR('Out[%i]:'%k,output)) #return TABLE(TR('In[%i]:'%k,PRE(command)),TR('Out[%i]:'%k,output))
return 'In [%i] : %s%s\n' % (k + 1, command, output) return 'In [%i] : %s%s\n' % (k + 1, command, output)
def reset(): def reset():
app = request.args(0) or 'admin' app = request.args(0) or 'admin'
session['commands:' + app] = [] session['commands:' + app] = []
@@ -2,10 +2,12 @@ import os
from gluon.settings import global_settings, read_file from gluon.settings import global_settings, read_file
# #
def index(): def index():
app = request.args(0) app = request.args(0)
return dict(app=app) return dict(app=app)
def profiler(): def profiler():
""" """
to use the profiler start web2py with -F profiler.log to use the profiler start web2py with -F profiler.log
@@ -82,6 +82,7 @@ def install(app_name, filename, data, overwrite=True):
return installed return installed
@service.jsonrpc @service.jsonrpc
def attach_debugger(host='localhost', port=6000, authkey='secret password'): def attach_debugger(host='localhost', port=6000, authkey='secret password'):
import gluon.contrib.qdb as qdb import gluon.contrib.qdb as qdb
@@ -124,6 +125,7 @@ def detach_debugger():
gluon.debug.qdb_debugger = None gluon.debug.qdb_debugger = None
return True return True
def call(): def call():
session.forget() session.forget()
return service() return service()
+84 -35
View File
@@ -1,9 +1,15 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import os, uuid, re, pickle, urllib, glob import os
import uuid
import re
import pickle
import urllib
import glob
from gluon.admin import app_create, plugin_install from gluon.admin import app_create, plugin_install
from gluon.fileutils import abspath, read_file, write_file from gluon.fileutils import abspath, read_file, write_file
def reset(session): def reset(session):
session.app = { session.app = {
'name': '', 'name': '',
@@ -30,16 +36,20 @@ def reset(session):
'page_error': '# Error: the document does not exist', 'page_error': '# Error: the document does not exist',
} }
if not session.app: reset(session) if not session.app:
reset(session)
def listify(x): def listify(x):
if not isinstance(x, (list, tuple)): if not isinstance(x, (list, tuple)):
return x and [x] or [] return x and [x] or []
return x return x
def clean(name): def clean(name):
return re.sub('\W+', '_', name.strip().lower()) return re.sub('\W+', '_', name.strip().lower())
def index(): def index():
response.view = 'wizard/step.html' response.view = 'wizard/step.html'
reset(session) reset(session)
@@ -49,11 +59,10 @@ def index():
if form.accepts(request.vars): if form.accepts(request.vars):
app = form.vars.name app = form.vars.name
session.app['name'] = app session.app['name'] = app
if MULTI_USER_MODE and db(db.app.name==app)\ if MULTI_USER_MODE and db(db.app.name == app)(db.app.owner != auth.user.id).count():
(db.app.owner!=auth.user.id).count():
session.flash = 'App belongs already to other user' session.flash = 'App belongs already to other user'
elif app in apps: elif app in apps:
meta = os.path.normpath(\ meta = os.path.normpath(
os.path.join(os.path.normpath(request.folder), os.path.join(os.path.normpath(request.folder),
'..', app, 'wizard.metadata')) '..', app, 'wizard.metadata'))
if os.path.exists(meta): if os.path.exists(meta):
@@ -96,20 +105,26 @@ def step1():
requires=IS_NOT_EMPTY()), requires=IS_NOT_EMPTY()),
Field('subtitle', default=params.get('subtitle', None)), Field('subtitle', default=params.get('subtitle', None)),
Field('author', default=params.get('author', None)), Field('author', default=params.get('author', None)),
Field('author_email',default=params.get('author_email',None)), Field(
'author_email', default=params.get('author_email', None)),
Field('keywords', default=params.get('keywords', None)), Field('keywords', default=params.get('keywords', None)),
Field('description', 'text', Field('description', 'text',
default=params.get('description', None)), default=params.get('description', None)),
Field('layout_theme', requires=IS_IN_SET(themes), Field('layout_theme', requires=IS_IN_SET(themes),
default=params.get('layout_theme', themes[0])), default=params.get('layout_theme', themes[0])),
Field('database_uri',default=params.get('database_uri',None)), Field(
Field('security_key',default=params.get('security_key',None)), 'database_uri', default=params.get('database_uri', None)),
Field('email_server',default=params.get('email_server',None)), Field(
Field('email_sender',default=params.get('email_sender',None)), 'security_key', default=params.get('security_key', None)),
Field(
'email_server', default=params.get('email_server', None)),
Field(
'email_sender', default=params.get('email_sender', None)),
Field('email_login', default=params.get('email_login', None)), Field('email_login', default=params.get('email_login', None)),
Field('login_method', requires=IS_IN_SET(('local', 'janrain')), Field('login_method', requires=IS_IN_SET(('local', 'janrain')),
default=params.get('login_method', 'local')), default=params.get('login_method', 'local')),
Field('login_config',default=params.get('login_config',None)), Field(
'login_config', default=params.get('login_config', None)),
Field('plugins', 'list:string', requires=IS_IN_SET(plugins, multiple=True))) Field('plugins', 'list:string', requires=IS_IN_SET(plugins, multiple=True)))
if form.accepts(request.vars): if form.accepts(request.vars):
@@ -118,14 +133,15 @@ def step1():
redirect(URL('step2')) redirect(URL('step2'))
return dict(step='1: Setting Parameters', form=form) return dict(step='1: Setting Parameters', form=form)
def step2(): def step2():
response.view = 'wizard/step.html' response.view = 'wizard/step.html'
form = SQLFORM.factory(Field('table_names', 'list:string', form = SQLFORM.factory(Field('table_names', 'list:string',
default=session.app['tables'])) default=session.app['tables']))
if form.accepts(request.vars): if form.accepts(request.vars):
table_names = [clean(t) for t in listify(form.vars.table_names) \ table_names = [clean(t) for t in listify(form.vars.table_names)
if t.strip()] if t.strip()]
if [t for t in table_names if t.startswith('auth_') and \ if [t for t in table_names if t.startswith('auth_') and
not t == 'auth_user']: not t == 'auth_user']:
form.error.table_names = \ form.error.table_names = \
T('invalid table names (auth_* tables already defined)') T('invalid table names (auth_* tables already defined)')
@@ -146,11 +162,13 @@ def step2():
redirect(URL('step4')) redirect(URL('step4'))
return dict(step='2: Tables', form=form) return dict(step='2: Tables', form=form)
def step3(): def step3():
response.view = 'wizard/step.html' response.view = 'wizard/step.html'
n = int(request.args(0) or 0) n = int(request.args(0) or 0)
m = len(session.app['tables']) m = len(session.app['tables'])
if n>=m: redirect(URL('step2')) if n >= m:
redirect(URL('step2'))
table = session.app['tables'][n] table = session.app['tables'][n]
form = SQLFORM.factory(Field('field_names', 'list:string', form = SQLFORM.factory(Field('field_names', 'list:string',
default=session.app.get('table_' + table, []))) default=session.app.get('table_' + table, [])))
@@ -172,9 +190,10 @@ def step3():
redirect(URL('step3', args=n + 1)) redirect(URL('step3', args=n + 1))
else: else:
redirect(URL('step4')) redirect(URL('step4'))
return dict(step='3: Fields for table "%s" (%s of %s)' \ return dict(step='3: Fields for table "%s" (%s of %s)'
% (table, n + 1, m), table=table, form=form) % (table, n + 1, m), table=table, form=form)
def step4(): def step4():
response.view = 'wizard/step.html' response.view = 'wizard/step.html'
form = SQLFORM.factory(Field('pages', 'list:string', form = SQLFORM.factory(Field('pages', 'list:string',
@@ -189,11 +208,13 @@ def step4():
redirect(URL('step6')) redirect(URL('step6'))
return dict(step='4: Pages', form=form) return dict(step='4: Pages', form=form)
def step5(): def step5():
response.view = 'wizard/step.html' response.view = 'wizard/step.html'
n = int(request.args(0) or 0) n = int(request.args(0) or 0)
m = len(session.app['pages']) m = len(session.app['pages'])
if n>=m: redirect(URL('step4')) if n >= m:
redirect(URL('step4'))
page = session.app['pages'][n] page = session.app['pages'][n]
markmin_url = 'http://web2py.com/examples/static/markmin.html' markmin_url = 'http://web2py.com/examples/static/markmin.html'
form = SQLFORM.factory(Field('content', 'text', form = SQLFORM.factory(Field('content', 'text',
@@ -209,6 +230,7 @@ def step5():
redirect(URL('step6')) redirect(URL('step6'))
return dict(step='5: View for page "%s" (%s of %s)' % (page, n + 1, m), form=form) return dict(step='5: View for page "%s" (%s of %s)' % (page, n + 1, m), form=form)
def step6(): def step6():
response.view = 'wizard/step.html' response.view = 'wizard/step.html'
params = dict(session.app['params']) params = dict(session.app['params'])
@@ -230,9 +252,11 @@ def step6():
redirect(URL('generated')) redirect(URL('generated'))
return dict(step='6: Generate app "%s"' % app, form=form) return dict(step='6: Generate app "%s"' % app, form=form)
def generated(): def generated():
return dict(app=session.app['name']) return dict(app=session.app['name'])
def sort_tables(tables): def sort_tables(tables):
import re import re
regex = re.compile('(%s)' % '|'.join(tables)) regex = re.compile('(%s)' % '|'.join(tables))
@@ -245,6 +269,7 @@ def sort_tables(tables):
tables = [] tables = []
if is_auth_user: if is_auth_user:
tables.append('auth_user') tables.append('auth_user')
def append(table, trail=[]): def append(table, trail=[]):
if table in trail: if table in trail:
raise RuntimeError raise RuntimeError
@@ -253,12 +278,15 @@ def sort_tables(tables):
append(t, trail=trail + [table]) append(t, trail=trail + [table])
if not table in tables: if not table in tables:
tables.append(table) tables.append(table)
for table in d: append(table) for table in d:
append(table)
return tables return tables
def make_table(table, fields): def make_table(table, fields):
rawtable = table rawtable = table
if table!='auth_user': table='t_'+table if table != 'auth_user':
table = 't_' + table
s = '' s = ''
s += '\n' + '#' * 40 + '\n' s += '\n' + '#' * 40 + '\n'
s += "db.define_table('%s',\n" % table s += "db.define_table('%s',\n" % table
@@ -277,11 +305,12 @@ def make_table(table,fields):
has[key] = True has[key] = True
tables = session.app['tables'] tables = session.app['tables']
refs = [t for t in tables if t in items] refs = [t for t in tables if t in items]
items = items[:1] + [x for x in items[1:] \ items = items[:1] + [x for x in items[1:]
if not x in keys and not x in tables] if not x in keys and not x in tables]
barename = name = '_'.join(items) barename = name = '_'.join(items)
if table[:2] == 't_': name = 'f_' + name if table[:2] == 't_': name = 'f_' + name
if first_field=='id': first_field=name if first_field == 'id':
first_field = name
### determine field type ### determine field type
ftype = 'string' ftype = 'string'
@@ -295,7 +324,8 @@ def make_table(table,fields):
ftype = t ftype = t
if refs: if refs:
key = refs[0] key = refs[0]
if not key=='auth_user': key='t_'+key if not key == 'auth_user':
key = 't_' + key
if 'multiple' in has: if 'multiple' in has:
ftype = 'list:reference %s' % key ftype = 'list:reference %s' % key
else: else:
@@ -352,17 +382,22 @@ def make_table(table,fields):
s += " migrate=settings.migrate)\n\n" s += " migrate=settings.migrate)\n\n"
if table == 'auth_user': if table == 'auth_user':
s += """ s += """
db.auth_user.first_name.requires = IS_NOT_EMPTY(error_message=auth.messages.is_empty) db.auth_user.first_name.requires = IS_NOT_EMPTY(
db.auth_user.last_name.requires = IS_NOT_EMPTY(error_message=auth.messages.is_empty) error_message=auth.messages.is_empty)
db.auth_user.password.requires = CRYPT(key=auth.settings.hmac_key, min_length=4) db.auth_user.last_name.requires = IS_NOT_EMPTY(
error_message=auth.messages.is_empty)
db.auth_user.password.requires = CRYPT(
key=auth.settings.hmac_key, min_length=4)
db.auth_user.username.requires = IS_NOT_IN_DB(db, db.auth_user.username) db.auth_user.username.requires = IS_NOT_IN_DB(db, db.auth_user.username)
db.auth_user.email.requires = (IS_EMAIL(error_message=auth.messages.invalid_email), db.auth_user.email.requires = (
IS_EMAIL(error_message=auth.messages.invalid_email),
IS_NOT_IN_DB(db, db.auth_user.email)) IS_NOT_IN_DB(db, db.auth_user.email))
""" """
else: else:
s += "db.define_table('%s_archive',db.%s,Field('current_record','reference %s',readable=False,writable=False))\n" % (table, table, table) s += "db.define_table('%s_archive',db.%s,Field('current_record','reference %s',readable=False,writable=False))\n" % (table, table, table)
return s return s
def fix_db(filename): def fix_db(filename):
params = dict(session.app['params']) params = dict(session.app['params'])
content = read_file(filename, 'rb') content = read_file(filename, 'rb')
@@ -370,7 +405,7 @@ def fix_db(filename):
auth_user = make_table('auth_user', session.app['table_auth_user']) auth_user = make_table('auth_user', session.app['table_auth_user'])
content = content.replace('sqlite://storage.sqlite', content = content.replace('sqlite://storage.sqlite',
params['database_uri']) params['database_uri'])
content = content.replace('auth.define_tables()',\ content = content.replace('auth.define_tables()',
auth_user + 'auth.define_tables(migrate = settings.migrate)') auth_user + 'auth.define_tables(migrate = settings.migrate)')
content += """ content += """
mail.settings.server = settings.email_server mail.settings.server = settings.email_server
@@ -380,7 +415,8 @@ mail.settings.login = settings.email_login
if params['login_method'] == 'janrain': if params['login_method'] == 'janrain':
content += """ content += """
from gluon.contrib.login_methods.rpx_account import RPXAccount from gluon.contrib.login_methods.rpx_account import RPXAccount
auth.settings.actions_disabled=['register','change_password','request_reset_password'] auth.settings.actions_disabled=['register','change_password',
'request_reset_password']
auth.settings.login_form = RPXAccount(request, auth.settings.login_form = RPXAccount(request,
api_key = settings.login_config.split(':')[-1], api_key = settings.login_config.split(':')[-1],
domain = settings.login_config.split(':')[0], domain = settings.login_config.split(':')[0],
@@ -388,6 +424,7 @@ auth.settings.login_form = RPXAccount(request,
""" """
write_file(filename, content, 'wb') write_file(filename, content, 'wb')
def make_menu(pages): def make_menu(pages):
s = '' s = ''
s += 'response.title = settings.title\n' s += 'response.title = settings.title\n'
@@ -408,6 +445,7 @@ def make_menu(pages):
s += ']' s += ']'
return s return s
def make_page(page, contents): def make_page(page, contents):
if 'auth_user' in session.app['tables'] and not page in ('index', 'error'): if 'auth_user' in session.app['tables'] and not page in ('index', 'error'):
s = "@auth.requires_login()\ndef %s():\n" % page s = "@auth.requires_login()\ndef %s():\n" % page
@@ -421,11 +459,13 @@ def make_page(page,contents):
s += " return dict()\n\n" s += " return dict()\n\n"
return s return s
def make_view(page, contents): def make_view(page, contents):
s = "{{extend 'layout.html'}}\n\n" s = "{{extend 'layout.html'}}\n\n"
s += str(MARKMIN(contents)) s += str(MARKMIN(contents))
return s return s
def populate(tables): def populate(tables):
s = 'from gluon.contrib.populate import populate\n' s = 'from gluon.contrib.populate import populate\n'
s += 'if db(db.auth_user).isempty():\n' s += 'if db(db.auth_user).isempty():\n'
@@ -434,6 +474,7 @@ def populate(tables):
s += " populate(db.%s,10)\n" % t s += " populate(db.%s,10)\n" % t
return s return s
def create(options): def create(options):
if DEMO_MODE: if DEMO_MODE:
session.flash = T('disabled in demo mode') session.flash = T('disabled in demo mode')
@@ -461,7 +502,8 @@ def create(options):
if options.apply_layout and params['layout_theme'] != 'Default': if options.apply_layout and params['layout_theme'] != 'Default':
try: try:
fn = 'web2py.plugin.layout_%s.w2p' % params['layout_theme'] fn = 'web2py.plugin.layout_%s.w2p' % params['layout_theme']
theme = urllib.urlopen(LAYOUTS_APP+'/static/plugin_layouts/plugins/'+fn) theme = urllib.urlopen(
LAYOUTS_APP + '/static/plugin_layouts/plugins/' + fn)
plugin_install(app, theme, request, fn) plugin_install(app, theme, request, fn)
except: except:
session.flash = T("unable to download layout") session.flash = T("unable to download layout")
@@ -502,20 +544,23 @@ def create(options):
### create newapp/models/db_wizard.py ### create newapp/models/db_wizard.py
if options.generate_model: if options.generate_model:
model = os.path.join(request.folder,'..',app,'models','db_wizard.py') model = os.path.join(
request.folder, '..', app, 'models', 'db_wizard.py')
file = open(model, 'wb') file = open(model, 'wb')
try: try:
file.write('### we prepend t_ to tablenames and f_ to fieldnames for disambiguity\n\n') file.write('### we prepend t_ to tablenames and f_ to fieldnames for disambiguity\n\n')
tables = sort_tables(session.app['tables']) tables = sort_tables(session.app['tables'])
for table in tables: for table in tables:
if table=='auth_user': continue if table == 'auth_user':
continue
file.write(make_table(table, session.app['table_' + table])) file.write(make_table(table, session.app['table_' + table]))
finally: finally:
file.close() file.close()
model = os.path.join(request.folder, '..', app, model = os.path.join(request.folder, '..', app,
'models', 'db_wizard_populate.py') 'models', 'db_wizard_populate.py')
if os.path.exists(model): os.unlink(model) if os.path.exists(model):
os.unlink(model)
if options.populate_database and session.app['tables']: if options.populate_database and session.app['tables']:
file = open(model, 'wb') file = open(model, 'wb')
try: try:
@@ -525,7 +570,8 @@ def create(options):
### create newapp/controllers/default.py ### create newapp/controllers/default.py
if options.generate_controller: if options.generate_controller:
controller = os.path.join(request.folder,'..',app,'controllers','default.py') controller = os.path.join(
request.folder, '..', app, 'controllers', 'default.py')
file = open(controller, 'wb') file = open(controller, 'wb')
try: try:
file.write("""# -*- coding: utf-8 -*- file.write("""# -*- coding: utf-8 -*-
@@ -536,17 +582,20 @@ def call(): return service()
### end requires ### end requires
""") """)
for page in session.app['pages']: for page in session.app['pages']:
file.write(make_page(page,session.app.get('page_'+page,''))) file.write(
make_page(page, session.app.get('page_' + page, '')))
finally: finally:
file.close() file.close()
### create newapp/views/default/*.html ### create newapp/views/default/*.html
if options.generate_views: if options.generate_views:
for page in session.app['pages']: for page in session.app['pages']:
view = os.path.join(request.folder,'..',app,'views','default',page+'.html') view = os.path.join(
request.folder, '..', app, 'views', 'default', page + '.html')
file = open(view, 'wb') file = open(view, 'wb')
try: try:
file.write(make_view(page,session.app.get('page_'+page,''))) file.write(
make_view(page, session.app.get('page_' + page, '')))
finally: finally:
file.close() file.close()
+10 -3
View File
@@ -1,4 +1,6 @@
import base64, os, time import base64
import os
import time
from gluon import portalocker from gluon import portalocker
from gluon.admin import apath from gluon.admin import apath
from gluon.fileutils import read_file from gluon.fileutils import read_file
@@ -24,7 +26,8 @@ elif not request.is_local and not DEMO_MODE:
try: try:
_config = {} _config = {}
port = int(request.env.server_port or 0) port = int(request.env.server_port or 0)
restricted(read_file(apath('../parameters_%i.py' % port, request)), _config) restricted(
read_file(apath('../parameters_%i.py' % port, request)), _config)
if not 'password' in _config or not _config['password']: if not 'password' in _config or not _config['password']:
raise HTTP(200, T('admin disabled because no admin password')) raise HTTP(200, T('admin disabled because no admin password'))
@@ -38,7 +41,8 @@ except IOError:
raise HTTP(200, raise HTTP(200,
T('admin disabled because not supported on google app engine')) T('admin disabled because not supported on google app engine'))
else: else:
raise HTTP(200, T('admin disabled because unable to access password file')) raise HTTP(
200, T('admin disabled because unable to access password file'))
def verify_password(password): def verify_password(password):
@@ -63,6 +67,7 @@ deny_file = os.path.join(request.folder, 'private', 'hosts.deny')
allowed_number_of_attempts = 5 allowed_number_of_attempts = 5
expiration_failed_logins = 3600 expiration_failed_logins = 3600
def read_hosts_deny(): def read_hosts_deny():
import datetime import datetime
hosts = {} hosts = {}
@@ -83,6 +88,7 @@ def read_hosts_deny():
f.close() f.close()
return hosts return hosts
def write_hosts_deny(denied_hosts): def write_hosts_deny(denied_hosts):
f = open(deny_file, 'w') f = open(deny_file, 'w')
portalocker.lock(f, portalocker.LOCK_EX) portalocker.lock(f, portalocker.LOCK_EX)
@@ -93,6 +99,7 @@ def write_hosts_deny(denied_hosts):
portalocker.unlock(f) portalocker.unlock(f)
f.close() f.close()
def login_record(success=True): def login_record(success=True):
denied_hosts = read_hosts_deny() denied_hosts = read_hosts_deny()
val = (0, 0) val = (0, 0)
+6
View File
@@ -2,11 +2,13 @@
import os import os
def A_button(*a, **b): def A_button(*a, **b):
b['_data-role'] = 'button' b['_data-role'] = 'button'
b['_data-inline'] = 'true' b['_data-inline'] = 'true'
return A(*a, **b) return A(*a, **b)
def button(href, label): def button(href, label):
if is_mobile: if is_mobile:
ret = A_button(SPAN(label), _href=href) ret = A_button(SPAN(label), _href=href)
@@ -14,6 +16,7 @@ def button(href, label):
ret = A(SPAN(label), _class='button', _href=href) ret = A(SPAN(label), _class='button', _href=href)
return ret return ret
def button_enable(href, app): def button_enable(href, app):
if os.path.exists(os.path.join(apath(app, r=request), 'DISABLED')): if os.path.exists(os.path.join(apath(app, r=request), 'DISABLED')):
label = SPAN(T('Enable'), _style='color:red') label = SPAN(T('Enable'), _style='color:red')
@@ -22,6 +25,7 @@ def button_enable(href, app):
id = 'enable_' + app id = 'enable_' + app
return A(label, _class='button', _id=id, callback=href, target=id) return A(label, _class='button', _id=id, callback=href, target=id)
def sp_button(href, label): def sp_button(href, label):
if request.user_agent().is_mobile: if request.user_agent().is_mobile:
ret = A_button(SPAN(label), _href=href) ret = A_button(SPAN(label), _href=href)
@@ -29,8 +33,10 @@ def sp_button(href, label):
ret = A(SPAN(label), _class='button special', _href=href) ret = A(SPAN(label), _class='button special', _href=href)
return ret return ret
def helpicon(): def helpicon():
return IMG(_src=URL('static', 'images/help.png'), _alt='help') return IMG(_src=URL('static', 'images/help.png'), _alt='help')
def searchbox(elementid): def searchbox(elementid):
return TAG[''](LABEL(IMG(_id="search_start", _src=URL('static', 'images/search.png'), _alt=T('filter')), _class='icon', _for=elementid), ' ', INPUT(_id=elementid, _type='text', _size=12)) return TAG[''](LABEL(IMG(_id="search_start", _src=URL('static', 'images/search.png'), _alt=T('filter')), _class='icon', _for=elementid), ' ', INPUT(_id=elementid, _type='text', _size=12))
+7 -3
View File
@@ -4,9 +4,12 @@
if MULTI_USER_MODE: if MULTI_USER_MODE:
db = DAL('sqlite://storage.sqlite') # if not, use SQLite or other DB db = DAL('sqlite://storage.sqlite') # if not, use SQLite or other DB
from gluon.tools import * from gluon.tools import *
auth = Auth(globals(),db) # authentication/authorization auth = Auth(
crud = Crud(globals(),db) # for CRUD helpers using auth globals(), db) # authentication/authorization
service = Service(globals()) # for json, xml, jsonrpc, xmlrpc, amfrpc crud = Crud(
globals(), db) # for CRUD helpers using auth
service = Service(
globals()) # for json, xml, jsonrpc, xmlrpc, amfrpc
plugins = PluginManager() plugins = PluginManager()
mail = auth.settings.mailer mail = auth.settings.mailer
@@ -29,6 +32,7 @@ if not session.authorized and MULTI_USER_MODE:
elif not request.function == 'user': elif not request.function == 'user':
redirect(URL('default', 'user/login')) redirect(URL('default', 'user/login'))
def is_manager(): def is_manager():
if not MULTI_USER_MODE: if not MULTI_USER_MODE:
return True return True
+2 -1
View File
@@ -30,6 +30,7 @@ else:
URL(_a, 'debug', 'interact'))) URL(_a, 'debug', 'interact')))
if os.path.exists('applications/examples'): if os.path.exists('applications/examples'):
response.menu.append((T('Help'), False, URL('examples','default','index'))) response.menu.append(
(T('Help'), False, URL('examples', 'default', 'index')))
else: else:
response.menu.append((T('Help'), False, 'http://web2py.com/examples')) response.menu.append((T('Help'), False, 'http://web2py.com/examples'))
@@ -1,3 +1,4 @@
response.files.append(URL('static','plugin_multiselect/jquery.multi-select.js')) response.files.append(
URL('static', 'plugin_multiselect/jquery.multi-select.js'))
response.files.append(URL('static', 'plugin_multiselect/multi-select.css')) response.files.append(URL('static', 'plugin_multiselect/multi-select.css'))
response.files.append(URL('static', 'plugin_multiselect/start.js')) response.files.append(URL('static', 'plugin_multiselect/start.js'))
+34 -16
View File
@@ -102,17 +102,16 @@ def query_by_table_type(tablename,db,request=request):
cond = '>0' cond = '>0'
if firstkey.type in ['string', 'text']: if firstkey.type in ['string', 'text']:
cond = '!=""' cond = '!=""'
qry = '%s.%s.%s%s' % (request.args[0], request.args[1], firstkey.name, cond) qry = '%s.%s.%s%s' % (
request.args[0], request.args[1], firstkey.name, cond)
else: else:
qry = '%s.%s.id>0' % tuple(request.args[:2]) qry = '%s.%s.id>0' % tuple(request.args[:2])
return qry return qry
# ########################################################## # ##########################################################
# ## list all databases and tables # ## list all databases and tables
# ########################################################### # ###########################################################
def index(): def index():
return dict(databases=databases) return dict(databases=databases)
@@ -140,6 +139,7 @@ def download():
db = get_database(request) db = get_database(request)
return response.download(request, db) return response.download(request, db)
def csv(): def csv():
import gluon.contenttype import gluon.contenttype
response.headers['Content-Type'] = \ response.headers['Content-Type'] = \
@@ -156,6 +156,7 @@ def csv():
def import_csv(table, file): def import_csv(table, file):
table.import_from_csv_file(file) table.import_from_csv_file(file)
def select(): def select():
import re import re
db = get_database(request) db = get_database(request)
@@ -192,7 +193,8 @@ def select():
session.last_query = request.vars.query session.last_query = request.vars.query
form = FORM(TABLE(TR(T('Query:'), '', INPUT(_style='width:400px', form = FORM(TABLE(TR(T('Query:'), '', INPUT(_style='width:400px',
_name='query', _value=request.vars.query or '', _name='query', _value=request.vars.query or '',
requires=IS_NOT_EMPTY(error_message=T("Cannot be empty")))), TR(T('Update:'), requires=IS_NOT_EMPTY(
error_message=T("Cannot be empty")))), TR(T('Update:'),
INPUT(_name='update_check', _type='checkbox', INPUT(_name='update_check', _type='checkbox',
value=False), INPUT(_style='width:400px', value=False), INPUT(_style='width:400px',
_name='update_fields', _value=request.vars.update_fields _name='update_fields', _value=request.vars.update_fields
@@ -218,9 +220,11 @@ def select():
response.flash = T('%s %%{row} deleted', nrows) response.flash = T('%s %%{row} deleted', nrows)
nrows = db(query).count() nrows = db(query).count()
if orderby: if orderby:
rows = db(query,ignore_common_filters=True).select(limitby=(start, stop), orderby=eval_in_global_env(orderby)) rows = db(query, ignore_common_filters=True).select(limitby=(
start, stop), orderby=eval_in_global_env(orderby))
else: else:
rows = db(query,ignore_common_filters=True).select(limitby=(start, stop)) rows = db(query, ignore_common_filters=True).select(
limitby=(start, stop))
except Exception, e: except Exception, e:
import traceback import traceback
tb = traceback.format_exc() tb = traceback.format_exc()
@@ -269,9 +273,11 @@ def update():
if keyed: if keyed:
key = [f for f in request.vars if f in db[table]._primarykey] key = [f for f in request.vars if f in db[table]._primarykey]
if key: if key:
record = db(db[table][key[0]] == request.vars[key[0]], ignore_common_filters=True).select().first() record = db(db[table][key[0]] == request.vars[key[
0]], ignore_common_filters=True).select().first()
else: else:
record = db(db[table].id == request.args(2),ignore_common_filters=True).select().first() record = db(db[table].id == request.args(
2), ignore_common_filters=True).select().first()
if not record: if not record:
qry = query_by_table_type(table, db) qry = query_by_table_type(table, db)
@@ -283,7 +289,8 @@ def update():
for k in db[table]._primarykey: for k in db[table]._primarykey:
db[table][k].writable = False db[table][k].writable = False
form = SQLFORM(db[table], record, deletable=True, delete_label=T('Check to delete'), form = SQLFORM(
db[table], record, deletable=True, delete_label=T('Check to delete'),
ignore_rw=ignore_rw and not keyed, ignore_rw=ignore_rw and not keyed,
linkto=URL('select', linkto=URL('select',
args=request.args[:1]), upload=URL(r=request, args=request.args[:1]), upload=URL(r=request,
@@ -305,11 +312,15 @@ def update():
def state(): def state():
return dict() return dict()
def ccache(): def ccache():
form = FORM( form = FORM(
P(TAG.BUTTON(T("Clear CACHE?"), _type="submit", _name="yes", _value="yes")), P(TAG.BUTTON(
P(TAG.BUTTON(T("Clear RAM"), _type="submit", _name="ram", _value="ram")), T("Clear CACHE?"), _type="submit", _name="yes", _value="yes")),
P(TAG.BUTTON(T("Clear DISK"), _type="submit", _name="disk", _value="disk")), P(TAG.BUTTON(
T("Clear RAM"), _type="submit", _name="ram", _value="ram")),
P(TAG.BUTTON(
T("Clear DISK"), _type="submit", _name="disk", _value="disk")),
) )
if form.accepts(request.vars, session): if form.accepts(request.vars, session):
@@ -333,11 +344,16 @@ def ccache():
redirect(URL(r=request)) redirect(URL(r=request))
try: try:
from guppy import hpy; hp=hpy() from guppy import hpy
hp = hpy()
except ImportError: except ImportError:
hp = False hp = False
import shelve, os, copy, time, math import shelve
import os
import copy
import time
import math
from gluon import portalocker from gluon import portalocker
ram = { ram = {
@@ -384,7 +400,8 @@ def ccache():
locker = open(os.path.join(request.folder, locker = open(os.path.join(request.folder,
'cache/cache.lock'), 'a') 'cache/cache.lock'), 'a')
portalocker.lock(locker, portalocker.LOCK_EX) portalocker.lock(locker, portalocker.LOCK_EX)
disk_storage = shelve.open(os.path.join(request.folder, 'cache/cache.shelve')) disk_storage = shelve.open(
os.path.join(request.folder, 'cache/cache.shelve'))
try: try:
for key, value in disk_storage.items(): for key, value in disk_storage.items():
if isinstance(value, dict): if isinstance(value, dict):
@@ -415,7 +432,8 @@ def ccache():
total['misses'] = ram['misses'] + disk['misses'] total['misses'] = ram['misses'] + disk['misses']
total['keys'] = ram['keys'] + disk['keys'] total['keys'] = ram['keys'] + disk['keys']
try: try:
total['ratio'] = total['hits'] * 100 / (total['hits'] + total['misses']) total['ratio'] = total['hits'] * 100 / (total['hits'] +
total['misses'])
except (KeyError, ZeroDivisionError): except (KeyError, ZeroDivisionError):
total['ratio'] = 0 total['ratio'] = 0
@@ -18,7 +18,7 @@ def cache_on_disk():
def cache_in_ram_and_disk(): def cache_in_ram_and_disk():
"""cache the output of the lambda function on disk and in ram""" """cache the output of the lambda function on disk and in ram"""
t = cache.ram('time', lambda : cache.disk('time', lambda : \ t = cache.ram('time', lambda: cache.disk('time', lambda:
time.ctime(), time_expire=5), time_expire=5) time.ctime(), time_expire=5), time_expire=5)
return dict(time=t, link=A('click to reload', _href=URL(r=request))) return dict(time=t, link=A('click to reload', _href=URL(r=request)))
+18 -2
View File
@@ -9,65 +9,81 @@ response.description = T('web2py Web Framework')
session.forget() session.forget()
cache_expire = not request.is_local and 300 or 0 cache_expire = not request.is_local and 300 or 0
@cache('index', time_expire=cache_expire) @cache('index', time_expire=cache_expire)
def index(): def index():
return response.render() return response.render()
@cache('what', time_expire=cache_expire) @cache('what', time_expire=cache_expire)
def what(): def what():
import urllib; import urllib
try: try:
images = XML(urllib.urlopen('http://web2py.com/poweredby/default/images').read()) images = XML(urllib.urlopen(
'http://web2py.com/poweredby/default/images').read())
except: except:
images = [] images = []
return response.render(images=images) return response.render(images=images)
@cache('download', time_expire=cache_expire) @cache('download', time_expire=cache_expire)
def download(): def download():
return response.render() return response.render()
@cache('who', time_expire=cache_expire) @cache('who', time_expire=cache_expire)
def who(): def who():
return response.render() return response.render()
@cache('support', time_expire=cache_expire) @cache('support', time_expire=cache_expire)
def support(): def support():
return response.render() return response.render()
@cache('documentation', time_expire=cache_expire) @cache('documentation', time_expire=cache_expire)
def documentation(): def documentation():
return response.render() return response.render()
@cache('usergroups', time_expire=cache_expire) @cache('usergroups', time_expire=cache_expire)
def usergroups(): def usergroups():
return response.render() return response.render()
def contact(): def contact():
redirect(URL('default', 'usergroups')) redirect(URL('default', 'usergroups'))
@cache('videos', time_expire=cache_expire) @cache('videos', time_expire=cache_expire)
def videos(): def videos():
return response.render() return response.render()
def security(): def security():
redirect('http://www.web2py.com/book/default/chapter/01#security') redirect('http://www.web2py.com/book/default/chapter/01#security')
def api(): def api():
redirect('http://web2py.com/book/default/chapter/04#API') redirect('http://web2py.com/book/default/chapter/04#API')
@cache('license', time_expire=cache_expire) @cache('license', time_expire=cache_expire)
def license(): def license():
import os import os
filename = os.path.join(request.env.gluon_parent, 'LICENSE') filename = os.path.join(request.env.gluon_parent, 'LICENSE')
return response.render(dict(license=MARKMIN(read_file(filename)))) return response.render(dict(license=MARKMIN(read_file(filename))))
def version(): def version():
return 'Version %s.%s.%s (%s) %s' % request.env.web2py_version return 'Version %s.%s.%s (%s) %s' % request.env.web2py_version
@cache('examples', time_expire=cache_expire) @cache('examples', time_expire=cache_expire)
def examples(): def examples():
return response.render() return response.render()
@cache('changelog', time_expire=cache_expire) @cache('changelog', time_expire=cache_expire)
def changelog(): def changelog():
import os import os
@@ -102,7 +102,6 @@ def rss_aggregator():
return rss2.dumps(rss) return rss2.dumps(rss)
def ajaxwiki(): def ajaxwiki():
default = """ default = """
# section # section
@@ -135,5 +134,6 @@ Quoted text
_onclick="ajax('ajaxwiki_onclick',['text'],'html')")) _onclick="ajax('ajaxwiki_onclick',['text'],'html')"))
return dict(form=form, html=DIV(_id='html')) return dict(form=form, html=DIV(_id='html'))
def ajaxwiki_onclick(): def ajaxwiki_onclick():
return MARKMIN(request.vars.text).xml() return MARKMIN(request.vars.text).xml()
@@ -1,8 +1,10 @@
from gluon.contrib.spreadsheet import Sheet from gluon.contrib.spreadsheet import Sheet
def callback(): def callback():
return cache.ram('sheet1', lambda: None, None).process(request) return cache.ram('sheet1', lambda: None, None).process(request)
def index(): def index():
sheet = cache.ram('sheet1', lambda: Sheet(10, 10, URL('callback')), 0) sheet = cache.ram('sheet1', lambda: Sheet(10, 10, URL('callback')), 0)
#sheet.cell('r0c3',value='=r0c0+r0c1+r0c2',readonly=True) #sheet.cell('r0c3',value='=r0c0+r0c1+r0c2',readonly=True)
+15 -15
View File
@@ -7,17 +7,18 @@ def group_feed_reader(group,mode='div',counter='5'):
g = feedparser.parse(url) g = feedparser.parse(url)
if mode == 'div': if mode == 'div':
html = XML(TAG.BLOCKQUOTE(UL(*[LI(A(entry['title']+' - ' +\ html = XML(TAG.BLOCKQUOTE(UL(*[LI(A(entry['title'] + ' - ' +
entry['author'][entry['author'].rfind('('):],\ entry['author'][
_href=entry['link'],_target='_blank'))\ entry['author'].rfind('('):],
for entry in g['entries'] ]),\ _href=entry['link'], _target='_blank'))
_class="boxInfo",\ for entry in g['entries']]),
_class="boxInfo",
_style="padding-bottom:5px;")) _style="padding-bottom:5px;"))
else: else:
html = XML(UL(*[LI(A(entry['title']+' - ' +\ html = XML(UL(*[LI(A(entry['title'] + ' - ' +
entry['author'][entry['author'].rfind('('):],\ entry['author'][entry['author'].rfind('('):],
_href=entry['link'],_target='_blank'))\ _href=entry['link'], _target='_blank'))
for entry in g['entries']])) for entry in g['entries']]))
return html return html
@@ -30,15 +31,14 @@ def code_feed_reader(project,mode='div'):
from gluon.contrib import feedparser from gluon.contrib import feedparser
g = feedparser.parse(url) g = feedparser.parse(url)
if mode == 'div': if mode == 'div':
html = XML(DIV(UL(*[LI(A(entry['title'],_href=entry['link'],\ html = XML(DIV(UL(*[LI(A(entry['title'], _href=entry['link'],
_target='_blank'))\ _target='_blank'))
for entry in g['entries'][0:5]]),\ for entry in g['entries'][0:5]]),
_class="boxInfo",\ _class="boxInfo",
_style="padding-bottom:5px;")) _style="padding-bottom:5px;"))
else: else:
html = XML(UL(*[LI(A(entry['title'],_href=entry['link'],\ html = XML(UL(*[LI(A(entry['title'], _href=entry['link'],
_target='_blank'))\ _target='_blank'))
for entry in g['entries'][0:5]])) for entry in g['entries'][0:5]]))
return html return html
+9 -7
View File
@@ -2,18 +2,19 @@ import gluon.template
markmin_dict = dict( markmin_dict = dict(
code_python=lambda code: str(CODE(code)), code_python=lambda code: str(CODE(code)),
template=lambda \ template=lambda
code: gluon.template.render(code, context=globals()), code: gluon.template.render(code, context=globals()),
sup=lambda \ sup=lambda
code: '<sup style="font-size:0.5em;">%s</sup>' % code, code: '<sup style="font-size:0.5em;">%s</sup>' % code,
br=lambda n: '<br>' * int(n), br=lambda n: '<br>' * int(n),
groupdates=lambda group: group_feed_reader(group), groupdates=lambda group: group_feed_reader(group),
) )
def get_content(b=None,\
c=request.controller,\ def get_content(b=None,
f=request.function,\ c=request.controller,
l='en',\ f=request.function,
l='en',
format='markmin'): format='markmin'):
"""Gets and renders the file in """Gets and renders the file in
<app>/private/content/<lang>/<controller>/<function>/<block>.<format> <app>/private/content/<lang>/<controller>/<function>/<block>.<format>
@@ -21,7 +22,8 @@ def get_content(b=None,\
def openfile(): def openfile():
import os import os
path = os.path.join(request.folder,'private','content',l,c,f,b+'.'+format) path = os.path.join(
request.folder, 'private', 'content', l, c, f, b + '.' + format)
return open(path) return open(path)
try: try:
+2 -1
View File
@@ -11,6 +11,8 @@ response.menu = [
######################################################################### #########################################################################
## Changes the menu active item ## Changes the menu active item
######################################################################### #########################################################################
def toggle_menuclass(cssclass='pressed', menuid='headermenu'): def toggle_menuclass(cssclass='pressed', menuid='headermenu'):
"""This function changes the menu class to put pressed appearance""" """This function changes the menu class to put pressed appearance"""
@@ -23,7 +25,6 @@ def toggle_menuclass(cssclass='pressed',menuid='headermenu'):
documentation='-520px -115px' documentation='-520px -115px'
) )
if request.function in positions.keys(): if request.function in positions.keys():
jscript = """ jscript = """
<script> <script>
+34 -16
View File
@@ -102,17 +102,16 @@ def query_by_table_type(tablename,db,request=request):
cond = '>0' cond = '>0'
if firstkey.type in ['string', 'text']: if firstkey.type in ['string', 'text']:
cond = '!=""' cond = '!=""'
qry = '%s.%s.%s%s' % (request.args[0], request.args[1], firstkey.name, cond) qry = '%s.%s.%s%s' % (
request.args[0], request.args[1], firstkey.name, cond)
else: else:
qry = '%s.%s.id>0' % tuple(request.args[:2]) qry = '%s.%s.id>0' % tuple(request.args[:2])
return qry return qry
# ########################################################## # ##########################################################
# ## list all databases and tables # ## list all databases and tables
# ########################################################### # ###########################################################
def index(): def index():
return dict(databases=databases) return dict(databases=databases)
@@ -140,6 +139,7 @@ def download():
db = get_database(request) db = get_database(request)
return response.download(request, db) return response.download(request, db)
def csv(): def csv():
import gluon.contenttype import gluon.contenttype
response.headers['Content-Type'] = \ response.headers['Content-Type'] = \
@@ -156,6 +156,7 @@ def csv():
def import_csv(table, file): def import_csv(table, file):
table.import_from_csv_file(file) table.import_from_csv_file(file)
def select(): def select():
import re import re
db = get_database(request) db = get_database(request)
@@ -192,7 +193,8 @@ def select():
session.last_query = request.vars.query session.last_query = request.vars.query
form = FORM(TABLE(TR(T('Query:'), '', INPUT(_style='width:400px', form = FORM(TABLE(TR(T('Query:'), '', INPUT(_style='width:400px',
_name='query', _value=request.vars.query or '', _name='query', _value=request.vars.query or '',
requires=IS_NOT_EMPTY(error_message=T("Cannot be empty")))), TR(T('Update:'), requires=IS_NOT_EMPTY(
error_message=T("Cannot be empty")))), TR(T('Update:'),
INPUT(_name='update_check', _type='checkbox', INPUT(_name='update_check', _type='checkbox',
value=False), INPUT(_style='width:400px', value=False), INPUT(_style='width:400px',
_name='update_fields', _value=request.vars.update_fields _name='update_fields', _value=request.vars.update_fields
@@ -218,9 +220,11 @@ def select():
response.flash = T('%s %%{row} deleted', nrows) response.flash = T('%s %%{row} deleted', nrows)
nrows = db(query).count() nrows = db(query).count()
if orderby: if orderby:
rows = db(query,ignore_common_filters=True).select(limitby=(start, stop), orderby=eval_in_global_env(orderby)) rows = db(query, ignore_common_filters=True).select(limitby=(
start, stop), orderby=eval_in_global_env(orderby))
else: else:
rows = db(query,ignore_common_filters=True).select(limitby=(start, stop)) rows = db(query, ignore_common_filters=True).select(
limitby=(start, stop))
except Exception, e: except Exception, e:
import traceback import traceback
tb = traceback.format_exc() tb = traceback.format_exc()
@@ -269,9 +273,11 @@ def update():
if keyed: if keyed:
key = [f for f in request.vars if f in db[table]._primarykey] key = [f for f in request.vars if f in db[table]._primarykey]
if key: if key:
record = db(db[table][key[0]] == request.vars[key[0]], ignore_common_filters=True).select().first() record = db(db[table][key[0]] == request.vars[key[
0]], ignore_common_filters=True).select().first()
else: else:
record = db(db[table].id == request.args(2),ignore_common_filters=True).select().first() record = db(db[table].id == request.args(
2), ignore_common_filters=True).select().first()
if not record: if not record:
qry = query_by_table_type(table, db) qry = query_by_table_type(table, db)
@@ -283,7 +289,8 @@ def update():
for k in db[table]._primarykey: for k in db[table]._primarykey:
db[table][k].writable = False db[table][k].writable = False
form = SQLFORM(db[table], record, deletable=True, delete_label=T('Check to delete'), form = SQLFORM(
db[table], record, deletable=True, delete_label=T('Check to delete'),
ignore_rw=ignore_rw and not keyed, ignore_rw=ignore_rw and not keyed,
linkto=URL('select', linkto=URL('select',
args=request.args[:1]), upload=URL(r=request, args=request.args[:1]), upload=URL(r=request,
@@ -305,11 +312,15 @@ def update():
def state(): def state():
return dict() return dict()
def ccache(): def ccache():
form = FORM( form = FORM(
P(TAG.BUTTON(T("Clear CACHE?"), _type="submit", _name="yes", _value="yes")), P(TAG.BUTTON(
P(TAG.BUTTON(T("Clear RAM"), _type="submit", _name="ram", _value="ram")), T("Clear CACHE?"), _type="submit", _name="yes", _value="yes")),
P(TAG.BUTTON(T("Clear DISK"), _type="submit", _name="disk", _value="disk")), P(TAG.BUTTON(
T("Clear RAM"), _type="submit", _name="ram", _value="ram")),
P(TAG.BUTTON(
T("Clear DISK"), _type="submit", _name="disk", _value="disk")),
) )
if form.accepts(request.vars, session): if form.accepts(request.vars, session):
@@ -333,11 +344,16 @@ def ccache():
redirect(URL(r=request)) redirect(URL(r=request))
try: try:
from guppy import hpy; hp=hpy() from guppy import hpy
hp = hpy()
except ImportError: except ImportError:
hp = False hp = False
import shelve, os, copy, time, math import shelve
import os
import copy
import time
import math
from gluon import portalocker from gluon import portalocker
ram = { ram = {
@@ -384,7 +400,8 @@ def ccache():
locker = open(os.path.join(request.folder, locker = open(os.path.join(request.folder,
'cache/cache.lock'), 'a') 'cache/cache.lock'), 'a')
portalocker.lock(locker, portalocker.LOCK_EX) portalocker.lock(locker, portalocker.LOCK_EX)
disk_storage = shelve.open(os.path.join(request.folder, 'cache/cache.shelve')) disk_storage = shelve.open(
os.path.join(request.folder, 'cache/cache.shelve'))
try: try:
for key, value in disk_storage.items(): for key, value in disk_storage.items():
if isinstance(value, dict): if isinstance(value, dict):
@@ -415,7 +432,8 @@ def ccache():
total['misses'] = ram['misses'] + disk['misses'] total['misses'] = ram['misses'] + disk['misses']
total['keys'] = ram['keys'] + disk['keys'] total['keys'] = ram['keys'] + disk['keys']
try: try:
total['ratio'] = total['hits'] * 100 / (total['hits'] + total['misses']) total['ratio'] = total['hits'] * 100 / (total['hits'] +
total['misses'])
except (KeyError, ZeroDivisionError): except (KeyError, ZeroDivisionError):
total['ratio'] = 0 total['ratio'] = 0
@@ -9,6 +9,7 @@
## - call exposes all registered services (none by default) ## - call exposes all registered services (none by default)
######################################################################### #########################################################################
def index(): def index():
""" """
example action using the internationalization operator T and flash example action using the internationalization operator T and flash
@@ -20,6 +21,7 @@ def index():
response.flash = T("Welcome to web2py!") response.flash = T("Welcome to web2py!")
return dict(message=T('Hello World')) return dict(message=T('Hello World'))
def user(): def user():
""" """
exposes: exposes:
+71 -35
View File
@@ -5,7 +5,8 @@
## Customize your APP title, subtitle and menus here ## Customize your APP title, subtitle and menus here
######################################################################### #########################################################################
response.title = ' '.join(word.capitalize() for word in request.application.split('_')) response.title = ' '.join(
word.capitalize() for word in request.application.split('_'))
response.subtitle = T('customize me!') response.subtitle = T('customize me!')
## read more at http://dev.w3.org/html5/markup/meta.name.html ## read more at http://dev.w3.org/html5/markup/meta.name.html
@@ -29,6 +30,7 @@ response.menu = [
## provide shortcuts for development. remove in production ## provide shortcuts for development. remove in production
######################################################################### #########################################################################
def _(): def _():
# shortcuts # shortcuts
app = request.application app = request.application
@@ -39,61 +41,95 @@ def _():
(T('My Sites'), False, URL('admin', 'default', 'site')), (T('My Sites'), False, URL('admin', 'default', 'site')),
(T('This App'), False, URL('admin', 'default', 'design/%s' % app), [ (T('This App'), False, URL('admin', 'default', 'design/%s' % app), [
(T('Controller'), False, (T('Controller'), False,
URL('admin','default','edit/%s/controllers/%s.py' % (app,ctr))), URL(
'admin', 'default', 'edit/%s/controllers/%s.py' % (app, ctr))),
(T('View'), False, (T('View'), False,
URL('admin','default','edit/%s/views/%s' % (app,response.view))), URL(
'admin', 'default', 'edit/%s/views/%s' % (app, response.view))),
(T('Layout'), False, (T('Layout'), False,
URL('admin','default','edit/%s/views/layout.html' % app)), URL(
'admin', 'default', 'edit/%s/views/layout.html' % app)),
(T('Stylesheet'), False, (T('Stylesheet'), False,
URL('admin','default','edit/%s/static/css/web2py.css' % app)), URL(
'admin', 'default', 'edit/%s/static/css/web2py.css' % app)),
(T('DB Model'), False, (T('DB Model'), False,
URL('admin','default','edit/%s/models/db.py' % app)), URL(
'admin', 'default', 'edit/%s/models/db.py' % app)),
(T('Menu Model'), False, (T('Menu Model'), False,
URL('admin','default','edit/%s/models/menu.py' % app)), URL(
'admin', 'default', 'edit/%s/models/menu.py' % app)),
(T('Database'), False, URL(app, 'appadmin', 'index')), (T('Database'), False, URL(app, 'appadmin', 'index')),
(T('Errors'),False, URL('admin','default','errors/' + app)), (T('Errors'), False, URL(
(T('About'),False, URL('admin','default','about/' + app)), 'admin', 'default', 'errors/' + app)),
(T('About'), False, URL(
'admin', 'default', 'about/' + app)),
]), ]),
('web2py.com', False, 'http://www.web2py.com', [ ('web2py.com', False, 'http://www.web2py.com', [
(T('Download'),False,'http://www.web2py.com/examples/default/download'), (T('Download'), False,
(T('Support'),False,'http://www.web2py.com/examples/default/support'), 'http://www.web2py.com/examples/default/download'),
(T('Support'), False,
'http://www.web2py.com/examples/default/support'),
(T('Demo'), False, 'http://web2py.com/demo_admin'), (T('Demo'), False, 'http://web2py.com/demo_admin'),
(T('Quick Examples'),False,'http://web2py.com/examples/default/examples'), (T('Quick Examples'), False,
'http://web2py.com/examples/default/examples'),
(T('FAQ'), False, 'http://web2py.com/AlterEgo'), (T('FAQ'), False, 'http://web2py.com/AlterEgo'),
(T('Videos'),False,'http://www.web2py.com/examples/default/videos/'), (T('Videos'), False,
(T('Free Applications'),False,'http://web2py.com/appliances'), 'http://www.web2py.com/examples/default/videos/'),
(T('Free Applications'),
False, 'http://web2py.com/appliances'),
(T('Plugins'), False, 'http://web2py.com/plugins'), (T('Plugins'), False, 'http://web2py.com/plugins'),
(T('Layouts'), False, 'http://web2py.com/layouts'), (T('Layouts'), False, 'http://web2py.com/layouts'),
(T('Recipes'), False, 'http://web2pyslices.com/'), (T('Recipes'), False, 'http://web2pyslices.com/'),
(T('Semantic'), False, 'http://web2py.com/semantic'), (T('Semantic'), False, 'http://web2py.com/semantic'),
]), ]),
(T('Documentation'), False, 'http://www.web2py.com/book', [ (T('Documentation'), False, 'http://www.web2py.com/book', [
(T('Preface'),False,'http://www.web2py.com/book/default/chapter/00'), (T('Preface'), False,
(T('Introduction'),False,'http://www.web2py.com/book/default/chapter/01'), 'http://www.web2py.com/book/default/chapter/00'),
(T('Python'),False,'http://www.web2py.com/book/default/chapter/02'), (T('Introduction'), False,
(T('Overview'),False,'http://www.web2py.com/book/default/chapter/03'), 'http://www.web2py.com/book/default/chapter/01'),
(T('The Core'),False,'http://www.web2py.com/book/default/chapter/04'), (T('Python'), False,
(T('The Views'),False,'http://www.web2py.com/book/default/chapter/05'), 'http://www.web2py.com/book/default/chapter/02'),
(T('Database'),False,'http://www.web2py.com/book/default/chapter/06'), (T('Overview'), False,
(T('Forms and Validators'),False,'http://www.web2py.com/book/default/chapter/07'), 'http://www.web2py.com/book/default/chapter/03'),
(T('Email and SMS'),False,'http://www.web2py.com/book/default/chapter/08'), (T('The Core'), False,
(T('Access Control'),False,'http://www.web2py.com/book/default/chapter/09'), 'http://www.web2py.com/book/default/chapter/04'),
(T('Services'),False,'http://www.web2py.com/book/default/chapter/10'), (T('The Views'), False,
(T('Ajax Recipes'),False,'http://www.web2py.com/book/default/chapter/11'), 'http://www.web2py.com/book/default/chapter/05'),
(T('Components and Plugins'),False,'http://www.web2py.com/book/default/chapter/12'), (T('Database'), False,
(T('Deployment Recipes'),False,'http://www.web2py.com/book/default/chapter/13'), 'http://www.web2py.com/book/default/chapter/06'),
(T('Other Recipes'),False,'http://www.web2py.com/book/default/chapter/14'), (T('Forms and Validators'), False,
(T('Buy this book'),False,'http://stores.lulu.com/web2py'), 'http://www.web2py.com/book/default/chapter/07'),
(T('Email and SMS'), False,
'http://www.web2py.com/book/default/chapter/08'),
(T('Access Control'), False,
'http://www.web2py.com/book/default/chapter/09'),
(T('Services'), False,
'http://www.web2py.com/book/default/chapter/10'),
(T('Ajax Recipes'), False,
'http://www.web2py.com/book/default/chapter/11'),
(T('Components and Plugins'), False,
'http://www.web2py.com/book/default/chapter/12'),
(T('Deployment Recipes'), False,
'http://www.web2py.com/book/default/chapter/13'),
(T('Other Recipes'), False,
'http://www.web2py.com/book/default/chapter/14'),
(T('Buy this book'), False,
'http://stores.lulu.com/web2py'),
]), ]),
(T('Community'), False, None, [ (T('Community'), False, None, [
(T('Groups'),False,'http://www.web2py.com/examples/default/usergroups'), (T('Groups'), False,
'http://www.web2py.com/examples/default/usergroups'),
(T('Twitter'), False, 'http://twitter.com/web2py'), (T('Twitter'), False, 'http://twitter.com/web2py'),
(T('Live Chat'),False,'http://webchat.freenode.net/?channels=web2py'), (T('Live Chat'), False,
'http://webchat.freenode.net/?channels=web2py'),
]), ]),
(T('Plugins'), False, None, [ (T('Plugins'), False, None, [
('plugin_wiki',False,'http://web2py.com/examples/default/download'), ('plugin_wiki', False,
(T('Other Plugins'),False,'http://web2py.com/plugins'), 'http://web2py.com/examples/default/download'),
(T('Layout Plugins'),False,'http://web2py.com/layouts'), (T('Other Plugins'), False,
'http://web2py.com/plugins'),
(T('Layout Plugins'),
False, 'http://web2py.com/layouts'),
]) ])
] ]
)] )]