Allow deploying to pythonanywhere from the web2py admin that you're running locally.

This commit is contained in:
Leonel Câmara
2015-09-08 00:51:09 +01:00
parent d4270373e1
commit 125cbd93a0
4 changed files with 669 additions and 377 deletions
@@ -0,0 +1,91 @@
# -*- coding: utf-8 -*-
import base64
import os
import re
import gzip
import tarfile
try:
from cStringIO import StringIO
except ImportError:
from StringIO import StringIO
from xmlrpclib import ProtocolError
from gluon.contrib.simplejsonrpc import ServerProxy
def deploy():
response.title = T('Deploy to pythonanywhere')
return {}
def crossdomainproxy():
if not request.vars:
raise HTTP(400)
import urllib, urllib2
url = 'https://www.pythonanywhere.com/api/web2py/create_account'
data = urllib.urlencode(request.vars)
req = urllib2.Request(url, data)
try:
reply = urllib2.urlopen(req)
except urllib2.HTTPError as error:
if error.code == 400:
reply = error
else:
raise
response.headers['Content-Type'] = 'application/json'
return reply.read()
def list_apps():
""" Get a list of apps both remote and local """
if not request.vars.username or not request.vars.password:
raise HTTP(400)
client = ServerProxy('https://%(username)s:%(password)s@%(username)s.pythonanywhere.com/admin/webservices/call/jsonrpc' % request.vars)
regex = re.compile('^\w+$')
local = [f for f in os.listdir(apath(r=request)) if regex.match(f)]
try:
pythonanywhere = client.list_apps()
except ProtocolError as error:
raise HTTP(error.errcode)
return response.json({'local': local, 'pythonanywhere': pythonanywhere})
def bulk_install():
""" Install a list of apps """
def b64pack(app):
"""
Given an app's name, return the base64 representation of its packed version.
"""
folder = apath(app, r=request)
tmpfile = StringIO()
tar = tarfile.TarFile(fileobj=tmpfile, mode='w')
try:
filenames = listdir(folder, '^[\w\.\-]+$', add_dirs=True,
exclude_content_from=['cache', 'sessions', 'errors'])
for fname in filenames:
tar.add(os.path.join(folder, fname), fname, False)
finally:
tar.close()
tmpfile.seek(0)
gzfile = StringIO()
w2pfp = gzip.GzipFile(fileobj=gzfile, mode='wb')
w2pfp.write(tmpfile.read())
w2pfp.close()
gzfile.seek(0)
return base64.b64encode(gzfile.read())
request.vars.apps = request.vars['apps[]']
if not request.vars.apps or not request.vars.username or not request.vars.password:
raise HTTP(400)
if not isinstance(request.vars.apps, list):
request.vars.apps = [request.vars.apps] # Only one app selected
client = ServerProxy('https://%(username)s:%(password)s@%(username)s.pythonanywhere.com/admin/webservices/call/jsonrpc' % request.vars)
for app in request.vars.apps:
try:
client.install(app, app+'.w2p', b64pack(app))
except ProtocolError as error:
raise HTTP(error.errcode)
return response.json({'status': 'ok'})
+404 -377
View File
@@ -1,377 +1,404 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
{ {
'!langcode!': 'pt', '!langcode!': 'pt',
'!langname!': 'Português', '!langname!': 'Português',
'"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=\'novo_valor\'". Não é permitido atualizar ou apagar 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=\'novo_valor\'". Não é permitido atualizar ou apagar resultados de um JOIN',
'%s %%{row} deleted': '%s registros apagados', '%s %%{row} deleted': '%s registros apagados',
'%s %%{row} updated': '%s registros atualizados', '%s %%{row} updated': '%s registros atualizados',
'%Y-%m-%d': '%d/%m/%Y', '%Y-%m-%d': '%d/%m/%Y',
'%Y-%m-%d %H:%M:%S': '%d/%m/%Y %H:%M:%S', '%Y-%m-%d %H:%M:%S': '%d/%m/%Y %H:%M:%S',
'(requires internet access)': '(requer acesso à internet)', '(requires internet access)': '(requer acesso à internet)',
'(requires internet access, experimental)': '(requer acesso à internet, experimental)', '(requires internet access, experimental)': '(requer acesso à internet, experimental)',
'(something like "it-it")': '(algo como "it-it")', '(something like "it-it")': '(algo como "it-it")',
'@markmin\x01(file **gluon/contrib/plural_rules/%s.py** is not found)': '(file **gluon/contrib/plural_rules/%s.py** is not found)', '@markmin\x01(file **gluon/contrib/plural_rules/%s.py** is not found)': '(file **gluon/contrib/plural_rules/%s.py** is not found)',
'@markmin\x01An error occured, please [[reload %s]] the page': 'An error occured, please [[reload %s]] the page', '@markmin\x01An error occured, please [[reload %s]] the page': 'An error occured, please [[reload %s]] the page',
'@markmin\x01Searching: **%s** %%{file}': 'Searching: **%s** files', '@markmin\x01Searching: **%s** %%{file}': 'Searching: **%s** files',
'A new version of web2py is available': 'Está disponível uma nova versão do web2py', 'A new version of web2py is available': 'Está disponível uma nova versão do web2py',
'A new version of web2py is available: %s': 'Está disponível uma nova versão do web2py: %s', 'A new version of web2py is available: %s': 'Está disponível uma nova versão do web2py: %s',
'About': 'sobre', 'About': 'sobre',
'About application': 'Sobre a aplicação', 'About application': 'Sobre a aplicação',
'additional code for your application': 'código adicional para sua aplicação', 'Accept Terms': 'Accept Terms',
'Additional code for your application': 'Código adicional para a sua aplicação', 'additional code for your application': 'código adicional para sua aplicação',
'admin disabled because no admin password': ' admin desabilitado por falta de senha definida', 'Additional code for your application': 'Código adicional para a sua aplicação',
'admin disabled because not supported on google app engine': 'admin dehabilitado, não é soportado no GAE', 'admin disabled because no admin password': ' admin desabilitado por falta de senha definida',
'admin disabled because unable to access password file': 'admin desabilitado, não foi possível ler o arquivo de senha', 'admin disabled because not supported on google app engine': 'admin dehabilitado, não é soportado no GAE',
'Admin is disabled because insecure channel': 'Admin desabilitado pois o canal não é seguro', 'admin disabled because unable to access password file': 'admin desabilitado, não foi possível ler o arquivo de senha',
'Admin is disabled because unsecure channel': 'Admin desabilitado pois o canal não é seguro', 'Admin is disabled because insecure channel': 'Admin desabilitado pois o canal não é seguro',
'Admin language': 'Linguagem do Admin', 'Admin is disabled because unsecure channel': 'Admin desabilitado pois o canal não é seguro',
'administrative interface': 'interface administrativa', 'Admin language': 'Linguagem do Admin',
'Administrator Password:': 'Senha de administrador:', 'administrative interface': 'interface administrativa',
'and rename it (required):': 'e renomeie (requerido):', 'Administrator Password:': 'Senha de administrador:',
'and rename it:': ' e renomeie:', 'and rename it (required):': 'e renomeie (requerido):',
'appadmin': 'appadmin', 'and rename it:': ' e renomeie:',
'appadmin is disabled because insecure channel': 'admin desabilitado, canal inseguro', 'appadmin': 'appadmin',
'application "%s" uninstalled': 'aplicação "%s" desinstalada', 'appadmin is disabled because insecure channel': 'admin desabilitado, canal inseguro',
'application compiled': 'aplicação compilada', 'application "%s" uninstalled': 'aplicação "%s" desinstalada',
'application is compiled and cannot be designed': 'A aplicação está compilada e não pode ser modificada', 'application compiled': 'aplicação compilada',
'Application name:': 'Nome da aplicação:', 'application is compiled and cannot be designed': 'A aplicação está compilada e não pode ser modificada',
'are not used': 'não usadas', 'Application name:': 'Nome da aplicação:',
'are not used yet': 'ainda não usadas', 'are not used': 'não usadas',
'Are you sure you want to delete file "%s"?': 'Tem certeza que deseja apagar o arquivo "%s"?', 'are not used yet': 'ainda não usadas',
'Are you sure you want to delete plugin "%s"?': 'Tem certeza que deseja apagar o plugin "%s"?', 'Are you sure you want to delete file "%s"?': 'Tem certeza que deseja apagar o arquivo "%s"?',
'Are you sure you want to delete this object?': 'Are you sure you want to delete this object?', 'Are you sure you want to delete plugin "%s"?': 'Tem certeza que deseja apagar o plugin "%s"?',
'Are you sure you want to uninstall application "%s"': 'Tem certeza que deseja apagar a aplicação "%s"?', 'Are you sure you want to delete this object?': 'Are you sure you want to delete this object?',
'Are you sure you want to uninstall application "%s"?': 'Tem certeza que deseja apagar a aplicação "%s"?', 'Are you sure you want to uninstall application "%s"': 'Tem certeza que deseja apagar a aplicação "%s"?',
'Are you sure you want to upgrade web2py now?': 'Tem certeza que deseja atualizar o web2py agora?', 'Are you sure you want to uninstall application "%s"?': 'Tem certeza que deseja apagar a aplicação "%s"?',
'arguments': 'argumentos', 'Are you sure you want to upgrade web2py now?': 'Tem certeza que deseja atualizar o web2py agora?',
'ATTENTION: Login requires a secure (HTTPS) connection or running on localhost.': 'ATENÇÃO o login requer uma conexão segura (HTTPS) ou executar de localhost.', 'arguments': 'argumentos',
'ATTENTION: TESTING IS NOT THREAD SAFE SO DO NOT PERFORM MULTIPLE TESTS CONCURRENTLY.': 'ATENÇÃO OS TESTES NÃO THREAD SAFE, NÃO EFETUE MÚLTIPLOS TESTES AO MESMO TEMPO.', 'ATTENTION: Login requires a secure (HTTPS) connection or running on localhost.': 'ATENÇÃO o login requer uma conexão segura (HTTPS) ou executar de localhost.',
'ATTENTION: you cannot edit the running application!': 'ATENÇÃO: Não pode modificar a aplicação em execução!', 'ATTENTION: TESTING IS NOT THREAD SAFE SO DO NOT PERFORM MULTIPLE TESTS CONCURRENTLY.': 'ATENÇÃO OS TESTES NÃO THREAD SAFE, NÃO EFETUE MÚLTIPLOS TESTES AO MESMO TEMPO.',
'Autocomplete Python Code': 'Autocompletar Código Python', 'ATTENTION: you cannot edit the running application!': 'ATENÇÃO: Não pode modificar a aplicação em execução!',
'Available databases and tables': 'Bancos de dados e tabelas disponíveis', 'Autocomplete Python Code': 'Autocompletar Código Python',
'back': 'voltar', 'Available databases and tables': 'Bancos de dados e tabelas disponíveis',
'browse': 'buscar', 'back': 'voltar',
'cache': 'cache', 'Begin': 'Begin',
'cache, errors and sessions cleaned': 'cache, erros e sessões eliminadas', 'browse': 'buscar',
'can be a git repo': 'can be a git repo', 'cache': 'cache',
'Cannot be empty': 'Não pode ser vazio', 'cache, errors and sessions cleaned': 'cache, erros e sessões eliminadas',
'Cannot compile: there are errors in your app. Debug it, correct errors and try again.': 'Não é possível compilar: Existem erros em sua aplicação. Depure, corrija os errros e tente novamente', 'can be a git repo': 'can be a git repo',
'Cannot compile: there are errors in your app:': 'Não é possível compilar: Existem erros em sua aplicação', 'Cannot be empty': 'Não pode ser vazio',
'cannot create file': 'Não é possível criar o arquivo', 'Cannot compile: there are errors in your app. Debug it, correct errors and try again.': 'Não é possível compilar: Existem erros em sua aplicação. Depure, corrija os errros e tente novamente',
'cannot upload file "%(filename)s"': 'não é possível fazer upload do arquivo "%(filename)s"', 'Cannot compile: there are errors in your app:': 'Não é possível compilar: Existem erros em sua aplicação',
'Change admin password': 'mudar senha de administrador', 'cannot create file': 'Não é possível criar o arquivo',
'change editor settings': 'mudar definições do editor', 'cannot upload file "%(filename)s"': 'não é possível fazer upload do arquivo "%(filename)s"',
'Change Password': 'Trocar Senha', 'Change admin password': 'mudar senha de administrador',
'check all': 'marcar todos', 'change editor settings': 'mudar definições do editor',
'Check for upgrades': 'checar por atualizações', 'Change Password': 'Trocar Senha',
'Check to delete': 'Marque para apagar', 'check all': 'marcar todos',
'Checking for upgrades...': 'Buscando atualizações...', 'Check for upgrades': 'checar por atualizações',
'Clean': 'limpar', 'Check to delete': 'Marque para apagar',
'click here for online examples': 'clique para ver exemplos online', 'Checking for upgrades...': 'Buscando atualizações...',
'click here for the administrative interface': 'Clique aqui para acessar a interface administrativa', 'Clean': 'limpar',
'Click row to expand traceback': 'Clique em uma coluna para expandir o log do erro', 'click here for online examples': 'clique para ver exemplos online',
'click to check for upgrades': 'clique aqui para checar por atualizações', 'click here for the administrative interface': 'Clique aqui para acessar a interface administrativa',
'click to open': 'clique para abrir', 'Click row to expand traceback': 'Clique em uma coluna para expandir o log do erro',
'Client IP': 'IP do cliente', 'click to check for upgrades': 'clique aqui para checar por atualizações',
'code': 'código', 'click to open': 'clique para abrir',
'collapse/expand all': 'colapsar/expandir tudo', 'Client IP': 'IP do cliente',
'commit (mercurial)': 'commit (mercurial)', 'code': 'código',
'Compile': 'compilar', 'collapse/expand all': 'colapsar/expandir tudo',
'compiled application removed': 'aplicação compilada removida', 'commit (mercurial)': 'commit (mercurial)',
'Controllers': 'Controladores', 'Compile': 'compilar',
'controllers': 'controladores', 'compiled application removed': 'aplicação compilada removida',
'Count': 'Contagem', 'Controllers': 'Controladores',
'Create': 'criar', 'controllers': 'controladores',
'create file with filename:': 'criar um arquivo com o nome:', 'Count': 'Contagem',
'Create new application using the Wizard': 'Criar nova aplicação utilizando o assistente', 'Create': 'criar',
'create new application:': 'nome da nova aplicação:', 'create file with filename:': 'criar um arquivo com o nome:',
'Create new simple application': 'Crie uma nova aplicação', 'Create new application using the Wizard': 'Criar nova aplicação utilizando o assistente',
'Create/Upload': 'Create/Upload', 'create new application:': 'nome da nova aplicação:',
'created by': 'criado por', 'Create new simple application': 'Crie uma nova aplicação',
'crontab': 'crontab', 'Create/Upload': 'Create/Upload',
'Current request': 'Requisição atual', 'created by': 'criado por',
'Current response': 'Resposta atual', 'crontab': 'crontab',
'Current session': 'Sessão atual', 'Current request': 'Requisição atual',
'currently running': 'Executando', 'Current response': 'Resposta atual',
'currently saved or': 'Atualmente salvo ou', 'Current session': 'Sessão atual',
'customize me!': 'Modifique-me', 'currently running': 'Executando',
'data uploaded': 'Dados enviados', 'currently saved or': 'Atualmente salvo ou',
'database': 'banco de dados', 'customize me!': 'Modifique-me',
'database %s select': 'Seleção no banco de dados %s', 'data uploaded': 'Dados enviados',
'database administration': 'administração de banco de dados', 'database': 'banco de dados',
'Date and Time': 'Data e Hora', 'database %s select': 'Seleção no banco de dados %s',
'db': 'db', 'database administration': 'administração de banco de dados',
'Debug': 'Debug', 'Date and Time': 'Data e Hora',
'defines tables': 'define as tabelas', 'db': 'db',
'Delete': 'Apague', 'Debug': 'Debug',
'delete': 'apagar', 'defines tables': 'define as tabelas',
'delete all checked': 'apagar marcados', 'Delete': 'Apague',
'delete plugin': 'apagar plugin', 'delete': 'apagar',
'Delete this file (you will be asked to confirm deletion)': 'Delete this file (you will be asked to confirm deletion)', 'delete all checked': 'apagar marcados',
'Delete:': 'Apague:', 'delete plugin': 'apagar plugin',
'Deploy': 'publicar', 'Delete this file (you will be asked to confirm deletion)': 'Delete this file (you will be asked to confirm deletion)',
'Deploy on Google App Engine': 'Publicar no Google App Engine', 'Delete:': 'Apague:',
'Deploy to OpenShift': 'Deploy to OpenShift', 'Deploy': 'publicar',
'Description': 'Descrição', 'Deploy on Google App Engine': 'Publicar no Google App Engine',
'design': 'modificar', 'Deploy to OpenShift': 'Deploy to OpenShift',
'DESIGN': 'Projeto', 'Deploy to pythonanywhere': 'Deploy to pythonanywhere',
'Design for': 'Projeto de', 'Deploy to PythonAnywhere': 'Deploy to PythonAnywhere',
'Detailed traceback description': 'Detailed traceback description', 'Deployment Interface': 'Deployment Interface',
'direction: ltr': 'direção: ltr', 'Description': 'Descrição',
'Disable': 'Disable', 'design': 'modificar',
'docs': 'docs', 'DESIGN': 'Projeto',
'done!': 'feito!', 'Design for': 'Projeto de',
'download layouts': 'download layouts', 'Detailed traceback description': 'Detailed traceback description',
'Download layouts from repository': 'Download layouts from repository', 'details': 'details',
'download plugins': 'download plugins', 'direction: ltr': 'direção: ltr',
'Download plugins from repository': 'Download plugins from repository', 'Disable': 'Disable',
'E-mail': 'E-mail', 'docs': 'docs',
'EDIT': 'EDITAR', 'done!': 'feito!',
'Edit': 'editar', 'download layouts': 'download layouts',
'Edit application': 'Editar aplicação', 'Download layouts from repository': 'Download layouts from repository',
'edit controller': 'editar controlador', 'download plugins': 'download plugins',
'Edit current record': 'Editar o registro atual', 'Download plugins from repository': 'Download plugins from repository',
'Edit Profile': 'Editar Perfil', 'E-mail': 'E-mail',
'edit views:': 'editar visões:', 'EDIT': 'EDITAR',
'Editing %s': 'A Editar %s', 'Edit': 'editar',
'Editing file': 'Editando arquivo', 'Edit application': 'Editar aplicação',
'Editing file "%s"': 'Editando arquivo "%s"', 'edit controller': 'editar controlador',
'Editing Language file': 'Editando arquivo de linguagem', 'Edit current record': 'Editar o registro atual',
'Enterprise Web Framework': 'Framework web empresarial', 'Edit Profile': 'Editar Perfil',
'Error': 'Erro', 'edit views:': 'editar visões:',
'Error logs for "%(app)s"': 'Logs de erro para "%(app)s"', 'Editing %s': 'A Editar %s',
'Error snapshot': 'Error snapshot', 'Editing file': 'Editando arquivo',
'Error ticket': 'Error ticket', 'Editing file "%s"': 'Editando arquivo "%s"',
'Errors': 'erros', 'Editing Language file': 'Editando arquivo de linguagem',
'Exception instance attributes': 'Atributos da instancia de excessão', 'Email Address': 'Email Address',
'Exit Fullscreen': 'Sair de Ecrã Inteiro', 'Enterprise Web Framework': 'Framework web empresarial',
'Expand Abbreviation (html files only)': 'Expandir Abreviação (só para ficheiros html)', 'Error': 'Erro',
'export as csv file': 'exportar como arquivo CSV', 'Error logs for "%(app)s"': 'Logs de erro para "%(app)s"',
'exposes': 'expõe', 'Error snapshot': 'Error snapshot',
'extends': 'estende', 'Error ticket': 'Error ticket',
'failed to reload module': 'Falha ao recarregar o módulo', 'Errors': 'erros',
'failed to reload module because:': 'falha ao recarregar o módulo por:', 'Exception instance attributes': 'Atributos da instancia de excessão',
'File': 'Arquivo', 'Exit Fullscreen': 'Sair de Ecrã Inteiro',
'file "%(filename)s" created': 'arquivo "%(filename)s" criado', 'Expand Abbreviation (html files only)': 'Expandir Abreviação (só para ficheiros html)',
'file "%(filename)s" deleted': 'arquivo "%(filename)s" apagado', 'export as csv file': 'exportar como arquivo CSV',
'file "%(filename)s" uploaded': 'arquivo "%(filename)s" enviado', 'exposes': 'expõe',
'file "%(filename)s" was not deleted': 'arquivo "%(filename)s" não foi apagado', 'exposes:': 'exposes:',
'file "%s" of %s restored': 'arquivo "%s" de %s restaurado', 'extends': 'estende',
'file changed on disk': 'arquivo modificado no disco', 'failed to reload module': 'Falha ao recarregar o módulo',
'file does not exist': 'arquivo não existe', 'failed to reload module because:': 'falha ao recarregar o módulo por:',
'file saved on %(time)s': 'arquivo salvo em %(time)s', 'File': 'Arquivo',
'file saved on %s': 'arquivo salvo em %s', 'file "%(filename)s" created': 'arquivo "%(filename)s" criado',
'filter': 'filtro', 'file "%(filename)s" deleted': 'arquivo "%(filename)s" apagado',
'Find Next': 'Localizar Seguinte', 'file "%(filename)s" uploaded': 'arquivo "%(filename)s" enviado',
'Find Previous': 'Localizar Anterior', 'file "%(filename)s" was not deleted': 'arquivo "%(filename)s" não foi apagado',
'First name': 'Nome', 'file "%s" of %s restored': 'arquivo "%s" de %s restaurado',
'Frames': 'Frames', 'file changed on disk': 'arquivo modificado no disco',
'Functions with no doctests will result in [passed] tests.': 'Funções sem doctests resultarão em testes [aceitos].', 'file does not exist': 'arquivo não existe',
'graph model': 'graph model', 'file saved on %(time)s': 'arquivo salvo em %(time)s',
'Group ID': 'ID do Grupo', 'file saved on %s': 'arquivo salvo em %s',
'Hello World': 'Olá Mundo', 'filter': 'filtro',
'Help': 'ajuda', 'Find Next': 'Localizar Seguinte',
'Hide/Show Translated strings': '', 'Find Previous': 'Localizar Anterior',
'htmledit': 'htmledit', 'First name': 'Nome',
'If the report above contains a ticket number it indicates a failure in executing the controller, before any attempt to execute the doctests. This is usually due to an indentation error or an error outside function code.\nA green title indicates that all tests (if defined) passed. In this case test results are not shown.': 'Se o relatório acima contém um número de ticket, isso indica uma falha no controlador em execução, antes de tantar executar os doctests. Isto acontece geralmente por erro de endentação ou erro fora do código da função.\r\nO titulo em verde indica que os testes (se definidos) passaram. Neste caso os testes não são mostrados.', 'Form has errors': 'Form has errors',
'Import/Export': 'Importar/Exportar', 'Frames': 'Frames',
'includes': 'inclui', 'Functions with no doctests will result in [passed] tests.': 'Funções sem doctests resultarão em testes [aceitos].',
'insert new': 'inserir novo', 'graph model': 'graph model',
'insert new %s': 'inserir novo %s', 'Group ID': 'ID do Grupo',
'inspect attributes': 'inspecionar atributos', 'Hello World': 'Olá Mundo',
'Install': 'instalar', 'Help': 'ajuda',
'Installed applications': 'Aplicações instaladas', 'Hide/Show Translated strings': '',
'internal error': 'erro interno', 'htmledit': 'htmledit',
'Internal State': 'Estado Interno', 'If the report above contains a ticket number it indicates a failure in executing the controller, before any attempt to execute the doctests. This is usually due to an indentation error or an error outside function code.\nA green title indicates that all tests (if defined) passed. In this case test results are not shown.': 'Se o relatório acima contém um número de ticket, isso indica uma falha no controlador em execução, antes de tantar executar os doctests. Isto acontece geralmente por erro de endentação ou erro fora do código da função.\r\nO titulo em verde indica que os testes (se definidos) passaram. Neste caso os testes não são mostrados.',
'Invalid action': 'Ação inválida', 'Import/Export': 'Importar/Exportar',
'Invalid email': 'E-mail inválido', 'includes': 'inclui',
'invalid password': 'senha inválida', 'insert new': 'inserir novo',
'Invalid Query': 'Consulta inválida', 'insert new %s': 'inserir novo %s',
'invalid request': 'solicitação inválida', 'inspect attributes': 'inspecionar atributos',
'invalid ticket': 'ticket inválido', 'Install': 'instalar',
'Keyboard shortcuts': 'Atalhos de teclado', 'Installed applications': 'Aplicações instaladas',
'language file "%(filename)s" created/updated': 'arquivo de linguagem "%(filename)s" criado/atualizado', 'internal error': 'erro interno',
'Language files (static strings) updated': 'Arquivos de linguagem (textos estáticos) atualizados', 'Internal State': 'Estado Interno',
'languages': 'linguagens', 'Invalid action': 'Ação inválida',
'Languages': 'Linguagens', 'Invalid email': 'E-mail inválido',
'languages updated': 'linguagens atualizadas', 'invalid password': 'senha inválida',
'Last name': 'Sobrenome', 'Invalid Query': 'Consulta inválida',
'Last saved on:': 'Salvo em:', 'invalid request': 'solicitação inválida',
'License for': 'Licença para', 'invalid ticket': 'ticket inválido',
'loading...': 'carregando...', 'Keyboard shortcuts': 'Atalhos de teclado',
'locals': 'locals', 'language file "%(filename)s" created/updated': 'arquivo de linguagem "%(filename)s" criado/atualizado',
'Login': 'Entrar', 'Language files (static strings) updated': 'Arquivos de linguagem (textos estáticos) atualizados',
'login': 'inicio de sessão', 'languages': 'linguagens',
'Login to the Administrative Interface': 'Entrar na interface adminitrativa', 'Languages': 'Linguagens',
'Logout': 'finalizar sessão', 'languages updated': 'linguagens atualizadas',
'Lost Password': 'Senha perdida', 'Last name': 'Sobrenome',
'Manage': 'Manage', 'Last saved on:': 'Salvo em:',
'manage': 'gerenciar', 'License for': 'Licença para',
'merge': 'juntar', 'lists by ticket': 'lists by ticket',
'Models': 'Modelos', 'Loading...': 'Loading...',
'models': 'modelos', 'loading...': 'carregando...',
'Modules': 'Módulos', 'Local Apps': 'Local Apps',
'modules': 'módulos', 'locals': 'locals',
'Name': 'Nome', 'Login': 'Entrar',
'new application "%s" created': 'nova aplicação "%s" criada', 'login': 'inicio de sessão',
'New application wizard': 'Assistente para novas aplicações ', 'Login successful': 'Login successful',
'new plugin installed': 'novo plugin instalado', 'Login to the Administrative Interface': 'Entrar na interface adminitrativa',
'New Record': 'Novo registro', 'Login/Register': 'Login/Register',
'new record inserted': 'novo registro inserido', 'Logout': 'finalizar sessão',
'New simple application': 'Nova aplicação básica', 'Lost Password': 'Senha perdida',
'next 100 rows': 'próximos 100 registros', 'Manage': 'Manage',
'NO': 'NÃO', 'manage': 'gerenciar',
'No databases in this application': 'Não existem bancos de dados nesta aplicação', 'merge': 'juntar',
'no match': 'não encontrado', 'Models': 'Modelos',
'no package selected': 'nenhum pacote selecionado', 'models': 'modelos',
'online designer': 'online designer', 'Modules': 'Módulos',
'or alternatively': 'or alternatively', 'modules': 'módulos',
'Or Get from URL:': 'Ou Obtenha do URL:', 'Name': 'Nome',
'or import from csv file': 'ou importar de um arquivo CSV', 'new application "%s" created': 'nova aplicação "%s" criada',
'or provide app url:': 'ou forneça a url de uma aplicação:', 'New Application Wizard': 'New Application Wizard',
'or provide application url:': 'ou forneça a url de uma aplicação:', 'New application wizard': 'Assistente para novas aplicações ',
'Origin': 'Origem', 'new plugin installed': 'novo plugin instalado',
'Original/Translation': 'Original/Tradução', 'New Record': 'Novo registro',
'Overwrite installed app': 'sobrescrever aplicação instalada', 'new record inserted': 'novo registro inserido',
'Pack all': 'criar pacote', 'New simple application': 'Nova aplicação básica',
'Pack compiled': 'criar pacote compilado', 'next 100 rows': 'próximos 100 registros',
'Pack custom': 'Pack custom', 'NO': 'NÃO',
'pack plugin': 'empacotar plugin', 'No databases in this application': 'Não existem bancos de dados nesta aplicação',
'PAM authenticated user, cannot change password here': 'usuario autenticado por PAM, não pode alterar a senha por aqui', 'no match': 'não encontrado',
'Password': 'Senha', 'no package selected': 'nenhum pacote selecionado',
'password changed': 'senha alterada', 'No ticket_storage.txt found under /private folder': 'No ticket_storage.txt found under /private folder',
'Peeking at file': 'Visualizando arquivo', 'online designer': 'online designer',
'plugin "%(plugin)s" deleted': 'plugin "%(plugin)s" eliminado', 'or alternatively': 'or alternatively',
'Plugin "%s" in application': 'Plugin "%s" na aplicação', 'Or Get from URL:': 'Ou Obtenha do URL:',
'plugins': 'plugins', 'or import from csv file': 'ou importar de um arquivo CSV',
'Plugins': 'Plugins', 'or provide app url:': 'ou forneça a url de uma aplicação:',
'Plural-Forms:': 'Plural-Forms:', 'or provide application url:': 'ou forneça a url de uma aplicação:',
'Powered by': 'Este site utiliza', 'Origin': 'Origem',
'previous 100 rows': '100 registros anteriores', 'Original/Translation': 'Original/Tradução',
'Private files': 'Private files', 'Overwrite installed app': 'sobrescrever aplicação instalada',
'private files': 'private files', 'Pack all': 'criar pacote',
'Query:': 'Consulta:', 'Pack compiled': 'criar pacote compilado',
'Rapid Search': 'Rapid Search', 'Pack custom': 'Pack custom',
'record': 'registro', 'pack plugin': 'empacotar plugin',
'record does not exist': 'o registro não existe', 'PAM authenticated user, cannot change password here': 'usuario autenticado por PAM, não pode alterar a senha por aqui',
'record id': 'id do registro', 'Password': 'Senha',
'Record ID': 'ID do Registro', 'password changed': 'senha alterada',
'Register': 'Registrar-se', 'Peeking at file': 'Visualizando arquivo',
'Registration key': 'Chave de registro', 'Please wait, giving pythonanywhere a moment...': 'Please wait, giving pythonanywhere a moment...',
'Reload routes': 'Reload routes', 'plugin "%(plugin)s" deleted': 'plugin "%(plugin)s" eliminado',
'Remove compiled': 'eliminar compilados', 'Plugin "%s" in application': 'Plugin "%s" na aplicação',
'Replace': 'Substituir', 'plugins': 'plugins',
'Replace All': 'Substituir Tudo', 'Plugins': 'Plugins',
'request': 'request', 'Plural-Forms:': 'Plural-Forms:',
'Resolve Conflict file': 'Arquivo de resolução de conflito', 'Powered by': 'Este site utiliza',
'response': 'response', 'previous 100 rows': '100 registros anteriores',
'restore': 'restaurar', 'Private files': 'Private files',
'revert': 'reverter', 'private files': 'private files',
'Role': 'Papel', 'PythonAnywhere Apps': 'PythonAnywhere Apps',
'Rows in table': 'Registros na tabela', 'PythonAnywhere Password': 'PythonAnywhere Password',
'Rows selected': 'Registros selecionados', 'Query:': 'Consulta:',
'rules are not defined': 'rules are not defined', 'Rapid Search': 'Rapid Search',
"Run tests in this file (to run all files, you may also use the button labelled 'test')": "Run tests in this file (to run all files, you may also use the button labelled 'test')", 'record': 'registro',
'Running on %s': 'A correr em %s', 'record does not exist': 'o registro não existe',
'Save': 'Save', 'record id': 'id do registro',
'save': 'salvar', 'Record ID': 'ID do Registro',
'Save file:': 'Gravar ficheiro:', 'Register': 'Registrar-se',
'Save file: %s': 'Gravar ficheiro: %s', 'Registration key': 'Chave de registro',
'Save via Ajax': 'Gravar via Ajax', 'Reload routes': 'Reload routes',
'Saved file hash:': 'Hash do arquivo salvo:', 'Remove compiled': 'eliminar compilados',
'selected': 'selecionado(s)', 'Replace': 'Substituir',
'session': 'session', 'Replace All': 'Substituir Tudo',
'session expired': 'sessão expirada', 'request': 'request',
'shell': 'Terminal', 'requires python-git, but not installed': 'requires python-git, but not installed',
'Site': 'site', 'Resolve Conflict file': 'Arquivo de resolução de conflito',
'some files could not be removed': 'alguns arquicos não puderam ser removidos', 'response': 'response',
'Start searching': 'Start searching', 'restore': 'restaurar',
'Start wizard': 'iniciar assistente', 'revert': 'reverter',
'state': 'estado', 'Role': 'Papel',
'Static': 'Static', 'Rows in table': 'Registros na tabela',
'static': 'estáticos', 'Rows selected': 'Registros selecionados',
'Static files': 'Arquivos estáticos', 'rules are not defined': 'rules are not defined',
'Submit': 'Submit', "Run tests in this file (to run all files, you may also use the button labelled 'test')": "Run tests in this file (to run all files, you may also use the button labelled 'test')",
'submit': 'enviar', 'Running on %s': 'A correr em %s',
'Sure you want to delete this object?': 'Tem certeza que deseja apaagr este objeto?', 'Save': 'Save',
'table': 'tabela', 'save': 'salvar',
'Table name': 'Nome da tabela', 'Save file:': 'Gravar ficheiro:',
'test': 'testar', 'Save file: %s': 'Gravar ficheiro: %s',
'Testing application': 'Testando a aplicação', 'Save via Ajax': 'Gravar via Ajax',
'The "query" is a condition like "db.table1.field1==\'value\'". Something like "db.table1.field1==db.table2.field2" results in a SQL JOIN.': 'A "consulta" é uma condição como "db.tabela.campo1==\'valor\'". Algo como "db.tabela1.campo1==db.tabela2.campo2" resulta em um JOIN SQL.', 'Saved file hash:': 'Hash do arquivo salvo:',
'the application logic, each URL path is mapped in one exposed function in the controller': 'A lógica da aplicação, cada URL é mapeada para uma função exposta pelo controlador', 'selected': 'selecionado(s)',
'The application logic, each URL path is mapped in one exposed function in the controller': 'The application logic, each URL path is mapped in one exposed function in the controller', 'session': 'session',
'the data representation, define database tables and sets': 'A representação dos dadps, define tabelas e estruturas de dados', 'session expired': 'sessão expirada',
'The data representation, define database tables and sets': 'The data representation, define database tables and sets', 'shell': 'Terminal',
'The presentations layer, views are also known as templates': 'The presentations layer, views are also known as templates', 'Site': 'site',
'the presentations layer, views are also known as templates': 'A camada de apresentação, As visões também são chamadas de templates', 'some files could not be removed': 'alguns arquicos não puderam ser removidos',
'There are no controllers': 'Não existem controllers', 'Something went wrong please wait a few minutes before retrying': 'Something went wrong please wait a few minutes before retrying',
'There are no models': 'Não existem modelos', 'source : filesystem': 'source : filesystem',
'There are no modules': 'Não existem módulos', 'Start a new app': 'Start a new app',
'There are no plugins': 'There are no plugins', 'Start searching': 'Start searching',
'There are no private files': '', 'Start wizard': 'iniciar assistente',
'There are no static files': 'Não existem arquicos estáticos', 'state': 'estado',
'There are no translators, only default language is supported': 'Não há traduções, somente a linguagem padrão é suportada', 'Static': 'Static',
'There are no views': 'Não existem visões', 'static': 'estáticos',
'These files are not served, they are only available from within your app': 'These files are not served, they are only available from within your app', 'Static files': 'Arquivos estáticos',
'These files are served without processing, your images go here': 'These files are served without processing, your images go here', 'Submit': 'Submit',
'these files are served without processing, your images go here': 'Estes arquivos são servidos sem processamento, suas imagens ficam aqui', 'submit': 'enviar',
'This is the %(filename)s template': 'Este é o template %(filename)s', 'Sure you want to delete this object?': 'Tem certeza que deseja apaagr este objeto?',
'Ticket': 'Ticket', 'switch to : db': 'switch to : db',
'Ticket ID': 'Ticket ID', 'table': 'tabela',
'Timestamp': 'Data Atual', 'Table name': 'Nome da tabela',
'TM': 'MR', 'test': 'testar',
'to previous version.': 'para a versão anterior.', 'Testing application': 'Testando a aplicação',
'To create a plugin, name a file/folder plugin_[name]': 'Para criar um plugin, nomeio um arquivo/pasta como plugin_[nome]', 'The "query" is a condition like "db.table1.field1==\'value\'". Something like "db.table1.field1==db.table2.field2" results in a SQL JOIN.': 'A "consulta" é uma condição como "db.tabela.campo1==\'valor\'". Algo como "db.tabela1.campo1==db.tabela2.campo2" resulta em um JOIN SQL.',
'toggle breakpoint': 'toggle breakpoint', 'the application logic, each URL path is mapped in one exposed function in the controller': 'A lógica da aplicação, cada URL é mapeada para uma função exposta pelo controlador',
'Toggle comment': 'Toggle comment', 'The application logic, each URL path is mapped in one exposed function in the controller': 'The application logic, each URL path is mapped in one exposed function in the controller',
'Toggle Fullscreen': 'Toggle Fullscreen', 'the data representation, define database tables and sets': 'A representação dos dadps, define tabelas e estruturas de dados',
'Traceback': 'Traceback', 'The data representation, define database tables and sets': 'The data representation, define database tables and sets',
'translation strings for the application': 'textos traduzidos para a aplicação', 'The presentations layer, views are also known as templates': 'The presentations layer, views are also known as templates',
'Translation strings for the application': 'Translation strings for the application', 'the presentations layer, views are also known as templates': 'A camada de apresentação, As visões também são chamadas de templates',
'try': 'tente', 'There are no controllers': 'Não existem controllers',
'try something like': 'tente algo como', 'There are no models': 'Não existem modelos',
'Try the mobile interface': 'Try the mobile interface', 'There are no modules': 'Não existem módulos',
'Unable to check for upgrades': 'Não é possível checar as atualizações', 'There are no plugins': 'There are no plugins',
'unable to create application "%s"': 'não é possível criar a aplicação "%s"', 'There are no private files': '',
'unable to delete file "%(filename)s"': 'não é possível criar o arquico "%(filename)s"', 'There are no static files': 'Não existem arquicos estáticos',
'unable to delete file plugin "%(plugin)s"': 'não é possível criar o plugin "%(plugin)s"', 'There are no translators, only default language is supported': 'Não há traduções, somente a linguagem padrão é suportada',
'Unable to download': 'Não é possível efetuar o download', 'There are no views': 'Não existem visões',
'Unable to download app': 'Não é possível baixar a aplicação', 'These files are not served, they are only available from within your app': 'These files are not served, they are only available from within your app',
'Unable to download app because:': 'Não é possível baixar a aplicação porque:', 'These files are served without processing, your images go here': 'These files are served without processing, your images go here',
'Unable to download because': 'Não é possível baixar porque', 'these files are served without processing, your images go here': 'Estes arquivos são servidos sem processamento, suas imagens ficam aqui',
'unable to parse csv file': 'não é possível analisar o arquivo CSV', 'This is the %(filename)s template': 'Este é o template %(filename)s',
'unable to uninstall "%s"': 'não é possível instalar "%s"', 'Ticket': 'Ticket',
'unable to upgrade because "%s"': 'não é possível atualizar porque "%s"', 'Ticket ID': 'Ticket ID',
'uncheck all': 'desmarcar todos', 'Timestamp': 'Data Atual',
'Uninstall': 'desinstalar', 'TM': 'MR',
'update': 'atualizar', 'to previous version.': 'para a versão anterior.',
'update all languages': 'atualizar todas as linguagens', 'To create a plugin, name a file/folder plugin_[name]': 'Para criar um plugin, nomeio um arquivo/pasta como plugin_[nome]',
'Update:': 'Atualizar:', 'toggle breakpoint': 'toggle breakpoint',
'upgrade web2py now': 'atualize o web2py agora', 'Toggle comment': 'Toggle comment',
'upload': 'upload', 'Toggle Fullscreen': 'Toggle Fullscreen',
'Upload': 'Upload', 'Traceback': 'Traceback',
'Upload & install packed application': 'Faça upload e instale uma aplicação empacotada', 'translation strings for the application': 'textos traduzidos para a aplicação',
'Upload a package:': 'Faça upload de um pacote:', 'Translation strings for the application': 'Translation strings for the application',
'Upload and install packed application': 'Upload and install packed application', 'try': 'tente',
'upload application:': 'Fazer upload de uma aplicação:', 'try something like': 'tente algo como',
'Upload existing application': 'Faça upload de uma aplicação existente', 'Try the mobile interface': 'Try the mobile interface',
'upload file:': 'Enviar arquivo:', 'Unable to check for upgrades': 'Não é possível checar as atualizações',
'upload plugin file:': 'Enviar arquivo de plugin:', 'unable to create application "%s"': 'não é possível criar a aplicação "%s"',
'Use (...)&(...) for AND, (...)|(...) for OR, and ~(...) for NOT to build more complex queries.': 'Use (...)&(...) para AND, (...)|(...) para OR, y ~(...) para NOT, para criar consultas mais complexas.', 'unable to delete file "%(filename)s"': 'não é possível criar o arquico "%(filename)s"',
'Use an url:': 'Use uma url:', 'unable to delete file plugin "%(plugin)s"': 'não é possível criar o plugin "%(plugin)s"',
'User ID': 'ID do Usuario', 'Unable to download': 'Não é possível efetuar o download',
'variables': 'variáveis', 'Unable to download app': 'Não é possível baixar a aplicação',
'Version': 'Versão', 'Unable to download app because:': 'Não é possível baixar a aplicação porque:',
'versioning': 'versionamento', 'Unable to download because': 'Não é possível baixar porque',
'Versioning': 'Versioning', 'unable to parse csv file': 'não é possível analisar o arquivo CSV',
'view': 'visão', 'unable to uninstall "%s"': 'não é possível instalar "%s"',
'Views': 'Visões', 'unable to upgrade because "%s"': 'não é possível atualizar porque "%s"',
'views': 'visões', 'uncheck all': 'desmarcar todos',
'Web Framework': 'Web Framework', 'Uninstall': 'desinstalar',
'web2py is up to date': 'web2py está atualizado', 'update': 'atualizar',
'web2py Recent Tweets': 'Tweets Recentes de @web2py', 'update all languages': 'atualizar todas as linguagens',
'web2py upgraded; please restart it': 'web2py atualizado; favor reiniciar', 'Update:': 'Atualizar:',
'Welcome to web2py': 'Bem-vindo ao web2py', 'upgrade now to %s': 'upgrade now to %s',
'YES': 'SIM', 'upgrade web2py now': 'atualize o web2py agora',
} 'upload': 'upload',
'Upload': 'Upload',
'Upload & install packed application': 'Faça upload e instale uma aplicação empacotada',
'Upload a package:': 'Faça upload de um pacote:',
'Upload and install packed application': 'Upload and install packed application',
'upload application:': 'Fazer upload de uma aplicação:',
'Upload existing application': 'Faça upload de uma aplicação existente',
'upload file:': 'Enviar arquivo:',
'upload plugin file:': 'Enviar arquivo de plugin:',
'Use (...)&(...) for AND, (...)|(...) for OR, and ~(...) for NOT to build more complex queries.': 'Use (...)&(...) para AND, (...)|(...) para OR, y ~(...) para NOT, para criar consultas mais complexas.',
'Use an url:': 'Use uma url:',
'User ID': 'ID do Usuario',
'Username': 'Username',
'variables': 'variáveis',
'Version': 'Versão',
'versioning': 'versionamento',
'Versioning': 'Versioning',
'view': 'visão',
'Views': 'Visões',
'views': 'visões',
'Web Framework': 'Web Framework',
'web2py Admin Password': 'web2py Admin Password',
'web2py is up to date': 'web2py está atualizado',
'web2py Recent Tweets': 'Tweets Recentes de @web2py',
'web2py upgraded; please restart it': 'web2py atualizado; favor reiniciar',
'Welcome to web2py': 'Bem-vindo ao web2py',
'YES': 'SIM',
}
@@ -138,6 +138,7 @@
<p class="row-buttons"> <p class="row-buttons">
{{=button(URL('gae','deploy'), T('Deploy on Google App Engine'))}} {{=button(URL('gae','deploy'), T('Deploy on Google App Engine'))}}
{{=button(URL('openshift','deploy'),T('Deploy to OpenShift'))}} {{=button(URL('openshift','deploy'),T('Deploy to OpenShift'))}}
{{=button(URL('pythonanywhere','deploy'), T('Deploy to PythonAnywhere'))}}
</p> </p>
</div> <!-- /DEPLOY ON GAE --> </div> <!-- /DEPLOY ON GAE -->
<!-- APP WIZARD --> <!-- APP WIZARD -->
@@ -0,0 +1,173 @@
{{extend 'layout.html'}}
<h2><span style="color:#139FD7">python</span>anywhere {{=T('Deployment Interface')}}</h2>
<div id="register_form">
<h3>{{=T('Login/Register')}}</h3>
<form class="form-horizontal" id="palogin">
<div class="control-group" id="username__row">
<label class="control-label" for="username">{{=T('Username')}}</label>
<div class="controls">
<input type="text" name="username" id="username">
<span class="help-block"></span>
</div>
</div>
<div class="control-group" id="email_address__row">
<label class="control-label" for="email_address">{{=T('Email Address')}}</label>
<div class="controls">
<input type="text" name="email_address" id="email_address">
<span class="help-block"></span>
</div>
</div>
<div class="control-group" id="pythonanywhere_password__row">
<label class="control-label" for="pythonanywhere_password">{{=T('PythonAnywhere Password')}}</label>
<div class="controls">
<input type="password" name="pythonanywhere_password" id="pythonanywhere_password">
<span class="help-block"></span>
</div>
</div>
<div class="control-group" id="web2py_admin_password__row">
<label class="control-label" for="web2py_admin_password">{{=T('web2py Admin Password')}}</label>
<div class="controls">
<input type="password" name="web2py_admin_password" id="web2py_admin_password">
<span class="help-block"></span>
</div>
</div>
<div class="control-group" id="accepts_terms__row">
<div class="controls">
<label class="checkbox">
<input type="checkbox" name="accepts_terms" id="accepts_terms"> {{=T('Accept Terms')}}
</label>
<span class="help-block"></span>
</div>
</div>
<div class="control-group">
<div class="controls">
<button type="submit" class="btn btn-primary" id="submit_palogin">{{=T('Submit')}}</button>
</div>
</div>
</form>
</div>
<div class="row-fluid" id="app_manager" style="display:none;">
<div class="span6">
<h3>{{=T('Local Apps')}}</h3>
<form id="apppicker">
<select name="apps" class="form-control" id="local" multiple>
<option>{{=T('Loading...')}}</option>
</select>
<input type="submit" value="Deploy" id="deploy_button" class="btn btn-primary">
</form>
</div>
<div class="span6">
<h3>{{=T('PythonAnywhere Apps')}}</h3>
<ul id="pythonanywhere">
<li>{{=T('Loading...')}}</li>
</ul>
</div>
</div>
<script>
$(document).ready(function() {
$('#palogin').off('submit');
$('#palogin').submit(function(event) {
var data = $('#palogin').serialize();
$.web2py.disableElement($('#submit_palogin'));
$.web2py.disableFormElements($('#palogin'));
$.ajax({
url: '{{=URL("pythonanywhere", "crossdomainproxy")}}',
type: 'POST',
data: data,
dataType: 'json',
}).done(function(data, textStatus, jqXHR) {
console.log(data);
$('#palogin .error').removeClass('error');
$('#palogin .help-block').text('');
if(data.status == 'error') {
for(var error in data.errors) {
$('#' + error + '__row').addClass('error');
$('#' + error + '__row .help-block').text(data.errors[error][0]);
}
$.web2py.enableElement($('#submit_palogin'));
$.web2py.enableFormElements($('#palogin'));
$.web2py.flash("{{=T('Form has errors')}}");
} else {
$.web2py.flash("{{=T('Login successful')}}");
$('#register_form').hide();
$('#app_manager').show();
refresh_apps();
}
}).fail(function(){
$.web2py.flash("{{=T('Something went wrong please wait a few minutes before retrying')}}");
$.web2py.enableElement($('#submit_palogin'));
$.web2py.enableFormElements($('#palogin'));
});
event.preventDefault();
});
$('#apppicker').off('submit');
$('#apppicker').submit(function(event) {
var data = $('#apppicker').serialize();
$.web2py.disableElement($('#deploy_button'));
$.ajax({
url: '{{=URL("pythonanywhere", "bulk_install")}}',
type: 'POST',
data: {username: $('#username').val(), password: $('#web2py_admin_password').val(), apps: $('#local').val()},
dataType: 'json',
}).done(function(data, textStatus, jqXHR) {
console.log(data);
refresh_apps();
$.web2py.enableElement($('#deploy_button'));
}).fail(function(){
$.web2py.flash("{{=T('Something went wrong please wait a few minutes before retrying')}}");
$.web2py.enableElement($('#deploy_button'));
});
event.preventDefault();
});
});
function refresh_apps() {
// Refresh List of Apps
$('#deploy_button').prop('disabled', true);
$.ajax({
url: '{{=URL("pythonanywhere", "list_apps")}}',
type: 'GET',
data: {username: $('#username').val(), password: $('#web2py_admin_password').val()},
dataType: 'json',
}).done(function(data, textStatus, jqXHR) {
var i = 0;
$('#local').html('')
for(i = 0; i < data.local.length; i++) {
$('#local').append($('<option>', {
value: data.local[i],
text: data.local[i]
}));
}
$('#local').multiSelect('refresh');
$('#pythonanywhere').html('')
for(i = 0; i < data.pythonanywhere.length; i++) {
$('#pythonanywhere').append($('<li>', {
text: data.pythonanywhere[i]
}));
}
$('#deploy_button').prop('disabled', false);
$.web2py.hide_flash();
}).fail(function(){
// Mostly this happens if it's a new account, just waiting a bit should be enough.
$.get('http://' + $('#username').val() + '.pythonanywhere.com'); // Kickstart the instance
$.web2py.flash("{{=T('Please wait, giving pythonanywhere a moment...')}}");
setTimeout(refresh_apps, 30000);
});
}
</script>