Merge branch 'master' of github.com:web2py/web2py
This commit is contained in:
@@ -0,0 +1,105 @@
|
|||||||
|
# -*- 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 create_account():
|
||||||
|
""" Create a PythonAnywhere account """
|
||||||
|
if not request.vars:
|
||||||
|
raise HTTP(400)
|
||||||
|
|
||||||
|
if request.vars.username and request.vars.web2py_admin_password:
|
||||||
|
# Check if web2py is already there otherwise we get an error 500 too.
|
||||||
|
client = ServerProxy('https://%(username)s:%(web2py_admin_password)s@%(username)s.pythonanywhere.com/admin/webservices/call/jsonrpc' % request.vars)
|
||||||
|
try:
|
||||||
|
if client.login() is True:
|
||||||
|
return response.json({'status': 'ok'})
|
||||||
|
except ProtocolError as error:
|
||||||
|
pass
|
||||||
|
|
||||||
|
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
|
||||||
|
elif error.code == 500:
|
||||||
|
return response.json({'status':'error', 'errors':{'username': ['An App other than web2py is installed in the domain %(username)s.pythonanywhere.com' % request.vars]}})
|
||||||
|
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'})
|
||||||
@@ -17,6 +17,7 @@
|
|||||||
'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',
|
||||||
|
'Accept Terms': 'Accept Terms',
|
||||||
'additional code for your application': 'código adicional para sua aplicação',
|
'additional code for your application': 'código adicional para sua aplicação',
|
||||||
'Additional code for your application': 'Código adicional para a sua aplicação',
|
'Additional code for your application': 'Código adicional para a sua aplicação',
|
||||||
'admin disabled because no admin password': ' admin desabilitado por falta de senha definida',
|
'admin disabled because no admin password': ' admin desabilitado por falta de senha definida',
|
||||||
@@ -50,6 +51,7 @@
|
|||||||
'Autocomplete Python Code': 'Autocompletar Código Python',
|
'Autocomplete Python Code': 'Autocompletar Código Python',
|
||||||
'Available databases and tables': 'Bancos de dados e tabelas disponíveis',
|
'Available databases and tables': 'Bancos de dados e tabelas disponíveis',
|
||||||
'back': 'voltar',
|
'back': 'voltar',
|
||||||
|
'Begin': 'Begin',
|
||||||
'browse': 'buscar',
|
'browse': 'buscar',
|
||||||
'cache': 'cache',
|
'cache': 'cache',
|
||||||
'cache, errors and sessions cleaned': 'cache, erros e sessões eliminadas',
|
'cache, errors and sessions cleaned': 'cache, erros e sessões eliminadas',
|
||||||
@@ -112,11 +114,15 @@
|
|||||||
'Deploy': 'publicar',
|
'Deploy': 'publicar',
|
||||||
'Deploy on Google App Engine': 'Publicar no Google App Engine',
|
'Deploy on Google App Engine': 'Publicar no Google App Engine',
|
||||||
'Deploy to OpenShift': 'Deploy to OpenShift',
|
'Deploy to OpenShift': 'Deploy to OpenShift',
|
||||||
|
'Deploy to pythonanywhere': 'Deploy to pythonanywhere',
|
||||||
|
'Deploy to PythonAnywhere': 'Deploy to PythonAnywhere',
|
||||||
|
'Deployment Interface': 'Deployment Interface',
|
||||||
'Description': 'Descrição',
|
'Description': 'Descrição',
|
||||||
'design': 'modificar',
|
'design': 'modificar',
|
||||||
'DESIGN': 'Projeto',
|
'DESIGN': 'Projeto',
|
||||||
'Design for': 'Projeto de',
|
'Design for': 'Projeto de',
|
||||||
'Detailed traceback description': 'Detailed traceback description',
|
'Detailed traceback description': 'Detailed traceback description',
|
||||||
|
'details': 'details',
|
||||||
'direction: ltr': 'direção: ltr',
|
'direction: ltr': 'direção: ltr',
|
||||||
'Disable': 'Disable',
|
'Disable': 'Disable',
|
||||||
'docs': 'docs',
|
'docs': 'docs',
|
||||||
@@ -137,6 +143,7 @@
|
|||||||
'Editing file': 'Editando arquivo',
|
'Editing file': 'Editando arquivo',
|
||||||
'Editing file "%s"': 'Editando arquivo "%s"',
|
'Editing file "%s"': 'Editando arquivo "%s"',
|
||||||
'Editing Language file': 'Editando arquivo de linguagem',
|
'Editing Language file': 'Editando arquivo de linguagem',
|
||||||
|
'Email Address': 'Email Address',
|
||||||
'Enterprise Web Framework': 'Framework web empresarial',
|
'Enterprise Web Framework': 'Framework web empresarial',
|
||||||
'Error': 'Erro',
|
'Error': 'Erro',
|
||||||
'Error logs for "%(app)s"': 'Logs de erro para "%(app)s"',
|
'Error logs for "%(app)s"': 'Logs de erro para "%(app)s"',
|
||||||
@@ -148,6 +155,7 @@
|
|||||||
'Expand Abbreviation (html files only)': 'Expandir Abreviação (só para ficheiros html)',
|
'Expand Abbreviation (html files only)': 'Expandir Abreviação (só para ficheiros html)',
|
||||||
'export as csv file': 'exportar como arquivo CSV',
|
'export as csv file': 'exportar como arquivo CSV',
|
||||||
'exposes': 'expõe',
|
'exposes': 'expõe',
|
||||||
|
'exposes:': 'exposes:',
|
||||||
'extends': 'estende',
|
'extends': 'estende',
|
||||||
'failed to reload module': 'Falha ao recarregar o módulo',
|
'failed to reload module': 'Falha ao recarregar o módulo',
|
||||||
'failed to reload module because:': 'falha ao recarregar o módulo por:',
|
'failed to reload module because:': 'falha ao recarregar o módulo por:',
|
||||||
@@ -165,6 +173,7 @@
|
|||||||
'Find Next': 'Localizar Seguinte',
|
'Find Next': 'Localizar Seguinte',
|
||||||
'Find Previous': 'Localizar Anterior',
|
'Find Previous': 'Localizar Anterior',
|
||||||
'First name': 'Nome',
|
'First name': 'Nome',
|
||||||
|
'Form has errors': 'Form has errors',
|
||||||
'Frames': 'Frames',
|
'Frames': 'Frames',
|
||||||
'Functions with no doctests will result in [passed] tests.': 'Funções sem doctests resultarão em testes [aceitos].',
|
'Functions with no doctests will result in [passed] tests.': 'Funções sem doctests resultarão em testes [aceitos].',
|
||||||
'graph model': 'graph model',
|
'graph model': 'graph model',
|
||||||
@@ -174,6 +183,7 @@
|
|||||||
'Hide/Show Translated strings': '',
|
'Hide/Show Translated strings': '',
|
||||||
'htmledit': 'htmledit',
|
'htmledit': 'htmledit',
|
||||||
'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.',
|
'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.',
|
||||||
|
'if your application uses a database other than sqlite you will then have to configure its DAL in pythonanywhere.': 'if your application uses a database other than sqlite you will then have to configure its DAL in pythonanywhere.',
|
||||||
'Import/Export': 'Importar/Exportar',
|
'Import/Export': 'Importar/Exportar',
|
||||||
'includes': 'inclui',
|
'includes': 'inclui',
|
||||||
'insert new': 'inserir novo',
|
'insert new': 'inserir novo',
|
||||||
@@ -198,22 +208,28 @@
|
|||||||
'Last name': 'Sobrenome',
|
'Last name': 'Sobrenome',
|
||||||
'Last saved on:': 'Salvo em:',
|
'Last saved on:': 'Salvo em:',
|
||||||
'License for': 'Licença para',
|
'License for': 'Licença para',
|
||||||
|
'lists by ticket': 'lists by ticket',
|
||||||
|
'Loading...': 'Loading...',
|
||||||
'loading...': 'carregando...',
|
'loading...': 'carregando...',
|
||||||
|
'Local Apps': 'Local Apps',
|
||||||
'locals': 'locals',
|
'locals': 'locals',
|
||||||
'Login': 'Entrar',
|
'Login': 'Entrar',
|
||||||
'login': 'inicio de sessão',
|
'login': 'inicio de sessão',
|
||||||
|
'Login successful': 'Login successful',
|
||||||
'Login to the Administrative Interface': 'Entrar na interface adminitrativa',
|
'Login to the Administrative Interface': 'Entrar na interface adminitrativa',
|
||||||
|
'Login/Register': 'Login/Register',
|
||||||
'Logout': 'finalizar sessão',
|
'Logout': 'finalizar sessão',
|
||||||
'Lost Password': 'Senha perdida',
|
'Lost Password': 'Senha perdida',
|
||||||
'Manage': 'Manage',
|
|
||||||
'manage': 'gerenciar',
|
'manage': 'gerenciar',
|
||||||
|
'Manage': 'Manage',
|
||||||
'merge': 'juntar',
|
'merge': 'juntar',
|
||||||
'Models': 'Modelos',
|
|
||||||
'models': 'modelos',
|
'models': 'modelos',
|
||||||
|
'Models': 'Modelos',
|
||||||
'Modules': 'Módulos',
|
'Modules': 'Módulos',
|
||||||
'modules': 'módulos',
|
'modules': 'módulos',
|
||||||
'Name': 'Nome',
|
'Name': 'Nome',
|
||||||
'new application "%s" created': 'nova aplicação "%s" criada',
|
'new application "%s" created': 'nova aplicação "%s" criada',
|
||||||
|
'New Application Wizard': 'New Application Wizard',
|
||||||
'New application wizard': 'Assistente para novas aplicações ',
|
'New application wizard': 'Assistente para novas aplicações ',
|
||||||
'new plugin installed': 'novo plugin instalado',
|
'new plugin installed': 'novo plugin instalado',
|
||||||
'New Record': 'Novo registro',
|
'New Record': 'Novo registro',
|
||||||
@@ -224,6 +240,7 @@
|
|||||||
'No databases in this application': 'Não existem bancos de dados nesta aplicação',
|
'No databases in this application': 'Não existem bancos de dados nesta aplicação',
|
||||||
'no match': 'não encontrado',
|
'no match': 'não encontrado',
|
||||||
'no package selected': 'nenhum pacote selecionado',
|
'no package selected': 'nenhum pacote selecionado',
|
||||||
|
'No ticket_storage.txt found under /private folder': 'No ticket_storage.txt found under /private folder',
|
||||||
'online designer': 'online designer',
|
'online designer': 'online designer',
|
||||||
'or alternatively': 'or alternatively',
|
'or alternatively': 'or alternatively',
|
||||||
'Or Get from URL:': 'Ou Obtenha do URL:',
|
'Or Get from URL:': 'Ou Obtenha do URL:',
|
||||||
@@ -241,6 +258,7 @@
|
|||||||
'Password': 'Senha',
|
'Password': 'Senha',
|
||||||
'password changed': 'senha alterada',
|
'password changed': 'senha alterada',
|
||||||
'Peeking at file': 'Visualizando arquivo',
|
'Peeking at file': 'Visualizando arquivo',
|
||||||
|
'Please wait, giving pythonanywhere a moment...': 'Please wait, giving pythonanywhere a moment...',
|
||||||
'plugin "%(plugin)s" deleted': 'plugin "%(plugin)s" eliminado',
|
'plugin "%(plugin)s" deleted': 'plugin "%(plugin)s" eliminado',
|
||||||
'Plugin "%s" in application': 'Plugin "%s" na aplicação',
|
'Plugin "%s" in application': 'Plugin "%s" na aplicação',
|
||||||
'plugins': 'plugins',
|
'plugins': 'plugins',
|
||||||
@@ -250,8 +268,11 @@
|
|||||||
'previous 100 rows': '100 registros anteriores',
|
'previous 100 rows': '100 registros anteriores',
|
||||||
'Private files': 'Private files',
|
'Private files': 'Private files',
|
||||||
'private files': 'private files',
|
'private files': 'private files',
|
||||||
|
'PythonAnywhere Apps': 'PythonAnywhere Apps',
|
||||||
|
'PythonAnywhere Password': 'PythonAnywhere Password',
|
||||||
'Query:': 'Consulta:',
|
'Query:': 'Consulta:',
|
||||||
'Rapid Search': 'Rapid Search',
|
'Rapid Search': 'Rapid Search',
|
||||||
|
'Read': 'Read',
|
||||||
'record': 'registro',
|
'record': 'registro',
|
||||||
'record does not exist': 'o registro não existe',
|
'record does not exist': 'o registro não existe',
|
||||||
'record id': 'id do registro',
|
'record id': 'id do registro',
|
||||||
@@ -263,6 +284,7 @@
|
|||||||
'Replace': 'Substituir',
|
'Replace': 'Substituir',
|
||||||
'Replace All': 'Substituir Tudo',
|
'Replace All': 'Substituir Tudo',
|
||||||
'request': 'request',
|
'request': 'request',
|
||||||
|
'requires python-git, but not installed': 'requires python-git, but not installed',
|
||||||
'Resolve Conflict file': 'Arquivo de resolução de conflito',
|
'Resolve Conflict file': 'Arquivo de resolução de conflito',
|
||||||
'response': 'response',
|
'response': 'response',
|
||||||
'restore': 'restaurar',
|
'restore': 'restaurar',
|
||||||
@@ -285,6 +307,9 @@
|
|||||||
'shell': 'Terminal',
|
'shell': 'Terminal',
|
||||||
'Site': 'site',
|
'Site': 'site',
|
||||||
'some files could not be removed': 'alguns arquicos não puderam ser removidos',
|
'some files could not be removed': 'alguns arquicos não puderam ser removidos',
|
||||||
|
'Something went wrong please wait a few minutes before retrying': 'Something went wrong please wait a few minutes before retrying',
|
||||||
|
'source : filesystem': 'source : filesystem',
|
||||||
|
'Start a new app': 'Start a new app',
|
||||||
'Start searching': 'Start searching',
|
'Start searching': 'Start searching',
|
||||||
'Start wizard': 'iniciar assistente',
|
'Start wizard': 'iniciar assistente',
|
||||||
'state': 'estado',
|
'state': 'estado',
|
||||||
@@ -294,6 +319,7 @@
|
|||||||
'Submit': 'Submit',
|
'Submit': 'Submit',
|
||||||
'submit': 'enviar',
|
'submit': 'enviar',
|
||||||
'Sure you want to delete this object?': 'Tem certeza que deseja apaagr este objeto?',
|
'Sure you want to delete this object?': 'Tem certeza que deseja apaagr este objeto?',
|
||||||
|
'switch to : db': 'switch to : db',
|
||||||
'table': 'tabela',
|
'table': 'tabela',
|
||||||
'Table name': 'Nome da tabela',
|
'Table name': 'Nome da tabela',
|
||||||
'test': 'testar',
|
'test': 'testar',
|
||||||
@@ -348,6 +374,7 @@
|
|||||||
'update': 'atualizar',
|
'update': 'atualizar',
|
||||||
'update all languages': 'atualizar todas as linguagens',
|
'update all languages': 'atualizar todas as linguagens',
|
||||||
'Update:': 'Atualizar:',
|
'Update:': 'Atualizar:',
|
||||||
|
'upgrade now to %s': 'upgrade now to %s',
|
||||||
'upgrade web2py now': 'atualize o web2py agora',
|
'upgrade web2py now': 'atualize o web2py agora',
|
||||||
'upload': 'upload',
|
'upload': 'upload',
|
||||||
'Upload': 'Upload',
|
'Upload': 'Upload',
|
||||||
@@ -361,6 +388,7 @@
|
|||||||
'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 (...)&(...) 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:',
|
'Use an url:': 'Use uma url:',
|
||||||
'User ID': 'ID do Usuario',
|
'User ID': 'ID do Usuario',
|
||||||
|
'Username': 'Username',
|
||||||
'variables': 'variáveis',
|
'variables': 'variáveis',
|
||||||
'Version': 'Versão',
|
'Version': 'Versão',
|
||||||
'versioning': 'versionamento',
|
'versioning': 'versionamento',
|
||||||
@@ -368,10 +396,13 @@
|
|||||||
'view': 'visão',
|
'view': 'visão',
|
||||||
'Views': 'Visões',
|
'Views': 'Visões',
|
||||||
'views': 'visões',
|
'views': 'visões',
|
||||||
|
'Warning!': 'Warning!',
|
||||||
'Web Framework': 'Web Framework',
|
'Web Framework': 'Web Framework',
|
||||||
|
'web2py Admin Password': 'web2py Admin Password',
|
||||||
'web2py is up to date': 'web2py está atualizado',
|
'web2py is up to date': 'web2py está atualizado',
|
||||||
'web2py Recent Tweets': 'Tweets Recentes de @web2py',
|
'web2py Recent Tweets': 'Tweets Recentes de @web2py',
|
||||||
'web2py upgraded; please restart it': 'web2py atualizado; favor reiniciar',
|
'web2py upgraded; please restart it': 'web2py atualizado; favor reiniciar',
|
||||||
'Welcome to web2py': 'Bem-vindo ao web2py',
|
'Welcome to web2py': 'Bem-vindo ao web2py',
|
||||||
'YES': 'SIM',
|
'YES': 'SIM',
|
||||||
|
'You only need these if you have already registered': 'You only need these if you have already registered',
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,176 @@
|
|||||||
|
{{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-inline">*</span>
|
||||||
|
<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-inline">*</span>
|
||||||
|
<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"><a target="_blank" href="https://www.pythonanywhere.com/terms/">{{=T('Accept Terms')}}</a>
|
||||||
|
</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>
|
||||||
|
<p>* {{=T('You only need these if you have already registered')}}</p>
|
||||||
|
</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 class="alert alert-info">
|
||||||
|
<strong>{{=T('Warning!')}}</strong> {{=T('if your application uses a database other than sqlite you will then have to configure its DAL in pythonanywhere.')}}
|
||||||
|
</div>
|
||||||
|
</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", "create_account")}}',
|
||||||
|
type: 'POST',
|
||||||
|
data: data,
|
||||||
|
dataType: 'json',
|
||||||
|
}).done(function(data, textStatus, jqXHR) {
|
||||||
|
$('#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) {
|
||||||
|
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>
|
||||||
|
|
||||||
+1
-1
@@ -652,7 +652,7 @@ def run_view_in(environment):
|
|||||||
"""
|
"""
|
||||||
request = current.request
|
request = current.request
|
||||||
response = current.response
|
response = current.response
|
||||||
view = response.view
|
view = environment['response'].view
|
||||||
folder = request.folder
|
folder = request.folder
|
||||||
path = pjoin(folder, 'compiled')
|
path = pjoin(folder, 'compiled')
|
||||||
badv = 'invalid view (%s)' % view
|
badv = 'invalid view (%s)' % view
|
||||||
|
|||||||
@@ -146,8 +146,8 @@ class TokenHandler(tornado.web.RequestHandler):
|
|||||||
|
|
||||||
class DistributeHandler(tornado.websocket.WebSocketHandler):
|
class DistributeHandler(tornado.websocket.WebSocketHandler):
|
||||||
|
|
||||||
def check_origin(self, origin):
|
def check_origin(self, origin):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def open(self, params):
|
def open(self, params):
|
||||||
group, token, name = params.split('/') + [None, None]
|
group, token, name = params.split('/') + [None, None]
|
||||||
|
|||||||
@@ -1080,6 +1080,7 @@ class Session(Storage):
|
|||||||
if response.session_storage_type == 'file':
|
if response.session_storage_type == 'file':
|
||||||
target = recfile.generate(response.session_filename)
|
target = recfile.generate(response.session_filename)
|
||||||
try:
|
try:
|
||||||
|
self._close(response)
|
||||||
os.unlink(target)
|
os.unlink(target)
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|||||||
+1
-1
@@ -6392,7 +6392,7 @@ class Wiki(object):
|
|||||||
count = db.wiki_tag.wiki_page.count()
|
count = db.wiki_tag.wiki_page.count()
|
||||||
fields = [db.wiki_page.id, db.wiki_page.slug,
|
fields = [db.wiki_page.id, db.wiki_page.slug,
|
||||||
db.wiki_page.title, db.wiki_page.tags,
|
db.wiki_page.title, db.wiki_page.tags,
|
||||||
db.wiki_page.can_read, db.wiki+page.can_edit]
|
db.wiki_page.can_read, db.wiki_page.can_edit]
|
||||||
if preview:
|
if preview:
|
||||||
fields.append(db.wiki_page.body)
|
fields.append(db.wiki_page.body)
|
||||||
if query is None:
|
if query is None:
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#!/bin/bash
|
||||||
echo "This script will:
|
echo "This script will:
|
||||||
1) Install modules needed to run web2py on Fedora and CentOS/RHEL
|
1) Install modules needed to run web2py on Fedora and CentOS/RHEL
|
||||||
2) Install Python 2.6 to /opt and recompile wsgi if not provided
|
2) Install Python 2.6 to /opt and recompile wsgi if not provided
|
||||||
@@ -27,7 +28,7 @@ Press ENTER to continue...[ctrl+C to abort]"
|
|||||||
|
|
||||||
read CONFIRM
|
read CONFIRM
|
||||||
|
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
###
|
###
|
||||||
### Phase 0 - This may get messy. Lets work from a temporary directory
|
### Phase 0 - This may get messy. Lets work from a temporary directory
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#!/bin/bash
|
||||||
echo "This script will:
|
echo "This script will:
|
||||||
1) install all modules need to run web2py on Ubuntu 14.04
|
1) install all modules need to run web2py on Ubuntu 14.04
|
||||||
2) install web2py in /home/www-data/
|
2) install web2py in /home/www-data/
|
||||||
@@ -12,7 +13,7 @@ Press a key to continue...[ctrl+C to abort]"
|
|||||||
|
|
||||||
read CONFIRM
|
read CONFIRM
|
||||||
|
|
||||||
#!/bin/bash
|
|
||||||
# optional
|
# optional
|
||||||
# dpkg-reconfigure console-setup
|
# dpkg-reconfigure console-setup
|
||||||
# dpkg-reconfigure timezoneconf
|
# dpkg-reconfigure timezoneconf
|
||||||
@@ -88,9 +89,27 @@ WSGIDaemonProcess web2py user=www-data group=www-data
|
|||||||
|
|
||||||
<VirtualHost *:80>
|
<VirtualHost *:80>
|
||||||
|
|
||||||
RewriteEngine On
|
WSGIProcessGroup web2py
|
||||||
RewriteCond %{HTTPS} !=on
|
WSGIScriptAlias / /home/www-data/web2py/wsgihandler.py
|
||||||
RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R,L]
|
WSGIPassAuthorization On
|
||||||
|
|
||||||
|
<Directory /home/www-data/web2py>
|
||||||
|
AllowOverride None
|
||||||
|
Require all denied
|
||||||
|
<Files wsgihandler.py>
|
||||||
|
Require all granted
|
||||||
|
</Files>
|
||||||
|
</Directory>
|
||||||
|
|
||||||
|
AliasMatch ^/([^/]+)/static/(?:_[\d]+.[\d]+.[\d]+/)?(.*) \
|
||||||
|
/home/www-data/web2py/applications/$1/static/$2
|
||||||
|
|
||||||
|
<Directory /home/www-data/web2py/applications/*/static/>
|
||||||
|
Options -Indexes
|
||||||
|
ExpiresActive On
|
||||||
|
ExpiresDefault "access plus 1 hour"
|
||||||
|
Require all granted
|
||||||
|
</Directory>
|
||||||
|
|
||||||
CustomLog /var/log/apache2/access.log common
|
CustomLog /var/log/apache2/access.log common
|
||||||
ErrorLog /var/log/apache2/error.log
|
ErrorLog /var/log/apache2/error.log
|
||||||
|
|||||||
Reference in New Issue
Block a user