From 63529e5ad85bbd089272f5a0e2f5626a713eca66 Mon Sep 17 00:00:00 2001 From: mdipierro Date: Wed, 6 Aug 2014 14:50:51 -0500 Subject: [PATCH] not sure what happened but fixing local commit --- VERSION | 2 +- applications/admin/controllers/default.py | 10 +- applications/admin/languages/af.py | 2 +- applications/admin/languages/bg.py | 2 +- applications/admin/languages/cs.py | 2 +- applications/admin/languages/de.py | 2 +- applications/admin/languages/default.py | 2 +- applications/admin/languages/fr.py | 2 +- applications/admin/languages/he.py | 2 +- applications/admin/languages/ja.py | 2 +- applications/admin/languages/nl.py | 2 +- applications/admin/languages/pl.py | 2 +- applications/admin/languages/pt.py | 328 +++++++++--------- applications/admin/languages/ro.py | 2 +- applications/admin/languages/ru.py | 2 +- applications/admin/languages/sl.py | 2 +- applications/admin/languages/sr-cr.py | 2 +- applications/admin/languages/sr-lt.py | 2 +- applications/admin/languages/uk.py | 2 +- applications/admin/languages/zh-tw.py | 2 +- applications/admin/languages/zh.py | 2 +- .../examples/controllers/soap_examples.py | 2 +- applications/welcome/languages/cs.py | 2 +- applications/welcome/languages/default.py | 2 +- applications/welcome/languages/fr-ca.py | 2 +- applications/welcome/languages/fr.py | 2 +- applications/welcome/languages/hi.py | 2 +- applications/welcome/languages/hu.py | 2 +- applications/welcome/languages/id.py | 2 +- applications/welcome/languages/it.py | 2 +- applications/welcome/languages/my.py | 2 +- applications/welcome/languages/nl.py | 2 +- applications/welcome/languages/pl.py | 2 +- applications/welcome/languages/pt.py | 2 +- applications/welcome/languages/ro.py | 2 +- applications/welcome/languages/ru.py | 2 +- applications/welcome/languages/sk.py | 2 +- applications/welcome/languages/uk.py | 2 +- applications/welcome/languages/zh-cn.py | 2 +- applications/welcome/languages/zh-tw.py | 2 +- applications/welcome/languages/zh.py | 2 +- gluon/contrib/websocket_messaging.py | 2 +- gluon/dal.py | 22 +- gluon/scheduler.py | 137 +++++++- gluon/sqlhtml.py | 2 +- 45 files changed, 349 insertions(+), 230 deletions(-) diff --git a/VERSION b/VERSION index 8ae28d40..9b587c61 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Version 2.9.5-trunk+timestamp.2014.07.28.23.28.19 +Version 2.9.5-trunk+timestamp.2014.07.29.09.56.18 diff --git a/applications/admin/controllers/default.py b/applications/admin/controllers/default.py index b24f347a..547d6c94 100644 --- a/applications/admin/controllers/default.py +++ b/applications/admin/controllers/default.py @@ -1,4 +1,4 @@ -# coding: utf8 +# -*- coding: utf-8 -*- EXPERIMENTAL_STUFF = True MAXNFILES = 1000 @@ -1292,7 +1292,7 @@ def create_file(): langinfo = read_possible_languages(apath(app, r=request))[lang] text = dedent(""" #!/usr/bin/env python - # -*- coding: utf8 -*- + # -*- coding: utf-8 -*- # Plural-Forms for %(lang)s (%(langname)s) nplurals=2 # for example, English language has 2 forms: @@ -1333,7 +1333,7 @@ def create_file(): if len(filename) == 3: raise SyntaxError - text = '# coding: utf8\n' + text = '# -*- coding: utf-8 -*-\n' elif path[-13:] == '/controllers/': # Handle python controllers @@ -1343,7 +1343,7 @@ def create_file(): if len(filename) == 3: raise SyntaxError - text = '# coding: utf8\n# %s\ndef index(): return dict(message="hello from %s")' + text = '# -*- coding: utf-8 -*-\n# %s\ndef index(): return dict(message="hello from %s")' text = text % (T('try something like'), filename) elif path[-7:] == '/views/': @@ -1383,7 +1383,7 @@ def create_file(): text = dedent(""" #!/usr/bin/env python - # coding: utf8 + # -*- coding: utf-8 -*- from gluon import *\n""")[1:] elif (path[-8:] == '/static/') or (path[-9:] == '/private/'): diff --git a/applications/admin/languages/af.py b/applications/admin/languages/af.py index 5d164923..d1a83621 100644 --- a/applications/admin/languages/af.py +++ b/applications/admin/languages/af.py @@ -1,4 +1,4 @@ -# coding: utf8 +# -*- coding: utf-8 -*- { '!langcode!': 'af', '!langname!': 'Afrikaanse', diff --git a/applications/admin/languages/bg.py b/applications/admin/languages/bg.py index 46e90655..c8d02f87 100644 --- a/applications/admin/languages/bg.py +++ b/applications/admin/languages/bg.py @@ -1,4 +1,4 @@ -# coding: utf8 +# -*- coding: utf-8 -*- { '!langcode!': 'bg', '!langname!': 'Български', diff --git a/applications/admin/languages/cs.py b/applications/admin/languages/cs.py index f5dd2f6c..9c8c7b63 100644 --- a/applications/admin/languages/cs.py +++ b/applications/admin/languages/cs.py @@ -1,4 +1,4 @@ -# coding: utf8 +# -*- coding: utf-8 -*- { '!langcode!': 'cs-cz', '!langname!': 'čeština', diff --git a/applications/admin/languages/de.py b/applications/admin/languages/de.py index 0e58e35a..654aa43c 100644 --- a/applications/admin/languages/de.py +++ b/applications/admin/languages/de.py @@ -1,4 +1,4 @@ -# coding: utf8 +# -*- coding: utf-8 -*- { '!langcode!': 'de', '!langname!': 'Deutsch', diff --git a/applications/admin/languages/default.py b/applications/admin/languages/default.py index 1369b2fd..779145a8 100644 --- a/applications/admin/languages/default.py +++ b/applications/admin/languages/default.py @@ -1,4 +1,4 @@ -# coding: utf8 +# -*- coding: utf-8 -*- { '!langcode!': 'en-us', '!langname!': 'English (US)', diff --git a/applications/admin/languages/fr.py b/applications/admin/languages/fr.py index b89c4139..66326765 100644 --- a/applications/admin/languages/fr.py +++ b/applications/admin/languages/fr.py @@ -1,4 +1,4 @@ -# coding: utf8 +# -*- coding: utf-8 -*- { '!langcode!': 'fr', '!langname!': 'Français', diff --git a/applications/admin/languages/he.py b/applications/admin/languages/he.py index c209c3ec..79da3921 100644 --- a/applications/admin/languages/he.py +++ b/applications/admin/languages/he.py @@ -1,4 +1,4 @@ -# coding: utf8 +# -*- coding: utf-8 -*- { '!langcode!': 'he-il', '!langname!': 'עברית', diff --git a/applications/admin/languages/ja.py b/applications/admin/languages/ja.py index 633c4261..04bc9cf3 100644 --- a/applications/admin/languages/ja.py +++ b/applications/admin/languages/ja.py @@ -1,4 +1,4 @@ -# coding: utf8 +# -*- coding: utf-8 -*- { '!langcode!': 'ja-jp', '!langname!': '日本語', diff --git a/applications/admin/languages/nl.py b/applications/admin/languages/nl.py index ec586cf1..1a9c09be 100755 --- a/applications/admin/languages/nl.py +++ b/applications/admin/languages/nl.py @@ -1,4 +1,4 @@ -# coding: utf8 +# -*- coding: utf-8 -*- { '!langcode!': 'nl', '!langname!': 'Nederlands', diff --git a/applications/admin/languages/pl.py b/applications/admin/languages/pl.py index a4933694..67dfa16a 100644 --- a/applications/admin/languages/pl.py +++ b/applications/admin/languages/pl.py @@ -1,4 +1,4 @@ -# coding: utf8 +# -*- coding: utf-8 -*- { '!langcode!': 'pl', '!langname!': 'Polska', diff --git a/applications/admin/languages/pt.py b/applications/admin/languages/pt.py index 2bd8408a..da379dc4 100644 --- a/applications/admin/languages/pt.py +++ b/applications/admin/languages/pt.py @@ -1,180 +1,30 @@ -# coding: utf8 +# -*- coding: utf-8 -*- { '!langcode!': 'pt', '!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', -'%Y-%m-%d': '%d/%m/%Y', -'%Y-%m-%d %H:%M:%S': '%d/%m/%Y %H:%M:%S', '%s %%{row} deleted': '%s registros apagados', '%s %%{row} updated': '%s registros atualizados', -'(requires internet access, experimental)': '(requer acesso a internet, experimental)', +'%Y-%m-%d': '%d/%m/%Y', +'%Y-%m-%d %H:%M:%S': '%d/%m/%Y %H:%M:%S', +'(requires internet access)': '(requer acesso a internet)', '(something like "it-it")': '(algo como "it-it")', +'@markmin\x01An error occured, please [[reload %s]] the page': 'An error occured, please [[reload %s]] the page', '@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: %s': 'Está disponível uma nova versão do web2py: %s', -'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: 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: you cannot edit the running application!': 'ATENÇÃO: Não pode modificar a aplicação em execução!', 'About': 'sobre', 'About application': 'Sobre a aplicação', -'Additional code for your application': 'Additional code for your application', -'Admin is disabled because insecure channel': 'Admin desabilitado pois o canal não é seguro', -'Admin is disabled because unsecure channel': 'Admin desabilitado pois o canal não é seguro', -'Admin language': 'Linguagem do Admin', -'Administrator Password:': 'Senha de administrador:', -'Application name:': 'Nome da aplicação:', -'Are you sure you want to delete file "%s"?': 'Tem certeza que deseja apagar o arquivo "%s"?', -'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 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?', -'Available databases and tables': 'Bancos de dados e tabelas disponíveis', -'Cannot be empty': 'Não pode ser vazio', -'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 compile: there are errors in your app:': 'Não é possível compilar: Existem erros em sua aplicação', -'Change Password': 'Trocar Senha', -'Change admin password': 'mudar senha de administrador', -'Check for upgrades': 'checar por atualizações', -'Check to delete': 'Marque para apagar', -'Checking for upgrades...': 'Buscando atualizações...', -'Clean': 'limpar', -'Click row to expand traceback': 'Clique em uma coluna para expandir o log do erro', -'Client IP': 'IP do cliente', -'Compile': 'compilar', -'Controllers': 'Controladores', -'Count': 'Contagem', -'Create': 'criar', -'Create new application using the Wizard': 'Criar nova aplicação utilizando o assistente', -'Create new simple application': 'Crie uma nova aplicação', -'Current request': 'Requisição atual', -'Current response': 'Resposta atual', -'Current session': 'Sessão atual', -'DESIGN': 'Projeto', -'Date and Time': 'Data e Hora', -'Delete': 'Apague', -'Delete:': 'Apague:', -'Deploy': 'publicar', -'Deploy on Google App Engine': 'Publicar no Google App Engine', -'Description': 'Descrição', -'Design for': 'Projeto de', -'Detailed traceback description': 'Detailed traceback description', -'E-mail': 'E-mail', -'EDIT': 'EDITAR', -'Edit': 'editar', -'Edit Profile': 'Editar Perfil', -'Edit application': 'Editar aplicação', -'Edit current record': 'Editar o registro atual', -'Editing Language file': 'Editando arquivo de linguagem', -'Editing file': 'Editando arquivo', -'Editing file "%s"': 'Editando arquivo "%s"', -'Enterprise Web Framework': 'Framework web empresarial', -'Error': 'Erro', -'Error logs for "%(app)s"': 'Logs de erro para "%(app)s"', -'Error snapshot': 'Error snapshot', -'Error ticket': 'Error ticket', -'Errors': 'erros', -'Exception instance attributes': 'Atributos da instancia de excessão', -'File': 'Arquivo', -'First name': 'Nome', -'Frames': 'Frames', -'Functions with no doctests will result in [passed] tests.': 'Funções sem doctests resultarão em testes [aceitos].', -'Group ID': 'ID do Grupo', -'Hello World': 'Olá Mundo', -'Help': 'ajuda', -'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.\nO titulo em verde indica que os testes (se definidos) passaram. Neste caso os testes não são mostrados.', -'Import/Export': 'Importar/Exportar', -'Install': 'instalar', -'Installed applications': 'Aplicações instaladas', -'Internal State': 'Estado Interno', -'Invalid Query': 'Consulta inválida', -'Invalid action': 'Ação inválida', -'Invalid email': 'E-mail inválido', -'Language files (static strings) updated': 'Arquivos de linguagem (textos estáticos) atualizados', -'Languages': 'Linguagens', -'Last name': 'Sobrenome', -'Last saved on:': 'Salvo em:', -'License for': 'Licença para', -'Login': 'Entrar', -'Login to the Administrative Interface': 'Entrar na interface adminitrativa', -'Logout': 'finalizar sessão', -'Lost Password': 'Senha perdida', -'Models': 'Modelos', -'Modules': 'Módulos', -'NO': 'NÃO', -'Name': 'Nome', -'New Record': 'Novo registro', -'New application wizard': 'Assistente para novas aplicações ', -'New simple application': 'Nova aplicação básica', -'No databases in this application': 'Não existem bancos de dados nesta aplicação', -'Origin': 'Origem', -'Original/Translation': 'Original/Tradução', -'Overwrite installed app': 'sobrescrever aplicação instalada', -'PAM authenticated user, cannot change password here': 'usuario autenticado por PAM, não pode alterar a senha por aqui', -'Pack all': 'criar pacote', -'Pack compiled': 'criar pacote compilado', -'Password': 'Senha', -'Peeking at file': 'Visualizando arquivo', -'Plugin "%s" in application': 'Plugin "%s" na aplicação', -'Plugins': 'Plugins', -'Powered by': 'Este site utiliza', -'Query:': 'Consulta:', -'Record ID': 'ID do Registro', -'Register': 'Registrar-se', -'Registration key': 'Chave de registro', -'Remove compiled': 'eliminar compilados', -'Resolve Conflict file': 'Arquivo de resolução de conflito', -'Role': 'Papel', -'Rows in table': 'Registros na tabela', -'Rows selected': 'Registros selecionados', -'Saved file hash:': 'Hash do arquivo salvo:', -'Site': 'site', -'Start wizard': 'iniciar assistente', -'Static files': 'Arquivos estáticos', -'Sure you want to delete this object?': 'Tem certeza que deseja apaagr este objeto?', -'TM': 'MR', -'Table name': 'Nome da tabela', -'Testing application': 'Testando a aplicação', -'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.', -'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', -'The data representation, define database tables and sets': 'The data representation, define database tables and sets', -'The presentations layer, views are also known as templates': 'The presentations layer, views are also known as templates', -'There are no controllers': 'Não existem controllers', -'There are no models': 'Não existem modelos', -'There are no modules': 'Não existem módulos', -'There are no plugins': 'There are no plugins', -'There are no static files': 'Não existem arquicos estáticos', -'There are no translators, only default language is supported': 'Não há traduções, somente a linguagem padrão é suportada', -'There are no views': 'Não existem visões', -'These files are served without processing, your images go here': 'These files are served without processing, your images go here', -'This is the %(filename)s template': 'Este é o template %(filename)s', -'Ticket': 'Ticket', -'Ticket ID': 'Ticket ID', -'Timestamp': 'Data Atual', -'To create a plugin, name a file/folder plugin_[name]': 'Para criar um plugin, nomeio um arquivo/pasta como plugin_[nome]', -'Traceback': 'Traceback', -'Translation strings for the application': 'Translation strings for the application', -'Unable to check for upgrades': 'Não é possível checar as atualizações', -'Unable to download': 'Não é possível efetuar o download', -'Unable to download app': 'Não é possível baixar a aplicação', -'Unable to download app because:': 'Não é possível baixar a aplicação porque:', -'Unable to download because': 'Não é possível baixar porque', -'Uninstall': 'desinstalar', -'Update:': 'Atualizar:', -'Upload and install packed application': 'Faça upload e instale uma aplicação empacotada', -'Upload a package:': 'Faça upload de um pacote:', -'Upload existing application': 'Faça upload de uma aplicação existente', -'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', -'Version': 'Versão', -'Views': 'Visões', -'Welcome to web2py': 'Bem-vindo ao web2py', -'YES': 'SIM', 'additional code for your application': 'código adicional para sua aplicação', +'Additional code for your application': 'Additional code for your application', 'admin disabled because no admin password': ' admin desabilitado por falta de senha definida', 'admin disabled because not supported on google app engine': 'admin dehabilitado, não é soportado no GAE', 'admin disabled because unable to access password file': 'admin desabilitado, não foi possível ler o arquivo de senha', +'Admin is disabled because insecure channel': 'Admin desabilitado pois o canal não é seguro', +'Admin is disabled because unsecure channel': 'Admin desabilitado pois o canal não é seguro', +'Admin language': 'Linguagem do Admin', 'administrative interface': 'interface administrativa', +'Administrator Password:': 'Senha de administrador:', 'and rename it (required):': 'e renomeie (requerido):', 'and rename it:': ' e renomeie:', 'appadmin': 'appadmin', @@ -182,27 +32,58 @@ 'application "%s" uninstalled': 'aplicação "%s" desinstalada', 'application compiled': 'aplicação compilada', 'application is compiled and cannot be designed': 'A aplicação está compilada e não pode ser modificada', +'Application name:': 'Nome da aplicação:', +'Are you sure you want to delete file "%s"?': 'Tem certeza que deseja apagar o arquivo "%s"?', +'Are you sure you want to delete plugin "%s"?': 'Tem certeza que deseja apagar o plugin "%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?', 'arguments': 'argumentos', +'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: 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: 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', 'back': 'voltar', 'browse': 'buscar', 'cache': 'cache', 'cache, errors and sessions cleaned': 'cache, erros e sessões eliminadas', +'Cannot be empty': 'Não pode ser vazio', +'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 compile: there are errors in your app:': 'Não é possível compilar: Existem erros em sua aplicação', 'cannot create file': 'Não é possível criar o arquivo', 'cannot upload file "%(filename)s"': 'não é possível fazer upload do arquivo "%(filename)s"', +'Change admin password': 'mudar senha de administrador', +'Change Password': 'Trocar Senha', 'check all': 'marcar todos', +'Check for upgrades': 'checar por atualizações', +'Check to delete': 'Marque para apagar', +'Checking for upgrades...': 'Buscando atualizações...', +'Clean': 'limpar', 'click here for online examples': 'clique para ver exemplos online', 'click here for the administrative interface': 'Clique aqui para acessar a interface administrativa', +'Click row to expand traceback': 'Clique em uma coluna para expandir o log do erro', 'click to check for upgrades': 'clique aqui para checar por atualizações', 'click to open': 'clique para abrir', +'Client IP': 'IP do cliente', 'code': 'código', 'collapse/expand all': 'collapse/expand all', 'commit (mercurial)': 'commit (mercurial)', +'Compile': 'compilar', 'compiled application removed': 'aplicação compilada removida', +'Controllers': 'Controladores', 'controllers': 'controladores', +'Count': 'Contagem', +'Create': 'criar', 'create file with filename:': 'criar um arquivo com o nome:', +'Create new application using the Wizard': 'Criar nova aplicação utilizando o assistente', 'create new application:': 'nome da nova aplicação:', +'Create new simple application': 'Crie uma nova aplicação', 'created by': 'criado por', 'crontab': 'crontab', +'Current request': 'Requisição atual', +'Current response': 'Resposta atual', +'Current session': 'Sessão atual', 'currently running': 'Executando', 'currently saved or': 'Atualmente salvo ou', 'customize me!': 'Modifique-me', @@ -210,23 +91,50 @@ 'database': 'banco de dados', 'database %s select': 'Seleção no banco de dados %s', 'database administration': 'administração de banco de dados', +'Date and Time': 'Data e Hora', 'db': 'db', +'Debug': 'Debug', 'defines tables': 'define as tabelas', +'Delete': 'Apague', 'delete': 'apagar', 'delete all checked': 'apagar marcados', 'delete plugin': 'apagar plugin', +'Delete:': 'Apague:', +'Deploy': 'publicar', +'Deploy on Google App Engine': 'Publicar no Google App Engine', +'Description': 'Descrição', +'DESIGN': 'Projeto', 'design': 'modificar', +'Design for': 'Projeto de', +'Detailed traceback description': 'Detailed traceback description', 'direction: ltr': 'direção: ltr', 'done!': 'feito!', 'download layouts': 'download layouts', 'download plugins': 'download plugins', +'E-mail': 'E-mail', +'EDIT': 'EDITAR', +'Edit': 'editar', +'Edit application': 'Editar aplicação', 'edit controller': 'editar controlador', +'Edit current record': 'Editar o registro atual', +'Edit Profile': 'Editar Perfil', 'edit views:': 'editar visões:', +'Editing file': 'Editando arquivo', +'Editing file "%s"': 'Editando arquivo "%s"', +'Editing Language file': 'Editando arquivo de linguagem', +'Enterprise Web Framework': 'Framework web empresarial', +'Error': 'Erro', +'Error logs for "%(app)s"': 'Logs de erro para "%(app)s"', +'Error snapshot': 'Error snapshot', +'Error ticket': 'Error ticket', +'Errors': 'erros', +'Exception instance attributes': 'Atributos da instancia de excessão', 'export as csv file': 'exportar como arquivo CSV', 'exposes': 'expõe', 'extends': 'estende', 'failed to reload module': 'Falha ao recarregar o módulo', 'failed to reload module because:': 'falha ao recarregar o módulo por:', +'File': 'Arquivo', 'file "%(filename)s" created': 'arquivo "%(filename)s" criado', 'file "%(filename)s" deleted': 'arquivo "%(filename)s" apagado', 'file "%(filename)s" uploaded': 'arquivo "%(filename)s" enviado', @@ -237,83 +145,181 @@ 'file saved on %(time)s': 'arquivo salvo em %(time)s', 'file saved on %s': 'arquivo salvo em %s', 'filter': 'filter', +'First name': 'Nome', +'Frames': 'Frames', +'Functions with no doctests will result in [passed] tests.': 'Funções sem doctests resultarão em testes [aceitos].', +'Group ID': 'ID do Grupo', +'Hello World': 'Olá Mundo', +'Help': 'ajuda', '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.\nO titulo em verde indica que os testes (se definidos) passaram. Neste caso os testes não são mostrados.', +'Import/Export': 'Importar/Exportar', 'includes': 'inclui', 'insert new': 'inserir novo', 'insert new %s': 'inserir novo %s', 'inspect attributes': 'inspect attributes', +'Install': 'instalar', +'Installed applications': 'Aplicações instaladas', 'internal error': 'erro interno', +'Internal State': 'Estado Interno', +'Invalid action': 'Ação inválida', +'Invalid email': 'E-mail inválido', 'invalid password': 'senha inválida', +'Invalid Query': 'Consulta inválida', 'invalid request': 'solicitação inválida', 'invalid ticket': 'ticket inválido', 'language file "%(filename)s" created/updated': 'arquivo de linguagem "%(filename)s" criado/atualizado', +'Language files (static strings) updated': 'Arquivos de linguagem (textos estáticos) atualizados', 'languages': 'linguagens', +'Languages': 'Linguagens', 'languages updated': 'linguagens atualizadas', +'Last name': 'Sobrenome', +'Last saved on:': 'Salvo em:', +'License for': 'Licença para', 'loading...': 'carregando...', 'locals': 'locals', 'login': 'inicio de sessão', +'Login': 'Entrar', +'Login to the Administrative Interface': 'Entrar na interface adminitrativa', +'Logout': 'finalizar sessão', +'Lost Password': 'Senha perdida', 'manage': 'gerenciar', 'merge': 'juntar', +'Models': 'Modelos', 'models': 'modelos', +'Modules': 'Módulos', 'modules': 'módulos', +'Name': 'Nome', 'new application "%s" created': 'nova aplicação "%s" criada', +'New application wizard': 'Assistente para novas aplicações ', 'new plugin installed': 'novo plugin instalado', +'New Record': 'Novo registro', 'new record inserted': 'novo registro inserido', +'New simple application': 'Nova aplicação básica', 'next 100 rows': 'próximos 100 registros', +'NO': 'NÃO', +'No databases in this application': 'Não existem bancos de dados nesta aplicação', 'no match': 'não encontrado', +'no package selected': 'no package selected', 'or import from csv file': 'ou importar de um arquivo CSV', 'or provide app url:': 'ou forneça a url de uma aplicação:', 'or provide application url:': 'ou forneça a url de uma aplicação:', +'Origin': 'Origem', +'Original/Translation': 'Original/Tradução', +'Overwrite installed app': 'sobrescrever aplicação instalada', +'Pack all': 'criar pacote', +'Pack compiled': 'criar pacote compilado', 'pack plugin': 'empacotar plugin', +'PAM authenticated user, cannot change password here': 'usuario autenticado por PAM, não pode alterar a senha por aqui', +'Password': 'Senha', 'password changed': 'senha alterada', +'Peeking at file': 'Visualizando arquivo', 'plugin "%(plugin)s" deleted': 'plugin "%(plugin)s" eliminado', +'Plugin "%s" in application': 'Plugin "%s" na aplicação', 'plugins': 'plugins', +'Plugins': 'Plugins', +'Powered by': 'Este site utiliza', 'previous 100 rows': '100 registros anteriores', +'Query:': 'Consulta:', 'record': 'registro', 'record does not exist': 'o registro não existe', 'record id': 'id do registro', +'Record ID': 'ID do Registro', +'Register': 'Registrar-se', +'Registration key': 'Chave de registro', +'Remove compiled': 'eliminar compilados', 'request': 'request', +'Resolve Conflict file': 'Arquivo de resolução de conflito', 'response': 'response', 'restore': 'restaurar', 'revert': 'reverter', +'Role': 'Papel', +'Rows in table': 'Registros na tabela', +'Rows selected': 'Registros selecionados', 'save': 'salvar', +'Saved file hash:': 'Hash do arquivo salvo:', 'selected': 'selecionado(s)', 'session': 'session', 'session expired': 'sessão expirada', 'shell': 'Terminal', +'Site': 'site', 'some files could not be removed': 'alguns arquicos não puderam ser removidos', +'Start wizard': 'iniciar assistente', 'state': 'estado', 'static': 'estáticos', +'Static files': 'Arquivos estáticos', 'submit': 'enviar', +'Sure you want to delete this object?': 'Tem certeza que deseja apaagr este objeto?', 'table': 'tabela', +'Table name': 'Nome da tabela', 'test': 'testar', +'Testing application': 'Testando a aplicação', +'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.', +'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', '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', +'The data representation, define database tables and sets': 'The data representation, define database tables and sets', 'the data representation, define database tables and sets': 'A representação dos dadps, define tabelas e estruturas de dados', +'The presentations layer, views are also known as templates': 'The presentations layer, views are also known as templates', 'the presentations layer, views are also known as templates': 'A camada de apresentação, As visões também são chamadas de templates', +'There are no controllers': 'Não existem controllers', +'There are no models': 'Não existem modelos', +'There are no modules': 'Não existem módulos', +'There are no plugins': 'There are no plugins', +'There are no static files': 'Não existem arquicos estáticos', +'There are no translators, only default language is supported': 'Não há traduções, somente a linguagem padrão é suportada', +'There are no views': 'Não existem visões', 'these files are served without processing, your images go here': 'Estes arquivos são servidos sem processamento, suas imagens ficam aqui', +'These files are served without processing, your images go here': 'These files are served without processing, your images go here', +'This is the %(filename)s template': 'Este é o template %(filename)s', +'Ticket': 'Ticket', +'Ticket ID': 'Ticket ID', +'Timestamp': 'Data Atual', +'TM': 'MR', 'to previous version.': 'para a versão anterior.', +'To create a plugin, name a file/folder plugin_[name]': 'Para criar um plugin, nomeio um arquivo/pasta como plugin_[nome]', +'Traceback': 'Traceback', 'translation strings for the application': 'textos traduzidos para a aplicação', +'Translation strings for the application': 'Translation strings for the application', 'try': 'tente', 'try something like': 'tente algo como', +'Unable to check for upgrades': 'Não é possível checar as atualizações', 'unable to create application "%s"': 'não é possível criar a aplicação "%s"', 'unable to delete file "%(filename)s"': 'não é possível criar o arquico "%(filename)s"', 'unable to delete file plugin "%(plugin)s"': 'não é possível criar o plugin "%(plugin)s"', +'Unable to download': 'Não é possível efetuar o download', +'Unable to download app': 'Não é possível baixar a aplicação', +'Unable to download app because:': 'Não é possível baixar a aplicação porque:', +'Unable to download because': 'Não é possível baixar porque', 'unable to parse csv file': 'não é possível analisar o arquivo CSV', 'unable to uninstall "%s"': 'não é possível instalar "%s"', 'unable to upgrade because "%s"': 'não é possível atualizar porque "%s"', 'uncheck all': 'desmarcar todos', +'Uninstall': 'desinstalar', 'update': 'atualizar', 'update all languages': 'atualizar todas as linguagens', +'Update:': 'Atualizar:', 'upgrade web2py now': 'atualize o web2py agora', '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 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', 'variables': 'variáveis', +'Version': 'Versão', 'versioning': 'versionamento', +'Versioning': 'Versioning', 'view': 'visão', +'Views': 'Visões', 'views': 'visões', -'web2py Recent Tweets': 'Tweets Recentes de @web2py', +'Web Framework': 'Web Framework', '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', } diff --git a/applications/admin/languages/ro.py b/applications/admin/languages/ro.py index 65ca658e..aec84f9f 100644 --- a/applications/admin/languages/ro.py +++ b/applications/admin/languages/ro.py @@ -1,4 +1,4 @@ -# coding: utf8 +# -*- coding: utf-8 -*- { '!=': '!=', '!langcode!': 'ro', diff --git a/applications/admin/languages/ru.py b/applications/admin/languages/ru.py index 7a91ccfc..04ad7ede 100644 --- a/applications/admin/languages/ru.py +++ b/applications/admin/languages/ru.py @@ -1,4 +1,4 @@ -# coding: utf8 +# -*- coding: utf-8 -*- { '!langcode!': 'ru', '!langname!': 'Русский', diff --git a/applications/admin/languages/sl.py b/applications/admin/languages/sl.py index 701a8170..e4a1c1c6 100755 --- a/applications/admin/languages/sl.py +++ b/applications/admin/languages/sl.py @@ -1,4 +1,4 @@ -# coding: utf8 +# -*- coding: utf-8 -*- { '!langcode!': 'sl', '!langname!': 'Slovenski', diff --git a/applications/admin/languages/sr-cr.py b/applications/admin/languages/sr-cr.py index a0acdbd9..04ff676c 100644 --- a/applications/admin/languages/sr-cr.py +++ b/applications/admin/languages/sr-cr.py @@ -1,4 +1,4 @@ -# coding: utf8 +# -*- coding: utf-8 -*- { '!langcode!': 'sr-cr', '!langname!': 'Српски (Ћирилица)', diff --git a/applications/admin/languages/sr-lt.py b/applications/admin/languages/sr-lt.py index 7ab1bda6..64f8eb7f 100644 --- a/applications/admin/languages/sr-lt.py +++ b/applications/admin/languages/sr-lt.py @@ -1,4 +1,4 @@ -# coding: utf8 +# -*- coding: utf-8 -*- { '!langcode!': 'sr-lt', '!langname!': 'Srpski (Latinica)', diff --git a/applications/admin/languages/uk.py b/applications/admin/languages/uk.py index 558ee92e..ca54e12c 100644 --- a/applications/admin/languages/uk.py +++ b/applications/admin/languages/uk.py @@ -1,4 +1,4 @@ -# coding: utf8 +# -*- coding: utf-8 -*- { '!langcode!': 'uk', '!langname!': 'Українська', diff --git a/applications/admin/languages/zh-tw.py b/applications/admin/languages/zh-tw.py index d04b2c48..79cb4183 100644 --- a/applications/admin/languages/zh-tw.py +++ b/applications/admin/languages/zh-tw.py @@ -1,4 +1,4 @@ -# coding: utf8 +# -*- coding: utf-8 -*- { '!langcode!': 'zh-tw', '!langname!': '台灣中文', diff --git a/applications/admin/languages/zh.py b/applications/admin/languages/zh.py index 4633a17a..d62b0804 100644 --- a/applications/admin/languages/zh.py +++ b/applications/admin/languages/zh.py @@ -1,4 +1,4 @@ -# coding: utf8 +# -*- coding: utf-8 -*- { '!langcode!': 'zh-cn', '!langname!': '中文', diff --git a/applications/examples/controllers/soap_examples.py b/applications/examples/controllers/soap_examples.py index e9ab84a3..7840105e 100644 --- a/applications/examples/controllers/soap_examples.py +++ b/applications/examples/controllers/soap_examples.py @@ -1,4 +1,4 @@ -# coding: utf8 +# -*- coding: utf-8 -*- # SOAP webservices (server and client) example and basic test # (using pysimplesoap contrib included in web2py) diff --git a/applications/welcome/languages/cs.py b/applications/welcome/languages/cs.py index f5dd2f6c..9c8c7b63 100644 --- a/applications/welcome/languages/cs.py +++ b/applications/welcome/languages/cs.py @@ -1,4 +1,4 @@ -# coding: utf8 +# -*- coding: utf-8 -*- { '!langcode!': 'cs-cz', '!langname!': 'čeština', diff --git a/applications/welcome/languages/default.py b/applications/welcome/languages/default.py index 5e6e8125..6524a902 100644 --- a/applications/welcome/languages/default.py +++ b/applications/welcome/languages/default.py @@ -1,4 +1,4 @@ -# coding: utf8 +# -*- coding: utf-8 -*- { '!langcode!': 'en-us', '!langname!': 'English (US)', diff --git a/applications/welcome/languages/fr-ca.py b/applications/welcome/languages/fr-ca.py index 7693d5b4..55dfb9ed 100644 --- a/applications/welcome/languages/fr-ca.py +++ b/applications/welcome/languages/fr-ca.py @@ -1,4 +1,4 @@ -# coding: utf8 +# -*- coding: utf-8 -*- { '!langcode!': 'fr-ca', '!langname!': 'Français (Canadien)', diff --git a/applications/welcome/languages/fr.py b/applications/welcome/languages/fr.py index c3922ad3..048ac1b1 100644 --- a/applications/welcome/languages/fr.py +++ b/applications/welcome/languages/fr.py @@ -1,4 +1,4 @@ -# coding: utf8 +# -*- coding: utf-8 -*- { '!langcode!': 'fr', '!langname!': 'Français', diff --git a/applications/welcome/languages/hi.py b/applications/welcome/languages/hi.py index 46a47e86..63a7acdc 100644 --- a/applications/welcome/languages/hi.py +++ b/applications/welcome/languages/hi.py @@ -1,4 +1,4 @@ -# coding: utf8 +# -*- coding: utf-8 -*- { '!langcode!': 'hi-in', '!langname!': 'हिन्दी', diff --git a/applications/welcome/languages/hu.py b/applications/welcome/languages/hu.py index bc32c8dd..615ee394 100644 --- a/applications/welcome/languages/hu.py +++ b/applications/welcome/languages/hu.py @@ -1,4 +1,4 @@ -# coding: utf8 +# -*- coding: utf-8 -*- { '!langcode!': 'hu', '!langname!': 'Magyar', diff --git a/applications/welcome/languages/id.py b/applications/welcome/languages/id.py index 0bb837dc..2273ae5a 100755 --- a/applications/welcome/languages/id.py +++ b/applications/welcome/languages/id.py @@ -1,4 +1,4 @@ -# coding: utf8 +# -*- coding: utf-8 -*- { '!langcode!': 'id', '!langname!': 'Indonesian', diff --git a/applications/welcome/languages/it.py b/applications/welcome/languages/it.py index 77a706be..b44bf2e8 100644 --- a/applications/welcome/languages/it.py +++ b/applications/welcome/languages/it.py @@ -1,4 +1,4 @@ -# coding: utf8 +# -*- coding: utf-8 -*- { '!=': '!=', '!langcode!': 'it', diff --git a/applications/welcome/languages/my.py b/applications/welcome/languages/my.py index d5b85f95..8e634d4d 100755 --- a/applications/welcome/languages/my.py +++ b/applications/welcome/languages/my.py @@ -1,4 +1,4 @@ -# coding: utf8 +# -*- coding: utf-8 -*- { '!langcode!': 'my', '!langname!': 'Malay', diff --git a/applications/welcome/languages/nl.py b/applications/welcome/languages/nl.py index 39892e52..4b942d52 100644 --- a/applications/welcome/languages/nl.py +++ b/applications/welcome/languages/nl.py @@ -1,4 +1,4 @@ -# coding: utf8 +# -*- coding: utf-8 -*- { '!langcode!': 'nl', '!langname!': 'Nederlands', diff --git a/applications/welcome/languages/pl.py b/applications/welcome/languages/pl.py index aa1e5701..fa0f3c96 100644 --- a/applications/welcome/languages/pl.py +++ b/applications/welcome/languages/pl.py @@ -1,4 +1,4 @@ -# coding: utf8 +# -*- coding: utf-8 -*- { '!langcode!': 'pl', '!langname!': 'Polska', diff --git a/applications/welcome/languages/pt.py b/applications/welcome/languages/pt.py index 8d36be6f..c34aee8a 100644 --- a/applications/welcome/languages/pt.py +++ b/applications/welcome/languages/pt.py @@ -1,4 +1,4 @@ -# coding: utf8 +# -*- coding: utf-8 -*- { '!langcode!': 'pt', '!langname!': 'Português', diff --git a/applications/welcome/languages/ro.py b/applications/welcome/languages/ro.py index 0f830e3d..63c9741b 100644 --- a/applications/welcome/languages/ro.py +++ b/applications/welcome/languages/ro.py @@ -1,4 +1,4 @@ -# coding: utf8 +# -*- coding: utf-8 -*- { '!=': '!=', '!langcode!': 'ro', diff --git a/applications/welcome/languages/ru.py b/applications/welcome/languages/ru.py index 85644ea2..0487a715 100644 --- a/applications/welcome/languages/ru.py +++ b/applications/welcome/languages/ru.py @@ -1,4 +1,4 @@ -# coding: utf8 +# -*- coding: utf-8 -*- { '!langcode!': 'ru', '!langname!': 'Русский', diff --git a/applications/welcome/languages/sk.py b/applications/welcome/languages/sk.py index 88f8343f..e90ccf81 100644 --- a/applications/welcome/languages/sk.py +++ b/applications/welcome/languages/sk.py @@ -1,4 +1,4 @@ -# coding: utf8 +# -*- coding: utf-8 -*- { '!langcode!': 'sk', '!langname!': 'Slovenský', diff --git a/applications/welcome/languages/uk.py b/applications/welcome/languages/uk.py index 17bfde51..3a5f791f 100644 --- a/applications/welcome/languages/uk.py +++ b/applications/welcome/languages/uk.py @@ -1,4 +1,4 @@ -# coding: utf8 +# -*- coding: utf-8 -*- { '!langcode!': 'uk', '!langname!': 'Українська', diff --git a/applications/welcome/languages/zh-cn.py b/applications/welcome/languages/zh-cn.py index 61009f6e..d92a8c53 100644 --- a/applications/welcome/languages/zh-cn.py +++ b/applications/welcome/languages/zh-cn.py @@ -1,4 +1,4 @@ -# coding: utf8 +# -*- coding: utf-8 -*- { '!langcode!': 'zh-cn', '!langname!': '中文', diff --git a/applications/welcome/languages/zh-tw.py b/applications/welcome/languages/zh-tw.py index 5b109604..fa805aa4 100644 --- a/applications/welcome/languages/zh-tw.py +++ b/applications/welcome/languages/zh-tw.py @@ -1,4 +1,4 @@ -# coding: utf8 +# -*- coding: utf-8 -*- { '!langcode!': 'zh-cn', '!langname!': '中文', diff --git a/applications/welcome/languages/zh.py b/applications/welcome/languages/zh.py index 263918ce..d4790627 100644 --- a/applications/welcome/languages/zh.py +++ b/applications/welcome/languages/zh.py @@ -1,4 +1,4 @@ -# coding: utf8 +# -*- coding: utf-8 -*- { '!langcode!': 'zh-tw', '!langname!': '中文', diff --git a/gluon/contrib/websocket_messaging.py b/gluon/contrib/websocket_messaging.py index c7f5d03f..7755e650 100644 --- a/gluon/contrib/websocket_messaging.py +++ b/gluon/contrib/websocket_messaging.py @@ -1,4 +1,4 @@ -# -*- coding: utf8 -*- +# -*- coding: utf-8 -*- #!/usr/bin/env python """ diff --git a/gluon/dal.py b/gluon/dal.py index 39373095..2677b723 100644 --- a/gluon/dal.py +++ b/gluon/dal.py @@ -7535,7 +7535,7 @@ class Row(object): def as_dict(self, datetime_to_str=False, custom_types=None): SERIALIZABLE_TYPES = [str, unicode, int, long, float, bool, list, dict] if isinstance(custom_types, (list, tuple, set)): - SERIALIZABLE_TYPES += custom_types + SERIALIZABLE_TYPES += list(custom_types) elif custom_types: SERIALIZABLE_TYPES.append(custom_types) d = dict(self) @@ -11189,7 +11189,7 @@ class Rows(object): items = [item.as_dict(datetime_to_str, custom_types) for item in self] else: items = [item for item in self] - self.compact = compact + self.compact = oc return items def as_dict(self, @@ -11233,13 +11233,25 @@ class Rows(object): else: return dict([(key(r), r) for r in rows]) - def as_trees(self, parent_name='parent_id', children_name='children'): + def as_trees(self, parent_name='parent_id', children_name='children', render=False): + """ + returns the data as list of trees. + + :param parent_name: the name of the field to holding the reference to + the parent (default parent_id). + :param children_name: the name where the children of each row will be + stored as a list (default children). + :param render: whether we will render the fields using their represent + (default False) can be a list of fields to render or + True to render all. + """ roots = [] drows = {} - for row in self: + rows = list(self.render(fields=None if render is True else render)) if render else self + for row in rows: drows[row.id] = row row[children_name] = [] - for row in self: + for row in rows: parent = row[parent_name] if parent is None: roots.append(row) diff --git a/gluon/scheduler.py b/gluon/scheduler.py index 9639d50b..ca48556e 100644 --- a/gluon/scheduler.py +++ b/gluon/scheduler.py @@ -91,7 +91,7 @@ try: except: from simplejson import loads, dumps -IDENTIFIER = "%s#%s" % (socket.gethostname(), os.getpid()) +IDENTIFIER = "%s#%s" % (socket.gethostname(),os.getpid()) logger = logging.getLogger('web2py.scheduler.%s' % IDENTIFIER) @@ -117,7 +117,7 @@ STOP_TASK = 'STOP_TASK' EXPIRED = 'EXPIRED' SECONDS = 1 HEARTBEAT = 3 * SECONDS -MAXHIBERNATION = 10 * HEARTBEAT +MAXHIBERNATION = 10 CLEAROUT = '!clear!' CALLABLETYPES = (types.LambdaType, types.FunctionType, @@ -129,7 +129,6 @@ class Task(object): """Defines a "task" object that gets passed from the main thread to the executor's one """ - def __init__(self, app, function, timeout, args='[]', vars='{}', **kwargs): logger.debug(' new task allocated: %s.%s', app, function) self.app = app @@ -147,7 +146,6 @@ class TaskReport(object): """Defines a "task report" object that gets passed from the executor's thread to the main one """ - def __init__(self, status, result=None, output=None, tb=None): logger.debug(' new task report: %s', status) if tb: @@ -162,6 +160,52 @@ class TaskReport(object): def __str__(self): return '' % self.status +class JobGraph(object): + """Experimental: with JobGraph you can specify + dependencies amongs tasks""" + + def __init__(self, db, job_name): + self.job_name = job_name or 'job_0' + self.db = db + + def add_deps(self, task_parent, task_child): + self.db.scheduler_task_deps.insert(task_parent=task_parent, task_child=task_child, job_name=self.job_name) + + def validate(self, job_name): + db = self.db + sd = db.scheduler_task_deps + if job_name: + q = sd.job_name == job_name + else: + q = sd.id > 0 + + edges = db(q).select() + nested_dict = {} + for row in edges: + k = row.task_parent + if k in nested_dict: + nested_dict[k].add(row.task_child) + else: + nested_dict[k] = set((row.task_child,)) + try: + rtn = [] + for k, v in nested_dict.items(): + v.discard(k) # Ignore self dependencies + extra_items_in_deps = reduce(set.union, nested_dict.values()) - set(nested_dict.keys()) + nested_dict.update(dict((item, set()) for item in extra_items_in_deps)) + while True: + ordered = set(item for item,dep in nested_dict.items() if not dep) + if not ordered: + break + rtn.append(ordered) + nested_dict = dict((item, (dep - ordered)) for item, dep in nested_dict.items() + if item not in ordered) + assert not nested_dict, "A cyclic dependency exists amongst %r" % nested_dict + db.commit() + return rtn + except: + db.rollback() + return None def demo_function(*argv, **kwargs): """ test function """ @@ -170,10 +214,9 @@ def demo_function(*argv, **kwargs): time.sleep(1) return 'done' -#the two functions below deal with simplejson decoding as unicode, -#esp for the dict decode and subsequent usage as function Keyword arguments -#unicode variable names won't work! -#borrowed from http://stackoverflow.com/questions/956867/ +#the two functions below deal with simplejson decoding as unicode, esp for the dict decode +#and subsequent usage as function Keyword arguments unicode variable names won't work! +#borrowed from http://stackoverflow.com/questions/956867/how-to-get-string-objects-instead-unicode-ones-from-json-in-python def _decode_list(lst): @@ -220,7 +263,7 @@ def executor(queue, task, out): def write(self, data): self.out_queue.put(data) - W2P_TASK = Storage({'id': task.task_id, 'uuid': task.uuid}) + W2P_TASK = Storage({'id' : task.task_id, 'uuid' : task.uuid}) stdout = LogOutput(out) try: if task.app: @@ -245,7 +288,7 @@ def executor(queue, task, out): raise NameError( "name '%s' not found in scheduler's environment" % f) #Inject W2P_TASK into environment - _env.update({'W2P_TASK': W2P_TASK}) + _env.update({'W2P_TASK' : W2P_TASK}) #Inject W2P_TASK into current from gluon import current current.W2P_TASK = W2P_TASK @@ -620,6 +663,15 @@ class Scheduler(MetaScheduler): migrate=self.__get_migrate('scheduler_worker', migrate) ) + db.define_table( + 'scheduler_task_deps', + Field('job_name', default='job_0'), + Field('task_parent', 'reference scheduler_task'), + Field('task_child', 'reference scheduler_task'), + Field('can_visit', 'boolean', default=False), + migrate=self.__get_migrate('scheduler_task_deps', migrate) + ) + if migrate is not False: db.commit() @@ -846,6 +898,7 @@ class Scheduler(MetaScheduler): times_failed=0 ) db(st.id == task.task_id).update(**d) + self.update_dependencies(db, task.task_id) else: st_mapping = {'FAILED': 'FAILED', 'TIMEOUT': 'TIMEOUT', @@ -861,6 +914,9 @@ class Scheduler(MetaScheduler): ) logger.info('task completed (%s)', task_report.status) + def update_dependencies(self, db, task_id): + db(db.scheduler_task_deps.task_child == task_id).update(can_visit=True) + def adj_hibernation(self): """Used to increase the "sleep" interval for DISABLED workers""" if self.w_stats.status == DISABLED: @@ -905,12 +961,11 @@ class Scheduler(MetaScheduler): if mybackedstatus == DISABLED: # keep sleeping self.w_stats.status = DISABLED - if self.w_stats.sleep >= MAXHIBERNATION: - logger.debug('........recording heartbeat (%s)', - self.w_stats.status) - db(sw.worker_name == self.worker_name).update( - last_heartbeat=now, - worker_stats=self.w_stats) + logger.debug('........recording heartbeat (%s)', + self.w_stats.status) + db(sw.worker_name == self.worker_name).update( + last_heartbeat=now, + worker_stats=self.w_stats) elif mybackedstatus == TERMINATE: self.w_stats.status = TERMINATE logger.debug("Waiting to terminate the current task") @@ -1007,7 +1062,7 @@ class Scheduler(MetaScheduler): Deals with group_name(s) logic, in order to assign linearly tasks to available workers for those groups """ - sw, st = db.scheduler_worker, db.scheduler_task + sw, st, sd = db.scheduler_worker, db.scheduler_task, db.scheduler_task_deps now = self.now() all_workers = db(sw.status == ACTIVE).select() #build workers as dict of groups @@ -1028,14 +1083,36 @@ class Scheduler(MetaScheduler): (st.stop_time < now) ).update(status=EXPIRED) + deps_with_no_deps = db( + (sd.can_visit == False) & + (~sd.task_child.belongs( + db(sd.can_visit == False)._select(sd.task_parent) + ) + ) + )._select(sd.task_child) + no_deps = db( + (st.status.belongs((QUEUED,ASSIGNED))) & + ( + (sd.id == None) | (st.id.belongs(deps_with_no_deps)) + + ) + )._select(st.id, distinct=True, left=sd.on( + (st.id == sd.task_parent) & + (sd.can_visit == False) + ) + ) + all_available = db( (st.status.belongs((QUEUED, ASSIGNED))) & ((st.times_run < st.repeats) | (st.repeats == 0)) & (st.start_time <= now) & ((st.stop_time == None) | (st.stop_time > now)) & (st.next_run_time <= now) & - (st.enabled == True) + (st.enabled == True) & + (st.id.belongs(no_deps)) ) + + limit = len(all_workers) * (50 / (len(wkgroups) or 1)) #if there are a moltitude of tasks, let's figure out a maximum of #tasks per worker. This can be further tuned with some added @@ -1302,6 +1379,30 @@ class Scheduler(MetaScheduler): status=STOPPED) return rtn + def get_workers(self, only_ticker=False): + """ Returns a dict holding worker_name : {**columns} + representing all "registered" workers + only_ticker returns only the worker running as a TICKER, + if there is any + """ + db = self.db + if only_ticker: + workers = db(db.scheduler_worker.is_ticker == True).select() + else: + workers = db(db.scheduler_worker.id > 0).select() + all_workers = {} + for row in workers: + all_workers[row.worker_name] = Storage(dict( + status=row.status, + first_heartbeat=row.first_heartbeat, + last_heartbeat=row.last_heartbeat, + group_names=row.group_names, + is_ticker=row.is_ticker, + worker_stats=row.worker_stats + ) + ) + return all_workers + def main(): """ diff --git a/gluon/sqlhtml.py b/gluon/sqlhtml.py index 62e53507..cb85158d 100644 --- a/gluon/sqlhtml.py +++ b/gluon/sqlhtml.py @@ -1768,7 +1768,7 @@ class SQLFORM(FORM): iso_format = {'_data-w2p_date_format' : '%Y-%m-%d'} value_input = SQLFORM.widgets.date.widget(field, field.default, _id=_id, **iso_format) elif field.type == 'datetime': - iso_format = iso_format = {'_data-w2p_datetime_format' : '%Y-%m-%d %H:%M:%S'} + iso_format = {'_data-w2p_datetime_format' : '%Y-%m-%d %H:%M:%S'} value_input = SQLFORM.widgets.datetime.widget(field, field.default, _id=_id, **iso_format) elif (field.type.startswith('reference ') or field.type.startswith('list:reference ')) and \