initial commit
This commit is contained in:
@@ -0,0 +1,430 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ##########################################################
|
||||
# ## make sure administrator is on localhost
|
||||
# ###########################################################
|
||||
|
||||
import os
|
||||
import socket
|
||||
import datetime
|
||||
import copy
|
||||
import gluon.contenttype
|
||||
import gluon.fileutils
|
||||
|
||||
# ## critical --- make a copy of the environment
|
||||
|
||||
global_env = copy.copy(globals())
|
||||
global_env['datetime'] = datetime
|
||||
|
||||
http_host = request.env.http_host.split(':')[0]
|
||||
remote_addr = request.env.remote_addr
|
||||
try:
|
||||
hosts = (http_host, socket.gethostname(),
|
||||
socket.gethostbyname(http_host),
|
||||
'::1','127.0.0.1','::ffff:127.0.0.1')
|
||||
except:
|
||||
hosts = (http_host, )
|
||||
|
||||
if request.env.http_x_forwarded_for or request.env.wsgi_url_scheme\
|
||||
in ['https', 'HTTPS']:
|
||||
session.secure()
|
||||
elif (remote_addr not in hosts) and (remote_addr != "127.0.0.1"):
|
||||
raise HTTP(200, T('appadmin is disabled because insecure channel'))
|
||||
|
||||
if (request.application=='admin' and not session.authorized) or \
|
||||
(request.application!='admin' and not gluon.fileutils.check_credentials(request)):
|
||||
redirect(URL('admin', 'default', 'index',
|
||||
vars=dict(send=URL(args=request.args,vars=request.vars))))
|
||||
|
||||
ignore_rw = True
|
||||
response.view = 'appadmin.html'
|
||||
response.menu = [[T('design'), False, URL('admin', 'default', 'design',
|
||||
args=[request.application])], [T('db'), False,
|
||||
URL('index')], [T('state'), False,
|
||||
URL('state')], [T('cache'), False,
|
||||
URL('ccache')]]
|
||||
|
||||
# ##########################################################
|
||||
# ## auxiliary functions
|
||||
# ###########################################################
|
||||
|
||||
|
||||
def get_databases(request):
|
||||
dbs = {}
|
||||
for (key, value) in global_env.items():
|
||||
cond = False
|
||||
try:
|
||||
cond = isinstance(value, GQLDB)
|
||||
except:
|
||||
cond = isinstance(value, SQLDB)
|
||||
if cond:
|
||||
dbs[key] = value
|
||||
return dbs
|
||||
|
||||
|
||||
databases = get_databases(None)
|
||||
|
||||
|
||||
def eval_in_global_env(text):
|
||||
exec ('_ret=%s' % text, {}, global_env)
|
||||
return global_env['_ret']
|
||||
|
||||
|
||||
def get_database(request):
|
||||
if request.args and request.args[0] in databases:
|
||||
return eval_in_global_env(request.args[0])
|
||||
else:
|
||||
session.flash = T('invalid request')
|
||||
redirect(URL('index'))
|
||||
|
||||
|
||||
def get_table(request):
|
||||
db = get_database(request)
|
||||
if len(request.args) > 1 and request.args[1] in db.tables:
|
||||
return (db, request.args[1])
|
||||
else:
|
||||
session.flash = T('invalid request')
|
||||
redirect(URL('index'))
|
||||
|
||||
|
||||
def get_query(request):
|
||||
try:
|
||||
return eval_in_global_env(request.vars.query)
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
|
||||
def query_by_table_type(tablename,db,request=request):
|
||||
keyed = hasattr(db[tablename],'_primarykey')
|
||||
if keyed:
|
||||
firstkey = db[tablename][db[tablename]._primarykey[0]]
|
||||
cond = '>0'
|
||||
if firstkey.type in ['string', 'text']:
|
||||
cond = '!=""'
|
||||
qry = '%s.%s.%s%s' % (request.args[0], request.args[1], firstkey.name, cond)
|
||||
else:
|
||||
qry = '%s.%s.id>0' % tuple(request.args[:2])
|
||||
return qry
|
||||
|
||||
|
||||
|
||||
# ##########################################################
|
||||
# ## list all databases and tables
|
||||
# ###########################################################
|
||||
|
||||
|
||||
def index():
|
||||
return dict(databases=databases)
|
||||
|
||||
|
||||
# ##########################################################
|
||||
# ## insert a new record
|
||||
# ###########################################################
|
||||
|
||||
|
||||
def insert():
|
||||
(db, table) = get_table(request)
|
||||
form = SQLFORM(db[table], ignore_rw=ignore_rw)
|
||||
if form.accepts(request.vars, session):
|
||||
response.flash = T('new record inserted')
|
||||
return dict(form=form,table=db[table])
|
||||
|
||||
|
||||
# ##########################################################
|
||||
# ## list all records in table and insert new record
|
||||
# ###########################################################
|
||||
|
||||
|
||||
def download():
|
||||
import os
|
||||
db = get_database(request)
|
||||
return response.download(request,db)
|
||||
|
||||
def csv():
|
||||
import gluon.contenttype
|
||||
response.headers['Content-Type'] = \
|
||||
gluon.contenttype.contenttype('.csv')
|
||||
db = get_database(request)
|
||||
query = get_query(request)
|
||||
if not query:
|
||||
return None
|
||||
response.headers['Content-disposition'] = 'attachment; filename=%s_%s.csv'\
|
||||
% tuple(request.vars.query.split('.')[:2])
|
||||
return str(db(query).select())
|
||||
|
||||
|
||||
def import_csv(table, file):
|
||||
table.import_from_csv_file(file)
|
||||
|
||||
def select():
|
||||
import re
|
||||
db = get_database(request)
|
||||
dbname = request.args[0]
|
||||
regex = re.compile('(?P<table>\w+)\.(?P<field>\w+)=(?P<value>\d+)')
|
||||
if len(request.args)>1 and hasattr(db[request.args[1]],'_primarykey'):
|
||||
regex = re.compile('(?P<table>\w+)\.(?P<field>\w+)=(?P<value>.+)')
|
||||
if request.vars.query:
|
||||
match = regex.match(request.vars.query)
|
||||
if match:
|
||||
request.vars.query = '%s.%s.%s==%s' % (request.args[0],
|
||||
match.group('table'), match.group('field'),
|
||||
match.group('value'))
|
||||
else:
|
||||
request.vars.query = session.last_query
|
||||
query = get_query(request)
|
||||
if request.vars.start:
|
||||
start = int(request.vars.start)
|
||||
else:
|
||||
start = 0
|
||||
nrows = 0
|
||||
stop = start + 100
|
||||
table = None
|
||||
rows = []
|
||||
orderby = request.vars.orderby
|
||||
if orderby:
|
||||
orderby = dbname + '.' + orderby
|
||||
if orderby == session.last_orderby:
|
||||
if orderby[0] == '~':
|
||||
orderby = orderby[1:]
|
||||
else:
|
||||
orderby = '~' + orderby
|
||||
session.last_orderby = orderby
|
||||
session.last_query = request.vars.query
|
||||
form = FORM(TABLE(TR(T('Query:'), '', INPUT(_style='width:400px',
|
||||
_name='query', _value=request.vars.query or '',
|
||||
requires=IS_NOT_EMPTY(error_message=T("Cannot be empty")))), TR(T('Update:'),
|
||||
INPUT(_name='update_check', _type='checkbox',
|
||||
value=False), INPUT(_style='width:400px',
|
||||
_name='update_fields', _value=request.vars.update_fields
|
||||
or '')), TR(T('Delete:'), INPUT(_name='delete_check',
|
||||
_class='delete', _type='checkbox', value=False), ''),
|
||||
TR('', '', INPUT(_type='submit', _value='submit'))),
|
||||
_action=URL(r=request,args=request.args))
|
||||
if request.vars.csvfile != None:
|
||||
try:
|
||||
import_csv(db[request.vars.table],
|
||||
request.vars.csvfile.file)
|
||||
response.flash = T('data uploaded')
|
||||
except Exception, e:
|
||||
response.flash = DIV(T('unable to parse csv file'),PRE(str(e)))
|
||||
if form.accepts(request.vars, formname=None):
|
||||
# regex = re.compile(request.args[0] + '\.(?P<table>\w+)\.id\>0')
|
||||
regex = re.compile(request.args[0] + '\.(?P<table>\w+)\..+')
|
||||
|
||||
match = regex.match(form.vars.query.strip())
|
||||
if match:
|
||||
table = match.group('table')
|
||||
try:
|
||||
nrows = db(query).count()
|
||||
if form.vars.update_check and form.vars.update_fields:
|
||||
db(query).update(**eval_in_global_env('dict(%s)'
|
||||
% form.vars.update_fields))
|
||||
response.flash = T('%s rows updated', nrows)
|
||||
elif form.vars.delete_check:
|
||||
db(query).delete()
|
||||
response.flash = T('%s rows deleted', nrows)
|
||||
nrows = db(query).count()
|
||||
if orderby:
|
||||
rows = db(query).select(limitby=(start, stop),
|
||||
orderby=eval_in_global_env(orderby))
|
||||
else:
|
||||
rows = db(query).select(limitby=(start, stop))
|
||||
except Exception, e:
|
||||
(rows, nrows) = ([], 0)
|
||||
response.flash = DIV(T('Invalid Query'),PRE(str(e)))
|
||||
return dict(
|
||||
form=form,
|
||||
table=table,
|
||||
start=start,
|
||||
stop=stop,
|
||||
nrows=nrows,
|
||||
rows=rows,
|
||||
query=request.vars.query,
|
||||
)
|
||||
|
||||
|
||||
# ##########################################################
|
||||
# ## edit delete one record
|
||||
# ###########################################################
|
||||
|
||||
|
||||
def update():
|
||||
(db, table) = get_table(request)
|
||||
keyed = hasattr(db[table],'_primarykey')
|
||||
record = None
|
||||
if keyed:
|
||||
key = [f for f in request.vars if f in db[table]._primarykey]
|
||||
if key:
|
||||
record = db(db[table][key[0]] == request.vars[key[0]]).select().first()
|
||||
else:
|
||||
record = db(db[table].id == request.args(2)).select().first()
|
||||
|
||||
if not record:
|
||||
qry = query_by_table_type(table, db)
|
||||
session.flash = T('record does not exist')
|
||||
redirect(URL('select', args=request.args[:1],
|
||||
vars=dict(query=qry)))
|
||||
|
||||
if keyed:
|
||||
for k in db[table]._primarykey:
|
||||
db[table][k].writable=False
|
||||
|
||||
form = SQLFORM(db[table], record, deletable=True, delete_label=T('Check to delete'),
|
||||
ignore_rw=ignore_rw and not keyed,
|
||||
linkto=URL('select',
|
||||
args=request.args[:1]), upload=URL(r=request,
|
||||
f='download', args=request.args[:1]))
|
||||
|
||||
if form.accepts(request.vars, session):
|
||||
session.flash = T('done!')
|
||||
qry = query_by_table_type(table, db)
|
||||
redirect(URL('select', args=request.args[:1],
|
||||
vars=dict(query=qry)))
|
||||
return dict(form=form,table=db[table])
|
||||
|
||||
|
||||
# ##########################################################
|
||||
# ## get global variables
|
||||
# ###########################################################
|
||||
|
||||
|
||||
def state():
|
||||
return dict()
|
||||
|
||||
def ccache():
|
||||
form = FORM(
|
||||
P(TAG.BUTTON("Clear CACHE?", _type="submit", _name="yes", _value="yes")),
|
||||
P(TAG.BUTTON("Clear RAM", _type="submit", _name="ram", _value="ram")),
|
||||
P(TAG.BUTTON("Clear DISK", _type="submit", _name="disk", _value="disk")),
|
||||
)
|
||||
|
||||
if form.accepts(request.vars, session):
|
||||
clear_ram = False
|
||||
clear_disk = False
|
||||
session.flash = ""
|
||||
if request.vars.yes:
|
||||
clear_ram = clear_disk = True
|
||||
if request.vars.ram:
|
||||
clear_ram = True
|
||||
if request.vars.disk:
|
||||
clear_disk = True
|
||||
|
||||
if clear_ram:
|
||||
cache.ram.clear()
|
||||
session.flash += "Ram Cleared "
|
||||
if clear_disk:
|
||||
cache.disk.clear()
|
||||
session.flash += "Disk Cleared"
|
||||
|
||||
redirect(URL(r=request))
|
||||
|
||||
try:
|
||||
from guppy import hpy; hp=hpy()
|
||||
except ImportError:
|
||||
hp = False
|
||||
|
||||
import shelve, os, copy, time, math
|
||||
from gluon import portalocker
|
||||
|
||||
ram = {
|
||||
'entries': 0,
|
||||
'bytes': 0,
|
||||
'objects': 0,
|
||||
'hits': 0,
|
||||
'misses': 0,
|
||||
'ratio': 0,
|
||||
'oldest': time.time(),
|
||||
'keys': []
|
||||
}
|
||||
disk = copy.copy(ram)
|
||||
total = copy.copy(ram)
|
||||
disk['keys'] = []
|
||||
total['keys'] = []
|
||||
|
||||
def GetInHMS(seconds):
|
||||
hours = math.floor(seconds / 3600)
|
||||
seconds -= hours * 3600
|
||||
minutes = math.floor(seconds / 60)
|
||||
seconds -= minutes * 60
|
||||
seconds = math.floor(seconds)
|
||||
|
||||
return (hours, minutes, seconds)
|
||||
|
||||
for key, value in cache.ram.storage.items():
|
||||
if isinstance(value, dict):
|
||||
ram['hits'] = value['hit_total'] - value['misses']
|
||||
ram['misses'] = value['misses']
|
||||
try:
|
||||
ram['ratio'] = ram['hits'] * 100 / value['hit_total']
|
||||
except (KeyError, ZeroDivisionError):
|
||||
ram['ratio'] = 0
|
||||
else:
|
||||
if hp:
|
||||
ram['bytes'] += hp.iso(value[1]).size
|
||||
ram['objects'] += hp.iso(value[1]).count
|
||||
ram['entries'] += 1
|
||||
if value[0] < ram['oldest']:
|
||||
ram['oldest'] = value[0]
|
||||
ram['keys'].append((key, GetInHMS(time.time() - value[0])))
|
||||
|
||||
locker = open(os.path.join(request.folder,
|
||||
'cache/cache.lock'), 'a')
|
||||
portalocker.lock(locker, portalocker.LOCK_EX)
|
||||
disk_storage = shelve.open(os.path.join(request.folder, 'cache/cache.shelve'))
|
||||
try:
|
||||
for key, value in disk_storage.items():
|
||||
if isinstance(value, dict):
|
||||
disk['hits'] = value['hit_total'] - value['misses']
|
||||
disk['misses'] = value['misses']
|
||||
try:
|
||||
disk['ratio'] = disk['hits'] * 100 / value['hit_total']
|
||||
except (KeyError, ZeroDivisionError):
|
||||
disk['ratio'] = 0
|
||||
else:
|
||||
if hp:
|
||||
disk['bytes'] += hp.iso(value[1]).size
|
||||
disk['objects'] += hp.iso(value[1]).count
|
||||
disk['entries'] += 1
|
||||
if value[0] < disk['oldest']:
|
||||
disk['oldest'] = value[0]
|
||||
disk['keys'].append((key, GetInHMS(time.time() - value[0])))
|
||||
|
||||
finally:
|
||||
portalocker.unlock(locker)
|
||||
locker.close()
|
||||
disk_storage.close()
|
||||
|
||||
total['entries'] = ram['entries'] + disk['entries']
|
||||
total['bytes'] = ram['bytes'] + disk['bytes']
|
||||
total['objects'] = ram['objects'] + disk['objects']
|
||||
total['hits'] = ram['hits'] + disk['hits']
|
||||
total['misses'] = ram['misses'] + disk['misses']
|
||||
total['keys'] = ram['keys'] + disk['keys']
|
||||
try:
|
||||
total['ratio'] = total['hits'] * 100 / (total['hits'] + total['misses'])
|
||||
except (KeyError, ZeroDivisionError):
|
||||
total['ratio'] = 0
|
||||
|
||||
if disk['oldest'] < ram['oldest']:
|
||||
total['oldest'] = disk['oldest']
|
||||
else:
|
||||
total['oldest'] = ram['oldest']
|
||||
|
||||
ram['oldest'] = GetInHMS(time.time() - ram['oldest'])
|
||||
disk['oldest'] = GetInHMS(time.time() - disk['oldest'])
|
||||
total['oldest'] = GetInHMS(time.time() - total['oldest'])
|
||||
|
||||
def key_table(keys):
|
||||
return TABLE(
|
||||
TR(TD(B('Key')), TD(B('Time in Cache (h:m:s)'))),
|
||||
*[TR(TD(k[0]), TD('%02d:%02d:%02d' % k[1])) for k in keys],
|
||||
**dict(_class='cache-keys',
|
||||
_style="border-collapse: separate; border-spacing: .5em;"))
|
||||
|
||||
ram['keys'] = key_table(ram['keys'])
|
||||
disk['keys'] = key_table(disk['keys'])
|
||||
total['keys'] = key_table(total['keys'])
|
||||
|
||||
return dict(form=form, total=total,
|
||||
ram=ram, disk=disk, object_stats=hp != False)
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import sys
|
||||
import cStringIO
|
||||
import gluon.contrib.shell
|
||||
import code, thread
|
||||
from gluon.debug import communicate
|
||||
|
||||
|
||||
if DEMO_MODE or MULTI_USER_MODE:
|
||||
session.flash = T('disabled in demo mode')
|
||||
redirect(URL('default','site'))
|
||||
|
||||
FE=10**9
|
||||
|
||||
def index():
|
||||
app = request.args(0) or 'admin'
|
||||
reset()
|
||||
# read buffer
|
||||
data = communicate()
|
||||
return dict(app=app,data=data)
|
||||
|
||||
def callback():
|
||||
app = request.args[0]
|
||||
command = request.vars.statement
|
||||
session['debug_commands:'+app].append(command)
|
||||
output = communicate(command)
|
||||
k = len(session['debug_commands:'+app]) - 1
|
||||
return '[%i] %s%s\n' % (k + 1, command, output)
|
||||
|
||||
def reset():
|
||||
app = request.args(0) or 'admin'
|
||||
session['debug_commands:'+app] = []
|
||||
return 'done'
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,87 @@
|
||||
### this works on linux only
|
||||
|
||||
import re
|
||||
try:
|
||||
import fcntl
|
||||
import subprocess
|
||||
import signal
|
||||
import os
|
||||
import shutil
|
||||
from gluon.fileutils import read_file, write_file
|
||||
except:
|
||||
session.flash='sorry, only on Unix systems'
|
||||
redirect(URL(request.application,'default','site'))
|
||||
|
||||
forever=10**8
|
||||
|
||||
def kill():
|
||||
p = cache.ram('gae_upload',lambda:None,forever)
|
||||
if not p or p.poll()!=None:
|
||||
return 'oops'
|
||||
os.kill(p.pid, signal.SIGKILL)
|
||||
cache.ram('gae_upload',lambda:None,-1)
|
||||
|
||||
class EXISTS(object):
|
||||
def __init__(self, error_message='file not found'):
|
||||
self.error_message = error_message
|
||||
def __call__(self, value):
|
||||
if os.path.exists(value):
|
||||
return (value,None)
|
||||
return (value,self.error_message)
|
||||
|
||||
def deploy():
|
||||
regex = re.compile('^\w+$')
|
||||
apps = sorted(file for file in os.listdir(apath(r=request)) if regex.match(file))
|
||||
form = SQLFORM.factory(
|
||||
Field('appcfg',default=GAE_APPCFG,label='Path to appcfg.py',
|
||||
requires=EXISTS(error_message=T('file not found'))),
|
||||
Field('google_application_id',requires=IS_ALPHANUMERIC()),
|
||||
Field('applications','list:string',
|
||||
requires=IS_IN_SET(apps,multiple=True),
|
||||
label=T('web2py apps to deploy')),
|
||||
Field('email',requires=IS_EMAIL(),label=T('GAE Email')),
|
||||
Field('password','password',requires=IS_NOT_EMPTY(),label=T('GAE Password')))
|
||||
cmd = output = errors= ""
|
||||
if form.accepts(request,session):
|
||||
try:
|
||||
kill()
|
||||
except:
|
||||
pass
|
||||
ignore_apps = [item for item in apps \
|
||||
if not item in form.vars.applications]
|
||||
regex = re.compile('\(applications/\(.*')
|
||||
yaml = apath('../app.yaml', r=request)
|
||||
if not os.path.exists(yaml):
|
||||
example = apath('../app.example.yaml', r=request)
|
||||
shutil.copyfile(example,yaml)
|
||||
data = read_file(yaml)
|
||||
data = re.sub('application:.*','application: %s' % form.vars.google_application_id,data)
|
||||
data = regex.sub('(applications/(%s)/.*)|' % '|'.join(ignore_apps),data)
|
||||
write_file(yaml, data)
|
||||
|
||||
path = request.env.applications_parent
|
||||
cmd = '%s --email=%s --passin update %s' % \
|
||||
(form.vars.appcfg, form.vars.email, path)
|
||||
p = cache.ram('gae_upload',
|
||||
lambda s=subprocess,c=cmd:s.Popen(c, shell=True,
|
||||
stdin=s.PIPE,
|
||||
stdout=s.PIPE,
|
||||
stderr=s.PIPE, close_fds=True),-1)
|
||||
p.stdin.write(form.vars.password+'\n')
|
||||
fcntl.fcntl(p.stdout.fileno(), fcntl.F_SETFL, os.O_NONBLOCK)
|
||||
fcntl.fcntl(p.stderr.fileno(), fcntl.F_SETFL, os.O_NONBLOCK)
|
||||
return dict(form=form,command=cmd)
|
||||
|
||||
def callback():
|
||||
p = cache.ram('gae_upload',lambda:None,forever)
|
||||
if not p or p.poll()!=None:
|
||||
return '<done/>'
|
||||
try:
|
||||
output = p.stdout.read()
|
||||
except:
|
||||
output=''
|
||||
try:
|
||||
errors = p.stderr.read()
|
||||
except:
|
||||
errors=''
|
||||
return (output+errors).replace('\n','<br/>')
|
||||
@@ -0,0 +1,82 @@
|
||||
from gluon.fileutils import read_file, write_file
|
||||
|
||||
if DEMO_MODE or MULTI_USER_MODE:
|
||||
session.flash = T('disabled in demo mode')
|
||||
redirect(URL('default','site'))
|
||||
if not have_mercurial:
|
||||
session.flash=T("Sorry, could not find mercurial installed")
|
||||
redirect(URL('default','design',args=request.args(0)))
|
||||
|
||||
_hgignore_content = """\
|
||||
syntax: glob
|
||||
*~
|
||||
*.pyc
|
||||
*.pyo
|
||||
*.bak
|
||||
*.bak2
|
||||
cache/*
|
||||
private/*
|
||||
uploads/*
|
||||
databases/*
|
||||
sessions/*
|
||||
errors/*
|
||||
"""
|
||||
|
||||
def hg_repo(path):
|
||||
import os
|
||||
uio = ui.ui()
|
||||
uio.quiet = True
|
||||
if not os.environ.get('HGUSER') and not uio.config("ui", "username"):
|
||||
os.environ['HGUSER'] = 'web2py@localhost'
|
||||
try:
|
||||
repo = hg.repository(ui=uio, path=path)
|
||||
except:
|
||||
repo = hg.repository(ui=uio, path=path, create=True)
|
||||
hgignore = os.path.join(path, '.hgignore')
|
||||
if not os.path.exists(hgignore):
|
||||
write_file(hgignore, _hgignore_content)
|
||||
return repo
|
||||
|
||||
def commit():
|
||||
app = request.args(0)
|
||||
path = apath(app, r=request)
|
||||
repo = hg_repo(path)
|
||||
form = FORM('Comment:',INPUT(_name='comment',requires=IS_NOT_EMPTY()),
|
||||
INPUT(_type='submit',_value='Commit'))
|
||||
if form.accepts(request.vars,session):
|
||||
oldid = repo[repo.lookup('.')]
|
||||
cmdutil.addremove(repo)
|
||||
repo.commit(text=form.vars.comment)
|
||||
if repo[repo.lookup('.')] == oldid:
|
||||
response.flash = 'no changes'
|
||||
try:
|
||||
files = TABLE(*[TR(file) for file in repo[repo.lookup('.')].files()])
|
||||
changes = TABLE(TR(TH('revision'),TH('description')))
|
||||
for change in repo.changelog:
|
||||
ctx=repo.changectx(change)
|
||||
revision, description = ctx.rev(), ctx.description()
|
||||
changes.append(TR(A(revision,_href=URL('revision',
|
||||
args=(app,revision))),
|
||||
description))
|
||||
except:
|
||||
files = []
|
||||
changes = []
|
||||
return dict(form=form,files=files,changes=changes,repo=repo)
|
||||
|
||||
def revision():
|
||||
app = request.args(0)
|
||||
path = apath(app, r=request)
|
||||
repo = hg_repo(path)
|
||||
revision = request.args(1)
|
||||
ctx=repo.changectx(revision)
|
||||
form=FORM(INPUT(_type='submit',_value='revert'))
|
||||
if form.accepts(request.vars):
|
||||
hg.update(repo, revision)
|
||||
session.flash = "reverted to revision %s" % ctx.rev()
|
||||
redirect(URL('default','design',args=app))
|
||||
return dict(
|
||||
files=ctx.files(),
|
||||
rev=str(ctx.rev()),
|
||||
desc=ctx.description(),
|
||||
form=form
|
||||
)
|
||||
@@ -0,0 +1,45 @@
|
||||
import sys
|
||||
import cStringIO
|
||||
import gluon.contrib.shell
|
||||
import code, thread
|
||||
from gluon.shell import env
|
||||
|
||||
if DEMO_MODE or MULTI_USER_MODE:
|
||||
session.flash = T('disabled in demo mode')
|
||||
redirect(URL('default','site'))
|
||||
|
||||
FE=10**9
|
||||
|
||||
def index():
|
||||
app = request.args(0) or 'admin'
|
||||
reset()
|
||||
return dict(app=app)
|
||||
|
||||
def callback():
|
||||
app = request.args[0]
|
||||
command = request.vars.statement
|
||||
escape = command[:1]!='!'
|
||||
history = session['history:'+app] = session.get('history:'+app,gluon.contrib.shell.History())
|
||||
if not escape:
|
||||
command = command[1:]
|
||||
if command == '%reset':
|
||||
reset()
|
||||
return '*** reset ***'
|
||||
elif command[0] == '%':
|
||||
try:
|
||||
command=session['commands:'+app][int(command[1:])]
|
||||
except ValueError:
|
||||
return ''
|
||||
session['commands:'+app].append(command)
|
||||
environ=env(app,True)
|
||||
output = gluon.contrib.shell.run(history,command,environ)
|
||||
k = len(session['commands:'+app]) - 1
|
||||
#output = PRE(output)
|
||||
#return TABLE(TR('In[%i]:'%k,PRE(command)),TR('Out[%i]:'%k,output))
|
||||
return 'In [%i] : %s%s\n' % (k + 1, command, output)
|
||||
|
||||
def reset():
|
||||
app = request.args(0) or 'admin'
|
||||
session['commands:'+app] = []
|
||||
session['history:'+app] = gluon.contrib.shell.History()
|
||||
return 'done'
|
||||
@@ -0,0 +1,29 @@
|
||||
import os
|
||||
from gluon.settings import global_settings, read_file
|
||||
#
|
||||
|
||||
def index():
|
||||
app = request.args(0)
|
||||
return dict(app=app)
|
||||
|
||||
def profiler():
|
||||
"""
|
||||
to use the profiler start web2py with -F profiler.log
|
||||
"""
|
||||
KEY = 'web2py_profiler_size'
|
||||
filename = global_settings.cmd_options.profiler_filename
|
||||
data = 'profiler disabled'
|
||||
if filename:
|
||||
if KEY in request.cookies:
|
||||
size = int(request.cookies[KEY].value)
|
||||
else:
|
||||
size = 0
|
||||
if os.path.exists(filename):
|
||||
data = read_file('profiler.log','rb')
|
||||
if size<len(data):
|
||||
data = data[size:]
|
||||
else:
|
||||
size=0
|
||||
size += len(data)
|
||||
response.cookies[KEY] = size
|
||||
return data
|
||||
@@ -0,0 +1,551 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import os, uuid, re, pickle, urllib, glob
|
||||
from gluon.admin import app_create, plugin_install
|
||||
from gluon.fileutils import abspath, read_file, write_file
|
||||
|
||||
def reset(session):
|
||||
session.app={
|
||||
'name':'',
|
||||
'params':[('title','My New App'),
|
||||
('subtitle','powered by web2py'),
|
||||
('author','you'),
|
||||
('author_email','you@example.com'),
|
||||
('keywords',''),
|
||||
('description',''),
|
||||
('layout_theme','Default'),
|
||||
('database_uri','sqlite://storage.sqlite'),
|
||||
('security_key',str(uuid.uuid4())),
|
||||
('email_server','localhost'),
|
||||
('email_sender','you@example.com'),
|
||||
('email_login',''),
|
||||
('login_method','local'),
|
||||
('login_config',''),
|
||||
('plugins',[])],
|
||||
'tables':['auth_user'],
|
||||
'table_auth_user':['username','first_name',
|
||||
'last_name','email','password'],
|
||||
'pages':['index','error'],
|
||||
'page_index':'# Welcome to my new app',
|
||||
'page_error':'# Error: the document does not exist',
|
||||
}
|
||||
|
||||
if not session.app: reset(session)
|
||||
|
||||
def listify(x):
|
||||
if not isinstance(x,(list,tuple)):
|
||||
return x and [x] or []
|
||||
return x
|
||||
|
||||
def clean(name):
|
||||
return re.sub('\W+','_',name.strip().lower())
|
||||
|
||||
def index():
|
||||
response.view='wizard/step.html'
|
||||
reset(session)
|
||||
apps=os.listdir(os.path.join(request.folder,'..'))
|
||||
form=SQLFORM.factory(Field('name',requires=[IS_NOT_EMPTY(),
|
||||
IS_ALPHANUMERIC()]))
|
||||
if form.accepts(request.vars):
|
||||
app = form.vars.name
|
||||
session.app['name'] = app
|
||||
if MULTI_USER_MODE and db(db.app.name==app)\
|
||||
(db.app.owner!=auth.user.id).count():
|
||||
session.flash = 'App belongs already to other user'
|
||||
elif app in apps:
|
||||
meta = os.path.normpath(\
|
||||
os.path.join(os.path.normpath(request.folder),
|
||||
'..',app,'wizard.metadata'))
|
||||
if os.path.exists(meta):
|
||||
try:
|
||||
metafile = open(meta,'rb')
|
||||
try:
|
||||
session.app = pickle.load(metafile)
|
||||
finally:
|
||||
metafile.close()
|
||||
session.flash = T("The app exists, was created by wizard, continue to overwrite!")
|
||||
except:
|
||||
session.flash = T("The app exists, was NOT created by wizard, continue to overwrite!")
|
||||
redirect(URL('step1'))
|
||||
return dict(step='Start',form=form)
|
||||
|
||||
|
||||
def step1():
|
||||
from gluon.contrib.simplejson import loads
|
||||
import urllib
|
||||
if not session.themes:
|
||||
url=LAYOUTS_APP+'/default/layouts.json'
|
||||
try:
|
||||
data = urllib.urlopen(url).read()
|
||||
session.themes = ['Default'] + loads(data)['layouts']
|
||||
except:
|
||||
session.themes = ['Default']
|
||||
themes = session.themes
|
||||
if not session.plugins:
|
||||
url = PLUGINS_APP+'/default/plugins.json'
|
||||
try:
|
||||
data = urllib.urlopen(url).read()
|
||||
session.plugins = loads(data)['plugins']
|
||||
except:
|
||||
session.plugins = []
|
||||
plugins = [x.split('.')[2] for x in session.plugins]
|
||||
response.view='wizard/step.html'
|
||||
params = dict(session.app['params'])
|
||||
form=SQLFORM.factory(
|
||||
Field('title',default=params.get('title',None),
|
||||
requires=IS_NOT_EMPTY()),
|
||||
Field('subtitle',default=params.get('subtitle',None)),
|
||||
Field('author',default=params.get('author',None)),
|
||||
Field('author_email',default=params.get('author_email',None)),
|
||||
Field('keywords',default=params.get('keywords',None)),
|
||||
Field('description','text',
|
||||
default=params.get('description',None)),
|
||||
Field('layout_theme',requires=IS_IN_SET(themes),
|
||||
default=params.get('layout_theme',themes[0])),
|
||||
Field('database_uri',default=params.get('database_uri',None)),
|
||||
Field('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('login_method',requires=IS_IN_SET(('local','janrain')),
|
||||
default=params.get('login_method','local')),
|
||||
Field('login_config',default=params.get('login_config',None)),
|
||||
Field('plugins','list:string',requires=IS_IN_SET(plugins,multiple=True)))
|
||||
|
||||
if form.accepts(request.vars):
|
||||
session.app['params']=[(key,form.vars.get(key,None))
|
||||
for key,value in session.app['params']]
|
||||
redirect(URL('step2'))
|
||||
return dict(step='1: Setting Parameters',form=form)
|
||||
|
||||
def step2():
|
||||
response.view='wizard/step.html'
|
||||
form=SQLFORM.factory(Field('table_names','list:string',
|
||||
default=session.app['tables']))
|
||||
if form.accepts(request.vars):
|
||||
table_names = [clean(t) for t in listify(form.vars.table_names) \
|
||||
if t.strip()]
|
||||
if [t for t in table_names if t.startswith('auth_') and \
|
||||
not t=='auth_user']:
|
||||
form.error.table_names = \
|
||||
T('invalid table names (auth_* tables already defined)')
|
||||
else:
|
||||
session.app['tables']=table_names
|
||||
for table in session.app['tables']:
|
||||
if not 'table_'+table in session.app:
|
||||
session.app['table_'+table]=['name']
|
||||
if not table=='auth_user':
|
||||
name = table+'_manage'
|
||||
if not name in session.app['pages']:
|
||||
session.app['pages'].append(name)
|
||||
session.app['page_'+name] = \
|
||||
'## Manage %s\n{{=form}}' % (table)
|
||||
if session.app['tables']:
|
||||
redirect(URL('step3',args=0))
|
||||
else:
|
||||
redirect(URL('step4'))
|
||||
return dict(step='2: Tables',form=form)
|
||||
|
||||
def step3():
|
||||
response.view='wizard/step.html'
|
||||
n=int(request.args(0) or 0)
|
||||
m=len(session.app['tables'])
|
||||
if n>=m: redirect(URL('step2'))
|
||||
table=session.app['tables'][n]
|
||||
form=SQLFORM.factory(Field('field_names','list:string',
|
||||
default=session.app.get('table_'+table,[])))
|
||||
if form.accepts(request.vars) and form.vars.field_names:
|
||||
fields=listify(form.vars.field_names)
|
||||
if table=='auth_user':
|
||||
for field in ['first_name','last_name','username','email','password']:
|
||||
if not field in fields:
|
||||
fields.append(field)
|
||||
session.app['table_'+table]=[t.strip().lower()
|
||||
for t in listify(form.vars.field_names)
|
||||
if t.strip()]
|
||||
try:
|
||||
tables=sort_tables(session.app['tables'])
|
||||
except RuntimeError:
|
||||
response.flash=T('invalid circual reference')
|
||||
else:
|
||||
if n<m-1:
|
||||
redirect(URL('step3',args=n+1))
|
||||
else:
|
||||
redirect(URL('step4'))
|
||||
return dict(step='3: Fields for table "%s" (%s of %s)' \
|
||||
% (table,n+1,m),table=table,form=form)
|
||||
|
||||
def step4():
|
||||
response.view='wizard/step.html'
|
||||
form=SQLFORM.factory(Field('pages','list:string',
|
||||
default=session.app['pages']))
|
||||
if form.accepts(request.vars):
|
||||
session.app['pages']=[clean(t)
|
||||
for t in listify(form.vars.pages)
|
||||
if t.strip()]
|
||||
if session.app['pages']:
|
||||
redirect(URL('step5',args=0))
|
||||
else:
|
||||
redirect(URL('step6'))
|
||||
return dict(step='4: Pages',form=form)
|
||||
|
||||
def step5():
|
||||
response.view='wizard/step.html'
|
||||
n=int(request.args(0) or 0)
|
||||
m=len(session.app['pages'])
|
||||
if n>=m: redirect(URL('step4'))
|
||||
page=session.app['pages'][n]
|
||||
markmin_url='http://web2py.com/examples/static/markmin.html'
|
||||
form=SQLFORM.factory(Field('content','text',
|
||||
default=session.app.get('page_'+page,[]),
|
||||
comment=A('use markmin',
|
||||
_href=markmin_url,_target='_blank')),
|
||||
formstyle='table2cols')
|
||||
if form.accepts(request.vars):
|
||||
session.app['page_'+page]=form.vars.content
|
||||
if n<m-1:
|
||||
redirect(URL('step5',args=n+1))
|
||||
else:
|
||||
redirect(URL('step6'))
|
||||
return dict(step='5: View for page "%s" (%s of %s)' % (page,n+1,m),form=form)
|
||||
|
||||
def step6():
|
||||
response.view='wizard/step.html'
|
||||
params = dict(session.app['params'])
|
||||
app = session.app['name']
|
||||
form=SQLFORM.factory(
|
||||
Field('generate_model','boolean',default=True),
|
||||
Field('generate_controller','boolean',default=True),
|
||||
Field('generate_views','boolean',default=True),
|
||||
Field('generate_menu','boolean',default=True),
|
||||
Field('apply_layout','boolean',default=True),
|
||||
Field('erase_database','boolean',default=True),
|
||||
Field('populate_database','boolean',default=True))
|
||||
if form.accepts(request.vars):
|
||||
if DEMO_MODE:
|
||||
session.flash = T('Application cannot be generated in demo mode')
|
||||
redirect(URL('index'))
|
||||
create(form.vars)
|
||||
session.flash = 'Application %s created' % app
|
||||
redirect(URL('generated'))
|
||||
return dict(step='6: Generate app "%s"' % app,form=form)
|
||||
|
||||
def generated():
|
||||
return dict(app=session.app['name'])
|
||||
|
||||
def sort_tables(tables):
|
||||
import re
|
||||
regex = re.compile('(%s)' % '|'.join(tables))
|
||||
is_auth_user = 'auth_user' in tables
|
||||
d={}
|
||||
for table in tables:
|
||||
d[table]=[]
|
||||
for field in session.app['table_%s' % table]:
|
||||
d[table]+=regex.findall(field)
|
||||
tables=[]
|
||||
if is_auth_user:
|
||||
tables.append('auth_user')
|
||||
def append(table,trail=[]):
|
||||
if table in trail:
|
||||
raise RuntimeError
|
||||
for t in d[table]: append(t,trail=trail+[table])
|
||||
if not table in tables: tables.append(table)
|
||||
for table in d: append(table)
|
||||
return tables
|
||||
|
||||
def make_table(table,fields):
|
||||
rawtable=table
|
||||
if table!='auth_user': table='t_'+table
|
||||
s=''
|
||||
s+='\n'+'#'*40+'\n'
|
||||
s+="db.define_table('%s',\n" % table
|
||||
first_field='id'
|
||||
for field in fields:
|
||||
items=[x.lower() for x in field.split()]
|
||||
has = {}
|
||||
keys = []
|
||||
for key in ['notnull','unique','integer','double','boolean','float',
|
||||
'boolean', 'date','time','datetime','text','wiki',
|
||||
'html','file','upload','image','true',
|
||||
'hidden','readonly','writeonly','multiple',
|
||||
'notempty','required']:
|
||||
if key in items[1:]:
|
||||
keys.append(key)
|
||||
has[key] = True
|
||||
tables = session.app['tables']
|
||||
refs = [t for t in tables if t in items]
|
||||
items = items[:1] + [x for x in items[1:] \
|
||||
if not x in keys and not x in tables]
|
||||
barename = name = '_'.join(items)
|
||||
if table[:2]=='t_': name='f_'+name
|
||||
if first_field=='id': first_field=name
|
||||
|
||||
### determine field type
|
||||
ftype='string'
|
||||
deftypes={'integer':'integer','double':'double','boolean':'boolean',
|
||||
'float':'double','bool':'boolean',
|
||||
'date':'date','time':'time','datetime':'datetime',
|
||||
'text':'text','file':'upload','image':'upload',
|
||||
'upload':'upload','wiki':'text', 'html':'text'}
|
||||
for key,t in deftypes.items():
|
||||
if key in has:
|
||||
ftype = t
|
||||
if refs:
|
||||
key = refs[0]
|
||||
if not key=='auth_user': key='t_'+key
|
||||
if 'multiple' in has:
|
||||
ftype='list:reference %s' % key
|
||||
else:
|
||||
ftype='reference %s' % key
|
||||
if ftype=='string' and 'multiple' in has:
|
||||
ftype='list:string'
|
||||
elif ftype=='integer' and 'multiple' in has:
|
||||
ftype='list:integer'
|
||||
elif name=='password':
|
||||
ftype='password'
|
||||
s+=" Field('%s', type='%s'" % (name, ftype)
|
||||
|
||||
### determine field attributes
|
||||
if 'notnull' in has or 'notempty' in has or 'required' in has:
|
||||
s+=', notnull=True'
|
||||
if 'unique' in has:
|
||||
s+=', unique=True'
|
||||
if ftype=='boolean' and 'true' in has:
|
||||
s+=",\n default=True"
|
||||
|
||||
### determine field representation
|
||||
elif 'wiki' in has:
|
||||
s+=",\n represent=lambda x, row: MARKMIN(x)"
|
||||
s+=",\n comment='WIKI (markmin)'"
|
||||
elif 'html' in has:
|
||||
s+=",\n represent=lambda x, row: XML(x,sanitize=True)"
|
||||
s+=",\n comment='HTML (sanitized)'"
|
||||
### determine field access
|
||||
if name=='password' or 'writeonly' in has:
|
||||
s+=",\n readable=False"
|
||||
elif 'hidden' in has:
|
||||
s+=",\n writable=False, readable=False"
|
||||
elif 'readonly' in has:
|
||||
s+=",\n writable=False"
|
||||
|
||||
### make up a label
|
||||
s+=",\n label=T('%s')),\n" % \
|
||||
' '.join(x.capitalize() for x in barename.split('_'))
|
||||
if table=='auth_user':
|
||||
s+=" Field('created_on','datetime',default=request.now,\n"
|
||||
s+=" label=T('Created On'),writable=False,readable=False),\n"
|
||||
s+=" Field('modified_on','datetime',default=request.now,\n"
|
||||
s+=" label=T('Modified On'),writable=False,readable=False,\n"
|
||||
s+=" update=request.now),\n"
|
||||
s+=" Field('registration_key',default='',\n"
|
||||
s+=" writable=False,readable=False),\n"
|
||||
s+=" Field('reset_password_key',default='',\n"
|
||||
s+=" writable=False,readable=False),\n"
|
||||
s+=" Field('registration_id',default='',\n"
|
||||
s+=" writable=False,readable=False),\n"
|
||||
elif 'auth_user' in session.app['tables']:
|
||||
s+=" auth.signature,\n"
|
||||
s+=" format='%("+first_field+")s',\n"
|
||||
s+=" migrate=settings.migrate)\n\n"
|
||||
if table=='auth_user':
|
||||
s+="""
|
||||
db.auth_user.first_name.requires = IS_NOT_EMPTY(error_message=auth.messages.is_empty)
|
||||
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)
|
||||
db.auth_user.username.requires = IS_NOT_IN_DB(db, db.auth_user.username)
|
||||
db.auth_user.registration_id.requires = IS_NOT_IN_DB(db, db.auth_user.registration_id)
|
||||
db.auth_user.email.requires = (IS_EMAIL(error_message=auth.messages.invalid_email),
|
||||
IS_NOT_IN_DB(db, db.auth_user.email))
|
||||
"""
|
||||
else:
|
||||
s+="db.define_table('%s_archive',db.%s,Field('current_record','reference %s',readable=False,writable=False))\n" % (table,table,table)
|
||||
return s
|
||||
|
||||
def fix_db(filename):
|
||||
params = dict(session.app['params'])
|
||||
content = read_file(filename,'rb')
|
||||
if 'auth_user' in session.app['tables']:
|
||||
auth_user = make_table('auth_user',session.app['table_auth_user'])
|
||||
content = content.replace('sqlite://storage.sqlite',
|
||||
params['database_uri'])
|
||||
content = content.replace('auth.define_tables()',\
|
||||
auth_user+'auth.define_tables(migrate = settings.migrate)')
|
||||
content += """
|
||||
mail.settings.server = settings.email_server
|
||||
mail.settings.sender = settings.email_sender
|
||||
mail.settings.login = settings.email_login
|
||||
"""
|
||||
if params['login_method']=='janrain':
|
||||
content+="""
|
||||
from gluon.contrib.login_methods.rpx_account import RPXAccount
|
||||
auth.settings.actions_disabled=['register','change_password','request_reset_password']
|
||||
auth.settings.login_form = RPXAccount(request,
|
||||
api_key = settings.login_config.split(':')[-1],
|
||||
domain = settings.login_config.split(':')[0],
|
||||
url = "http://%s/%s/default/user/login" % (request.env.http_host,request.application))
|
||||
"""
|
||||
write_file(filename, content, 'wb')
|
||||
|
||||
def make_menu(pages):
|
||||
s=''
|
||||
s+='response.title = settings.title\n'
|
||||
s+='response.subtitle = settings.subtitle\n'
|
||||
s+="response.meta.author = '%(author)s <%(author_email)s>' % settings\n"
|
||||
s+='response.meta.keywords = settings.keywords\n'
|
||||
s+='response.meta.description = settings.description\n'
|
||||
s+='response.menu = [\n'
|
||||
for page in pages:
|
||||
if not page.startswith('error'):
|
||||
if page.endswith('_manage'):
|
||||
page_name = page[:-7]
|
||||
else:
|
||||
page_name = page
|
||||
page_name = ' '.join(x.capitalize() for x in page_name.split('_'))
|
||||
s+="(T('%s'),URL('default','%s')==URL(),URL('default','%s'),[]),\n" \
|
||||
% (page_name,page,page)
|
||||
s+=']'
|
||||
return s
|
||||
|
||||
def make_page(page,contents):
|
||||
if 'auth_user' in session.app['tables'] and not page in ('index','error'):
|
||||
s="@auth.requires_login()\ndef %s():\n" % page
|
||||
else:
|
||||
s="def %s():\n" % page
|
||||
items = page.rsplit('_',1)
|
||||
if items[0] in session.app['tables'] and len(items)==2 and items[1]=='manage':
|
||||
s+=" form = SQLFORM.smartgrid(db.t_%s,onupdate=auth.archive)\n" % items[0]
|
||||
s+=" return locals()\n\n"
|
||||
else:
|
||||
s+=" return dict()\n\n"
|
||||
return s
|
||||
|
||||
def make_view(page,contents):
|
||||
s="{{extend 'layout.html'}}\n\n"
|
||||
s+=str(MARKMIN(contents))
|
||||
return s
|
||||
|
||||
def populate(tables):
|
||||
s = 'from gluon.contrib.populate import populate\n'
|
||||
s+= 'if db(db.auth_user).isempty():\n'
|
||||
for table in sort_tables(tables):
|
||||
t=table=='auth_user' and 'auth_user' or 't_'+table
|
||||
s+=" populate(db.%s,10)\n" % t
|
||||
return s
|
||||
|
||||
def create(options):
|
||||
if DEMO_MODE:
|
||||
session.flash = T('disabled in demo mode')
|
||||
redirect(URL('step6'))
|
||||
params = dict(session.app['params'])
|
||||
app = session.app['name']
|
||||
if not app_create(app,request,force=True,key=params['security_key']):
|
||||
session.flash = 'Failure to create application'
|
||||
redirect(URL('step6'))
|
||||
|
||||
### save metadata in newapp/wizard.metadata
|
||||
try:
|
||||
meta = os.path.join(request.folder,'..',app,'wizard.metadata')
|
||||
file=open(meta,'wb')
|
||||
pickle.dump(session.app,file)
|
||||
file.close()
|
||||
except IOError:
|
||||
session.flash = 'Failure to write wizard metadata'
|
||||
redirect(URL('step6'))
|
||||
|
||||
### apply theme
|
||||
if options.apply_layout and params['layout_theme']!='Default':
|
||||
try:
|
||||
fn = 'web2py.plugin.layout_%s.w2p' % params['layout_theme']
|
||||
theme = urllib.urlopen(LAYOUTS_APP+'/static/plugin_layouts/plugins/'+fn)
|
||||
plugin_install(app, theme, request, fn)
|
||||
except:
|
||||
session.flash = T("unable to download layout")
|
||||
|
||||
### apply plugins
|
||||
for plugin in params['plugins']:
|
||||
try:
|
||||
plugin_name = 'web2py.plugin.'+plugin+'.w2p'
|
||||
stream = urllib.urlopen(PLUGINS_APP+'/static/'+plugin_name)
|
||||
plugin_install(app, stream, request, plugin_name)
|
||||
except Exception, e:
|
||||
session.flash = T("unable to download plugin: %s" % plugin)
|
||||
|
||||
### write configuration file into newapp/models/0.py
|
||||
model = os.path.join(request.folder,'..',app,'models','0.py')
|
||||
file = open(model, 'wb')
|
||||
try:
|
||||
file.write("from gluon.storage import Storage\n")
|
||||
file.write("settings = Storage()\n\n")
|
||||
file.write("settings.migrate = True\n")
|
||||
for key,value in session.app['params']:
|
||||
file.write("settings.%s = %s\n" % (key,repr(value)))
|
||||
finally:
|
||||
file.close()
|
||||
|
||||
### write configuration file into newapp/models/menu.py
|
||||
if options.generate_menu:
|
||||
model = os.path.join(request.folder,'..',app,'models','menu.py')
|
||||
file = open(model,'wb')
|
||||
try:
|
||||
file.write(make_menu(session.app['pages']))
|
||||
finally:
|
||||
file.close()
|
||||
|
||||
### customize the auth_user table
|
||||
model = os.path.join(request.folder,'..',app,'models','db.py')
|
||||
fix_db(model)
|
||||
|
||||
### create newapp/models/db_wizard.py
|
||||
if options.generate_model:
|
||||
model = os.path.join(request.folder,'..',app,'models','db_wizard.py')
|
||||
file = open(model,'wb')
|
||||
try:
|
||||
file.write('### we prepend t_ to tablenames and f_ to fieldnames for disambiguity\n\n')
|
||||
tables = sort_tables(session.app['tables'])
|
||||
for table in tables:
|
||||
if table=='auth_user': continue
|
||||
file.write(make_table(table,session.app['table_'+table]))
|
||||
finally:
|
||||
file.close()
|
||||
|
||||
model = os.path.join(request.folder,'..',app,
|
||||
'models','db_wizard_populate.py')
|
||||
if os.path.exists(model): os.unlink(model)
|
||||
if options.populate_database and session.app['tables']:
|
||||
file = open(model,'wb')
|
||||
try:
|
||||
file.write(populate(session.app['tables']))
|
||||
finally:
|
||||
file.close()
|
||||
|
||||
### create newapp/controllers/default.py
|
||||
if options.generate_controller:
|
||||
controller = os.path.join(request.folder,'..',app,'controllers','default.py')
|
||||
file = open(controller,'wb')
|
||||
try:
|
||||
file.write("""# -*- coding: utf-8 -*-
|
||||
### required - do no delete
|
||||
def user(): return dict(form=auth())
|
||||
def download(): return response.download(request,db)
|
||||
def call(): return service()
|
||||
### end requires
|
||||
""")
|
||||
for page in session.app['pages']:
|
||||
file.write(make_page(page,session.app.get('page_'+page,'')))
|
||||
finally:
|
||||
file.close()
|
||||
|
||||
### create newapp/views/default/*.html
|
||||
if options.generate_views:
|
||||
for page in session.app['pages']:
|
||||
view = os.path.join(request.folder,'..',app,'views','default',page+'.html')
|
||||
file = open(view,'wb')
|
||||
try:
|
||||
file.write(make_view(page,session.app.get('page_'+page,'')))
|
||||
finally:
|
||||
file.close()
|
||||
|
||||
if options.erase_database:
|
||||
path = os.path.join(request.folder,'..',app,'databases','*')
|
||||
for file in glob.glob(path):
|
||||
os.unlink(file)
|
||||
Reference in New Issue
Block a user