Compare commits
58 Commits
fix-missin
...
fake_migra
| Author | SHA1 | Date | |
|---|---|---|---|
| 179edb659a | |||
| b4c2ee8304 | |||
| cb0c2e6edd | |||
|
|
2c364c2079 | ||
|
|
8faa5e2a82 | ||
|
|
0557fe9c58 | ||
|
|
5945edebfd | ||
|
|
558afd886c | ||
|
|
1bc8ea6838 | ||
|
|
24d970a943 | ||
|
|
e66dda8641 | ||
|
|
320a28d564 | ||
|
|
9db1c6b0b0 | ||
|
|
f307fe7d56 | ||
|
|
f845497479 | ||
|
|
f1f65275f7 | ||
|
|
2989beae02 | ||
|
|
2a7b16d61f | ||
|
|
14c1b3e400 | ||
|
|
8823cde350 | ||
|
|
3e09add351 | ||
|
|
7385904f97 | ||
|
|
c82f0ba619 | ||
|
|
409a499dd0 | ||
|
|
9d52f5498e | ||
|
|
0fe9d0aa34 | ||
|
|
89a4da0594 | ||
|
|
f2e95d1bb6 | ||
|
|
273ebb9a70 | ||
|
|
1bfffc4f12 | ||
|
|
6d7900be82 | ||
|
|
dadf363122 | ||
|
|
ce25d8dc31 | ||
|
|
1c5b2d7fce | ||
|
|
9b831a64c0 | ||
|
|
e6e92b43c9 | ||
|
|
c02ee6a5c0 | ||
|
|
22f95677d9 | ||
|
|
4fd44ff682 | ||
|
|
da253f7ba8 | ||
|
|
a24926ad6f | ||
| c6837a9e73 | |||
|
|
bd892556e1 | ||
|
|
99d3d1d465 | ||
| b365d12a2e | |||
| 4455fa48c4 | |||
| 96534ccf30 | |||
|
|
7a225da44e | ||
|
|
3f15d1ceb8 | ||
|
|
9769314f01 | ||
|
|
b79b5951f8 | ||
|
|
7b9d2c87c2 | ||
|
|
c03c962778 | ||
|
|
ca7b676591 | ||
|
|
7a0e113a5f | ||
|
|
7e30be377d | ||
|
|
f9db6a8306 | ||
|
|
50878f33bd |
@@ -30,7 +30,7 @@ except:
|
||||
|
||||
if request.is_https:
|
||||
session.secure()
|
||||
elif (remote_addr not in hosts) and (remote_addr != "127.0.0.1") and \
|
||||
elif (remote_addr not in hosts) and (remote_addr != '127.0.0.1') and \
|
||||
(request.function != 'manage'):
|
||||
raise HTTP(200, T('appadmin is disabled because insecure channel'))
|
||||
|
||||
@@ -46,7 +46,7 @@ if request.function == 'manage':
|
||||
auth.table_permission()])
|
||||
manager_role = manager_action.get('role', None) if manager_action else None
|
||||
if not (gluon.fileutils.check_credentials(request) or auth.has_membership(manager_role)):
|
||||
raise HTTP(403, "Not authorized")
|
||||
raise HTTP(403, 'Not authorized')
|
||||
menu = False
|
||||
elif (request.application == 'admin' and not session.authorized) or \
|
||||
(request.application != 'admin' and not gluon.fileutils.check_credentials(request)):
|
||||
@@ -182,7 +182,7 @@ def select():
|
||||
db = get_database(request)
|
||||
dbname = request.args[0]
|
||||
try:
|
||||
is_imap = db._uri.startswith("imap://")
|
||||
is_imap = db._uri.startswith('imap://')
|
||||
except (KeyError, AttributeError, TypeError):
|
||||
is_imap = False
|
||||
regex = re.compile(r'(?P<table>\w+)\.(?P<field>\w+)=(?P<value>\d+)')
|
||||
@@ -224,15 +224,15 @@ def select():
|
||||
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 '', _class="form-control",
|
||||
_name='query', _value=request.vars.query or '', _class='form-control',
|
||||
requires=IS_NOT_EMPTY(
|
||||
error_message=T("Cannot be empty")))), TR(T('Update:'),
|
||||
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 '', _class="form-control")), TR(T('Delete:'), INPUT(_name='delete_check',
|
||||
or '', _class='form-control')), TR(T('Delete:'), INPUT(_name='delete_check',
|
||||
_class='delete', _type='checkbox', value=False), ''),
|
||||
TR('', '', INPUT(_type='submit', _value=T('submit'), _class="btn btn-primary"))),
|
||||
TR('', '', INPUT(_type='submit', _value=T('Submit'), _class='btn btn-primary'))),
|
||||
_action=URL(r=request, args=request.args))
|
||||
|
||||
tb = None
|
||||
@@ -254,8 +254,8 @@ def select():
|
||||
|
||||
if is_imap:
|
||||
fields = [db[table][name] for name in
|
||||
("id", "uid", "created", "to",
|
||||
"sender", "subject")]
|
||||
('id', 'uid', 'created', 'to',
|
||||
'sender', 'subject')]
|
||||
if orderby:
|
||||
rows = db(query, ignore_common_filters=True).select(
|
||||
*fields, limitby=(start, stop),
|
||||
@@ -271,10 +271,10 @@ def select():
|
||||
# begin handle upload csv
|
||||
csv_table = table or request.vars.table
|
||||
if csv_table:
|
||||
formcsv = FORM(str(T('or import from csv file')) + " ",
|
||||
formcsv = FORM(str(T('or import from csv file')) + ' ',
|
||||
INPUT(_type='file', _name='csvfile'),
|
||||
INPUT(_type='hidden', _value=csv_table, _name='table'),
|
||||
INPUT(_type='submit', _value=T('import'), _class="btn btn-primary"))
|
||||
INPUT(_type='submit', _value=T('import'), _class='btn btn-primary'))
|
||||
else:
|
||||
formcsv = None
|
||||
if formcsv and formcsv.process().accepted:
|
||||
@@ -356,26 +356,26 @@ def state():
|
||||
def ccache():
|
||||
if is_gae:
|
||||
form = FORM(
|
||||
P(TAG.BUTTON(T("Clear CACHE?"), _type="submit", _name="yes", _value="yes")))
|
||||
P(TAG.BUTTON(T('Clear CACHE?'), _type='submit', _name='yes', _value='yes')))
|
||||
else:
|
||||
cache.ram.initialize()
|
||||
cache.disk.initialize()
|
||||
|
||||
form = FORM(
|
||||
P(TAG.BUTTON(
|
||||
T("Clear CACHE?"), _type="submit", _name="yes", _value="yes")),
|
||||
T('Clear CACHE?'), _type='submit', _name='yes', _value='yes')),
|
||||
P(TAG.BUTTON(
|
||||
T("Clear RAM"), _type="submit", _name="ram", _value="ram")),
|
||||
T('Clear RAM'), _type='submit', _name='ram', _value='ram')),
|
||||
P(TAG.BUTTON(
|
||||
T("Clear DISK"), _type="submit", _name="disk", _value="disk")),
|
||||
T('Clear DISK'), _type='submit', _name='disk', _value='disk')),
|
||||
)
|
||||
|
||||
if form.accepts(request.vars, session):
|
||||
session.flash = ""
|
||||
session.flash = ''
|
||||
if is_gae:
|
||||
if request.vars.yes:
|
||||
cache.ram.clear()
|
||||
session.flash += T("Cache Cleared")
|
||||
session.flash += T('Cache Cleared')
|
||||
else:
|
||||
clear_ram = False
|
||||
clear_disk = False
|
||||
@@ -387,10 +387,10 @@ def ccache():
|
||||
clear_disk = True
|
||||
if clear_ram:
|
||||
cache.ram.clear()
|
||||
session.flash += T("Ram Cleared")
|
||||
session.flash += T('Ram Cleared')
|
||||
if clear_disk:
|
||||
cache.disk.clear()
|
||||
session.flash += T("Disk Cleared")
|
||||
session.flash += T('Disk Cleared')
|
||||
redirect(URL(r=request))
|
||||
|
||||
try:
|
||||
@@ -436,7 +436,7 @@ def ccache():
|
||||
gae_stats['ratio'] = ((gae_stats['hits'] * 100) /
|
||||
(gae_stats['hits'] + gae_stats['misses']))
|
||||
except ZeroDivisionError:
|
||||
gae_stats['ratio'] = T("?")
|
||||
gae_stats['ratio'] = T('?')
|
||||
gae_stats['oldest'] = GetInHMS(time.time() - gae_stats['oldest_item_age'])
|
||||
total.update(gae_stats)
|
||||
else:
|
||||
@@ -502,7 +502,7 @@ def ccache():
|
||||
TR(TD(B(T('Key'))), TD(B(T('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;"))
|
||||
_style='border-collapse: separate; border-spacing: .5em;'))
|
||||
|
||||
if not is_gae:
|
||||
ram['keys'] = key_table(ram['keys'])
|
||||
@@ -536,26 +536,26 @@ def table_template(table):
|
||||
# This is horribe HTML but the only one graphiz understands
|
||||
rows = []
|
||||
cellpadding = 4
|
||||
color = "#000000"
|
||||
bgcolor = "#FFFFFF"
|
||||
face = "Helvetica"
|
||||
face_bold = "Helvetica Bold"
|
||||
color = '#000000'
|
||||
bgcolor = '#FFFFFF'
|
||||
face = 'Helvetica'
|
||||
face_bold = 'Helvetica Bold'
|
||||
border = 0
|
||||
|
||||
rows.append(TR(TD(FONT(table, _face=face_bold, _color=bgcolor),
|
||||
_colspan=3, _cellpadding=cellpadding,
|
||||
_align="center", _bgcolor=color)))
|
||||
_align='center', _bgcolor=color)))
|
||||
for row in db[table]:
|
||||
rows.append(TR(TD(FONT(row.name, _color=color, _face=face_bold),
|
||||
_align="left", _cellpadding=cellpadding,
|
||||
_align='left', _cellpadding=cellpadding,
|
||||
_border=border),
|
||||
TD(FONT(row.type, _color=color, _face=face),
|
||||
_align="left", _cellpadding=cellpadding,
|
||||
_align='left', _cellpadding=cellpadding,
|
||||
_border=border),
|
||||
TD(FONT(types(row), _color=color, _face=face),
|
||||
_align="center", _cellpadding=cellpadding,
|
||||
_align='center', _cellpadding=cellpadding,
|
||||
_border=border)))
|
||||
return "< %s >" % TABLE(*rows, **dict(_bgcolor=bgcolor, _border=1,
|
||||
return '< %s >' % TABLE(*rows, **dict(_bgcolor=bgcolor, _border=1,
|
||||
_cellborder=0, _cellspacing=0)
|
||||
).xml()
|
||||
|
||||
@@ -632,15 +632,15 @@ def hooks():
|
||||
if len(functions):
|
||||
method_hooks.append({'name': op, 'functions':functions})
|
||||
if len(method_hooks):
|
||||
tables.append({'name': "%s.%s" % (db_str, t), 'slug': IS_SLUG()("%s.%s" % (db_str,t))[0], 'method_hooks':method_hooks})
|
||||
tables.append({'name': '%s.%s' % (db_str, t), 'slug': IS_SLUG()('%s.%s' % (db_str,t))[0], 'method_hooks':method_hooks})
|
||||
# Render
|
||||
ul_main = UL(_class='nav nav-list')
|
||||
for t in tables:
|
||||
ul_main.append(A(t['name'], _onclick="collapse('a_%s')" % t['slug']))
|
||||
ul_t = UL(_class='nav nav-list', _id="a_%s" % t['slug'], _style='display:none')
|
||||
ul_t = UL(_class='nav nav-list', _id='a_%s' % t['slug'], _style='display:none')
|
||||
for op in t['method_hooks']:
|
||||
ul_t.append(LI(op['name']))
|
||||
ul_t.append(UL([LI(A(f['funcname'], _class="editor_filelink", _href=f['url']if 'url' in f else None, **{'_data-lineno':f['lineno']-1})) for f in op['functions']]))
|
||||
ul_t.append(UL([LI(A(f['funcname'], _class='editor_filelink', _href=f['url']if 'url' in f else None, **{'_data-lineno':f['lineno']-1})) for f in op['functions']]))
|
||||
ul_main.append(ul_t)
|
||||
return ul_main
|
||||
|
||||
@@ -650,11 +650,11 @@ def hooks():
|
||||
# ###########################################################
|
||||
|
||||
def d3_graph_model():
|
||||
""" See https://www.facebook.com/web2py/posts/145613995589010 from Bruno Rocha
|
||||
''' See https://www.facebook.com/web2py/posts/145613995589010 from Bruno Rocha
|
||||
and also the app_admin bg_graph_model function
|
||||
|
||||
Create a list of table dicts, called "nodes"
|
||||
"""
|
||||
Create a list of table dicts, called 'nodes'
|
||||
'''
|
||||
|
||||
nodes = []
|
||||
links = []
|
||||
@@ -670,10 +670,10 @@ def d3_graph_model():
|
||||
elif f_type == 'string':
|
||||
disp = field.length
|
||||
elif f_type == 'id':
|
||||
disp = "PK"
|
||||
disp = 'PK'
|
||||
elif f_type.startswith('reference') or \
|
||||
f_type.startswith('list:reference'):
|
||||
disp = "FK"
|
||||
disp = 'FK'
|
||||
else:
|
||||
disp = ' '
|
||||
fields.append(dict(name=field.name, type=field.type, disp=disp))
|
||||
@@ -685,7 +685,7 @@ def d3_graph_model():
|
||||
|
||||
links.append(dict(source=tablename, target = referenced_table))
|
||||
|
||||
nodes.append(dict(name=tablename, type="table", fields = fields))
|
||||
nodes.append(dict(name=tablename, type='table', fields = fields))
|
||||
|
||||
# d3 v4 allows individual modules to be specified. The complete d3 library is included below.
|
||||
response.files.append(URL('admin','static','js/d3.min.js'))
|
||||
|
||||
0
applications/admin/languages/af.py
Executable file → Normal file
0
applications/admin/languages/bg.py
Executable file → Normal file
0
applications/admin/languages/cs.py
Executable file → Normal file
0
applications/admin/languages/en.py
Executable file → Normal file
0
applications/admin/languages/es.py
Executable file → Normal file
0
applications/admin/languages/fr.py
Executable file → Normal file
0
applications/admin/languages/he.py
Executable file → Normal file
0
applications/admin/languages/it.py
Executable file → Normal file
0
applications/admin/languages/ja.py
Executable file → Normal file
0
applications/admin/languages/my-mm.py
Executable file → Normal file
0
applications/admin/languages/nl.py
Executable file → Normal file
0
applications/admin/languages/pl.py
Executable file → Normal file
0
applications/admin/languages/plural-en.py
Executable file → Normal file
0
applications/admin/languages/plural-ru.py
Executable file → Normal file
0
applications/admin/languages/plural-uk.py
Executable file → Normal file
0
applications/admin/languages/pt-br.py
Executable file → Normal file
0
applications/admin/languages/pt.py
Executable file → Normal file
0
applications/admin/languages/ro.py
Executable file → Normal file
0
applications/admin/languages/ru.py
Executable file → Normal file
0
applications/admin/languages/sl.py
Executable file → Normal file
0
applications/admin/languages/sr-cr.py
Executable file → Normal file
0
applications/admin/languages/sr-lt.py
Executable file → Normal file
0
applications/admin/languages/tr.py
Executable file → Normal file
0
applications/admin/languages/uk.py
Executable file → Normal file
0
applications/admin/languages/zh-tw.py
Executable file → Normal file
0
applications/admin/languages/zh.py
Executable file → Normal file
@@ -1,9 +1,12 @@
|
||||
[DEFAULT]
|
||||
|
||||
[editor]
|
||||
theme = web2py
|
||||
editor = default
|
||||
theme = twilight
|
||||
editor = sublime
|
||||
closetag = true
|
||||
tabwidth = 4
|
||||
highlightline = true
|
||||
linenumbers = true
|
||||
codefolding = false
|
||||
indentwithtabs = false
|
||||
|
||||
[editor_sessions]
|
||||
welcome = welcome/models/db.py,welcome/controllers/default.py,welcome/views/default/index.html
|
||||
|
||||
0
applications/admin/static/css/jqueryMultiSelect.css
Executable file → Normal file
0
applications/admin/static/js/jqueryMultiSelect.js
vendored
Executable file → Normal file
0
applications/admin/static/plugin_jqmobile/images/ajax-loader.png
Executable file → Normal file
|
Before Width: | Height: | Size: 366 B After Width: | Height: | Size: 366 B |
0
applications/admin/static/plugin_jqmobile/images/icons-18-black.png
Executable file → Normal file
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
0
applications/admin/static/plugin_jqmobile/images/icons-18-white.png
Executable file → Normal file
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
0
applications/admin/static/plugin_jqmobile/images/icons-36-black.png
Executable file → Normal file
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
0
applications/admin/static/plugin_jqmobile/images/icons-36-white.png
Executable file → Normal file
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.7 KiB |
0
applications/admin/static/plugin_multiselect/jquery.multi-select.js
Executable file → Normal file
0
applications/admin/static/plugin_multiselect/multi-select.css
Executable file → Normal file
0
applications/admin/static/plugin_multiselect/switch.png
Executable file → Normal file
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.0 KiB |
@@ -38,19 +38,19 @@ def file_upload_form(location):
|
||||
INPUT(_type="text",_name="filename",requires=IS_NOT_EMPTY()),
|
||||
INPUT(_type="hidden",_name="location",_value=location),
|
||||
INPUT(_type="hidden",_name="sender",_value=URL('design/'+app)),
|
||||
INPUT(_type="submit",_value=T("submit")),_action=URL('upload_file'))
|
||||
INPUT(_type="submit",_value=T("Submit")),_action=URL('upload_file'))
|
||||
return form
|
||||
def file_create_form(location):
|
||||
form=FORM(T("create file with filename:")," ",
|
||||
INPUT(_type="text",_name="filename",requires=IS_NOT_EMPTY()),
|
||||
INPUT(_type="hidden",_name="location",_value=location),
|
||||
INPUT(_type="hidden",_name="sender",_value=URL('design/'+app)),
|
||||
INPUT(_type="submit",_value=T("submit")),_action=URL('create_file'))
|
||||
INPUT(_type="submit",_value=T("Submit")),_action=URL('create_file'))
|
||||
return form
|
||||
def upload_plugin_form(app):
|
||||
form=FORM(T("upload plugin file:")," ",
|
||||
INPUT(_type="file",_name="pluginfile"),
|
||||
INPUT(_type="submit",_value=T("submit")))
|
||||
INPUT(_type="submit",_value=T("Submit")))
|
||||
return form
|
||||
def deletefile(arglist):
|
||||
return A_delete(SPAN(T('Delete')), _href=URL('delete',args=arglist,vars=dict(sender=request.function+'/'+app)))
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
return files
|
||||
}}
|
||||
{{themes = [f[:-4] for f in listfiles('admin', "static/codemirror/theme", regexp='.*\.css$' )]}}
|
||||
{{editors = ['default', 'vim', 'emacs']}}
|
||||
{{editors = ['default', 'vim', 'emacs', 'sublime']}}
|
||||
|
||||
<form id="editor_settings_form" class="form-horizontal" action="">
|
||||
<div class="control-group">
|
||||
@@ -27,7 +27,7 @@
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="tabwidth">{{=T('Tab width (# characters)')}}</label>
|
||||
<div class="controls">{{=SELECT(range(1,9, 1), value=editor_settings['tabwidth'], _name="tabwidth" )}}</div>
|
||||
<div class="controls">{{=SELECT(list(range(1,9, 1)), value=editor_settings['tabwidth'], _name="tabwidth" )}}</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="indentwithtabs">{{=T('Indent with tabs')}}</label>
|
||||
|
||||
@@ -24,7 +24,7 @@ def file_upload_form(location):
|
||||
INPUT(_type="hidden",_name="location",_value=location),
|
||||
INPUT(_type="hidden",_name="token",_value=session.token),
|
||||
INPUT(_type="hidden",_name="sender",_value=URL('design/'+app)),
|
||||
INPUT(_type="submit",_value=T("submit")),_action=URL('upload_file'))
|
||||
INPUT(_type="submit",_value=T("Submit")),_action=URL('upload_file'))
|
||||
return form
|
||||
def file_create_form(location):
|
||||
form=FORM(T("create file with filename:")," ",
|
||||
@@ -32,7 +32,7 @@ def file_create_form(location):
|
||||
INPUT(_type="hidden",_name="location",_value=location),
|
||||
INPUT(_type="hidden",_name="token",_value=session.token),
|
||||
INPUT(_type="hidden",_name="sender",_value=URL('design/'+app)),
|
||||
INPUT(_type="submit",_value=T("submit")),_action=URL('create_file'))
|
||||
INPUT(_type="submit",_value=T("Submit")),_action=URL('create_file'))
|
||||
return form
|
||||
def deletefile(arglist):
|
||||
return A(TAG[''](IMG(_src=URL('static', 'images/delete_icon.png')),
|
||||
|
||||
@@ -30,7 +30,7 @@ except:
|
||||
|
||||
if request.is_https:
|
||||
session.secure()
|
||||
elif (remote_addr not in hosts) and (remote_addr != "127.0.0.1") and \
|
||||
elif (remote_addr not in hosts) and (remote_addr != '127.0.0.1') and \
|
||||
(request.function != 'manage'):
|
||||
raise HTTP(200, T('appadmin is disabled because insecure channel'))
|
||||
|
||||
@@ -46,7 +46,7 @@ if request.function == 'manage':
|
||||
auth.table_permission()])
|
||||
manager_role = manager_action.get('role', None) if manager_action else None
|
||||
if not (gluon.fileutils.check_credentials(request) or auth.has_membership(manager_role)):
|
||||
raise HTTP(403, "Not authorized")
|
||||
raise HTTP(403, 'Not authorized')
|
||||
menu = False
|
||||
elif (request.application == 'admin' and not session.authorized) or \
|
||||
(request.application != 'admin' and not gluon.fileutils.check_credentials(request)):
|
||||
@@ -182,7 +182,7 @@ def select():
|
||||
db = get_database(request)
|
||||
dbname = request.args[0]
|
||||
try:
|
||||
is_imap = db._uri.startswith("imap://")
|
||||
is_imap = db._uri.startswith('imap://')
|
||||
except (KeyError, AttributeError, TypeError):
|
||||
is_imap = False
|
||||
regex = re.compile(r'(?P<table>\w+)\.(?P<field>\w+)=(?P<value>\d+)')
|
||||
@@ -224,15 +224,15 @@ def select():
|
||||
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 '', _class="form-control",
|
||||
_name='query', _value=request.vars.query or '', _class='form-control',
|
||||
requires=IS_NOT_EMPTY(
|
||||
error_message=T("Cannot be empty")))), TR(T('Update:'),
|
||||
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 '', _class="form-control")), TR(T('Delete:'), INPUT(_name='delete_check',
|
||||
or '', _class='form-control')), TR(T('Delete:'), INPUT(_name='delete_check',
|
||||
_class='delete', _type='checkbox', value=False), ''),
|
||||
TR('', '', INPUT(_type='submit', _value=T('submit'), _class="btn btn-primary"))),
|
||||
TR('', '', INPUT(_type='submit', _value=T('Submit'), _class='btn btn-primary'))),
|
||||
_action=URL(r=request, args=request.args))
|
||||
|
||||
tb = None
|
||||
@@ -254,8 +254,8 @@ def select():
|
||||
|
||||
if is_imap:
|
||||
fields = [db[table][name] for name in
|
||||
("id", "uid", "created", "to",
|
||||
"sender", "subject")]
|
||||
('id', 'uid', 'created', 'to',
|
||||
'sender', 'subject')]
|
||||
if orderby:
|
||||
rows = db(query, ignore_common_filters=True).select(
|
||||
*fields, limitby=(start, stop),
|
||||
@@ -271,10 +271,10 @@ def select():
|
||||
# begin handle upload csv
|
||||
csv_table = table or request.vars.table
|
||||
if csv_table:
|
||||
formcsv = FORM(str(T('or import from csv file')) + " ",
|
||||
formcsv = FORM(str(T('or import from csv file')) + ' ',
|
||||
INPUT(_type='file', _name='csvfile'),
|
||||
INPUT(_type='hidden', _value=csv_table, _name='table'),
|
||||
INPUT(_type='submit', _value=T('import'), _class="btn btn-primary"))
|
||||
INPUT(_type='submit', _value=T('import'), _class='btn btn-primary'))
|
||||
else:
|
||||
formcsv = None
|
||||
if formcsv and formcsv.process().accepted:
|
||||
@@ -356,26 +356,26 @@ def state():
|
||||
def ccache():
|
||||
if is_gae:
|
||||
form = FORM(
|
||||
P(TAG.BUTTON(T("Clear CACHE?"), _type="submit", _name="yes", _value="yes")))
|
||||
P(TAG.BUTTON(T('Clear CACHE?'), _type='submit', _name='yes', _value='yes')))
|
||||
else:
|
||||
cache.ram.initialize()
|
||||
cache.disk.initialize()
|
||||
|
||||
form = FORM(
|
||||
P(TAG.BUTTON(
|
||||
T("Clear CACHE?"), _type="submit", _name="yes", _value="yes")),
|
||||
T('Clear CACHE?'), _type='submit', _name='yes', _value='yes')),
|
||||
P(TAG.BUTTON(
|
||||
T("Clear RAM"), _type="submit", _name="ram", _value="ram")),
|
||||
T('Clear RAM'), _type='submit', _name='ram', _value='ram')),
|
||||
P(TAG.BUTTON(
|
||||
T("Clear DISK"), _type="submit", _name="disk", _value="disk")),
|
||||
T('Clear DISK'), _type='submit', _name='disk', _value='disk')),
|
||||
)
|
||||
|
||||
if form.accepts(request.vars, session):
|
||||
session.flash = ""
|
||||
session.flash = ''
|
||||
if is_gae:
|
||||
if request.vars.yes:
|
||||
cache.ram.clear()
|
||||
session.flash += T("Cache Cleared")
|
||||
session.flash += T('Cache Cleared')
|
||||
else:
|
||||
clear_ram = False
|
||||
clear_disk = False
|
||||
@@ -387,10 +387,10 @@ def ccache():
|
||||
clear_disk = True
|
||||
if clear_ram:
|
||||
cache.ram.clear()
|
||||
session.flash += T("Ram Cleared")
|
||||
session.flash += T('Ram Cleared')
|
||||
if clear_disk:
|
||||
cache.disk.clear()
|
||||
session.flash += T("Disk Cleared")
|
||||
session.flash += T('Disk Cleared')
|
||||
redirect(URL(r=request))
|
||||
|
||||
try:
|
||||
@@ -436,7 +436,7 @@ def ccache():
|
||||
gae_stats['ratio'] = ((gae_stats['hits'] * 100) /
|
||||
(gae_stats['hits'] + gae_stats['misses']))
|
||||
except ZeroDivisionError:
|
||||
gae_stats['ratio'] = T("?")
|
||||
gae_stats['ratio'] = T('?')
|
||||
gae_stats['oldest'] = GetInHMS(time.time() - gae_stats['oldest_item_age'])
|
||||
total.update(gae_stats)
|
||||
else:
|
||||
@@ -502,7 +502,7 @@ def ccache():
|
||||
TR(TD(B(T('Key'))), TD(B(T('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;"))
|
||||
_style='border-collapse: separate; border-spacing: .5em;'))
|
||||
|
||||
if not is_gae:
|
||||
ram['keys'] = key_table(ram['keys'])
|
||||
@@ -536,26 +536,26 @@ def table_template(table):
|
||||
# This is horribe HTML but the only one graphiz understands
|
||||
rows = []
|
||||
cellpadding = 4
|
||||
color = "#000000"
|
||||
bgcolor = "#FFFFFF"
|
||||
face = "Helvetica"
|
||||
face_bold = "Helvetica Bold"
|
||||
color = '#000000'
|
||||
bgcolor = '#FFFFFF'
|
||||
face = 'Helvetica'
|
||||
face_bold = 'Helvetica Bold'
|
||||
border = 0
|
||||
|
||||
rows.append(TR(TD(FONT(table, _face=face_bold, _color=bgcolor),
|
||||
_colspan=3, _cellpadding=cellpadding,
|
||||
_align="center", _bgcolor=color)))
|
||||
_align='center', _bgcolor=color)))
|
||||
for row in db[table]:
|
||||
rows.append(TR(TD(FONT(row.name, _color=color, _face=face_bold),
|
||||
_align="left", _cellpadding=cellpadding,
|
||||
_align='left', _cellpadding=cellpadding,
|
||||
_border=border),
|
||||
TD(FONT(row.type, _color=color, _face=face),
|
||||
_align="left", _cellpadding=cellpadding,
|
||||
_align='left', _cellpadding=cellpadding,
|
||||
_border=border),
|
||||
TD(FONT(types(row), _color=color, _face=face),
|
||||
_align="center", _cellpadding=cellpadding,
|
||||
_align='center', _cellpadding=cellpadding,
|
||||
_border=border)))
|
||||
return "< %s >" % TABLE(*rows, **dict(_bgcolor=bgcolor, _border=1,
|
||||
return '< %s >' % TABLE(*rows, **dict(_bgcolor=bgcolor, _border=1,
|
||||
_cellborder=0, _cellspacing=0)
|
||||
).xml()
|
||||
|
||||
@@ -632,15 +632,15 @@ def hooks():
|
||||
if len(functions):
|
||||
method_hooks.append({'name': op, 'functions':functions})
|
||||
if len(method_hooks):
|
||||
tables.append({'name': "%s.%s" % (db_str, t), 'slug': IS_SLUG()("%s.%s" % (db_str,t))[0], 'method_hooks':method_hooks})
|
||||
tables.append({'name': '%s.%s' % (db_str, t), 'slug': IS_SLUG()('%s.%s' % (db_str,t))[0], 'method_hooks':method_hooks})
|
||||
# Render
|
||||
ul_main = UL(_class='nav nav-list')
|
||||
for t in tables:
|
||||
ul_main.append(A(t['name'], _onclick="collapse('a_%s')" % t['slug']))
|
||||
ul_t = UL(_class='nav nav-list', _id="a_%s" % t['slug'], _style='display:none')
|
||||
ul_t = UL(_class='nav nav-list', _id='a_%s' % t['slug'], _style='display:none')
|
||||
for op in t['method_hooks']:
|
||||
ul_t.append(LI(op['name']))
|
||||
ul_t.append(UL([LI(A(f['funcname'], _class="editor_filelink", _href=f['url']if 'url' in f else None, **{'_data-lineno':f['lineno']-1})) for f in op['functions']]))
|
||||
ul_t.append(UL([LI(A(f['funcname'], _class='editor_filelink', _href=f['url']if 'url' in f else None, **{'_data-lineno':f['lineno']-1})) for f in op['functions']]))
|
||||
ul_main.append(ul_t)
|
||||
return ul_main
|
||||
|
||||
@@ -650,11 +650,11 @@ def hooks():
|
||||
# ###########################################################
|
||||
|
||||
def d3_graph_model():
|
||||
""" See https://www.facebook.com/web2py/posts/145613995589010 from Bruno Rocha
|
||||
''' See https://www.facebook.com/web2py/posts/145613995589010 from Bruno Rocha
|
||||
and also the app_admin bg_graph_model function
|
||||
|
||||
Create a list of table dicts, called "nodes"
|
||||
"""
|
||||
Create a list of table dicts, called 'nodes'
|
||||
'''
|
||||
|
||||
nodes = []
|
||||
links = []
|
||||
@@ -670,10 +670,10 @@ def d3_graph_model():
|
||||
elif f_type == 'string':
|
||||
disp = field.length
|
||||
elif f_type == 'id':
|
||||
disp = "PK"
|
||||
disp = 'PK'
|
||||
elif f_type.startswith('reference') or \
|
||||
f_type.startswith('list:reference'):
|
||||
disp = "FK"
|
||||
disp = 'FK'
|
||||
else:
|
||||
disp = ' '
|
||||
fields.append(dict(name=field.name, type=field.type, disp=disp))
|
||||
@@ -685,7 +685,7 @@ def d3_graph_model():
|
||||
|
||||
links.append(dict(source=tablename, target = referenced_table))
|
||||
|
||||
nodes.append(dict(name=tablename, type="table", fields = fields))
|
||||
nodes.append(dict(name=tablename, type='table', fields = fields))
|
||||
|
||||
# d3 v4 allows individual modules to be specified. The complete d3 library is included below.
|
||||
response.files.append(URL('admin','static','js/d3.min.js'))
|
||||
|
||||
@@ -30,7 +30,7 @@ except:
|
||||
|
||||
if request.is_https:
|
||||
session.secure()
|
||||
elif (remote_addr not in hosts) and (remote_addr != "127.0.0.1") and \
|
||||
elif (remote_addr not in hosts) and (remote_addr != '127.0.0.1') and \
|
||||
(request.function != 'manage'):
|
||||
raise HTTP(200, T('appadmin is disabled because insecure channel'))
|
||||
|
||||
@@ -46,7 +46,7 @@ if request.function == 'manage':
|
||||
auth.table_permission()])
|
||||
manager_role = manager_action.get('role', None) if manager_action else None
|
||||
if not (gluon.fileutils.check_credentials(request) or auth.has_membership(manager_role)):
|
||||
raise HTTP(403, "Not authorized")
|
||||
raise HTTP(403, 'Not authorized')
|
||||
menu = False
|
||||
elif (request.application == 'admin' and not session.authorized) or \
|
||||
(request.application != 'admin' and not gluon.fileutils.check_credentials(request)):
|
||||
@@ -182,7 +182,7 @@ def select():
|
||||
db = get_database(request)
|
||||
dbname = request.args[0]
|
||||
try:
|
||||
is_imap = db._uri.startswith("imap://")
|
||||
is_imap = db._uri.startswith('imap://')
|
||||
except (KeyError, AttributeError, TypeError):
|
||||
is_imap = False
|
||||
regex = re.compile(r'(?P<table>\w+)\.(?P<field>\w+)=(?P<value>\d+)')
|
||||
@@ -224,15 +224,15 @@ def select():
|
||||
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 '', _class="form-control",
|
||||
_name='query', _value=request.vars.query or '', _class='form-control',
|
||||
requires=IS_NOT_EMPTY(
|
||||
error_message=T("Cannot be empty")))), TR(T('Update:'),
|
||||
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 '', _class="form-control")), TR(T('Delete:'), INPUT(_name='delete_check',
|
||||
or '', _class='form-control')), TR(T('Delete:'), INPUT(_name='delete_check',
|
||||
_class='delete', _type='checkbox', value=False), ''),
|
||||
TR('', '', INPUT(_type='submit', _value=T('submit'), _class="btn btn-primary"))),
|
||||
TR('', '', INPUT(_type='submit', _value=T('Submit'), _class='btn btn-primary'))),
|
||||
_action=URL(r=request, args=request.args))
|
||||
|
||||
tb = None
|
||||
@@ -254,8 +254,8 @@ def select():
|
||||
|
||||
if is_imap:
|
||||
fields = [db[table][name] for name in
|
||||
("id", "uid", "created", "to",
|
||||
"sender", "subject")]
|
||||
('id', 'uid', 'created', 'to',
|
||||
'sender', 'subject')]
|
||||
if orderby:
|
||||
rows = db(query, ignore_common_filters=True).select(
|
||||
*fields, limitby=(start, stop),
|
||||
@@ -271,10 +271,10 @@ def select():
|
||||
# begin handle upload csv
|
||||
csv_table = table or request.vars.table
|
||||
if csv_table:
|
||||
formcsv = FORM(str(T('or import from csv file')) + " ",
|
||||
formcsv = FORM(str(T('or import from csv file')) + ' ',
|
||||
INPUT(_type='file', _name='csvfile'),
|
||||
INPUT(_type='hidden', _value=csv_table, _name='table'),
|
||||
INPUT(_type='submit', _value=T('import'), _class="btn btn-primary"))
|
||||
INPUT(_type='submit', _value=T('import'), _class='btn btn-primary'))
|
||||
else:
|
||||
formcsv = None
|
||||
if formcsv and formcsv.process().accepted:
|
||||
@@ -356,26 +356,26 @@ def state():
|
||||
def ccache():
|
||||
if is_gae:
|
||||
form = FORM(
|
||||
P(TAG.BUTTON(T("Clear CACHE?"), _type="submit", _name="yes", _value="yes")))
|
||||
P(TAG.BUTTON(T('Clear CACHE?'), _type='submit', _name='yes', _value='yes')))
|
||||
else:
|
||||
cache.ram.initialize()
|
||||
cache.disk.initialize()
|
||||
|
||||
form = FORM(
|
||||
P(TAG.BUTTON(
|
||||
T("Clear CACHE?"), _type="submit", _name="yes", _value="yes")),
|
||||
T('Clear CACHE?'), _type='submit', _name='yes', _value='yes')),
|
||||
P(TAG.BUTTON(
|
||||
T("Clear RAM"), _type="submit", _name="ram", _value="ram")),
|
||||
T('Clear RAM'), _type='submit', _name='ram', _value='ram')),
|
||||
P(TAG.BUTTON(
|
||||
T("Clear DISK"), _type="submit", _name="disk", _value="disk")),
|
||||
T('Clear DISK'), _type='submit', _name='disk', _value='disk')),
|
||||
)
|
||||
|
||||
if form.accepts(request.vars, session):
|
||||
session.flash = ""
|
||||
session.flash = ''
|
||||
if is_gae:
|
||||
if request.vars.yes:
|
||||
cache.ram.clear()
|
||||
session.flash += T("Cache Cleared")
|
||||
session.flash += T('Cache Cleared')
|
||||
else:
|
||||
clear_ram = False
|
||||
clear_disk = False
|
||||
@@ -387,10 +387,10 @@ def ccache():
|
||||
clear_disk = True
|
||||
if clear_ram:
|
||||
cache.ram.clear()
|
||||
session.flash += T("Ram Cleared")
|
||||
session.flash += T('Ram Cleared')
|
||||
if clear_disk:
|
||||
cache.disk.clear()
|
||||
session.flash += T("Disk Cleared")
|
||||
session.flash += T('Disk Cleared')
|
||||
redirect(URL(r=request))
|
||||
|
||||
try:
|
||||
@@ -436,7 +436,7 @@ def ccache():
|
||||
gae_stats['ratio'] = ((gae_stats['hits'] * 100) /
|
||||
(gae_stats['hits'] + gae_stats['misses']))
|
||||
except ZeroDivisionError:
|
||||
gae_stats['ratio'] = T("?")
|
||||
gae_stats['ratio'] = T('?')
|
||||
gae_stats['oldest'] = GetInHMS(time.time() - gae_stats['oldest_item_age'])
|
||||
total.update(gae_stats)
|
||||
else:
|
||||
@@ -502,7 +502,7 @@ def ccache():
|
||||
TR(TD(B(T('Key'))), TD(B(T('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;"))
|
||||
_style='border-collapse: separate; border-spacing: .5em;'))
|
||||
|
||||
if not is_gae:
|
||||
ram['keys'] = key_table(ram['keys'])
|
||||
@@ -536,26 +536,26 @@ def table_template(table):
|
||||
# This is horribe HTML but the only one graphiz understands
|
||||
rows = []
|
||||
cellpadding = 4
|
||||
color = "#000000"
|
||||
bgcolor = "#FFFFFF"
|
||||
face = "Helvetica"
|
||||
face_bold = "Helvetica Bold"
|
||||
color = '#000000'
|
||||
bgcolor = '#FFFFFF'
|
||||
face = 'Helvetica'
|
||||
face_bold = 'Helvetica Bold'
|
||||
border = 0
|
||||
|
||||
rows.append(TR(TD(FONT(table, _face=face_bold, _color=bgcolor),
|
||||
_colspan=3, _cellpadding=cellpadding,
|
||||
_align="center", _bgcolor=color)))
|
||||
_align='center', _bgcolor=color)))
|
||||
for row in db[table]:
|
||||
rows.append(TR(TD(FONT(row.name, _color=color, _face=face_bold),
|
||||
_align="left", _cellpadding=cellpadding,
|
||||
_align='left', _cellpadding=cellpadding,
|
||||
_border=border),
|
||||
TD(FONT(row.type, _color=color, _face=face),
|
||||
_align="left", _cellpadding=cellpadding,
|
||||
_align='left', _cellpadding=cellpadding,
|
||||
_border=border),
|
||||
TD(FONT(types(row), _color=color, _face=face),
|
||||
_align="center", _cellpadding=cellpadding,
|
||||
_align='center', _cellpadding=cellpadding,
|
||||
_border=border)))
|
||||
return "< %s >" % TABLE(*rows, **dict(_bgcolor=bgcolor, _border=1,
|
||||
return '< %s >' % TABLE(*rows, **dict(_bgcolor=bgcolor, _border=1,
|
||||
_cellborder=0, _cellspacing=0)
|
||||
).xml()
|
||||
|
||||
@@ -632,15 +632,15 @@ def hooks():
|
||||
if len(functions):
|
||||
method_hooks.append({'name': op, 'functions':functions})
|
||||
if len(method_hooks):
|
||||
tables.append({'name': "%s.%s" % (db_str, t), 'slug': IS_SLUG()("%s.%s" % (db_str,t))[0], 'method_hooks':method_hooks})
|
||||
tables.append({'name': '%s.%s' % (db_str, t), 'slug': IS_SLUG()('%s.%s' % (db_str,t))[0], 'method_hooks':method_hooks})
|
||||
# Render
|
||||
ul_main = UL(_class='nav nav-list')
|
||||
for t in tables:
|
||||
ul_main.append(A(t['name'], _onclick="collapse('a_%s')" % t['slug']))
|
||||
ul_t = UL(_class='nav nav-list', _id="a_%s" % t['slug'], _style='display:none')
|
||||
ul_t = UL(_class='nav nav-list', _id='a_%s' % t['slug'], _style='display:none')
|
||||
for op in t['method_hooks']:
|
||||
ul_t.append(LI(op['name']))
|
||||
ul_t.append(UL([LI(A(f['funcname'], _class="editor_filelink", _href=f['url']if 'url' in f else None, **{'_data-lineno':f['lineno']-1})) for f in op['functions']]))
|
||||
ul_t.append(UL([LI(A(f['funcname'], _class='editor_filelink', _href=f['url']if 'url' in f else None, **{'_data-lineno':f['lineno']-1})) for f in op['functions']]))
|
||||
ul_main.append(ul_t)
|
||||
return ul_main
|
||||
|
||||
@@ -650,11 +650,11 @@ def hooks():
|
||||
# ###########################################################
|
||||
|
||||
def d3_graph_model():
|
||||
""" See https://www.facebook.com/web2py/posts/145613995589010 from Bruno Rocha
|
||||
''' See https://www.facebook.com/web2py/posts/145613995589010 from Bruno Rocha
|
||||
and also the app_admin bg_graph_model function
|
||||
|
||||
Create a list of table dicts, called "nodes"
|
||||
"""
|
||||
Create a list of table dicts, called 'nodes'
|
||||
'''
|
||||
|
||||
nodes = []
|
||||
links = []
|
||||
@@ -670,10 +670,10 @@ def d3_graph_model():
|
||||
elif f_type == 'string':
|
||||
disp = field.length
|
||||
elif f_type == 'id':
|
||||
disp = "PK"
|
||||
disp = 'PK'
|
||||
elif f_type.startswith('reference') or \
|
||||
f_type.startswith('list:reference'):
|
||||
disp = "FK"
|
||||
disp = 'FK'
|
||||
else:
|
||||
disp = ' '
|
||||
fields.append(dict(name=field.name, type=field.type, disp=disp))
|
||||
@@ -685,7 +685,7 @@ def d3_graph_model():
|
||||
|
||||
links.append(dict(source=tablename, target = referenced_table))
|
||||
|
||||
nodes.append(dict(name=tablename, type="table", fields = fields))
|
||||
nodes.append(dict(name=tablename, type='table', fields = fields))
|
||||
|
||||
# d3 v4 allows individual modules to be specified. The complete d3 library is included below.
|
||||
response.files.append(URL('admin','static','js/d3.min.js'))
|
||||
|
||||
0
applications/welcome/languages/ar.py
Executable file → Normal file
0
applications/welcome/languages/ca.py
Executable file → Normal file
0
applications/welcome/languages/cs.py
Executable file → Normal file
0
applications/welcome/languages/en.py
Executable file → Normal file
0
applications/welcome/languages/es.py
Executable file → Normal file
0
applications/welcome/languages/fr-ca.py
Executable file → Normal file
0
applications/welcome/languages/fr.py
Executable file → Normal file
0
applications/welcome/languages/hi.py
Executable file → Normal file
0
applications/welcome/languages/hu.py
Executable file → Normal file
0
applications/welcome/languages/id.py
Executable file → Normal file
0
applications/welcome/languages/it.py
Executable file → Normal file
0
applications/welcome/languages/my-mm.py
Executable file → Normal file
0
applications/welcome/languages/my.py
Executable file → Normal file
0
applications/welcome/languages/nl.py
Executable file → Normal file
0
applications/welcome/languages/pl.py
Executable file → Normal file
0
applications/welcome/languages/plural-cs.py
Executable file → Normal file
0
applications/welcome/languages/plural-en.py
Executable file → Normal file
0
applications/welcome/languages/plural-es.py
Executable file → Normal file
0
applications/welcome/languages/plural-ru.py
Executable file → Normal file
0
applications/welcome/languages/plural-uk.py
Executable file → Normal file
208
applications/welcome/languages/pt-br.py
Executable file → Normal file
@@ -1,8 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
{
|
||||
'!=': '!=',
|
||||
'!langcode!': 'pt-br',
|
||||
'!langname!': 'Português (do Brasil)',
|
||||
'"update" is an optional expression like "field1=\'newvalue\'". You cannot update or delete the results of a JOIN': '"update" é uma expressão opcional como "campo1=\'novovalor\'". Você não pode atualizar ou apagar os resultados de um JOIN',
|
||||
'%(nrows)s records found': '%(nrows)s registros encontrados',
|
||||
'%s %%{row} deleted': '%s linha apagadas',
|
||||
'%s %%{row} updated': '%s linha atualizadas',
|
||||
'%s selected': '%s selecionado',
|
||||
@@ -12,6 +14,13 @@
|
||||
'**%(items)s** %%{item(items)}, **%(bytes)s** %%{byte(bytes)}': '**%(items)s** %%{item(items)}, **%(bytes)s** %%{byte(bytes)}',
|
||||
'**%(items)s** items, **%(bytes)s** %%{byte(bytes)}': '**%(items)s** items, **%(bytes)s** %%{byte(bytes)}',
|
||||
'**not available** (requires the Python [[guppy http://pypi.python.org/pypi/guppy/ popup]] library)': '**not available** (requires the Python [[guppy http://pypi.python.org/pypi/guppy/ popup]] library)',
|
||||
'+ And': '+ E',
|
||||
'+ Or': '+ Ou',
|
||||
'<': '<',
|
||||
'<=': '<=',
|
||||
'=': '=',
|
||||
'>': '>',
|
||||
'>=': '>=',
|
||||
'?': '?',
|
||||
'@markmin\x01(**%.0d MB**)': '(**%.0d MB**)',
|
||||
'@markmin\x01**%(items)s** %%{item(items)}, **%(bytes)s** %%{byte(bytes)}': '**%(items)s** %%{item(items)}, **%(bytes)s** %%{byte(bytes)}',
|
||||
@@ -22,23 +31,28 @@
|
||||
'@markmin\x01Cache contains items up to **%(hours)02d** %%{hour(hours)} **%(min)02d** %%{minute(min)} **%(sec)02d** %%{second(sec)} old.': 'Cache contains items up to **%(hours)02d** %%{hour(hours)} **%(min)02d** %%{minute(min)} **%(sec)02d** %%{second(sec)} old.',
|
||||
'@markmin\x01DISK contains items up to **%(hours)02d** %%{hour(hours)} **%(min)02d** %%{minute(min)} **%(sec)02d** %%{second(sec)} old.': 'DISK contains items up to **%(hours)02d** %%{hour(hours)} **%(min)02d** %%{minute(min)} **%(sec)02d** %%{second(sec)} old.',
|
||||
'@markmin\x01Hit Ratio: **%(ratio)s%%** (**%(hits)s** %%{hit(hits)} and **%(misses)s** %%{miss(misses)})': 'Hit Ratio: **%(ratio)s%%** (**%(hits)s** %%{hit(hits)} and **%(misses)s** %%{miss(misses)})',
|
||||
'@markmin\x01Number of entries: **%s**': 'Number of entries: **%s**',
|
||||
'@markmin\x01Number of entries: **%s**': 'Número de entradas: **%s**',
|
||||
'@markmin\x01RAM contains items up to **%(hours)02d** %%{hour(hours)} **%(min)02d** %%{minute(min)} **%(sec)02d** %%{second(sec)} old.': 'RAM contains items up to **%(hours)02d** %%{hour(hours)} **%(min)02d** %%{minute(min)} **%(sec)02d** %%{second(sec)} old.',
|
||||
'``**not available**``:red (requires the Python [[guppy http://pypi.python.org/pypi/guppy/ popup]] library)': '``**not available**``:red (requires the Python [[guppy http://pypi.python.org/pypi/guppy/ popup]] library)',
|
||||
'A new password was emailed to you': 'A new password was emailed to you',
|
||||
'A new password was emailed to you': 'Uma nova senha foi enviada por email para você',
|
||||
'About': 'Sobre',
|
||||
'Access Control': 'Controle de Acesso',
|
||||
'Add Record': 'Novo Registro',
|
||||
'Add record to database': 'Adicionar registro ao banco de dados',
|
||||
'Add this to the search as an AND term': 'Adicionar à pesquisa como um termo E',
|
||||
'Add this to the search as an OR term': 'Adicionar à pesquisa como um termo OU',
|
||||
'admin': 'admin',
|
||||
'Administrative Interface': 'Interface Administrativa',
|
||||
'Administrative interface': 'Interface administrativa',
|
||||
'Ajax Recipes': 'Receitas de Ajax',
|
||||
'An error occured, please [[reload %s]] the page': 'An error occured, please [[reload %s]] the page',
|
||||
'API Example': 'API Example',
|
||||
'API Example': 'Exmplo de API',
|
||||
'appadmin is disabled because insecure channel': 'Administração desativada porque o canal não é seguro',
|
||||
'Apply changes': 'Apply changes',
|
||||
'Apply changes': 'Aplicar Mudanças',
|
||||
'Are you sure you want to delete this object?': 'Você tem certeza que quer apagar este objeto?',
|
||||
'Authentication code': 'Authentication code',
|
||||
'Authentication code': 'Código de autenticação',
|
||||
'Available Databases and Tables': 'Bancos de dados e tabelas disponíveis',
|
||||
'Back': 'Voltar',
|
||||
'Buy this book': 'Compre o livro',
|
||||
"Buy web2py's book": 'Compre o livro do web2py',
|
||||
'cache': 'cache',
|
||||
@@ -48,19 +62,27 @@
|
||||
'Cache Keys': 'Chaves de cache',
|
||||
'Cannot be empty': 'Não pode estar vazio',
|
||||
'change password': 'mudar senha',
|
||||
'Change Password': 'Change Password',
|
||||
'Change password': 'Change password',
|
||||
'Change Password': 'Trocar Senhar',
|
||||
'Change password': 'Trocar senha',
|
||||
'Check to delete': 'Marque para apagar',
|
||||
'Clear': 'Limpar',
|
||||
'Clear CACHE?': 'Limpar CACHE?',
|
||||
'Clear DISK': 'Limpar DISCO',
|
||||
'Clear RAM': 'Limpar memória RAM',
|
||||
'Click on the link %(link)s to reset your password': 'Click on the link %(link)s to reset your password',
|
||||
'Client IP': 'IP do cliente',
|
||||
'Close': 'Fechar',
|
||||
'Comma-separated export including columns not shown; fields from other tables are exported as raw values for faster export': 'Comma-separated export including columns not shown; fields from other tables are exported as raw values for faster export',
|
||||
'Comma-separated export of visible columns. Fields from other tables are exported as they appear on-screen but this may be slow for many rows': 'Comma-separated export of visible columns. Fields from other tables are exported as they appear on-screen but this may be slow for many rows',
|
||||
'Community': 'Comunidade',
|
||||
'Components and Plugins': 'Componentes e Plugins',
|
||||
'Config.ini': 'Config.ini',
|
||||
'Confirm Password': 'Confirme a Senha',
|
||||
'contains': 'contém',
|
||||
'Controller': 'Controlador',
|
||||
'Copyright': 'Copyright',
|
||||
'CSV': 'CSV',
|
||||
'CSV (hidden cols)': 'CSV (col. ocultas)',
|
||||
'Current request': 'Requisição atual',
|
||||
'Current response': 'Resposta atual',
|
||||
'Current session': 'Sessão atual',
|
||||
@@ -68,9 +90,10 @@
|
||||
'data uploaded': 'dados enviados',
|
||||
'Database': 'banco de dados',
|
||||
'Database %s select': 'Selecionar banco de dados %s',
|
||||
'Database Administration (appadmin)': 'Database Administration (appadmin)',
|
||||
'Database Administration (appadmin)': 'Administração de Banco de Dados (appadmin)',
|
||||
'db': 'bd',
|
||||
'DB Model': 'Modelo BD',
|
||||
'Delete': 'Excluir',
|
||||
'Delete:': 'Apagar:',
|
||||
'Demo': 'Demo',
|
||||
'Deployment Recipes': 'Receitas de deploy',
|
||||
@@ -91,50 +114,57 @@
|
||||
'edit profile': 'editar perfil',
|
||||
'Edit This App': 'Editar esta aplicação',
|
||||
'Email and SMS': 'Email e SMS',
|
||||
'Email sent': 'Email sent',
|
||||
'Email verification': 'Email verification',
|
||||
'Email verified': 'Email verified',
|
||||
'Email sent': 'Email enviado',
|
||||
'Email verification': 'Verificação de email',
|
||||
'Email verified': 'Email verificado',
|
||||
'Enter an integer between %(min)g and %(max)g': 'Informe um valor inteiro entre %(min)g e %(max)g',
|
||||
'Errors': 'Erros',
|
||||
'export as csv file': 'exportar como um arquivo csv',
|
||||
'Export:': 'Exportar:',
|
||||
'FAQ': 'Perguntas frequentes',
|
||||
'First name': 'Nome',
|
||||
'Forms and Validators': 'Formulários e Validadores',
|
||||
'Free Applications': 'Aplicações gratuitas',
|
||||
'Function disabled': 'Function disabled',
|
||||
'Graph Model': 'Graph Model',
|
||||
'Function disabled': 'Função desabilitada',
|
||||
'Graph Model': 'Modelo em Grafo',
|
||||
'Grid Example': 'Exemplo de Grade',
|
||||
'Group %(group_id)s created': 'Group %(group_id)s created',
|
||||
'Group %(group_id)s deleted': 'Group %(group_id)s deleted',
|
||||
'Group %(group_id)s created': 'Grupo %(group_id)s criado',
|
||||
'Group %(group_id)s deleted': 'Grupo %(group_id)s excluído',
|
||||
'Group ID': 'ID do Grupo',
|
||||
'Group uniquely assigned to user %(id)s': 'Group uniquely assigned to user %(id)s',
|
||||
'Group uniquely assigned to user %(id)s': 'Gurpo unicamente atribuído ao usuário %(id)s',
|
||||
'Groups': 'Grupos',
|
||||
'Hello World': 'Olá Mundo',
|
||||
'Helping web2py': 'Helping web2py',
|
||||
'Helping web2py': 'Ajudando web2py',
|
||||
'Hit Ratio: **%(ratio)s%%** (**%(hits)s** %%{hit(hits)} and **%(misses)s** %%{miss(misses)})': 'Hit Ratio: **%(ratio)s%%** (**%(hits)s** %%{hit(hits)} and **%(misses)s** %%{miss(misses)})',
|
||||
'Home': 'Principal',
|
||||
'How did you get here?': 'Como você chegou aqui?',
|
||||
'HTML': 'HTML',
|
||||
'HTML export of visible columns': 'HTML exportar colunas visíveis',
|
||||
'Id': 'Id',
|
||||
'import': 'importar',
|
||||
'Import/Export': 'Importar/Exportar',
|
||||
'in': 'em',
|
||||
'Incorrect code. {0} more attempt(s) remaining.': 'Incorrect code. {0} more attempt(s) remaining.',
|
||||
'Index': 'Início',
|
||||
'insert new': 'inserir novo',
|
||||
'insert new %s': 'inserir novo %s',
|
||||
'Insufficient privileges': 'Insufficient privileges',
|
||||
'Insufficient privileges': 'Privilégios insuficientes',
|
||||
'Internal State': 'Estado Interno',
|
||||
'Introduction': 'Introdução',
|
||||
'Invalid email': 'Email inválido',
|
||||
'Invalid key': 'Invalid key',
|
||||
'Invalid login': 'Invalid login',
|
||||
'Invalid password': 'Invalid password',
|
||||
'Invalid key': 'Chave inválida',
|
||||
'Invalid login': 'Login Inválido',
|
||||
'Invalid password': 'Senha inválida',
|
||||
'Invalid Query': 'Consulta Inválida',
|
||||
'invalid request': 'requisição inválida',
|
||||
'Invalid reset password': 'Invalid reset password',
|
||||
'Invalid user': 'Invalid user',
|
||||
'Invalid username': 'Invalid username',
|
||||
'Invitation to join %(site)s': 'Invitation to join %(site)s',
|
||||
'Invalid reset password': 'Recriação de senha inválida',
|
||||
'Invalid user': 'Usuário inválido',
|
||||
'Invalid username': 'Nome de usuário inválido',
|
||||
'Invitation to join %(site)s': 'Convite para entrar %(site)s',
|
||||
'JSON': 'JSON',
|
||||
'JSON export of visible columns': 'JSON exportar colunas visíveis',
|
||||
'Key': 'Chave',
|
||||
'Key verified': 'Key verified',
|
||||
'Key verified': 'Chave verificada',
|
||||
'Last name': 'Sobrenome',
|
||||
'Layout': 'Layout',
|
||||
'Layout Plugins': 'Plugins de Layout',
|
||||
@@ -142,13 +172,13 @@
|
||||
'Live chat': 'Chat ao vivo',
|
||||
'Live Chat': 'Chat ao vivo',
|
||||
'Log In': 'Entrar',
|
||||
'Logged in': 'Logged in',
|
||||
'Logged out': 'Logged out',
|
||||
'Logged in': 'Conectado',
|
||||
'Logged out': 'Desconectado',
|
||||
'login': 'Entrar',
|
||||
'Login': 'Entrar',
|
||||
'Login disabled by administrator': 'Login disabled by administrator',
|
||||
'Login disabled by administrator': 'Login desabilitado pelo administrador',
|
||||
'logout': 'Sair',
|
||||
'Logout': 'Logout',
|
||||
'Logout': 'Sair',
|
||||
'Lost Password': 'Esqueceu sua senha?',
|
||||
'lost password?': 'esqueceu sua senha?',
|
||||
'Lost your password?': 'Esqueceu sua senha?',
|
||||
@@ -160,16 +190,19 @@
|
||||
'Menu Model': 'Modelo de Menu',
|
||||
'My Sites': 'Meus sites',
|
||||
'Name': 'Nome',
|
||||
'New password': 'New password',
|
||||
'New password': 'Nova senha',
|
||||
'New Record': 'Novo Registro',
|
||||
'new record inserted': 'novo registro inserido',
|
||||
'New Search': 'Nova pesquisa',
|
||||
'next %s rows': 'próximas %s ´linhas',
|
||||
'next 100 rows': 'próximas 100 linhas',
|
||||
'No databases in this application': 'Não há bancos de dados nesta aplicação',
|
||||
'No records found': 'Não foram encontrados registros',
|
||||
'not in': 'não está em',
|
||||
'Number of entries: **%s**': 'Número de entradas: **%s**',
|
||||
'Object or table name': 'Nome do objeto do da tabela',
|
||||
'Old password': 'Old password',
|
||||
'Online book': 'Online book',
|
||||
'Old password': 'Senha antiga',
|
||||
'Online book': 'Livro online',
|
||||
'Online examples': 'Exemplos online',
|
||||
'or import from csv file': 'ou importar de um arquivo csv',
|
||||
'Origin': 'Origem',
|
||||
@@ -177,66 +210,71 @@
|
||||
'Other Recipes': 'Outras Receitas',
|
||||
'Overview': 'Visão Geral',
|
||||
'Password': 'Senha',
|
||||
'Password changed': 'Password changed',
|
||||
"Password fields don't match": "Password fields don't match",
|
||||
'Password reset': 'Password reset',
|
||||
'Password retrieve': 'Password retrieve',
|
||||
'Permission': 'Permission',
|
||||
'Permissions': 'Permissions',
|
||||
'please input your password again': 'please input your password again',
|
||||
'Password changed': 'Senha trocada',
|
||||
"Password fields don't match": 'Senhas não conferem',
|
||||
'Password reset': 'Recriar senha',
|
||||
'Password retrieve': 'Recuperar senha',
|
||||
'Permission': 'Permissão',
|
||||
'Permissions': 'Permissões',
|
||||
'please input your password again': 'por favor digite a senha novamente',
|
||||
'Plugins': 'Plugins',
|
||||
'Powered by': 'Desenvolvido com',
|
||||
'Preface': 'Prefácio',
|
||||
'previous %s rows': '%s linhas anteriores',
|
||||
'previous 100 rows': '100 linhas anteriores',
|
||||
'Profile': 'Profile',
|
||||
'Profile updated': 'Profile updated',
|
||||
'Profile': 'Perfil',
|
||||
'Profile updated': 'Perfil atualizado',
|
||||
'pygraphviz library not found': 'biblioteca pygraphviz não encontrada',
|
||||
'Python': 'Python',
|
||||
'Query:': 'Consulta:',
|
||||
'Quick Examples': 'Exemplos rápidos',
|
||||
'RAM': 'RAM',
|
||||
'RAM Cache Keys': 'RAM Cache Keys',
|
||||
'RAM Cache Keys': 'Chaves de Cache RAM ',
|
||||
'Ram Cleared': 'Ram Limpa',
|
||||
'RAM contains items up to **%(hours)02d** %%{hour(hours)} **%(min)02d** %%{minute(min)} **%(sec)02d** %%{second(sec)} old.': 'RAM contains items up to **%(hours)02d** %%{hour(hours)} **%(min)02d** %%{minute(min)} **%(sec)02d** %%{second(sec)} old.',
|
||||
'Recipes': 'Receitas',
|
||||
'Record': 'Registro',
|
||||
'Record %(id)s created': 'Record %(id)s created',
|
||||
'Record %(id)s deleted': 'Record %(id)s deleted',
|
||||
'Record %(id)s read': 'Record %(id)s read',
|
||||
'Record %(id)s updated': 'Record %(id)s updated',
|
||||
'Record Created': 'Record Created',
|
||||
'Record Deleted': 'Record Deleted',
|
||||
'Record %(id)s created': 'Registro %(id)s criado',
|
||||
'Record %(id)s deleted': 'Registro %(id)s excluído',
|
||||
'Record %(id)s read': 'Registro %(id)s lido',
|
||||
'Record %(id)s updated': 'Registro %(id)s atualizado',
|
||||
'Record Created': 'Registro Criado',
|
||||
'Record Deleted': 'Registro Excluído',
|
||||
'record does not exist': 'registro não existe',
|
||||
'Record ID': 'ID do Registro',
|
||||
'Record id': 'id do registro',
|
||||
'Record Updated': 'Record Updated',
|
||||
'register': 'Registre-se',
|
||||
'Register': 'Registre-se',
|
||||
'Registration identifier': 'Idenficador de registro',
|
||||
'Registration is pending approval': 'Registration is pending approval',
|
||||
'Registration key': 'Chave de registro',
|
||||
'Registration needs verification': 'Registration needs verification',
|
||||
'Registration successful': 'Registration successful',
|
||||
'Record Updated': 'Registro Atualizado',
|
||||
'register': 'Cadastre-se',
|
||||
'Register': 'Cadastre-se',
|
||||
'Registration identifier': 'Idenficador de Cadastro',
|
||||
'Registration is pending approval': 'Aprovação de cadastro pendente',
|
||||
'Registration key': 'Chave de cadastro',
|
||||
'Registration needs verification': 'Cadastro necessita verficação',
|
||||
'Registration successful': 'Cadastro finalizado',
|
||||
'Remember me (for 30 days)': 'Mantenha-me logado (por 30 dias)',
|
||||
'Request reset password': 'Request reset password',
|
||||
'Request reset password': 'Requerer recriação de senha',
|
||||
'Reset Password key': 'Resetar chave de senha',
|
||||
'Resources': 'Recursos',
|
||||
'Role': 'Papel',
|
||||
'Roles': 'Roles',
|
||||
'Roles': 'Papéis',
|
||||
'Rows in Table': 'Linhas na tabela',
|
||||
'Rows selected': 'Linhas selecionadas',
|
||||
'Save model as...': 'Salvar modelo como...',
|
||||
'Search': 'Pesquisar',
|
||||
'Semantic': 'Semântico',
|
||||
'Services': 'Serviço',
|
||||
'Sign Up': 'Cadastrar',
|
||||
'Sign up': 'Cadastrar',
|
||||
'Size of cache:': 'Tamanho do cache:',
|
||||
'Spreadsheet-optimised export of tab-separated content including hidden columns. May be slow': 'Spreadsheet-optimised export of tab-separated content including hidden columns. May be slow',
|
||||
'Spreadsheet-optimised export of tab-separated content, visible columns only. May be slow.': 'Spreadsheet-optimised export of tab-separated content, visible columns only. May be slow.',
|
||||
'Start building a new search': 'Comerçar um nova pesquisa',
|
||||
'starts with': 'começa com',
|
||||
'state': 'estado',
|
||||
'Statistics': 'Estatísticas',
|
||||
'Stylesheet': 'Folha de estilo',
|
||||
'submit': 'enviar',
|
||||
'Submit': 'Submit',
|
||||
'Submit': 'Enviar',
|
||||
'Support': 'Suporte',
|
||||
'Sure you want to delete this object?': 'Está certo(a) que deseja apagar este objeto?',
|
||||
'Table': 'Tabela',
|
||||
@@ -252,31 +290,33 @@
|
||||
'Time in Cache (h:m:s)': 'Tempo em Cache (h:m:s)',
|
||||
'Timestamp': 'Timestamp',
|
||||
'Traceback': 'Traceback',
|
||||
'TSV (Spreadsheets)': 'TSV (Planilhas)',
|
||||
'TSV (Spreadsheets, hidden cols)': 'TSV (Planilhas, col. ocultas)',
|
||||
'Twitter': 'Twitter',
|
||||
'Two-step Login Authentication Code': 'Two-step Login Authentication Code',
|
||||
'Two-step Login Authentication Code': 'Código de Autenticação de Login em Dois Fatores',
|
||||
'unable to parse csv file': 'não foi possível analisar arquivo csv',
|
||||
'Unable to send email': 'Unable to send email',
|
||||
'Unable to send email': 'Não foi possível enviar email',
|
||||
'Update:': 'Atualizar:',
|
||||
'Use (...)&(...) for AND, (...)|(...) for OR, and ~(...) for NOT to build more complex queries.': 'Use (...)&(...) para AND, (...)|(...) para OR, e ~(...) para NOT para construir consultas mais complexas.',
|
||||
'User': 'User',
|
||||
'User': 'Usuário',
|
||||
'User %(id)s is impersonating %(other_id)s': 'User %(id)s is impersonating %(other_id)s',
|
||||
'User %(id)s Logged-in': 'User %(id)s Logged-in',
|
||||
'User %(id)s Logged-out': 'User %(id)s Logged-out',
|
||||
'User %(id)s Password changed': 'User %(id)s Password changed',
|
||||
'User %(id)s Password reset': 'User %(id)s Password reset',
|
||||
'User %(id)s Password retrieved': 'User %(id)s Password retrieved',
|
||||
'User %(id)s Profile updated': 'User %(id)s Profile updated',
|
||||
'User %(id)s Registered': 'User %(id)s Registered',
|
||||
'User %(id)s Username retrieved': 'User %(id)s Username retrieved',
|
||||
'User %(id)s Verification email sent': 'User %(id)s Verification email sent',
|
||||
'User %(id)s verified registration key': 'User %(id)s verified registration key',
|
||||
'User %(id)s Logged-in': 'Usuário %(id)s entrou',
|
||||
'User %(id)s Logged-out': 'Usuário %(id)s saiu',
|
||||
'User %(id)s Password changed': 'Usuário %(id)s trocou a senha',
|
||||
'User %(id)s Password reset': 'Usuário %(id)s recirar a senha',
|
||||
'User %(id)s Password retrieved': 'Usuário %(id)s Recuperou a senha',
|
||||
'User %(id)s Profile updated': 'Usuário %(id)s Atualizou perfil',
|
||||
'User %(id)s Registered': 'Usuário %(id)s Cadastrou-se',
|
||||
'User %(id)s Username retrieved': 'Usuário %(id)s Recuperou nome de usuário',
|
||||
'User %(id)s Verification email sent': 'Usuário %(id)s Email de verificação enviado',
|
||||
'User %(id)s verified registration key': 'Usuário %(id)s chave de cadastro verificada',
|
||||
'User ID': 'ID do Usuário',
|
||||
'User Voice': 'Opinião dos usuários',
|
||||
'Username': 'Username',
|
||||
'Username already taken': 'Username already taken',
|
||||
'Username retrieve': 'Username retrieve',
|
||||
'Users': 'Users',
|
||||
'Verify Password': 'Verify Password',
|
||||
'Username': 'Nome de Usuário',
|
||||
'Username already taken': 'Nome de usuário já existe',
|
||||
'Username retrieve': 'Recuperar nome de usuário',
|
||||
'Users': 'Usuários',
|
||||
'Verify Password': 'Verificar Senha',
|
||||
'Videos': 'Vídeos',
|
||||
'View': 'Visualização',
|
||||
'Web2py': 'Web2py',
|
||||
@@ -286,15 +326,17 @@
|
||||
'Welcome to web2py': 'Bem-vindo ao web2py',
|
||||
'Welcome to web2py!': 'Bem-vindo ao web2py!',
|
||||
'Which called the function %s located in the file %s': 'Que chamou a função %s localizada no arquivo %s',
|
||||
'Wiki Example': 'Wiki Example',
|
||||
'Wiki Example': 'Exmplo de Wiki',
|
||||
'Working...': 'Trabalhando...',
|
||||
'XML': 'XML',
|
||||
'XML export of columns shown': 'XML exportar colunas visíveis',
|
||||
'You are successfully running web2py': 'Você está executando o web2py com sucesso',
|
||||
'You are successfully running web2py.': 'Você está executando o web2py com sucesso.',
|
||||
'You can modify this application and adapt it to your needs': 'Você pode modificar esta aplicação e adaptá-la às suas necessidades',
|
||||
'You have been invited to join %(site)s, click %(link)s to complete the process': 'You have been invited to join %(site)s, click %(link)s to complete the process',
|
||||
'You visited the url %s': 'Você acessou a url %s',
|
||||
'Your password is: %(password)s': 'Your password is: %(password)s',
|
||||
'Your temporary login code is {0}': 'Your temporary login code is {0}',
|
||||
'Your username is: %(username)s': 'Your username is: %(username)s',
|
||||
'Your username was emailed to you': 'Your username was emailed to you',
|
||||
'Your password is: %(password)s': 'Sua senha é: %(password)s',
|
||||
'Your temporary login code is {0}': 'Seu código temporário de login é {0}',
|
||||
'Your username is: %(username)s': 'Seu nome de usuário é: %(username)s',
|
||||
'Your username was emailed to you': 'Seu nome de usuário foi enviado por email para você',
|
||||
}
|
||||
|
||||
0
applications/welcome/languages/pt.py
Executable file → Normal file
0
applications/welcome/languages/ro.py
Executable file → Normal file
0
applications/welcome/languages/ru.py
Executable file → Normal file
0
applications/welcome/languages/sk.py
Executable file → Normal file
0
applications/welcome/languages/tr.py
Executable file → Normal file
0
applications/welcome/languages/uk.py
Executable file → Normal file
0
applications/welcome/languages/zh-cn.py
Executable file → Normal file
0
applications/welcome/languages/zh-tw.py
Executable file → Normal file
0
applications/welcome/languages/zh.py
Executable file → Normal file
@@ -1,2 +0,0 @@
|
||||
The files in this folder must be run from the main web2py folder.
|
||||
They are for building windows and osx binary distribution and not meant for the end user.
|
||||
4
extras/build_web2py/README.md
Normal file
@@ -0,0 +1,4 @@
|
||||
# build-web2py
|
||||
|
||||
The files in this folder must be run from the main web2py folder.
|
||||
They are for building windows and osx binary distribution using PyInstaller and not meant for the end user.
|
||||
164
extras/build_web2py/build_web2py.py
Normal file
@@ -0,0 +1,164 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# up to 2019, we have used py2applet, py2exe and bbfreeze for building web2py binaries
|
||||
# The original scripts can be found on GitHub for web2py up to version 2.18.4
|
||||
# See also Niphlod's work on http://www.web2pyslices.com/slice/show/1726/build-windows-binaries
|
||||
# Then we switched to Pyinstaller in order to fully support Python 3
|
||||
|
||||
from distutils.core import setup
|
||||
from gluon.import_all import base_modules, contributed_modules
|
||||
from gluon.fileutils import readlines_file
|
||||
from glob import glob
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
import re
|
||||
import zipfile
|
||||
import subprocess
|
||||
import platform
|
||||
|
||||
|
||||
USAGE = """
|
||||
build_web2py - make web2py Windows and MacOS binaries with pyinstaller
|
||||
Usage:
|
||||
Install the pyinstaller program, copy this file (plus web2py.*.spec files)
|
||||
to web2py root folder and run:
|
||||
|
||||
python build_py3.py
|
||||
|
||||
(tested with python 3.7.3 and 2.7.16 with PyInstaller 3.4)
|
||||
"""
|
||||
BUILD_DEBUG = False
|
||||
"""
|
||||
If BUILD_DEBUG is set to False, no gluon modules will be embedded inside the binary web2py.exe.
|
||||
Thus, you can easily update the build version by changing the gluon folder inside the resulting ZIP file.
|
||||
In case of problem , set BUILD_DEBUG to True. Then all the gluon modules will be analyzed and embedded, too.
|
||||
You can later analyze the .exe with 'pyi-archive_viewer web2py.exe' and then 'o PYZ-00.pyz'
|
||||
in order to check for missing system modules to be manually inserted in the SPEC file
|
||||
"""
|
||||
|
||||
if len(sys.argv) != 1 or not os.path.isfile('web2py.py'):
|
||||
print(USAGE)
|
||||
sys.exit(1)
|
||||
os_version = platform.system()
|
||||
if os_version not in ('Windows', 'Darwin'):
|
||||
print('Unsupported system: %s' % os_version)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def unzip(source_filename, dest_dir):
|
||||
with zipfile.ZipFile(source_filename) as zf:
|
||||
zf.extractall(dest_dir)
|
||||
|
||||
# borrowed from http://bytes.com/topic/python/answers/851018-how-zip-directory-python-using-zipfile
|
||||
|
||||
|
||||
def recursive_zip(zipf, directory, folder=""):
|
||||
for item in os.listdir(directory):
|
||||
if os.path.isfile(os.path.join(directory, item)):
|
||||
zipf.write(os.path.join(directory, item), folder + os.sep + item)
|
||||
elif os.path.isdir(os.path.join(directory, item)):
|
||||
recursive_zip(
|
||||
zipf, os.path.join(directory, item), folder + os.sep + item)
|
||||
|
||||
|
||||
# read web2py version from VERSION file
|
||||
web2py_version_line = readlines_file('VERSION')[0]
|
||||
# use regular expression to get just the version number
|
||||
v_re = re.compile('[0-9]+\.[0-9]+\.[0-9]+')
|
||||
web2py_version = v_re.search(web2py_version_line).group(0)
|
||||
|
||||
# Python base version
|
||||
python_version = sys.version_info[:3]
|
||||
|
||||
|
||||
if os_version == 'Windows':
|
||||
print("\nBuilding binary web2py for Windows\n")
|
||||
if BUILD_DEBUG: # debug only
|
||||
subprocess.call('pyinstaller --clean --icon=extras/icons/web2py.ico \
|
||||
--hidden-import=site-packages --hidden-import=gluon.packages.dal.pydal \
|
||||
--hidden-import=gluon.packages.yatl.yatl web2py.py')
|
||||
zip_filename = 'web2py_win_debug'
|
||||
else: # normal run
|
||||
subprocess.call('pyinstaller --clean web2py.win.spec')
|
||||
subprocess.call('pyinstaller --clean web2py.win_no_console.spec')
|
||||
source_no_console = 'dist/web2py_no_console/'
|
||||
files = 'web2py_no_console.exe'
|
||||
shutil.move(os.path.join(source_no_console, files), 'dist')
|
||||
shutil.rmtree(source_no_console)
|
||||
shutil.rmtree('build')
|
||||
zip_filename = 'web2py_win'
|
||||
|
||||
source = 'dist/web2py/'
|
||||
for files in os.listdir(source):
|
||||
shutil.move(os.path.join(source, files), 'dist')
|
||||
shutil.rmtree(source)
|
||||
os.unlink('dist/web2py.exe.manifest')
|
||||
|
||||
|
||||
|
||||
bin_folders = ['dist',]
|
||||
|
||||
|
||||
elif os_version == 'Darwin':
|
||||
print("\nBuilding binary web2py for MacOS\n")
|
||||
|
||||
if BUILD_DEBUG: #debug only
|
||||
subprocess.call("pyinstaller --clean --icon=extras/icons/web2py.icns --hidden-import=gluon.packages.dal.pydal --hidden-import=gluon.packages.yatl.yatl \
|
||||
--hidden-import=site-packages --windowed web2py.py", shell=True)
|
||||
zip_filename = 'web2py_osx_debug'
|
||||
else: # normal run
|
||||
subprocess.call("pyinstaller --clean web2py.mac.spec", shell=True)
|
||||
# cleanup + move binary files to dist folder
|
||||
#shutil.rmtree(os.path.join('dist', 'web2py'))
|
||||
shutil.rmtree('build')
|
||||
zip_filename = 'web2py_osx'
|
||||
|
||||
shutil.move((os.path.join('dist', 'web2py')),(os.path.join('dist', 'web2py_cmd')))
|
||||
bin_folders = [(os.path.join('dist', 'web2py.app/Contents/MacOS')), (os.path.join('dist', 'web2py_cmd'))]
|
||||
print("\nWeb2py binary successfully built!\n")
|
||||
|
||||
|
||||
# add data_files
|
||||
for req in ['CHANGELOG', 'LICENSE', 'VERSION']:
|
||||
for bin_folder in bin_folders:
|
||||
shutil.copy(req, os.path.join(bin_folder, req))
|
||||
# cleanup unuseful binary cache
|
||||
for dirpath, dirnames, files in os.walk('.'):
|
||||
if dirpath.endswith('__pycache__'):
|
||||
print('Deleting cached binary directory : %s' % dirpath)
|
||||
shutil.rmtree(dirpath)
|
||||
for dirpath, dirnames, files in os.walk('.'):
|
||||
for file in files:
|
||||
if file.endswith('.pyc'):
|
||||
print('Deleting cached binary file : %s' % file)
|
||||
os.unlink(os.path.join(dirpath, file))
|
||||
|
||||
print("\nPreparing package ...")
|
||||
# misc
|
||||
for folders in ['gluon', 'extras', 'site-packages', 'scripts', 'applications', 'examples', 'handlers']:
|
||||
for bin_folder in bin_folders:
|
||||
shutil.copytree(folders, os.path.join(bin_folder, folders))
|
||||
if not os.path.exists(os.path.join(bin_folder, 'logs')):
|
||||
os.mkdir(os.path.join(bin_folder, 'logs'))
|
||||
|
||||
|
||||
# create a web2py folder & copy dist's files into it
|
||||
shutil.copytree('dist', 'zip_temp/web2py')
|
||||
# create zip file
|
||||
zipf = zipfile.ZipFile(zip_filename + ".zip",
|
||||
"w", compression=zipfile.ZIP_DEFLATED)
|
||||
# just temp so the web2py directory is included in our zip file
|
||||
path = 'zip_temp'
|
||||
# leave the first folder as None, as path is root.
|
||||
recursive_zip(zipf, path)
|
||||
zipf.close()
|
||||
shutil.rmtree('zip_temp')
|
||||
shutil.rmtree('dist')
|
||||
|
||||
|
||||
print("Your binary version of web2py can be found in " + \
|
||||
zip_filename + ".zip")
|
||||
print("You may extract the archive anywhere and then run web2py without worrying about dependency")
|
||||
print("\nEnjoy binary web2py " + web2py_version_line + "\n with embedded Python " + sys.version + "\n")
|
||||
@@ -1,160 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
This is a setup.py script generated by py2applet
|
||||
|
||||
Usage:
|
||||
python setup.py py2app
|
||||
"""
|
||||
|
||||
copy_apps = False
|
||||
copy_scripts = True
|
||||
copy_site_packages = True
|
||||
remove_build_files = True
|
||||
make_zip = True
|
||||
zip_filename = "web2py_osx"
|
||||
|
||||
from setuptools import setup
|
||||
from gluon.import_all import base_modules, contributed_modules
|
||||
from gluon.fileutils import readlines_file
|
||||
import os
|
||||
import fnmatch
|
||||
import shutil
|
||||
import sys
|
||||
import re
|
||||
import zipfile
|
||||
|
||||
#read web2py version from VERSION file
|
||||
web2py_version_line = readlines_file('VERSION')[0]
|
||||
#use regular expression to get just the version number
|
||||
v_re = re.compile('[0-9]+\.[0-9]+\.[0-9]+')
|
||||
web2py_version = v_re.search(web2py_version_line).group(0)
|
||||
|
||||
class reglob:
|
||||
def __init__(self, directory, pattern="*"):
|
||||
self.stack = [directory]
|
||||
self.pattern = pattern
|
||||
self.files = []
|
||||
self.index = 0
|
||||
|
||||
def __getitem__(self, index):
|
||||
while 1:
|
||||
try:
|
||||
file = self.files[self.index]
|
||||
self.index = self.index + 1
|
||||
except IndexError:
|
||||
self.index = 0
|
||||
self.directory = self.stack.pop()
|
||||
self.files = os.listdir(self.directory)
|
||||
else:
|
||||
fullname = os.path.join(self.directory, file)
|
||||
if os.path.isdir(fullname) and not os.path.islink(fullname):
|
||||
self.stack.append(fullname)
|
||||
if not (file.startswith('.') or file.startswith('#') or file.endswith('~')) \
|
||||
and fnmatch.fnmatch(file, self.pattern):
|
||||
return fullname
|
||||
|
||||
setup(app=['web2py.py'],
|
||||
version=web2py_version,
|
||||
description="web2py web framework",
|
||||
author="Massimo DiPierro",
|
||||
license="LGPL v3",
|
||||
data_files=[
|
||||
'NEWINSTALL',
|
||||
'ABOUT',
|
||||
'LICENSE',
|
||||
'VERSION',
|
||||
'splashlogo.gif',
|
||||
'logging.example.conf',
|
||||
'options_std.py',
|
||||
],
|
||||
options={'py2app': {
|
||||
'argv_emulation': True,
|
||||
'includes': base_modules,
|
||||
}},
|
||||
setup_requires=['py2app'])
|
||||
|
||||
|
||||
def copy_folders(source, destination):
|
||||
"""Copy files & folders from source to destination (within dist/)"""
|
||||
print 'copying %s -> %s' % (source, destination)
|
||||
base = 'dist/web2py.app/Contents/Resources/'
|
||||
if os.path.exists(os.path.join(base, destination)):
|
||||
shutil.rmtree(os.path.join(base, destination))
|
||||
shutil.copytree(os.path.join(source), os.path.join(base, destination))
|
||||
|
||||
#Should we include applications?
|
||||
copy_folders('gluon','gluon')
|
||||
|
||||
if copy_apps:
|
||||
copy_folders('applications', 'applications')
|
||||
print "Your application(s) have been added"
|
||||
else:
|
||||
#only copy web2py's default applications
|
||||
copy_folders('applications/admin', 'applications/admin')
|
||||
copy_folders('applications/welcome', 'applications/welcome')
|
||||
copy_folders('applications/examples', 'applications/examples')
|
||||
print "Only web2py's admin, examples & welcome applications have been added"
|
||||
|
||||
|
||||
#should we copy project's site-packages into dist/site-packages
|
||||
if copy_site_packages:
|
||||
#copy site-packages
|
||||
copy_folders('site-packages', 'site-packages')
|
||||
else:
|
||||
#no worries, web2py will create the (empty) folder first run
|
||||
print "Skipping site-packages"
|
||||
pass
|
||||
|
||||
#should we copy project's scripts into dist/scripts
|
||||
if copy_scripts:
|
||||
#copy scripts
|
||||
copy_folders('scripts', 'scripts')
|
||||
else:
|
||||
#no worries, web2py will create the (empty) folder first run
|
||||
print "Skipping scripts"
|
||||
pass
|
||||
|
||||
|
||||
#borrowed from http://bytes.com/topic/python/answers/851018-how-zip-directory-python-using-zipfile
|
||||
def recursive_zip(zipf, directory, folder=""):
|
||||
for item in os.listdir(directory):
|
||||
if os.path.isfile(os.path.join(directory, item)):
|
||||
zipf.write(os.path.join(directory, item), folder + os.sep + item)
|
||||
elif os.path.isdir(os.path.join(directory, item)):
|
||||
recursive_zip(
|
||||
zipf, os.path.join(directory, item), folder + os.sep + item)
|
||||
|
||||
#should we create a zip file of the build?
|
||||
|
||||
if make_zip:
|
||||
#to keep consistent with how official web2py windows zip file is setup,
|
||||
#create a web2py folder & copy dist's files into it
|
||||
shutil.copytree('dist', 'zip_temp/web2py')
|
||||
#create zip file
|
||||
#use filename specified via command line
|
||||
zipf = zipfile.ZipFile(
|
||||
zip_filename + ".zip", "w", compression=zipfile.ZIP_DEFLATED)
|
||||
path = 'zip_temp' # just temp so the web2py directory is included in our zip file
|
||||
recursive_zip(
|
||||
zipf, path) # leave the first folder as None, as path is root.
|
||||
zipf.close()
|
||||
shutil.rmtree('zip_temp')
|
||||
print "Your Windows binary version of web2py can be found in " + \
|
||||
zip_filename + ".zip"
|
||||
print "You may extract the archive anywhere and then run web2py/web2py.exe"
|
||||
|
||||
#should py2exe build files be removed?
|
||||
if remove_build_files:
|
||||
shutil.rmtree('build')
|
||||
shutil.rmtree('deposit')
|
||||
shutil.rmtree('dist')
|
||||
print "py2exe build files removed"
|
||||
|
||||
#final info
|
||||
if not make_zip and not remove_build_files:
|
||||
print "Your Windows binary & associated files can also be found in /dist"
|
||||
|
||||
print "Finished!"
|
||||
print "Enjoy web2py " + web2py_version_line
|
||||
@@ -1,27 +0,0 @@
|
||||
[Setup]
|
||||
#py2exe often includes DLLS from windows which aren't licensed for
|
||||
#open source distribution. Should they be removed?
|
||||
remove_microsoft_dlls: Yes
|
||||
|
||||
#copy all web2py apps currently installed?
|
||||
#If no, only the default admin, welcome & example apps will be included
|
||||
copy_apps: No
|
||||
|
||||
#include the web2py\site-packages directory?
|
||||
copy_site_packages: Yes
|
||||
|
||||
#include the web2py\scripts directory?
|
||||
copy_scripts: Yes
|
||||
|
||||
#create a zip file of the build for easy distribution?
|
||||
make_zip: Yes
|
||||
|
||||
#what should the zip file be named? (leave off the .zip extension)
|
||||
zip_filename = web2py_win
|
||||
|
||||
#should the build, deposit & dist directories used by py2exe be removed?
|
||||
#if you created a zip file you likely don't need these directories anymore
|
||||
remove_build_files = Yes
|
||||
|
||||
#should the build include the gevented webserver (needs gevent)
|
||||
include_gevent = Yes
|
||||
@@ -1,232 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
#Adapted from http://bazaar.launchpad.net/~flavour/sahana-eden/trunk/view/head:/static/scripts/tools/standalone_exe.py
|
||||
|
||||
USAGE = """
|
||||
Usage:
|
||||
Copy this and setup_exe.conf to web2py root folder
|
||||
To build with py2exe:
|
||||
Install py2exe: http://sourceforge.net/projects/py2exe/files/
|
||||
run python setup_exe.py py2exe
|
||||
To build with bbfreeze:
|
||||
Install bbfreeze: https://pypi.python.org/pypi/bbfreeze/
|
||||
run python setup_exe.py bbfreeze
|
||||
"""
|
||||
|
||||
from distutils.core import setup
|
||||
from gluon.import_all import base_modules, contributed_modules
|
||||
from gluon.fileutils import readlines_file
|
||||
from glob import glob
|
||||
import fnmatch
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
import re
|
||||
import zipfile
|
||||
|
||||
if len(sys.argv) != 2 or not os.path.isfile('web2py.py'):
|
||||
print USAGE
|
||||
sys.exit(1)
|
||||
BUILD_MODE = sys.argv[1]
|
||||
if not BUILD_MODE in ('py2exe', 'bbfreeze'):
|
||||
print USAGE
|
||||
sys.exit(1)
|
||||
|
||||
def unzip(source_filename, dest_dir):
|
||||
with zipfile.ZipFile(source_filename) as zf:
|
||||
zf.extractall(dest_dir)
|
||||
|
||||
#borrowed from http://bytes.com/topic/python/answers/851018-how-zip-directory-python-using-zipfile
|
||||
def recursive_zip(zipf, directory, folder=""):
|
||||
for item in os.listdir(directory):
|
||||
if os.path.isfile(os.path.join(directory, item)):
|
||||
zipf.write(os.path.join(directory, item), folder + os.sep + item)
|
||||
elif os.path.isdir(os.path.join(directory, item)):
|
||||
recursive_zip(
|
||||
zipf, os.path.join(directory, item), folder + os.sep + item)
|
||||
|
||||
|
||||
#read web2py version from VERSION file
|
||||
web2py_version_line = readlines_file('VERSION')[0]
|
||||
#use regular expression to get just the version number
|
||||
v_re = re.compile('[0-9]+\.[0-9]+\.[0-9]+')
|
||||
web2py_version = v_re.search(web2py_version_line).group(0)
|
||||
|
||||
#pull in preferences from config file
|
||||
import ConfigParser
|
||||
Config = ConfigParser.ConfigParser()
|
||||
Config.read('setup_exe.conf')
|
||||
remove_msft_dlls = Config.getboolean("Setup", "remove_microsoft_dlls")
|
||||
copy_apps = Config.getboolean("Setup", "copy_apps")
|
||||
copy_site_packages = Config.getboolean("Setup", "copy_site_packages")
|
||||
copy_scripts = Config.getboolean("Setup", "copy_scripts")
|
||||
make_zip = Config.getboolean("Setup", "make_zip")
|
||||
zip_filename = Config.get("Setup", "zip_filename")
|
||||
remove_build_files = Config.getboolean("Setup", "remove_build_files")
|
||||
include_gevent = Config.getboolean("Setup", "include_gevent")
|
||||
|
||||
# Python base version
|
||||
python_version = sys.version_info[:3]
|
||||
|
||||
|
||||
|
||||
if BUILD_MODE == 'py2exe':
|
||||
import py2exe
|
||||
|
||||
setup(
|
||||
console=[{'script':'web2py.py',
|
||||
'icon_resources': [(0, 'extras/icons/web2py.ico')]
|
||||
}],
|
||||
windows=[{'script':'web2py.py',
|
||||
'icon_resources': [(1, 'extras/icons/web2py.ico')],
|
||||
'dest_base':'web2py_no_console' # MUST NOT be just 'web2py' otherwise it overrides the standard web2py.exe
|
||||
}],
|
||||
name="web2py",
|
||||
version=web2py_version,
|
||||
description="web2py web framework",
|
||||
author="Massimo DiPierro",
|
||||
license="LGPL v3",
|
||||
data_files=[
|
||||
'ABOUT',
|
||||
'LICENSE',
|
||||
'VERSION'
|
||||
],
|
||||
options={'py2exe': {
|
||||
'packages': contributed_modules,
|
||||
'includes': base_modules,
|
||||
}},
|
||||
)
|
||||
#py2exe packages lots of duplicates in the library.zip, let's save some space
|
||||
library_temp_dir = os.path.join('dist', 'library_temp')
|
||||
library_zip_archive = os.path.join('dist', 'library.zip')
|
||||
os.makedirs(library_temp_dir)
|
||||
unzip(library_zip_archive, library_temp_dir)
|
||||
os.unlink(library_zip_archive)
|
||||
zipl = zipfile.ZipFile(library_zip_archive, "w", compression=zipfile.ZIP_DEFLATED)
|
||||
recursive_zip(zipl, library_temp_dir)
|
||||
zipl.close()
|
||||
shutil.rmtree(library_temp_dir)
|
||||
print "web2py binary successfully built"
|
||||
|
||||
elif BUILD_MODE == 'bbfreeze':
|
||||
modules = base_modules + contributed_modules
|
||||
from bbfreeze import Freezer
|
||||
f = Freezer(distdir="dist", includes=(modules))
|
||||
f.addScript("web2py.py")
|
||||
#to make executable without GUI we need this trick
|
||||
shutil.copy("web2py.py", "web2py_no_console.py")
|
||||
f.addScript("web2py_no_console.py", gui_only=True)
|
||||
if include_gevent:
|
||||
#fetch the gevented webserver script and copy to root
|
||||
gevented_webserver = os.path.join("handlers", "web2py_on_gevent.py")
|
||||
shutil.copy(gevented_webserver, "web2py_on_gevent.py")
|
||||
f.addScript("web2py_on_gevent.py")
|
||||
f.setIcon('extras/icons/web2py.ico')
|
||||
f() # starts the freezing process
|
||||
os.unlink("web2py_no_console.py")
|
||||
if include_gevent:
|
||||
os.unlink("web2py_on_gevent.py")
|
||||
#add data_files
|
||||
for req in ['ABOUT', 'LICENSE', 'VERSION']:
|
||||
shutil.copy(req, os.path.join('dist', req))
|
||||
print "web2py binary successfully built"
|
||||
|
||||
try:
|
||||
os.unlink('storage.sqlite')
|
||||
except:
|
||||
pass
|
||||
|
||||
#This need to happen after bbfreeze is run because Freezer() deletes distdir before starting!
|
||||
if python_version > (2,5):
|
||||
# Python26 compatibility: http://www.py2exe.org/index.cgi/Tutorial#Step52
|
||||
try:
|
||||
shutil.copytree('C:\Bin\Microsoft.VC90.CRT', 'dist/Microsoft.VC90.CRT/')
|
||||
except:
|
||||
print "You MUST copy Microsoft.VC90.CRT folder into the archive"
|
||||
|
||||
def copy_folders(source, destination):
|
||||
"""Copy files & folders from source to destination (within dist/)"""
|
||||
if os.path.exists(os.path.join('dist', destination)):
|
||||
shutil.rmtree(os.path.join('dist', destination))
|
||||
shutil.copytree(os.path.join(source), os.path.join('dist', destination))
|
||||
|
||||
#should we remove Windows OS dlls user is unlikely to be able to distribute
|
||||
if remove_msft_dlls:
|
||||
print "Deleted Microsoft files not licensed for open source distribution"
|
||||
print "You are still responsible for making sure you have the rights to distribute any other included files!"
|
||||
#delete the API-MS-Win-Core DLLs
|
||||
for f in glob('dist/API-MS-Win-*.dll'):
|
||||
os.unlink(f)
|
||||
#then delete some other files belonging to Microsoft
|
||||
other_ms_files = ['KERNELBASE.dll', 'MPR.dll', 'MSWSOCK.dll',
|
||||
'POWRPROF.dll']
|
||||
for f in other_ms_files:
|
||||
try:
|
||||
os.unlink(os.path.join('dist', f))
|
||||
except:
|
||||
print "unable to delete dist/" + f
|
||||
|
||||
#Should we include applications?
|
||||
if copy_apps:
|
||||
copy_folders('applications', 'applications')
|
||||
print "Your application(s) have been added"
|
||||
else:
|
||||
#only copy web2py's default applications
|
||||
copy_folders('applications/admin', 'applications/admin')
|
||||
copy_folders('applications/welcome', 'applications/welcome')
|
||||
copy_folders('applications/examples', 'applications/examples')
|
||||
print "Only web2py's admin, examples & welcome applications have been added"
|
||||
|
||||
copy_folders('extras', 'extras')
|
||||
copy_folders('examples', 'examples')
|
||||
copy_folders('handlers', 'handlers')
|
||||
|
||||
|
||||
#should we copy project's site-packages into dist/site-packages
|
||||
if copy_site_packages:
|
||||
#copy site-packages
|
||||
copy_folders('site-packages', 'site-packages')
|
||||
else:
|
||||
#no worries, web2py will create the (empty) folder first run
|
||||
print "Skipping site-packages"
|
||||
|
||||
#should we copy project's scripts into dist/scripts
|
||||
if copy_scripts:
|
||||
#copy scripts
|
||||
copy_folders('scripts', 'scripts')
|
||||
else:
|
||||
#no worries, web2py will create the (empty) folder first run
|
||||
print "Skipping scripts"
|
||||
|
||||
#should we create a zip file of the build?
|
||||
if make_zip:
|
||||
#create a web2py folder & copy dist's files into it
|
||||
shutil.copytree('dist', 'zip_temp/web2py')
|
||||
#create zip file
|
||||
zipf = zipfile.ZipFile(zip_filename + ".zip",
|
||||
"w", compression=zipfile.ZIP_DEFLATED)
|
||||
# just temp so the web2py directory is included in our zip file
|
||||
path = 'zip_temp'
|
||||
# leave the first folder as None, as path is root.
|
||||
recursive_zip(zipf, path)
|
||||
zipf.close()
|
||||
shutil.rmtree('zip_temp')
|
||||
print "Your Windows binary version of web2py can be found in " + \
|
||||
zip_filename + ".zip"
|
||||
print "You may extract the archive anywhere and then run web2py/web2py.exe"
|
||||
|
||||
#should py2exe build files be removed?
|
||||
if remove_build_files:
|
||||
if BUILD_MODE == 'py2exe':
|
||||
shutil.rmtree('build')
|
||||
shutil.rmtree('deposit')
|
||||
shutil.rmtree('dist')
|
||||
print "build files removed"
|
||||
|
||||
#final info
|
||||
if not make_zip and not remove_build_files:
|
||||
print "Your Windows binary & associated files can also be found in /dist"
|
||||
|
||||
print "Finished!"
|
||||
print "Enjoy web2py " + web2py_version_line
|
||||
52
extras/build_web2py/web2py.mac.spec
Normal file
@@ -0,0 +1,52 @@
|
||||
# -*- mode: python -*-
|
||||
|
||||
block_cipher = None
|
||||
|
||||
|
||||
a = Analysis(['web2py.py'],
|
||||
pathex=['.'],
|
||||
binaries=[('/System/Library/Frameworks/Tk.framework/Tk', 'tk'), ('/System/Library/Frameworks/Tcl.framework/Tcl', 'tcl')],
|
||||
datas=[],
|
||||
hiddenimports=['site-packages', 'cgi', 'cgitb', 'code', 'concurrent', 'concurrent.futures',
|
||||
'concurrent.futures._base', 'concurrent.futures.process', 'concurrent.futures.thread', 'configparser', 'cProfile', 'csv', 'ctypes.wintypes',
|
||||
'email.mime', 'email.mime.base', 'email.mime.multipart', 'email.mime.nonmultipart', 'email.mime.text', 'html.parser', 'http.cookies',
|
||||
'ipaddress', 'imaplib', 'imp', 'json', 'json.decoder', 'json.encoder', 'json.scanner', 'logging.config', 'logging.handlers', 'profile', 'pstats',
|
||||
'psycopg2', 'psycopg2._ipaddress', 'psycopg2._json', 'psycopg2._range', 'psycopg2.extensions', 'psycopg2.extras', 'psycopg2.sql',
|
||||
'psycopg2.tz', 'pyodbc', 'python-ldap', 'rlcompleter', 'sched', 'site', 'smtplib', 'sqlite3', 'sqlite3.dbapi2', 'sqlite3.dump', 'timeit', 'tkinter',
|
||||
'tkinter.commondialog', 'tkinter.constants', 'tkinter.messagebox', 'uuid', 'win32evtlogutil', 'wsgiref',
|
||||
'wsgiref.handlers', 'wsgiref.headers', 'wsgiref.simple_server', 'wsgiref.util', 'xml.dom', 'xml.dom.NodeFilter', 'xml.dom.domreg',
|
||||
'xml.dom.expatbuilder', 'xml.dom.minicompat', 'xml.dom.minidom', 'xml.dom.pulldom', 'xml.dom.xmlbuilder', 'xmlrpc.server'],
|
||||
hookspath=[],
|
||||
runtime_hooks=[],
|
||||
excludes=['gluon'],
|
||||
win_no_prefer_redirects=False,
|
||||
win_private_assemblies=False,
|
||||
cipher=block_cipher,
|
||||
noarchive=False)
|
||||
pyz = PYZ(a.pure, a.zipped_data,
|
||||
cipher=block_cipher)
|
||||
exe = EXE(pyz,
|
||||
a.scripts,
|
||||
[],
|
||||
exclude_binaries=True,
|
||||
name='web2py',
|
||||
debug=False,
|
||||
bootloader_ignore_signals=False,
|
||||
strip=False,
|
||||
upx=True,
|
||||
console=False,
|
||||
icon='extras/icons/web2py.icns')
|
||||
coll = COLLECT(exe,
|
||||
a.binaries,
|
||||
a.zipfiles,
|
||||
a.datas,
|
||||
strip=False,
|
||||
upx=True,
|
||||
name='web2py')
|
||||
app = BUNDLE(coll,
|
||||
name='web2py.app',
|
||||
icon='extras/icons/web2py.icns',
|
||||
bundle_identifier=None,
|
||||
info_plist={
|
||||
'NSPrincipleClass': 'NSApplication',
|
||||
'NSAppleScriptEnabled': False})
|
||||
44
extras/build_web2py/web2py.win.spec
Normal file
@@ -0,0 +1,44 @@
|
||||
# -*- mode: python -*-
|
||||
|
||||
block_cipher = None
|
||||
|
||||
|
||||
a = Analysis(['web2py.py'],
|
||||
pathex=['.'],
|
||||
binaries=[],
|
||||
datas=[],
|
||||
hiddenimports=['site-packages', 'cgi', 'cgitb', 'code', 'concurrent', 'concurrent.futures',
|
||||
'concurrent.futures._base', 'concurrent.futures.process', 'concurrent.futures.thread', 'configparser', 'csv', 'ctypes.wintypes',
|
||||
'email.mime', 'email.mime.base', 'email.mime.multipart', 'email.mime.nonmultipart', 'email.mime.text', 'html.parser', 'http.cookies',
|
||||
'ipaddress', 'imp', 'json', 'json.decoder', 'json.encoder', 'json.scanner', 'logging.config', 'logging.handlers', 'profile', 'pstats',
|
||||
'psycopg2', 'psycopg2._ipaddress', 'psycopg2._json', 'psycopg2._range', 'psycopg2.extensions', 'psycopg2.extras', 'psycopg2.sql',
|
||||
'psycopg2.tz', 'pyodbc', 'python-ldap', 'rlcompleter', 'sched', 'site', 'smtplib', 'sqlite3', 'sqlite3.dbapi2', 'sqlite3.dump', 'timeit', 'tkinter',
|
||||
'tkinter.commondialog', 'tkinter.constants', 'tkinter.messagebox', 'uuid', 'win32con', 'win32evtlogutil', 'winerror', 'wsgiref',
|
||||
'wsgiref.handlers', 'wsgiref.headers', 'wsgiref.simple_server', 'wsgiref.util', 'xml.dom', 'xml.dom.NodeFilter', 'xml.dom.domreg',
|
||||
'xml.dom.expatbuilder', 'xml.dom.minicompat', 'xml.dom.minidom', 'xml.dom.pulldom', 'xml.dom.xmlbuilder', 'xmlrpc.server'],
|
||||
hookspath=[],
|
||||
runtime_hooks=[],
|
||||
excludes=['gluon'],
|
||||
win_no_prefer_redirects=False,
|
||||
win_private_assemblies=False,
|
||||
cipher=block_cipher,
|
||||
noarchive=False)
|
||||
pyz = PYZ(a.pure, a.zipped_data,
|
||||
cipher=block_cipher)
|
||||
exe = EXE(pyz,
|
||||
a.scripts,
|
||||
[],
|
||||
exclude_binaries=True,
|
||||
name='web2py',
|
||||
debug=False,
|
||||
bootloader_ignore_signals=False,
|
||||
strip=False,
|
||||
upx=True,
|
||||
console=True , icon='extras\\icons\\web2py.ico')
|
||||
coll = COLLECT(exe,
|
||||
a.binaries,
|
||||
a.zipfiles,
|
||||
a.datas,
|
||||
strip=False,
|
||||
upx=True,
|
||||
name='web2py')
|
||||
44
extras/build_web2py/web2py.win_no_console.spec
Normal file
@@ -0,0 +1,44 @@
|
||||
# -*- mode: python -*-
|
||||
|
||||
block_cipher = None
|
||||
|
||||
|
||||
a = Analysis(['web2py.py'],
|
||||
pathex=['.'],
|
||||
binaries=[],
|
||||
datas=[],
|
||||
hiddenimports=['site-packages', 'cgi', 'cgitb', 'code', 'concurrent', 'concurrent.futures',
|
||||
'concurrent.futures._base', 'concurrent.futures.process', 'concurrent.futures.thread', 'configparser', 'csv', 'ctypes.wintypes',
|
||||
'email.mime', 'email.mime.base', 'email.mime.multipart', 'email.mime.nonmultipart', 'email.mime.text', 'html.parser', 'http.cookies',
|
||||
'ipaddress', 'imp', 'json', 'json.decoder', 'json.encoder', 'json.scanner', 'logging.config', 'logging.handlers', 'profile', 'pstats',
|
||||
'psycopg2', 'psycopg2._ipaddress', 'psycopg2._json', 'psycopg2._range', 'psycopg2.extensions', 'psycopg2.extras', 'psycopg2.sql',
|
||||
'psycopg2.tz', 'pyodbc', 'python-ldap', 'rlcompleter', 'sched', 'site', 'smtplib', 'sqlite3', 'sqlite3.dbapi2', 'sqlite3.dump', 'timeit', 'tkinter',
|
||||
'tkinter.commondialog', 'tkinter.constants', 'tkinter.messagebox', 'uuid', 'win32con', 'win32evtlogutil', 'winerror', 'wsgiref',
|
||||
'wsgiref.handlers', 'wsgiref.headers', 'wsgiref.simple_server', 'wsgiref.util', 'xml.dom', 'xml.dom.NodeFilter', 'xml.dom.domreg',
|
||||
'xml.dom.expatbuilder', 'xml.dom.minicompat', 'xml.dom.minidom', 'xml.dom.pulldom', 'xml.dom.xmlbuilder', 'xmlrpc.server'],
|
||||
hookspath=[],
|
||||
runtime_hooks=[],
|
||||
excludes=['gluon'],
|
||||
win_no_prefer_redirects=False,
|
||||
win_private_assemblies=False,
|
||||
cipher=block_cipher,
|
||||
noarchive=False)
|
||||
pyz = PYZ(a.pure, a.zipped_data,
|
||||
cipher=block_cipher)
|
||||
exe = EXE(pyz,
|
||||
a.scripts,
|
||||
[],
|
||||
exclude_binaries=True,
|
||||
name='web2py_no_console',
|
||||
debug=False,
|
||||
bootloader_ignore_signals=False,
|
||||
strip=False,
|
||||
upx=True,
|
||||
console=False , icon='extras\\icons\\web2py.ico')
|
||||
coll = COLLECT(exe,
|
||||
a.binaries,
|
||||
a.zipfiles,
|
||||
a.datas,
|
||||
strip=False,
|
||||
upx=True,
|
||||
name='web2py_no_console')
|
||||
12
fabfile.py
vendored
@@ -27,7 +27,7 @@ def create_user(username):
|
||||
run('EDITOR="cp /tmp/sudoers.new" visudo')
|
||||
uncomment('~%s/.bashrc' % username, '#force_color_prompt=yes')
|
||||
|
||||
def install_web2py():
|
||||
def install_web2py():
|
||||
"""fab -H username@host install_web2py"""
|
||||
sudo('wget https://raw.githubusercontent.com/web2py/web2py/master/scripts/%s' % INSTALL_SCRIPT)
|
||||
sudo('chmod +x %s' % INSTALL_SCRIPT)
|
||||
@@ -119,7 +119,7 @@ def deploy(appname=None, all=False):
|
||||
os.unlink(zipfile)
|
||||
|
||||
backup = mkdir_or_backup(appname)
|
||||
|
||||
|
||||
if all=='all' or not backup:
|
||||
local('zip -r _update.zip * -x *~ -x .* -x \#* -x *.bak -x *.bak2')
|
||||
else:
|
||||
@@ -131,10 +131,10 @@ def deploy(appname=None, all=False):
|
||||
sudo('unzip -o /tmp/_update.zip')
|
||||
sudo('chown -R www-data:www-data *')
|
||||
sudo('echo "%s" > DATE_DEPLOYMENT' % now)
|
||||
|
||||
|
||||
finally:
|
||||
sudo('rm /tmp/_update.zip')
|
||||
|
||||
|
||||
if backup:
|
||||
print 'TO RESTORE: fab restore:%s' % backup
|
||||
|
||||
@@ -154,10 +154,10 @@ def deploynobackup(appname=None):
|
||||
sudo('unzip -o /tmp/_update.zip')
|
||||
sudo('chown -R www-data:www-data *')
|
||||
sudo('echo "%s" > DATE_DEPLOYMENT' % now)
|
||||
|
||||
|
||||
finally:
|
||||
sudo('rm /tmp/_update.zip')
|
||||
|
||||
|
||||
def restore(backup):
|
||||
"""fab -H username@host restore:backupfilename"""
|
||||
appname = backup.split('/')[-1].split('.')[0]
|
||||
|
||||
@@ -36,7 +36,7 @@ REGEX_EXTEND = r"""^\s*(?P<all>\{\{\s*extend\s+['"](?P<name>[^'"]+)['"]\s*\}\})"
|
||||
REGEX_INCLUDE = r"""(?P<all>\{\{\s*include\s+['"](?P<name>[^'"]+)['"]\s*\}\})"""
|
||||
|
||||
|
||||
# TODO: swap arguments, let first ('r' or whatever) be mandatory
|
||||
# TODO: swap arguments, let first ('r' or whatever) be mandatory
|
||||
def apath(path='', r=None):
|
||||
"""Builds a path inside an application folder
|
||||
|
||||
|
||||
@@ -437,7 +437,7 @@ def compile_views(folder, skip_failed_views=False):
|
||||
"""
|
||||
path = pjoin(folder, 'views')
|
||||
failed_views = []
|
||||
for fname in listdir(path, REGEX_VIEW_PATH):
|
||||
for fname in listdir(path, REGEX_VIEW_PATH, followlinks=True):
|
||||
try:
|
||||
data = parse_template(fname, path)
|
||||
except Exception as e:
|
||||
@@ -462,7 +462,7 @@ def compile_models(folder):
|
||||
Compiles all the models in the application specified by `folder`
|
||||
"""
|
||||
path = pjoin(folder, 'models')
|
||||
for fname in listdir(path, REGEX_MODEL_PATH):
|
||||
for fname in listdir(path, REGEX_MODEL_PATH, followlinks=True):
|
||||
data = read_file(pjoin(path, fname))
|
||||
modelfile = 'models.'+fname.replace(os.sep, '.')
|
||||
filename = pjoin(folder, 'compiled', modelfile)
|
||||
@@ -487,7 +487,7 @@ def compile_controllers(folder):
|
||||
Compiles all the controllers in the application specified by `folder`
|
||||
"""
|
||||
path = pjoin(folder, 'controllers')
|
||||
for fname in listdir(path, REGEX_CONTROLLER):
|
||||
for fname in listdir(path, REGEX_CONTROLLER, followlinks=True):
|
||||
data = read_file(pjoin(path, fname))
|
||||
exposed = find_exposed_functions(data)
|
||||
for function in exposed:
|
||||
|
||||
@@ -23,9 +23,15 @@ for the benefit of code maintainers/developers:
|
||||
'--run_system_tests')
|
||||
- remember to allow the '-' too as word separator (e.g.
|
||||
'--run-system-tests') but do not use this form on help
|
||||
(add the minus version of the option to _omitted_opts
|
||||
to hide it in usage help)
|
||||
- prefer short names on help messages, instead use
|
||||
all options names in warning/error messages (e.g.
|
||||
'-R/--run requires -S/--shell')
|
||||
|
||||
Notice that options must be included into opt_map dictionary
|
||||
(defined in parse_args function) to be available in
|
||||
configuration file.
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
@@ -90,11 +96,12 @@ def console(version):
|
||||
# most of the options but do not show both versions on help
|
||||
_omitted_opts = ('--add-options', '--errors-to-console',
|
||||
'--no-banner', '--log-level', '--no-gui', '--import-models',
|
||||
'--force-migrate',
|
||||
'--server-name', '--server-key', '--server-cert', '--ca-cert',
|
||||
'--pid-filename', '--log-filename', '--min-threads',
|
||||
'--max-threads', '--request-queue-size', '--socket-timeout',
|
||||
'--profiler-dir', '--with-scheduler', '--with-cron',
|
||||
'--soft-cron', '--cron-run',
|
||||
'--cron-threads', '--soft-cron', '--cron-run',
|
||||
'--run-doctests', '--run-system-tests', '--with-coverage')
|
||||
|
||||
_hidden_options = _omitted_opts + tuple(deprecated_opts.keys())
|
||||
@@ -259,6 +266,17 @@ web2py will attempt to run a GUI to ask for it when starting the web server
|
||||
'(default is %(default)s), see -S above. NOTE: when the APP_ENV '
|
||||
'argument of -S include a controller c automatic import of '
|
||||
'models is always enabled')
|
||||
g.add_argument('--fake_migrate',
|
||||
default=False,
|
||||
action='store_true',
|
||||
help=
|
||||
'force DAL to fake migrate all tables; '
|
||||
'monkeypatch in the DAL class to force _fake_migrate=True')
|
||||
g.add_argument('--force_migrate', '--force-migrate',
|
||||
default=False,
|
||||
action='store_true', help=
|
||||
'force DAL to migrate all tables that should be migrated when enabled; '
|
||||
'monkeypatch in the DAL class to force _migrate_enabled=True')
|
||||
g.add_argument('-R', '--run',
|
||||
type=existing_file,
|
||||
metavar='PYTHON_FILE', help=
|
||||
@@ -446,6 +464,19 @@ web2py will attempt to run a GUI to ask for it when starting the web server
|
||||
'only, the default behaviour is to read the crontab for all of the '
|
||||
'installed applications. NOTE: this option can be used multiple '
|
||||
'times to build the list of crontabs to be processed by cron')
|
||||
def positive_int(v, err_label='value'):
|
||||
try:
|
||||
iv = int(v)
|
||||
if iv <= 0: raise ValueError()
|
||||
return iv
|
||||
except ValueError:
|
||||
pass
|
||||
raise argparse.ArgumentTypeError("bad %s %s" % (err_label, v))
|
||||
def cron_threads(v):
|
||||
return positive_int(v, err_label='cron_threads')
|
||||
g.add_argument('--cron_threads', '--cron-threads',
|
||||
type=cron_threads, metavar='NUM',
|
||||
help='maximum number of cron threads (5)')
|
||||
g.add_argument('--soft_cron', '--soft-cron',
|
||||
'--softcron', # deprecated
|
||||
default=False,
|
||||
@@ -658,6 +689,7 @@ def parse_args(parser, cli_args, deprecated_opts, integer_log_level,
|
||||
'bpython': store_true,
|
||||
'plain': store_true,
|
||||
'import_models': store_true,
|
||||
'force_migrate': store_true,
|
||||
'run': str_or_default,
|
||||
'args': list_or_default,
|
||||
# web server options
|
||||
@@ -682,6 +714,7 @@ def parse_args(parser, cli_args, deprecated_opts, integer_log_level,
|
||||
# cron options
|
||||
'with_cron': store_true,
|
||||
'crontab': list_or_default,
|
||||
'cron_threads': str_or_default,
|
||||
'soft_cron': store_true,
|
||||
'cron_run': store_true,
|
||||
# test options
|
||||
|
||||
@@ -118,7 +118,7 @@ def saml2_handler(session, request, config_filename = None, entityid = None):
|
||||
elif request.env.request_method == 'POST':
|
||||
binding = BINDING_HTTP_POST
|
||||
if not request.vars.SAMLResponse:
|
||||
req_id, req = client.create_authn_request(destination, binding=binding)
|
||||
req_id, req = client.create_authn_request(destination, binding=BINDING_HTTP_POST)
|
||||
relay_state = web2py_uuid().replace('-','')
|
||||
session.saml_outstanding_queries = {req_id: request.url}
|
||||
session.saml_req_id = req_id
|
||||
|
||||
@@ -18,14 +18,14 @@ regex_title = re.compile('^#{1} (?P<t>[^\n]+)', re.M)
|
||||
regex_maps = [
|
||||
(re.compile('[ \t\r]+\n'), '\n'),
|
||||
(re.compile('\*\*(?P<t>[^\s\*]+( +[^\s\*]+)*)\*\*'), '{\\\\bf \g<t>}'),
|
||||
(re.compile("''(?P<t>[^\s']+( +[^\s']+)*)''"), '{\\it \g<t>}'),
|
||||
(re.compile("''(?P<t>[^\s']+( +[^\s']+)*)''"), '{\\\it \g<t>}'),
|
||||
(re.compile('^#{5,6}\s*(?P<t>[^\n]+)', re.M), '\n\n{\\\\bf \g<t>}\n'),
|
||||
(re.compile('^#{4}\s*(?P<t>[^\n]+)', re.M), '\n\n\\\\goodbreak\\subsubsection{\g<t>}\n'),
|
||||
(re.compile('^#{3}\s*(?P<t>[^\n]+)', re.M), '\n\n\\\\goodbreak\\subsection{\g<t>}\n'),
|
||||
(re.compile('^#{2}\s*(?P<t>[^\n]+)', re.M), '\n\n\\\\goodbreak\\section{\g<t>}\n'),
|
||||
(re.compile('^#{4}\s*(?P<t>[^\n]+)', re.M), '\n\n\\\\goodbreak\\\subsubsection{\g<t>}\n'),
|
||||
(re.compile('^#{3}\s*(?P<t>[^\n]+)', re.M), '\n\n\\\\goodbreak\\\subsection{\g<t>}\n'),
|
||||
(re.compile('^#{2}\s*(?P<t>[^\n]+)', re.M), '\n\n\\\\goodbreak\\\section{\g<t>}\n'),
|
||||
(re.compile('^#{1}\s*(?P<t>[^\n]+)', re.M), ''),
|
||||
(re.compile('^\- +(?P<t>.*)', re.M), '\\\\begin{itemize}\n\\item \g<t>\n\\end{itemize}'),
|
||||
(re.compile('^\+ +(?P<t>.*)', re.M), '\\\\begin{itemize}\n\\item \g<t>\n\\end{itemize}'),
|
||||
(re.compile('^\- +(?P<t>.*)', re.M), '\\\\begin{itemize}\n\\\item \g<t>\n\\\end{itemize}'),
|
||||
(re.compile('^\+ +(?P<t>.*)', re.M), '\\\\begin{itemize}\n\\\item \g<t>\n\\\end{itemize}'),
|
||||
(re.compile('\\\\end\{itemize\}\s+\\\\begin\{itemize\}'), '\n'),
|
||||
(re.compile('\n\s+\n'), '\n\n')]
|
||||
regex_table = re.compile('^\-{4,}\n(?P<t>.*?)\n\-{4,}(:(?P<c>\w+))?\n', re.M | re.S)
|
||||
@@ -97,7 +97,7 @@ def render(text,
|
||||
text = latex_escape(text, pound=False)
|
||||
|
||||
texts = text.split('## References', 1)
|
||||
text = regex_anchor.sub('\\label{\g<t>}', texts[0])
|
||||
text = regex_anchor.sub('\\\label{\g<t>}', texts[0])
|
||||
if len(texts) == 2:
|
||||
text += '\n\\begin{thebibliography}{999}\n'
|
||||
text += regex_bibitem.sub('\n\\\\bibitem{\g<t>}', texts[1])
|
||||
@@ -145,7 +145,7 @@ def render(text,
|
||||
text = regex_image_width.sub(sub, text)
|
||||
text = regex_image.sub(sub, text)
|
||||
|
||||
text = regex_link.sub('{\\\\footnotesize\\href{\g<k>}{\g<t>}}', text)
|
||||
text = regex_link.sub('{\\\\footnotesize\\\href{\g<k>}{\g<t>}}', text)
|
||||
text = regex_commas.sub('\g<t>', text)
|
||||
text = regex_noindent.sub('\n\\\\noindent \g<t>', text)
|
||||
|
||||
|
||||
4
gluon/contrib/plural_rules/fa.py
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf8 -*-
|
||||
# Plural-Forms for fa (Persian)
|
||||
0
gluon/contrib/pymysql/README.rst
Executable file → Normal file
@@ -64,7 +64,7 @@ class WebClient(object):
|
||||
headers=headers, method='GET')
|
||||
|
||||
def post(self, url, data=None, cookies=None,
|
||||
headers=None, auth=None, method='auto'):
|
||||
headers=None, auth=None, method='auto', charset='utf-8'):
|
||||
self.url = self.app + url
|
||||
|
||||
# if this POST form requires a postback do it
|
||||
@@ -147,7 +147,11 @@ class WebClient(object):
|
||||
else:#python2.5
|
||||
self.status = None
|
||||
|
||||
self.text = to_native(self.response.read())
|
||||
self.text = self.response.read()
|
||||
if charset:
|
||||
if charset == 'auto':
|
||||
charset = self.response.headers.getparam('charset')
|
||||
self.text = to_native(self.text, charset)
|
||||
# In PY3 self.response.headers are case sensitive
|
||||
self.headers = dict()
|
||||
for h in self.response.headers:
|
||||
@@ -173,9 +177,10 @@ class WebClient(object):
|
||||
self.sessions[name] = value
|
||||
|
||||
# find all forms and formkeys in page
|
||||
self.forms = {}
|
||||
for match in FORM_REGEX.finditer(to_native(self.text)):
|
||||
self.forms[match.group('formname')] = match.group('formkey')
|
||||
if charset:
|
||||
self.forms = {}
|
||||
for match in FORM_REGEX.finditer(self.text):
|
||||
self.forms[match.group('formname')] = match.group('formkey')
|
||||
|
||||
# log this request
|
||||
self.history.append((self.method, self.url, self.status, self.time))
|
||||
|
||||
@@ -148,7 +148,8 @@ def listdir(path,
|
||||
add_dirs=False,
|
||||
sort=True,
|
||||
maxnum=None,
|
||||
exclude_content_from=None
|
||||
exclude_content_from=None,
|
||||
followlinks=False
|
||||
):
|
||||
"""
|
||||
Like `os.listdir()` but you can specify a regex pattern to filter files.
|
||||
@@ -164,7 +165,7 @@ def listdir(path,
|
||||
n = 0
|
||||
regex = re.compile(expression)
|
||||
items = []
|
||||
for (root, dirs, files) in os.walk(path, topdown=True):
|
||||
for (root, dirs, files) in os.walk(path, topdown=True, followlinks=followlinks):
|
||||
for dir in dirs[:]:
|
||||
if dir.startswith('.'):
|
||||
dirs.remove(dir)
|
||||
|
||||
@@ -392,6 +392,12 @@ class lazyT(object):
|
||||
def __eq__(self, other):
|
||||
return str(self) == str(other)
|
||||
|
||||
def __lt__(self, other):
|
||||
return str(self) < str(other)
|
||||
|
||||
def __gt__(self, other):
|
||||
return str(self) > str(other)
|
||||
|
||||
def __ne__(self, other):
|
||||
return str(self) != str(other)
|
||||
|
||||
|
||||
@@ -334,7 +334,7 @@ class SimplePool(object):
|
||||
self.running = set()
|
||||
|
||||
def grow(self, size):
|
||||
if size > self.size:
|
||||
if size and size > self.size:
|
||||
self.size = size
|
||||
|
||||
def start(self, t):
|
||||
@@ -380,8 +380,14 @@ class SimplePool(object):
|
||||
|
||||
_dancer = SimplePool(5, worker_cls=SoftWorker)
|
||||
|
||||
def dancer_size(size):
|
||||
_dancer.grow(size)
|
||||
|
||||
_launcher = SimplePool(5)
|
||||
|
||||
def launcher_size(size):
|
||||
_launcher.grow(size)
|
||||
|
||||
def crondance(applications_parent, ctype='hard', startup=False, apps=None):
|
||||
"""
|
||||
Does the periodic job of cron service: read the crontab(s) and launch
|
||||
|
||||
@@ -204,7 +204,7 @@ def url_out(request, environ, application, controller, function,
|
||||
if host is True or (host is None and (scheme or port is not None)):
|
||||
host = request.env.http_host
|
||||
if not scheme or scheme is True:
|
||||
scheme = request.env.get('wsgi_url_scheme', 'http').lower() if request else 'http'
|
||||
scheme = 'https' if request and request.is_https else 'http'
|
||||
if host:
|
||||
host_port = host if not port else host.split(':', 1)[0] + ':%s' % port
|
||||
url = '%s://%s%s' % (scheme, host_port, url)
|
||||
|
||||
@@ -28,7 +28,6 @@ from gluon.restricted import RestrictedError
|
||||
from gluon.globals import Request, Response, Session
|
||||
from gluon.storage import Storage, List
|
||||
from gluon.admin import w2p_unpack
|
||||
from gluon.fileutils import create_missing_app_folders
|
||||
from pydal.base import BaseAdapter
|
||||
from gluon._compat import iteritems, ClassType, PY2
|
||||
|
||||
@@ -167,9 +166,6 @@ def env(
|
||||
path_info = '%s?%s' % (path_info, '&'.join(vars))
|
||||
request.env.path_info = path_info
|
||||
|
||||
# Ensure necessary folders are created
|
||||
create_missing_app_folders(request)
|
||||
|
||||
# Monkey patch so credentials checks pass.
|
||||
|
||||
def check_credentials(request, other_application='admin'):
|
||||
@@ -220,7 +216,9 @@ def run(
|
||||
bpython=False,
|
||||
python_code=None,
|
||||
cron_job=False,
|
||||
scheduler_job=False):
|
||||
scheduler_job=False,
|
||||
force_migrate=False,
|
||||
fake_migrate=False):
|
||||
"""
|
||||
Start interactive shell or run Python script (startfile) in web2py
|
||||
controller environment. appname is formatted like:
|
||||
@@ -250,6 +248,21 @@ def run(
|
||||
os.mkdir(adir)
|
||||
fileutils.create_app(adir)
|
||||
|
||||
if force_migrate:
|
||||
c = 'appadmin' # Load all models (hack already used for appadmin controller)
|
||||
import_models = True
|
||||
from gluon.dal import DAL
|
||||
orig_init = DAL.__init__
|
||||
|
||||
def custom_init(*args, **kwargs):
|
||||
kwargs['migrate_enabled'] = True
|
||||
kwargs['migrate'] = True
|
||||
kwargs['fake_migrate'] = fake_migrate
|
||||
logger.info('Forcing migrate_enabled=True')
|
||||
orig_init(*args, **kwargs)
|
||||
|
||||
DAL.__init__ = custom_init
|
||||
|
||||
if c:
|
||||
import_models = True
|
||||
extra_request = {}
|
||||
@@ -265,7 +278,7 @@ def run(
|
||||
if c:
|
||||
pyfile = os.path.join('applications', a, 'controllers', c + '.py')
|
||||
pycfile = os.path.join('applications', a, 'compiled',
|
||||
"controllers_%s_%s.pyc" % (c, f))
|
||||
"controllers.%s.%s.pyc" % (c, f))
|
||||
if ((cron_job and os.path.isfile(pycfile))
|
||||
or not os.path.isfile(pyfile)):
|
||||
exec(read_pyc(pycfile), _env)
|
||||
@@ -303,6 +316,15 @@ def run(
|
||||
print(traceback.format_exc())
|
||||
if import_models:
|
||||
BaseAdapter.close_all_instances('rollback')
|
||||
elif force_migrate:
|
||||
try:
|
||||
execfile("scripts/migrator.py", _env)
|
||||
if import_models:
|
||||
BaseAdapter.close_all_instances('commit')
|
||||
except:
|
||||
print(traceback.format_exc())
|
||||
if import_models:
|
||||
BaseAdapter.close_all_instances('rollback')
|
||||
else:
|
||||
if not plain:
|
||||
if bpython:
|
||||
|
||||