Merge pull request #2 from web2py/master

Merge w/ current master
This commit is contained in:
Mirko authored and GitHub committed 2019-09-02 13:43:56 +02:00
commit 4191d4c48c
374 files changed
+3559 -3073

No files matched your search

+2 -8
View File
@@ -1,27 +1,21 @@
language: python language: python
sudo: required sudo: required
cache: pip cache: pip
dist: "bionic"
dist: "xenial"
services: services:
- mysql - mysql
python: python:
- '2.7' - '2.7'
- '3.5'
- '3.6' - '3.6'
- '3.6-dev'
- '3.7' - '3.7'
- '3.7-dev'
- 'pypy3.5' - 'pypy3.5'
matrix: matrix:
allow_failures: allow_failures:
- python: '3.6-dev' - python: 'pypy3.5'
- python: '3.7-dev'
install: install:
- pip install -e . - pip install -e .
+23 -2
View File
@@ -1,5 +1,26 @@
## 2.18.1-2.18.4 ## 2.19.0
- pydal 19.02 - new command line options (Thanks Paolo Pastori)
OLD NAME NEW NAME
================== ==================
--debug --log_level
--nogui --no_gui
--ssl_private_key --server_key
--ssl_certificate --server_cert
--minthreads --min_threads
--maxthreads --max_threads
--profiler --profiler_dir
--run-cron --with_cron
--softcron --soft_cron
--cron --cron_run
--cronjob * --cron_job *
--test --run_doctests
--add_options
--interface
--crontab
## 2.18.1-2.18.5
- pydal 19.04
- made template its own module (Yet Another Template Language) - made template its own module (Yet Another Template Language)
- improved python 3.4-3.7 support - improved python 3.4-3.7 support
- better regular expressions - better regular expressions
+3 -3
View File
@@ -19,11 +19,11 @@ clean:
find applications/welcome/ -name '.*' -exec rm -f {} \; find applications/welcome/ -name '.*' -exec rm -f {} \;
find . -name '*.pyc' -exec rm -f {} \; find . -name '*.pyc' -exec rm -f {} \;
tests: tests:
python web2py.py --run_system_tests python web2py.py --verbose --run_system_tests
coverage: coverage:
coverage erase --rcfile=gluon/tests/coverage.ini coverage erase --rcfile=gluon/tests/coverage.ini
export COVERAGE_PROCESS_START=gluon/tests/coverage.ini export COVERAGE_PROCESS_START=gluon/tests/coverage.ini
python web2py.py --run_system_tests --with_coverage python web2py.py --verbose --run_system_tests --with_coverage
coverage combine --rcfile=gluon/tests/coverage.ini coverage combine --rcfile=gluon/tests/coverage.ini
sleep 1 sleep 1
coverage html --rcfile=gluon/tests/coverage.ini coverage html --rcfile=gluon/tests/coverage.ini
@@ -45,7 +45,7 @@ rmfiles:
rm -rf applications/examples/uploads/* rm -rf applications/examples/uploads/*
src: src:
### Use semantic versioning ### Use semantic versioning
echo 'Version 2.18.4-stable+timestamp.'`date +%Y.%m.%d.%H.%M.%S` > VERSION echo 'Version 2.18.5-stable+timestamp.'`date +%Y.%m.%d.%H.%M.%S` > VERSION
### rm -f all junk files ### rm -f all junk files
make clean make clean
# make rmfiles # make rmfiles
+1 -1
View File
@@ -1 +1 @@
Version 2.18.4-stable+timestamp.2019.03.12.22.20.22 Version 2.18.5-stable+timestamp.2019.04.07.21.13.59
+39 -39
View File
@@ -30,7 +30,7 @@ except:
if request.is_https: if request.is_https:
session.secure() 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'): (request.function != 'manage'):
raise HTTP(200, T('appadmin is disabled because insecure channel')) raise HTTP(200, T('appadmin is disabled because insecure channel'))
@@ -46,7 +46,7 @@ if request.function == 'manage':
auth.table_permission()]) auth.table_permission()])
manager_role = manager_action.get('role', None) if manager_action else None 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)): 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 menu = False
elif (request.application == 'admin' and not session.authorized) or \ elif (request.application == 'admin' and not session.authorized) or \
(request.application != 'admin' and not gluon.fileutils.check_credentials(request)): (request.application != 'admin' and not gluon.fileutils.check_credentials(request)):
@@ -182,7 +182,7 @@ def select():
db = get_database(request) db = get_database(request)
dbname = request.args[0] dbname = request.args[0]
try: try:
is_imap = db._uri.startswith("imap://") is_imap = db._uri.startswith('imap://')
except (KeyError, AttributeError, TypeError): except (KeyError, AttributeError, TypeError):
is_imap = False is_imap = False
regex = re.compile(r'(?P<table>\w+)\.(?P<field>\w+)=(?P<value>\d+)') 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_orderby = orderby
session.last_query = request.vars.query session.last_query = request.vars.query
form = FORM(TABLE(TR(T('Query:'), '', INPUT(_style='width:400px', form = FORM(TABLE(TR(T('Query:'), '', INPUT(_style='width:400px',
_name='query', _value=request.vars.query or '', _class="form-control", _name='query', _value=request.vars.query or '', _class='form-control',
requires=IS_NOT_EMPTY( 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', INPUT(_name='update_check', _type='checkbox',
value=False), INPUT(_style='width:400px', value=False), INPUT(_style='width:400px',
_name='update_fields', _value=request.vars.update_fields _name='update_fields', _value=request.vars.update_fields
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), ''), _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)) _action=URL(r=request, args=request.args))
tb = None tb = None
@@ -254,8 +254,8 @@ def select():
if is_imap: if is_imap:
fields = [db[table][name] for name in fields = [db[table][name] for name in
("id", "uid", "created", "to", ('id', 'uid', 'created', 'to',
"sender", "subject")] 'sender', 'subject')]
if orderby: if orderby:
rows = db(query, ignore_common_filters=True).select( rows = db(query, ignore_common_filters=True).select(
*fields, limitby=(start, stop), *fields, limitby=(start, stop),
@@ -271,10 +271,10 @@ def select():
# begin handle upload csv # begin handle upload csv
csv_table = table or request.vars.table csv_table = table or request.vars.table
if csv_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='file', _name='csvfile'),
INPUT(_type='hidden', _value=csv_table, _name='table'), 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: else:
formcsv = None formcsv = None
if formcsv and formcsv.process().accepted: if formcsv and formcsv.process().accepted:
@@ -356,26 +356,26 @@ def state():
def ccache(): def ccache():
if is_gae: if is_gae:
form = FORM( 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: else:
cache.ram.initialize() cache.ram.initialize()
cache.disk.initialize() cache.disk.initialize()
form = FORM( form = FORM(
P(TAG.BUTTON( P(TAG.BUTTON(
T("Clear CACHE?"), _type="submit", _name="yes", _value="yes")), T('Clear CACHE?'), _type='submit', _name='yes', _value='yes')),
P(TAG.BUTTON( P(TAG.BUTTON(
T("Clear RAM"), _type="submit", _name="ram", _value="ram")), T('Clear RAM'), _type='submit', _name='ram', _value='ram')),
P(TAG.BUTTON( 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): if form.accepts(request.vars, session):
session.flash = "" session.flash = ''
if is_gae: if is_gae:
if request.vars.yes: if request.vars.yes:
cache.ram.clear() cache.ram.clear()
session.flash += T("Cache Cleared") session.flash += T('Cache Cleared')
else: else:
clear_ram = False clear_ram = False
clear_disk = False clear_disk = False
@@ -387,10 +387,10 @@ def ccache():
clear_disk = True clear_disk = True
if clear_ram: if clear_ram:
cache.ram.clear() cache.ram.clear()
session.flash += T("Ram Cleared") session.flash += T('Ram Cleared')
if clear_disk: if clear_disk:
cache.disk.clear() cache.disk.clear()
session.flash += T("Disk Cleared") session.flash += T('Disk Cleared')
redirect(URL(r=request)) redirect(URL(r=request))
try: try:
@@ -436,7 +436,7 @@ def ccache():
gae_stats['ratio'] = ((gae_stats['hits'] * 100) / gae_stats['ratio'] = ((gae_stats['hits'] * 100) /
(gae_stats['hits'] + gae_stats['misses'])) (gae_stats['hits'] + gae_stats['misses']))
except ZeroDivisionError: except ZeroDivisionError:
gae_stats['ratio'] = T("?") gae_stats['ratio'] = T('?')
gae_stats['oldest'] = GetInHMS(time.time() - gae_stats['oldest_item_age']) gae_stats['oldest'] = GetInHMS(time.time() - gae_stats['oldest_item_age'])
total.update(gae_stats) total.update(gae_stats)
else: else:
@@ -502,7 +502,7 @@ def ccache():
TR(TD(B(T('Key'))), TD(B(T('Time in Cache (h:m:s)')))), 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], *[TR(TD(k[0]), TD('%02d:%02d:%02d' % k[1])) for k in keys],
**dict(_class='cache-keys', **dict(_class='cache-keys',
_style="border-collapse: separate; border-spacing: .5em;")) _style='border-collapse: separate; border-spacing: .5em;'))
if not is_gae: if not is_gae:
ram['keys'] = key_table(ram['keys']) ram['keys'] = key_table(ram['keys'])
@@ -536,26 +536,26 @@ def table_template(table):
# This is horribe HTML but the only one graphiz understands # This is horribe HTML but the only one graphiz understands
rows = [] rows = []
cellpadding = 4 cellpadding = 4
color = "#000000" color = '#000000'
bgcolor = "#FFFFFF" bgcolor = '#FFFFFF'
face = "Helvetica" face = 'Helvetica'
face_bold = "Helvetica Bold" face_bold = 'Helvetica Bold'
border = 0 border = 0
rows.append(TR(TD(FONT(table, _face=face_bold, _color=bgcolor), rows.append(TR(TD(FONT(table, _face=face_bold, _color=bgcolor),
_colspan=3, _cellpadding=cellpadding, _colspan=3, _cellpadding=cellpadding,
_align="center", _bgcolor=color))) _align='center', _bgcolor=color)))
for row in db[table]: for row in db[table]:
rows.append(TR(TD(FONT(row.name, _color=color, _face=face_bold), rows.append(TR(TD(FONT(row.name, _color=color, _face=face_bold),
_align="left", _cellpadding=cellpadding, _align='left', _cellpadding=cellpadding,
_border=border), _border=border),
TD(FONT(row.type, _color=color, _face=face), TD(FONT(row.type, _color=color, _face=face),
_align="left", _cellpadding=cellpadding, _align='left', _cellpadding=cellpadding,
_border=border), _border=border),
TD(FONT(types(row), _color=color, _face=face), TD(FONT(types(row), _color=color, _face=face),
_align="center", _cellpadding=cellpadding, _align='center', _cellpadding=cellpadding,
_border=border))) _border=border)))
return "< %s >" % TABLE(*rows, **dict(_bgcolor=bgcolor, _border=1, return '< %s >' % TABLE(*rows, **dict(_bgcolor=bgcolor, _border=1,
_cellborder=0, _cellspacing=0) _cellborder=0, _cellspacing=0)
).xml() ).xml()
@@ -632,15 +632,15 @@ def hooks():
if len(functions): if len(functions):
method_hooks.append({'name': op, 'functions':functions}) method_hooks.append({'name': op, 'functions':functions})
if len(method_hooks): 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 # Render
ul_main = UL(_class='nav nav-list') ul_main = UL(_class='nav nav-list')
for t in tables: for t in tables:
ul_main.append(A(t['name'], _onclick="collapse('a_%s')" % t['slug'])) 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']: for op in t['method_hooks']:
ul_t.append(LI(op['name'])) 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) ul_main.append(ul_t)
return ul_main return ul_main
@@ -650,11 +650,11 @@ def hooks():
# ########################################################### # ###########################################################
def d3_graph_model(): 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 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 = [] nodes = []
links = [] links = []
@@ -670,10 +670,10 @@ def d3_graph_model():
elif f_type == 'string': elif f_type == 'string':
disp = field.length disp = field.length
elif f_type == 'id': elif f_type == 'id':
disp = "PK" disp = 'PK'
elif f_type.startswith('reference') or \ elif f_type.startswith('reference') or \
f_type.startswith('list:reference'): f_type.startswith('list:reference'):
disp = "FK" disp = 'FK'
else: else:
disp = ' ' disp = ' '
fields.append(dict(name=field.name, type=field.type, disp=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)) 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. # 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')) response.files.append(URL('admin','static','js/d3.min.js'))
+22 -13
View File
@@ -166,9 +166,9 @@ def check_version():
new_version, version = check_new_version(request.env.web2py_version, new_version, version = check_new_version(request.env.web2py_version,
WEB2PY_VERSION_URL) WEB2PY_VERSION_URL)
if new_version == -1: if new_version in (-1, -2):
return A(T('Unable to check for upgrades'), _href=WEB2PY_URL) return A(T('Unable to check for upgrades'), _href=WEB2PY_URL)
elif new_version != True: elif not new_version:
return A(T('web2py is up to date'), _href=WEB2PY_URL) return A(T('web2py is up to date'), _href=WEB2PY_URL)
elif platform.system().lower() in ('windows', 'win32', 'win64') and os.path.exists("web2py.exe"): elif platform.system().lower() in ('windows', 'win32', 'win64') and os.path.exists("web2py.exe"):
return SPAN('You should upgrade to %s' % version.split('(')[0]) return SPAN('You should upgrade to %s' % version.split('(')[0])
@@ -814,8 +814,11 @@ def edit():
if len(request.args) > 2 and request.args[1] == 'controllers': if len(request.args) > 2 and request.args[1] == 'controllers':
controller = (request.args[2])[:-3] controller = (request.args[2])[:-3]
functions = find_exposed_functions(data) try:
functions = functions and sorted(functions) or [] functions = find_exposed_functions(data)
functions = functions and sorted(functions) or []
except SyntaxError as err:
functions = ['SyntaxError:Line:%d' % err.lineno]
else: else:
(controller, functions) = (None, None) (controller, functions) = (None, None)
@@ -1117,7 +1120,7 @@ def design():
defines = {} defines = {}
for m in models: for m in models:
data = safe_read(apath('%s/models/%s' % (app, m), r=request)) data = safe_read(apath('%s/models/%s' % (app, m), r=request))
defines[m] = regex_tables.findall(data) defines[m] = re.findall(REGEX_DEFINE_TABLE, data, re.MULTILINE)
defines[m].sort() defines[m].sort()
# Get all controllers # Get all controllers
@@ -1127,8 +1130,11 @@ def design():
functions = {} functions = {}
for c in controllers: for c in controllers:
data = safe_read(apath('%s/controllers/%s' % (app, c), r=request)) data = safe_read(apath('%s/controllers/%s' % (app, c), r=request))
items = find_exposed_functions(data) try:
functions[c] = items and sorted(items) or [] items = find_exposed_functions(data)
functions[c] = items and sorted(items) or []
except SyntaxError as err:
functions[c] = ['SyntaxError:Line:%d' % err.lineno]
# Get all views # Get all views
views = sorted( views = sorted(
@@ -1138,12 +1144,12 @@ def design():
include = {} include = {}
for c in views: for c in views:
data = safe_read(apath('%s/views/%s' % (app, c), r=request)) data = safe_read(apath('%s/views/%s' % (app, c), r=request))
items = regex_extend.findall(data) items = re.findall(REGEX_EXTEND, data, re.MULTILINE)
if items: if items:
extend[c] = items[0][1] extend[c] = items[0][1]
items = regex_include.findall(data) items = re.findall(REGEX_INCLUDE, data)
include[c] = [i[1] for i in items] include[c] = [i[1] for i in items]
# Get all modules # Get all modules
@@ -1265,8 +1271,11 @@ def plugin():
functions = {} functions = {}
for c in controllers: for c in controllers:
data = safe_read(apath('%s/controllers/%s' % (app, c), r=request)) data = safe_read(apath('%s/controllers/%s' % (app, c), r=request))
items = find_exposed_functions(data) try:
functions[c] = items and sorted(items) or [] items = find_exposed_functions(data)
functions[c] = items and sorted(items) or []
except SyntaxError as err:
functions[c] = ['SyntaxError:Line:%d' % err.lineno]
# Get all views # Get all views
views = sorted( views = sorted(
@@ -1276,11 +1285,11 @@ def plugin():
include = {} include = {}
for c in views: for c in views:
data = safe_read(apath('%s/views/%s' % (app, c), r=request)) data = safe_read(apath('%s/views/%s' % (app, c), r=request))
items = regex_extend.findall(data) items = re.findall(REGEX_EXTEND, data, re.MULTILINE)
if items: if items:
extend[c] = items[0][1] extend[c] = items[0][1]
items = regex_include.findall(data) items = re.findall(REGEX_INCLUDE, data)
include[c] = [i[1] for i in items] include[c] = [i[1] for i in items]
# Get all modules # Get all modules
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
-1
View File
@@ -25,6 +25,5 @@ from gluon.utils import md5_hash
from gluon.fileutils import listdir, cleanpath, up from gluon.fileutils import listdir, cleanpath, up
from gluon.fileutils import tar, tar_compiled, untar, fix_newlines from gluon.fileutils import tar, tar_compiled, untar, fix_newlines
from gluon.languages import findT, update_all_languages from gluon.languages import findT, update_all_languages
from gluon.myregex import *
from gluon.restricted import * from gluon.restricted import *
from gluon.compileapp import compile_application, remove_compiled_application from gluon.compileapp import compile_application, remove_compiled_application
+7 -4
View File
@@ -1,9 +1,12 @@
[DEFAULT]
[editor] [editor]
theme = web2py theme = twilight
editor = default editor = sublime
closetag = true closetag = true
tabwidth = 4
highlightline = true
linenumbers = true
codefolding = false
indentwithtabs = false
[editor_sessions] [editor_sessions]
welcome = welcome/models/db.py,welcome/controllers/default.py,welcome/views/default/index.html welcome = welcome/models/db.py,welcome/controllers/default.py,welcome/views/default/index.html
View File
File mode changed.
View File
File mode changed.
+1
View File
@@ -284,6 +284,7 @@
var redirect = xhr.getResponseHeader('web2py-redirect-location'); var redirect = xhr.getResponseHeader('web2py-redirect-location');
if (redirect !== null) { if (redirect !== null) {
window.location = redirect; window.location = redirect;
window.location.reload(); // Force reload even with anchors
} }
/* run this here only if this Ajax request is NOT for a web2py component. */ /* run this here only if this Ajax request is NOT for a web2py component. */
if (xhr.getResponseHeader('web2py-component-content') === null) { if (xhr.getResponseHeader('web2py-component-content') === null) {
View File
File mode changed.

Before

Width:  |  Height:  |  Size: 366 B

After

Width:  |  Height:  |  Size: 366 B

View File
File mode changed.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View File
File mode changed.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View File
File mode changed.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

View File
File mode changed.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

View File
File mode changed.
View File
File mode changed.
View File
File mode changed.

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="text",_name="filename",requires=IS_NOT_EMPTY()),
INPUT(_type="hidden",_name="location",_value=location), INPUT(_type="hidden",_name="location",_value=location),
INPUT(_type="hidden",_name="sender",_value=URL('design/'+app)), 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 return form
def file_create_form(location): def file_create_form(location):
form=FORM(T("create file with filename:")," ", form=FORM(T("create file with filename:")," ",
INPUT(_type="text",_name="filename",requires=IS_NOT_EMPTY()), INPUT(_type="text",_name="filename",requires=IS_NOT_EMPTY()),
INPUT(_type="hidden",_name="location",_value=location), INPUT(_type="hidden",_name="location",_value=location),
INPUT(_type="hidden",_name="sender",_value=URL('design/'+app)), 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 return form
def upload_plugin_form(app): def upload_plugin_form(app):
form=FORM(T("upload plugin file:")," ", form=FORM(T("upload plugin file:")," ",
INPUT(_type="file",_name="pluginfile"), INPUT(_type="file",_name="pluginfile"),
INPUT(_type="submit",_value=T("submit"))) INPUT(_type="submit",_value=T("Submit")))
return form return form
def deletefile(arglist): def deletefile(arglist):
return A_delete(SPAN(T('Delete')), _href=URL('delete',args=arglist,vars=dict(sender=request.function+'/'+app))) return A_delete(SPAN(T('Delete')), _href=URL('delete',args=arglist,vars=dict(sender=request.function+'/'+app)))
@@ -6,7 +6,7 @@
return files return files
}} }}
{{themes = [f[:-4] for f in listfiles('admin', "static/codemirror/theme", regexp='.*\.css$' )]}} {{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=""> <form id="editor_settings_form" class="form-horizontal" action="">
<div class="control-group"> <div class="control-group">
@@ -27,7 +27,7 @@
</div> </div>
<div class="control-group"> <div class="control-group">
<label class="control-label" for="tabwidth">{{=T('Tab width (# characters)')}}</label> <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>
<div class="control-group"> <div class="control-group">
<label class="control-label" for="indentwithtabs">{{=T('Indent with tabs')}}</label> <label class="control-label" for="indentwithtabs">{{=T('Indent with tabs')}}</label>
+2 -2
View File
@@ -24,7 +24,7 @@ def file_upload_form(location):
INPUT(_type="hidden",_name="location",_value=location), INPUT(_type="hidden",_name="location",_value=location),
INPUT(_type="hidden",_name="token",_value=session.token), INPUT(_type="hidden",_name="token",_value=session.token),
INPUT(_type="hidden",_name="sender",_value=URL('design/'+app)), 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 return form
def file_create_form(location): def file_create_form(location):
form=FORM(T("create file with filename:")," ", 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="location",_value=location),
INPUT(_type="hidden",_name="token",_value=session.token), INPUT(_type="hidden",_name="token",_value=session.token),
INPUT(_type="hidden",_name="sender",_value=URL('design/'+app)), 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 return form
def deletefile(arglist): def deletefile(arglist):
return A(TAG[''](IMG(_src=URL('static', 'images/delete_icon.png')), return A(TAG[''](IMG(_src=URL('static', 'images/delete_icon.png')),
+39 -39
View File
@@ -30,7 +30,7 @@ except:
if request.is_https: if request.is_https:
session.secure() 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'): (request.function != 'manage'):
raise HTTP(200, T('appadmin is disabled because insecure channel')) raise HTTP(200, T('appadmin is disabled because insecure channel'))
@@ -46,7 +46,7 @@ if request.function == 'manage':
auth.table_permission()]) auth.table_permission()])
manager_role = manager_action.get('role', None) if manager_action else None 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)): 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 menu = False
elif (request.application == 'admin' and not session.authorized) or \ elif (request.application == 'admin' and not session.authorized) or \
(request.application != 'admin' and not gluon.fileutils.check_credentials(request)): (request.application != 'admin' and not gluon.fileutils.check_credentials(request)):
@@ -182,7 +182,7 @@ def select():
db = get_database(request) db = get_database(request)
dbname = request.args[0] dbname = request.args[0]
try: try:
is_imap = db._uri.startswith("imap://") is_imap = db._uri.startswith('imap://')
except (KeyError, AttributeError, TypeError): except (KeyError, AttributeError, TypeError):
is_imap = False is_imap = False
regex = re.compile(r'(?P<table>\w+)\.(?P<field>\w+)=(?P<value>\d+)') 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_orderby = orderby
session.last_query = request.vars.query session.last_query = request.vars.query
form = FORM(TABLE(TR(T('Query:'), '', INPUT(_style='width:400px', form = FORM(TABLE(TR(T('Query:'), '', INPUT(_style='width:400px',
_name='query', _value=request.vars.query or '', _class="form-control", _name='query', _value=request.vars.query or '', _class='form-control',
requires=IS_NOT_EMPTY( 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', INPUT(_name='update_check', _type='checkbox',
value=False), INPUT(_style='width:400px', value=False), INPUT(_style='width:400px',
_name='update_fields', _value=request.vars.update_fields _name='update_fields', _value=request.vars.update_fields
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), ''), _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)) _action=URL(r=request, args=request.args))
tb = None tb = None
@@ -254,8 +254,8 @@ def select():
if is_imap: if is_imap:
fields = [db[table][name] for name in fields = [db[table][name] for name in
("id", "uid", "created", "to", ('id', 'uid', 'created', 'to',
"sender", "subject")] 'sender', 'subject')]
if orderby: if orderby:
rows = db(query, ignore_common_filters=True).select( rows = db(query, ignore_common_filters=True).select(
*fields, limitby=(start, stop), *fields, limitby=(start, stop),
@@ -271,10 +271,10 @@ def select():
# begin handle upload csv # begin handle upload csv
csv_table = table or request.vars.table csv_table = table or request.vars.table
if csv_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='file', _name='csvfile'),
INPUT(_type='hidden', _value=csv_table, _name='table'), 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: else:
formcsv = None formcsv = None
if formcsv and formcsv.process().accepted: if formcsv and formcsv.process().accepted:
@@ -356,26 +356,26 @@ def state():
def ccache(): def ccache():
if is_gae: if is_gae:
form = FORM( 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: else:
cache.ram.initialize() cache.ram.initialize()
cache.disk.initialize() cache.disk.initialize()
form = FORM( form = FORM(
P(TAG.BUTTON( P(TAG.BUTTON(
T("Clear CACHE?"), _type="submit", _name="yes", _value="yes")), T('Clear CACHE?'), _type='submit', _name='yes', _value='yes')),
P(TAG.BUTTON( P(TAG.BUTTON(
T("Clear RAM"), _type="submit", _name="ram", _value="ram")), T('Clear RAM'), _type='submit', _name='ram', _value='ram')),
P(TAG.BUTTON( 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): if form.accepts(request.vars, session):
session.flash = "" session.flash = ''
if is_gae: if is_gae:
if request.vars.yes: if request.vars.yes:
cache.ram.clear() cache.ram.clear()
session.flash += T("Cache Cleared") session.flash += T('Cache Cleared')
else: else:
clear_ram = False clear_ram = False
clear_disk = False clear_disk = False
@@ -387,10 +387,10 @@ def ccache():
clear_disk = True clear_disk = True
if clear_ram: if clear_ram:
cache.ram.clear() cache.ram.clear()
session.flash += T("Ram Cleared") session.flash += T('Ram Cleared')
if clear_disk: if clear_disk:
cache.disk.clear() cache.disk.clear()
session.flash += T("Disk Cleared") session.flash += T('Disk Cleared')
redirect(URL(r=request)) redirect(URL(r=request))
try: try:
@@ -436,7 +436,7 @@ def ccache():
gae_stats['ratio'] = ((gae_stats['hits'] * 100) / gae_stats['ratio'] = ((gae_stats['hits'] * 100) /
(gae_stats['hits'] + gae_stats['misses'])) (gae_stats['hits'] + gae_stats['misses']))
except ZeroDivisionError: except ZeroDivisionError:
gae_stats['ratio'] = T("?") gae_stats['ratio'] = T('?')
gae_stats['oldest'] = GetInHMS(time.time() - gae_stats['oldest_item_age']) gae_stats['oldest'] = GetInHMS(time.time() - gae_stats['oldest_item_age'])
total.update(gae_stats) total.update(gae_stats)
else: else:
@@ -502,7 +502,7 @@ def ccache():
TR(TD(B(T('Key'))), TD(B(T('Time in Cache (h:m:s)')))), 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], *[TR(TD(k[0]), TD('%02d:%02d:%02d' % k[1])) for k in keys],
**dict(_class='cache-keys', **dict(_class='cache-keys',
_style="border-collapse: separate; border-spacing: .5em;")) _style='border-collapse: separate; border-spacing: .5em;'))
if not is_gae: if not is_gae:
ram['keys'] = key_table(ram['keys']) ram['keys'] = key_table(ram['keys'])
@@ -536,26 +536,26 @@ def table_template(table):
# This is horribe HTML but the only one graphiz understands # This is horribe HTML but the only one graphiz understands
rows = [] rows = []
cellpadding = 4 cellpadding = 4
color = "#000000" color = '#000000'
bgcolor = "#FFFFFF" bgcolor = '#FFFFFF'
face = "Helvetica" face = 'Helvetica'
face_bold = "Helvetica Bold" face_bold = 'Helvetica Bold'
border = 0 border = 0
rows.append(TR(TD(FONT(table, _face=face_bold, _color=bgcolor), rows.append(TR(TD(FONT(table, _face=face_bold, _color=bgcolor),
_colspan=3, _cellpadding=cellpadding, _colspan=3, _cellpadding=cellpadding,
_align="center", _bgcolor=color))) _align='center', _bgcolor=color)))
for row in db[table]: for row in db[table]:
rows.append(TR(TD(FONT(row.name, _color=color, _face=face_bold), rows.append(TR(TD(FONT(row.name, _color=color, _face=face_bold),
_align="left", _cellpadding=cellpadding, _align='left', _cellpadding=cellpadding,
_border=border), _border=border),
TD(FONT(row.type, _color=color, _face=face), TD(FONT(row.type, _color=color, _face=face),
_align="left", _cellpadding=cellpadding, _align='left', _cellpadding=cellpadding,
_border=border), _border=border),
TD(FONT(types(row), _color=color, _face=face), TD(FONT(types(row), _color=color, _face=face),
_align="center", _cellpadding=cellpadding, _align='center', _cellpadding=cellpadding,
_border=border))) _border=border)))
return "< %s >" % TABLE(*rows, **dict(_bgcolor=bgcolor, _border=1, return '< %s >' % TABLE(*rows, **dict(_bgcolor=bgcolor, _border=1,
_cellborder=0, _cellspacing=0) _cellborder=0, _cellspacing=0)
).xml() ).xml()
@@ -632,15 +632,15 @@ def hooks():
if len(functions): if len(functions):
method_hooks.append({'name': op, 'functions':functions}) method_hooks.append({'name': op, 'functions':functions})
if len(method_hooks): 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 # Render
ul_main = UL(_class='nav nav-list') ul_main = UL(_class='nav nav-list')
for t in tables: for t in tables:
ul_main.append(A(t['name'], _onclick="collapse('a_%s')" % t['slug'])) 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']: for op in t['method_hooks']:
ul_t.append(LI(op['name'])) 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) ul_main.append(ul_t)
return ul_main return ul_main
@@ -650,11 +650,11 @@ def hooks():
# ########################################################### # ###########################################################
def d3_graph_model(): 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 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 = [] nodes = []
links = [] links = []
@@ -670,10 +670,10 @@ def d3_graph_model():
elif f_type == 'string': elif f_type == 'string':
disp = field.length disp = field.length
elif f_type == 'id': elif f_type == 'id':
disp = "PK" disp = 'PK'
elif f_type.startswith('reference') or \ elif f_type.startswith('reference') or \
f_type.startswith('list:reference'): f_type.startswith('list:reference'):
disp = "FK" disp = 'FK'
else: else:
disp = ' ' disp = ' '
fields.append(dict(name=field.name, type=field.type, disp=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)) 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. # 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')) response.files.append(URL('admin','static','js/d3.min.js'))
+39 -39
View File
@@ -30,7 +30,7 @@ except:
if request.is_https: if request.is_https:
session.secure() 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'): (request.function != 'manage'):
raise HTTP(200, T('appadmin is disabled because insecure channel')) raise HTTP(200, T('appadmin is disabled because insecure channel'))
@@ -46,7 +46,7 @@ if request.function == 'manage':
auth.table_permission()]) auth.table_permission()])
manager_role = manager_action.get('role', None) if manager_action else None 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)): 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 menu = False
elif (request.application == 'admin' and not session.authorized) or \ elif (request.application == 'admin' and not session.authorized) or \
(request.application != 'admin' and not gluon.fileutils.check_credentials(request)): (request.application != 'admin' and not gluon.fileutils.check_credentials(request)):
@@ -182,7 +182,7 @@ def select():
db = get_database(request) db = get_database(request)
dbname = request.args[0] dbname = request.args[0]
try: try:
is_imap = db._uri.startswith("imap://") is_imap = db._uri.startswith('imap://')
except (KeyError, AttributeError, TypeError): except (KeyError, AttributeError, TypeError):
is_imap = False is_imap = False
regex = re.compile(r'(?P<table>\w+)\.(?P<field>\w+)=(?P<value>\d+)') 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_orderby = orderby
session.last_query = request.vars.query session.last_query = request.vars.query
form = FORM(TABLE(TR(T('Query:'), '', INPUT(_style='width:400px', form = FORM(TABLE(TR(T('Query:'), '', INPUT(_style='width:400px',
_name='query', _value=request.vars.query or '', _class="form-control", _name='query', _value=request.vars.query or '', _class='form-control',
requires=IS_NOT_EMPTY( 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', INPUT(_name='update_check', _type='checkbox',
value=False), INPUT(_style='width:400px', value=False), INPUT(_style='width:400px',
_name='update_fields', _value=request.vars.update_fields _name='update_fields', _value=request.vars.update_fields
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), ''), _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)) _action=URL(r=request, args=request.args))
tb = None tb = None
@@ -254,8 +254,8 @@ def select():
if is_imap: if is_imap:
fields = [db[table][name] for name in fields = [db[table][name] for name in
("id", "uid", "created", "to", ('id', 'uid', 'created', 'to',
"sender", "subject")] 'sender', 'subject')]
if orderby: if orderby:
rows = db(query, ignore_common_filters=True).select( rows = db(query, ignore_common_filters=True).select(
*fields, limitby=(start, stop), *fields, limitby=(start, stop),
@@ -271,10 +271,10 @@ def select():
# begin handle upload csv # begin handle upload csv
csv_table = table or request.vars.table csv_table = table or request.vars.table
if csv_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='file', _name='csvfile'),
INPUT(_type='hidden', _value=csv_table, _name='table'), 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: else:
formcsv = None formcsv = None
if formcsv and formcsv.process().accepted: if formcsv and formcsv.process().accepted:
@@ -356,26 +356,26 @@ def state():
def ccache(): def ccache():
if is_gae: if is_gae:
form = FORM( 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: else:
cache.ram.initialize() cache.ram.initialize()
cache.disk.initialize() cache.disk.initialize()
form = FORM( form = FORM(
P(TAG.BUTTON( P(TAG.BUTTON(
T("Clear CACHE?"), _type="submit", _name="yes", _value="yes")), T('Clear CACHE?'), _type='submit', _name='yes', _value='yes')),
P(TAG.BUTTON( P(TAG.BUTTON(
T("Clear RAM"), _type="submit", _name="ram", _value="ram")), T('Clear RAM'), _type='submit', _name='ram', _value='ram')),
P(TAG.BUTTON( 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): if form.accepts(request.vars, session):
session.flash = "" session.flash = ''
if is_gae: if is_gae:
if request.vars.yes: if request.vars.yes:
cache.ram.clear() cache.ram.clear()
session.flash += T("Cache Cleared") session.flash += T('Cache Cleared')
else: else:
clear_ram = False clear_ram = False
clear_disk = False clear_disk = False
@@ -387,10 +387,10 @@ def ccache():
clear_disk = True clear_disk = True
if clear_ram: if clear_ram:
cache.ram.clear() cache.ram.clear()
session.flash += T("Ram Cleared") session.flash += T('Ram Cleared')
if clear_disk: if clear_disk:
cache.disk.clear() cache.disk.clear()
session.flash += T("Disk Cleared") session.flash += T('Disk Cleared')
redirect(URL(r=request)) redirect(URL(r=request))
try: try:
@@ -436,7 +436,7 @@ def ccache():
gae_stats['ratio'] = ((gae_stats['hits'] * 100) / gae_stats['ratio'] = ((gae_stats['hits'] * 100) /
(gae_stats['hits'] + gae_stats['misses'])) (gae_stats['hits'] + gae_stats['misses']))
except ZeroDivisionError: except ZeroDivisionError:
gae_stats['ratio'] = T("?") gae_stats['ratio'] = T('?')
gae_stats['oldest'] = GetInHMS(time.time() - gae_stats['oldest_item_age']) gae_stats['oldest'] = GetInHMS(time.time() - gae_stats['oldest_item_age'])
total.update(gae_stats) total.update(gae_stats)
else: else:
@@ -502,7 +502,7 @@ def ccache():
TR(TD(B(T('Key'))), TD(B(T('Time in Cache (h:m:s)')))), 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], *[TR(TD(k[0]), TD('%02d:%02d:%02d' % k[1])) for k in keys],
**dict(_class='cache-keys', **dict(_class='cache-keys',
_style="border-collapse: separate; border-spacing: .5em;")) _style='border-collapse: separate; border-spacing: .5em;'))
if not is_gae: if not is_gae:
ram['keys'] = key_table(ram['keys']) ram['keys'] = key_table(ram['keys'])
@@ -536,26 +536,26 @@ def table_template(table):
# This is horribe HTML but the only one graphiz understands # This is horribe HTML but the only one graphiz understands
rows = [] rows = []
cellpadding = 4 cellpadding = 4
color = "#000000" color = '#000000'
bgcolor = "#FFFFFF" bgcolor = '#FFFFFF'
face = "Helvetica" face = 'Helvetica'
face_bold = "Helvetica Bold" face_bold = 'Helvetica Bold'
border = 0 border = 0
rows.append(TR(TD(FONT(table, _face=face_bold, _color=bgcolor), rows.append(TR(TD(FONT(table, _face=face_bold, _color=bgcolor),
_colspan=3, _cellpadding=cellpadding, _colspan=3, _cellpadding=cellpadding,
_align="center", _bgcolor=color))) _align='center', _bgcolor=color)))
for row in db[table]: for row in db[table]:
rows.append(TR(TD(FONT(row.name, _color=color, _face=face_bold), rows.append(TR(TD(FONT(row.name, _color=color, _face=face_bold),
_align="left", _cellpadding=cellpadding, _align='left', _cellpadding=cellpadding,
_border=border), _border=border),
TD(FONT(row.type, _color=color, _face=face), TD(FONT(row.type, _color=color, _face=face),
_align="left", _cellpadding=cellpadding, _align='left', _cellpadding=cellpadding,
_border=border), _border=border),
TD(FONT(types(row), _color=color, _face=face), TD(FONT(types(row), _color=color, _face=face),
_align="center", _cellpadding=cellpadding, _align='center', _cellpadding=cellpadding,
_border=border))) _border=border)))
return "< %s >" % TABLE(*rows, **dict(_bgcolor=bgcolor, _border=1, return '< %s >' % TABLE(*rows, **dict(_bgcolor=bgcolor, _border=1,
_cellborder=0, _cellspacing=0) _cellborder=0, _cellspacing=0)
).xml() ).xml()
@@ -632,15 +632,15 @@ def hooks():
if len(functions): if len(functions):
method_hooks.append({'name': op, 'functions':functions}) method_hooks.append({'name': op, 'functions':functions})
if len(method_hooks): 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 # Render
ul_main = UL(_class='nav nav-list') ul_main = UL(_class='nav nav-list')
for t in tables: for t in tables:
ul_main.append(A(t['name'], _onclick="collapse('a_%s')" % t['slug'])) 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']: for op in t['method_hooks']:
ul_t.append(LI(op['name'])) 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) ul_main.append(ul_t)
return ul_main return ul_main
@@ -650,11 +650,11 @@ def hooks():
# ########################################################### # ###########################################################
def d3_graph_model(): 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 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 = [] nodes = []
links = [] links = []
@@ -670,10 +670,10 @@ def d3_graph_model():
elif f_type == 'string': elif f_type == 'string':
disp = field.length disp = field.length
elif f_type == 'id': elif f_type == 'id':
disp = "PK" disp = 'PK'
elif f_type.startswith('reference') or \ elif f_type.startswith('reference') or \
f_type.startswith('list:reference'): f_type.startswith('list:reference'):
disp = "FK" disp = 'FK'
else: else:
disp = ' ' disp = ' '
fields.append(dict(name=field.name, type=field.type, disp=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)) 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. # 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')) response.files.append(URL('admin','static','js/d3.min.js'))
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
+125 -83
View File
@@ -1,8 +1,10 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
{ {
'!=': '!=',
'!langcode!': 'pt-br', '!langcode!': 'pt-br',
'!langname!': 'Português (do Brasil)', '!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', '"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} deleted': '%s linha apagadas',
'%s %%{row} updated': '%s linha atualizadas', '%s %%{row} updated': '%s linha atualizadas',
'%s selected': '%s selecionado', '%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** %%{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)}', '**%(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)', '**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(**%.0d MB**)': '(**%.0d MB**)',
'@markmin\x01**%(items)s** %%{item(items)}, **%(bytes)s** %%{byte(bytes)}': '**%(items)s** %%{item(items)}, **%(bytes)s** %%{byte(bytes)}', '@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\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\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\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.', '@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)', '``**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', 'About': 'Sobre',
'Access Control': 'Controle de Acesso', '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', 'admin': 'admin',
'Administrative Interface': 'Interface Administrativa', 'Administrative Interface': 'Interface Administrativa',
'Administrative interface': 'Interface administrativa', 'Administrative interface': 'Interface administrativa',
'Ajax Recipes': 'Receitas de Ajax', 'Ajax Recipes': 'Receitas de Ajax',
'An error occured, please [[reload %s]] the page': 'An error occured, please [[reload %s]] the page', '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', '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?', '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', 'Available Databases and Tables': 'Bancos de dados e tabelas disponíveis',
'Back': 'Voltar',
'Buy this book': 'Compre o livro', 'Buy this book': 'Compre o livro',
"Buy web2py's book": 'Compre o livro do web2py', "Buy web2py's book": 'Compre o livro do web2py',
'cache': 'cache', 'cache': 'cache',
@@ -48,19 +62,27 @@
'Cache Keys': 'Chaves de cache', 'Cache Keys': 'Chaves de cache',
'Cannot be empty': 'Não pode estar vazio', 'Cannot be empty': 'Não pode estar vazio',
'change password': 'mudar senha', 'change password': 'mudar senha',
'Change Password': 'Change Password', 'Change Password': 'Trocar Senhar',
'Change password': 'Change password', 'Change password': 'Trocar senha',
'Check to delete': 'Marque para apagar', 'Check to delete': 'Marque para apagar',
'Clear': 'Limpar',
'Clear CACHE?': 'Limpar CACHE?', 'Clear CACHE?': 'Limpar CACHE?',
'Clear DISK': 'Limpar DISCO', 'Clear DISK': 'Limpar DISCO',
'Clear RAM': 'Limpar memória RAM', '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', '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', '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', 'Community': 'Comunidade',
'Components and Plugins': 'Componentes e Plugins', 'Components and Plugins': 'Componentes e Plugins',
'Config.ini': 'Config.ini', 'Config.ini': 'Config.ini',
'Confirm Password': 'Confirme a Senha',
'contains': 'contém',
'Controller': 'Controlador', 'Controller': 'Controlador',
'Copyright': 'Copyright', 'Copyright': 'Copyright',
'CSV': 'CSV',
'CSV (hidden cols)': 'CSV (col. ocultas)',
'Current request': 'Requisição atual', 'Current request': 'Requisição atual',
'Current response': 'Resposta atual', 'Current response': 'Resposta atual',
'Current session': 'Sessão atual', 'Current session': 'Sessão atual',
@@ -68,9 +90,10 @@
'data uploaded': 'dados enviados', 'data uploaded': 'dados enviados',
'Database': 'banco de dados', 'Database': 'banco de dados',
'Database %s select': 'Selecionar banco de dados %s', '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': 'bd',
'DB Model': 'Modelo BD', 'DB Model': 'Modelo BD',
'Delete': 'Excluir',
'Delete:': 'Apagar:', 'Delete:': 'Apagar:',
'Demo': 'Demo', 'Demo': 'Demo',
'Deployment Recipes': 'Receitas de deploy', 'Deployment Recipes': 'Receitas de deploy',
@@ -91,50 +114,57 @@
'edit profile': 'editar perfil', 'edit profile': 'editar perfil',
'Edit This App': 'Editar esta aplicação', 'Edit This App': 'Editar esta aplicação',
'Email and SMS': 'Email e SMS', 'Email and SMS': 'Email e SMS',
'Email sent': 'Email sent', 'Email sent': 'Email enviado',
'Email verification': 'Email verification', 'Email verification': 'Verificação de email',
'Email verified': 'Email verified', 'Email verified': 'Email verificado',
'Enter an integer between %(min)g and %(max)g': 'Informe um valor inteiro entre %(min)g e %(max)g', 'Enter an integer between %(min)g and %(max)g': 'Informe um valor inteiro entre %(min)g e %(max)g',
'Errors': 'Erros', 'Errors': 'Erros',
'export as csv file': 'exportar como um arquivo csv', 'export as csv file': 'exportar como um arquivo csv',
'Export:': 'Exportar:',
'FAQ': 'Perguntas frequentes', 'FAQ': 'Perguntas frequentes',
'First name': 'Nome', 'First name': 'Nome',
'Forms and Validators': 'Formulários e Validadores', 'Forms and Validators': 'Formulários e Validadores',
'Free Applications': 'Aplicações gratuitas', 'Free Applications': 'Aplicações gratuitas',
'Function disabled': 'Function disabled', 'Function disabled': 'Função desabilitada',
'Graph Model': 'Graph Model', 'Graph Model': 'Modelo em Grafo',
'Grid Example': 'Exemplo de Grade', 'Grid Example': 'Exemplo de Grade',
'Group %(group_id)s created': 'Group %(group_id)s created', 'Group %(group_id)s created': 'Grupo %(group_id)s criado',
'Group %(group_id)s deleted': 'Group %(group_id)s deleted', 'Group %(group_id)s deleted': 'Grupo %(group_id)s excluído',
'Group ID': 'ID do Grupo', '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', 'Groups': 'Grupos',
'Hello World': 'Olá Mundo', '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)})', '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', 'Home': 'Principal',
'How did you get here?': 'Como você chegou aqui?', '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': 'importar',
'Import/Export': 'Importar/Exportar', 'Import/Export': 'Importar/Exportar',
'in': 'em',
'Incorrect code. {0} more attempt(s) remaining.': 'Incorrect code. {0} more attempt(s) remaining.', 'Incorrect code. {0} more attempt(s) remaining.': 'Incorrect code. {0} more attempt(s) remaining.',
'Index': 'Início', 'Index': 'Início',
'insert new': 'inserir novo', 'insert new': 'inserir novo',
'insert new %s': 'inserir novo %s', 'insert new %s': 'inserir novo %s',
'Insufficient privileges': 'Insufficient privileges', 'Insufficient privileges': 'Privilégios insuficientes',
'Internal State': 'Estado Interno', 'Internal State': 'Estado Interno',
'Introduction': 'Introdução', 'Introduction': 'Introdução',
'Invalid email': 'Email inválido', 'Invalid email': 'Email inválido',
'Invalid key': 'Invalid key', 'Invalid key': 'Chave inválida',
'Invalid login': 'Invalid login', 'Invalid login': 'Login Inválido',
'Invalid password': 'Invalid password', 'Invalid password': 'Senha inválida',
'Invalid Query': 'Consulta Inválida', 'Invalid Query': 'Consulta Inválida',
'invalid request': 'requisição inválida', 'invalid request': 'requisição inválida',
'Invalid reset password': 'Invalid reset password', 'Invalid reset password': 'Recriação de senha inválida',
'Invalid user': 'Invalid user', 'Invalid user': 'Usuário inválido',
'Invalid username': 'Invalid username', 'Invalid username': 'Nome de usuário inválido',
'Invitation to join %(site)s': 'Invitation to join %(site)s', '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': 'Chave',
'Key verified': 'Key verified', 'Key verified': 'Chave verificada',
'Last name': 'Sobrenome', 'Last name': 'Sobrenome',
'Layout': 'Layout', 'Layout': 'Layout',
'Layout Plugins': 'Plugins de Layout', 'Layout Plugins': 'Plugins de Layout',
@@ -142,13 +172,13 @@
'Live chat': 'Chat ao vivo', 'Live chat': 'Chat ao vivo',
'Live Chat': 'Chat ao vivo', 'Live Chat': 'Chat ao vivo',
'Log In': 'Entrar', 'Log In': 'Entrar',
'Logged in': 'Logged in', 'Logged in': 'Conectado',
'Logged out': 'Logged out', 'Logged out': 'Desconectado',
'login': 'Entrar', 'login': 'Entrar',
'Login': 'Entrar', 'Login': 'Entrar',
'Login disabled by administrator': 'Login disabled by administrator', 'Login disabled by administrator': 'Login desabilitado pelo administrador',
'logout': 'Sair', 'logout': 'Sair',
'Logout': 'Logout', 'Logout': 'Sair',
'Lost Password': 'Esqueceu sua senha?', 'Lost Password': 'Esqueceu sua senha?',
'lost password?': 'esqueceu sua senha?', 'lost password?': 'esqueceu sua senha?',
'Lost your password?': 'Esqueceu sua senha?', 'Lost your password?': 'Esqueceu sua senha?',
@@ -160,16 +190,19 @@
'Menu Model': 'Modelo de Menu', 'Menu Model': 'Modelo de Menu',
'My Sites': 'Meus sites', 'My Sites': 'Meus sites',
'Name': 'Nome', 'Name': 'Nome',
'New password': 'New password', 'New password': 'Nova senha',
'New Record': 'Novo Registro', 'New Record': 'Novo Registro',
'new record inserted': 'novo registro inserido', 'new record inserted': 'novo registro inserido',
'New Search': 'Nova pesquisa',
'next %s rows': 'próximas %s ´linhas', 'next %s rows': 'próximas %s ´linhas',
'next 100 rows': 'próximas 100 linhas', 'next 100 rows': 'próximas 100 linhas',
'No databases in this application': 'Não há bancos de dados nesta aplicação', '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**', 'Number of entries: **%s**': 'Número de entradas: **%s**',
'Object or table name': 'Nome do objeto do da tabela', 'Object or table name': 'Nome do objeto do da tabela',
'Old password': 'Old password', 'Old password': 'Senha antiga',
'Online book': 'Online book', 'Online book': 'Livro online',
'Online examples': 'Exemplos online', 'Online examples': 'Exemplos online',
'or import from csv file': 'ou importar de um arquivo csv', 'or import from csv file': 'ou importar de um arquivo csv',
'Origin': 'Origem', 'Origin': 'Origem',
@@ -177,66 +210,71 @@
'Other Recipes': 'Outras Receitas', 'Other Recipes': 'Outras Receitas',
'Overview': 'Visão Geral', 'Overview': 'Visão Geral',
'Password': 'Senha', 'Password': 'Senha',
'Password changed': 'Password changed', 'Password changed': 'Senha trocada',
"Password fields don't match": "Password fields don't match", "Password fields don't match": 'Senhas não conferem',
'Password reset': 'Password reset', 'Password reset': 'Recriar senha',
'Password retrieve': 'Password retrieve', 'Password retrieve': 'Recuperar senha',
'Permission': 'Permission', 'Permission': 'Permissão',
'Permissions': 'Permissions', 'Permissions': 'Permissões',
'please input your password again': 'please input your password again', 'please input your password again': 'por favor digite a senha novamente',
'Plugins': 'Plugins', 'Plugins': 'Plugins',
'Powered by': 'Desenvolvido com', 'Powered by': 'Desenvolvido com',
'Preface': 'Prefácio', 'Preface': 'Prefácio',
'previous %s rows': '%s linhas anteriores', 'previous %s rows': '%s linhas anteriores',
'previous 100 rows': '100 linhas anteriores', 'previous 100 rows': '100 linhas anteriores',
'Profile': 'Profile', 'Profile': 'Perfil',
'Profile updated': 'Profile updated', 'Profile updated': 'Perfil atualizado',
'pygraphviz library not found': 'biblioteca pygraphviz não encontrada', 'pygraphviz library not found': 'biblioteca pygraphviz não encontrada',
'Python': 'Python', 'Python': 'Python',
'Query:': 'Consulta:', 'Query:': 'Consulta:',
'Quick Examples': 'Exemplos rápidos', 'Quick Examples': 'Exemplos rápidos',
'RAM': 'RAM', 'RAM': 'RAM',
'RAM Cache Keys': 'RAM Cache Keys', 'RAM Cache Keys': 'Chaves de Cache RAM ',
'Ram Cleared': 'Ram Limpa', '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.', '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', 'Recipes': 'Receitas',
'Record': 'Registro', 'Record': 'Registro',
'Record %(id)s created': 'Record %(id)s created', 'Record %(id)s created': 'Registro %(id)s criado',
'Record %(id)s deleted': 'Record %(id)s deleted', 'Record %(id)s deleted': 'Registro %(id)s excluído',
'Record %(id)s read': 'Record %(id)s read', 'Record %(id)s read': 'Registro %(id)s lido',
'Record %(id)s updated': 'Record %(id)s updated', 'Record %(id)s updated': 'Registro %(id)s atualizado',
'Record Created': 'Record Created', 'Record Created': 'Registro Criado',
'Record Deleted': 'Record Deleted', 'Record Deleted': 'Registro Excluído',
'record does not exist': 'registro não existe', 'record does not exist': 'registro não existe',
'Record ID': 'ID do Registro', 'Record ID': 'ID do Registro',
'Record id': 'id do registro', 'Record id': 'id do registro',
'Record Updated': 'Record Updated', 'Record Updated': 'Registro Atualizado',
'register': 'Registre-se', 'register': 'Cadastre-se',
'Register': 'Registre-se', 'Register': 'Cadastre-se',
'Registration identifier': 'Idenficador de registro', 'Registration identifier': 'Idenficador de Cadastro',
'Registration is pending approval': 'Registration is pending approval', 'Registration is pending approval': 'Aprovação de cadastro pendente',
'Registration key': 'Chave de registro', 'Registration key': 'Chave de cadastro',
'Registration needs verification': 'Registration needs verification', 'Registration needs verification': 'Cadastro necessita verficação',
'Registration successful': 'Registration successful', 'Registration successful': 'Cadastro finalizado',
'Remember me (for 30 days)': 'Mantenha-me logado (por 30 dias)', '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', 'Reset Password key': 'Resetar chave de senha',
'Resources': 'Recursos', 'Resources': 'Recursos',
'Role': 'Papel', 'Role': 'Papel',
'Roles': 'Roles', 'Roles': 'Papéis',
'Rows in Table': 'Linhas na tabela', 'Rows in Table': 'Linhas na tabela',
'Rows selected': 'Linhas selecionadas', 'Rows selected': 'Linhas selecionadas',
'Save model as...': 'Salvar modelo como...', 'Save model as...': 'Salvar modelo como...',
'Search': 'Pesquisar',
'Semantic': 'Semântico', 'Semantic': 'Semântico',
'Services': 'Serviço', 'Services': 'Serviço',
'Sign Up': 'Cadastrar', 'Sign Up': 'Cadastrar',
'Sign up': 'Cadastrar', 'Sign up': 'Cadastrar',
'Size of cache:': 'Tamanho do cache:', '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', 'state': 'estado',
'Statistics': 'Estatísticas', 'Statistics': 'Estatísticas',
'Stylesheet': 'Folha de estilo', 'Stylesheet': 'Folha de estilo',
'submit': 'enviar', 'submit': 'enviar',
'Submit': 'Submit', 'Submit': 'Enviar',
'Support': 'Suporte', 'Support': 'Suporte',
'Sure you want to delete this object?': 'Está certo(a) que deseja apagar este objeto?', 'Sure you want to delete this object?': 'Está certo(a) que deseja apagar este objeto?',
'Table': 'Tabela', 'Table': 'Tabela',
@@ -252,31 +290,33 @@
'Time in Cache (h:m:s)': 'Tempo em Cache (h:m:s)', 'Time in Cache (h:m:s)': 'Tempo em Cache (h:m:s)',
'Timestamp': 'Timestamp', 'Timestamp': 'Timestamp',
'Traceback': 'Traceback', 'Traceback': 'Traceback',
'TSV (Spreadsheets)': 'TSV (Planilhas)',
'TSV (Spreadsheets, hidden cols)': 'TSV (Planilhas, col. ocultas)',
'Twitter': 'Twitter', '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 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:', '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.', '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 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-in': 'Usuário %(id)s entrou',
'User %(id)s Logged-out': 'User %(id)s Logged-out', 'User %(id)s Logged-out': 'Usuário %(id)s saiu',
'User %(id)s Password changed': 'User %(id)s Password changed', 'User %(id)s Password changed': 'Usuário %(id)s trocou a senha',
'User %(id)s Password reset': 'User %(id)s Password reset', 'User %(id)s Password reset': 'Usuário %(id)s recirar a senha',
'User %(id)s Password retrieved': 'User %(id)s Password retrieved', 'User %(id)s Password retrieved': 'Usuário %(id)s Recuperou a senha',
'User %(id)s Profile updated': 'User %(id)s Profile updated', 'User %(id)s Profile updated': 'Usuário %(id)s Atualizou perfil',
'User %(id)s Registered': 'User %(id)s Registered', 'User %(id)s Registered': 'Usuário %(id)s Cadastrou-se',
'User %(id)s Username retrieved': 'User %(id)s Username retrieved', 'User %(id)s Username retrieved': 'Usuário %(id)s Recuperou nome de usuário',
'User %(id)s Verification email sent': 'User %(id)s Verification email sent', 'User %(id)s Verification email sent': 'Usuário %(id)s Email de verificação enviado',
'User %(id)s verified registration key': 'User %(id)s verified registration key', 'User %(id)s verified registration key': 'Usuário %(id)s chave de cadastro verificada',
'User ID': 'ID do Usuário', 'User ID': 'ID do Usuário',
'User Voice': 'Opinião dos usuários', 'User Voice': 'Opinião dos usuários',
'Username': 'Username', 'Username': 'Nome de Usuário',
'Username already taken': 'Username already taken', 'Username already taken': 'Nome de usuário já existe',
'Username retrieve': 'Username retrieve', 'Username retrieve': 'Recuperar nome de usuário',
'Users': 'Users', 'Users': 'Usuários',
'Verify Password': 'Verify Password', 'Verify Password': 'Verificar Senha',
'Videos': 'Vídeos', 'Videos': 'Vídeos',
'View': 'Visualização', 'View': 'Visualização',
'Web2py': 'Web2py', 'Web2py': 'Web2py',
@@ -286,15 +326,17 @@
'Welcome to web2py': 'Bem-vindo ao web2py', 'Welcome to web2py': 'Bem-vindo ao web2py',
'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', '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...', '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 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 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 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', 'You visited the url %s': 'Você acessou a url %s',
'Your password is: %(password)s': 'Your password is: %(password)s', 'Your password is: %(password)s': 'Sua senha é: %(password)s',
'Your temporary login code is {0}': 'Your temporary login code is {0}', 'Your temporary login code is {0}': 'Seu código temporário de login é {0}',
'Your username is: %(username)s': 'Your username is: %(username)s', 'Your username is: %(username)s': 'Seu nome de usuário é: %(username)s',
'Your username was emailed to you': 'Your username was emailed to you', 'Your username was emailed to you': 'Seu nome de usuário foi enviado por email para você',
} }
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
+1 -1
View File
@@ -19,4 +19,4 @@ WORKDIR /web2py
EXPOSE 443 EXPOSE 443
CMD python /web2py/web2py.py --nogui --no-banner -a 'a' -c web2py.crt -k web2py.key -i 0.0.0.0 -p 443 CMD python /web2py/web2py.py --no_gui --no_banner -a 'a' -k web2py.key -c web2py.crt -i 0.0.0.0 -p 443
View File
File mode changed.
View File
File mode changed.
+1 -1
View File
@@ -24,4 +24,4 @@ WORKDIR /home/web2py/web2py
EXPOSE 8000 EXPOSE 8000
CMD . /home/web2py/bin/activate && python /home/web2py/web2py/web2py.py --nogui --no-banner -a 'a' -i 0.0.0.0 -p 8000 CMD . /home/web2py/bin/activate && python /home/web2py/web2py/web2py.py --no_gui --no_banner -a 'a' -i 0.0.0.0 -p 8000
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
Loaded 100 of 374 files, more files were not shown because too many files have changed in this diff. Show more