Chapter 15: Ajudando o web2py

 Ajudando o web2py: Bugs, melhorias e documentação

O web2py é muito acolhedor em relação a relatórios de bugs, aprimoramentos e aprimoramentos de documentação.

 Grupo do Google

O principal fórum para discutir bugs e novos recursos é: web2py-users (URL é https://groups.google.com/forum/#!forum/web2py )

 Arquivar um relatório de bug

Até janeiro de 2015, os problemas foram rastreados no Google Code, e muitas referências históricas no grupo de notícias e em documentos antigos apontam você para lá. Como parte da migração para o GitHub, o projeto agora usa os problemas do GitHub. Apenas problemas em aberto foram transferidos para o GitHub.

Se você encontrou um bug e o discutiu no grupo, pode ser solicitado que você registre um relatório de bug criando um problema no GitHub.

Por favor, visite a página do GitHub do projeto e siga o link para Questões.

https://github.com/web2py/web2py

(ou visite diretamente https://github.com/web2py/web2py/issues).

Como de costume, um bom relatório de erros significa que precisamos conhecer seu sistema operacional, a versão do Python e o web2py, o que você esperava que acontecesse e o que aconteceu. Pontos de bônus para postar um exemplo de código completo que indique o problema: um pouco de código é melhor que mil palavras.

 Relatando Erros de Segurança

 

reporting security bugs
Ao relatar bugs de segurança, tenha cuidado ao divulgar informações que ajudem a uma exploração maliciosa. Depois de postar no grupo do Google ou de levantar um problema no GitHub, você será contatado por um desenvolvedor para compartilhar informações de maneira particular.

 Contribuindo com alterações de código e documentação

 Como o código do projeto é gerenciado

A base de código web2py é gerenciada em um repositório git do GitHub. O sistema de controle de versão original era Mercurial no Google Code, mas o desenvolvimento ativo está no GitHub.

 PyDAL: O DAL é agora um projeto independente

Uma parte importante do web2py é o DAL (Database Abstraction Layer - Camada de Abstração do Banco de Dados). No início de 2015, isso foi dissociado em uma base de código separada (PyDAL). Em termos de git, é um sub-módulo do repositório principal.

O uso de um sub-módulo requer um uso único do --recursive  flag para git clone se você está clonando o web2py do zero.

git clone --recursive https://github.com/web2py/web2py.git

Se você tem um repositório existente, os comandos abaixo precisam ser executados pelo menos uma vez:

git submodule update --init --recursive

Se você tem uma pasta gluon/dal  você deve excluí-lo:

rm -r gluon/dal

O PyDAL usa um ciclo de release estável separado para o resto do web2py. As versões do PyDAL usarão um esquema de nomeação de datas semelhante ao Ubuntu. Questões relacionadas ao PyDAL devem ser reportadas ao seu repositório separado.

 Repositórios GitHub

Os repositórios do GitHub são:

https://github.com/web2py/web2py

https://github.com/web2py/pydal

O web2py possui duas versões importantes: a versão estável atual e o instantâneo de desenvolvimento. No git, o instantâneo de desenvolvimento é geralmente referido como " master ", mas o projeto web2py tende a dizer" trunk ", que é o termo equivalente do Mercurial e SVN. Por favor, note que" trunk "normalmente é perfeitamente bom para usar na produção, mas não é uma garantia. Por favor use lançamentos marcados se você precisar de uma base de código estável.

Correções de bugs e melhorias vão para o trunk, então, para aproveitar rapidamente uma correção de bug, você precisará usar o trunk. A melhor maneira de fazer isso é clonar o repositório git. Este é o primeiro passo ao usar o código armazenado no GitHub e está bem documentado lá. Como os releases são marcados, você pode alternar entre a ramificação do tronco (que é 'master') e a release atual (ou qualquer release). Isso torna o repositório git muito prático, mesmo em produção.

As principais habilidades do git que você precisará são:

  1. clonagem de um repositório hospedado no GitHub
  2. finalizar o branch master
  3. verificar um ramo com base em uma tag

Estes são bem abordados pelos tutoriais do GitHub: veja abaixo.

 Discutindo as mudanças propostas

Se a alteração estiver relacionada a um bug, a discussão provavelmente ocorrerá no problema no GitHub (veja acima). Se a alteração estiver relacionada a um aprimoramento, o grupo de desenvolvedores é o melhor lugar inicialmente: web2py-developers group (URL é https://groups.google.com/forum/#!forum/web2py-developers )

Como o web2py promete compatibilidade retroativa para recursos não experimentais, aceitar uma alteração na base de código é uma promessa de manutenção para futuros usuários, e isso não é uma promessa que pode ser feita com leviandade. Usuários menos experientes podem descobrir, por meio de discussões, que existe um método existente para alcançar o que eles querem; infelizmente, a documentação dos recursos de energia às vezes fica atrasada (consulte o aprimoramento da documentação abaixo).

Quando você estiver pronto para enviar uma alteração de código, a discussão provavelmente será movida para os comentários anexados à solicitação de recebimento (discutida abaixo).

 Estilo de codificação

 

coding style
Geralmente, siga o estilo de codificação PEP8. http://www.python.org/dev/peps/pep-0008/

Há orientação específica aqui: web2py style

 Estilo de documentação

O estilo de documentação é especificado abaixo

 Dicas sobre como configurar um ambiente de desenvolvimento

Capítulo 14  tem algumas dicas sobre o uso de vários IDEs com o web2py.

 Preparação: usando o GitHub

patches
GitHub

Como o web2py usa o GitHub, o fluxo geral de alterações é assim:

  1. Você cria um clone de web2py no GitHub, que o GitHub chama de "fork".
  2. Você cria um clone do seu web2py 'fork' em sua máquina local (ou onde quer que você queira fazer alterações)
  3. Você cria um novo branch para suas mudanças git checkout -b novo_branch
  4. Você trabalha em seu novo branch e faz o commit git commit -a -m 'mensagem do commit'
  5. Você empurra as alterações de volta para o fork do GitHub git push origin novo_branch
  6. Você faz um pull request via GitHub
  7. Se a sua solicitação de recebimento for aceita, sua confirmação estará na ramificação principal de web2py.

No momento da escrita, as técnicas principais do git/GitHub são abordadas aqui: https://help.GitHub.com/articles/fork-a-repo

No entanto, você precisa seguir as instruções abaixo sobre como criar patches que podem ser mesclados corretamente.

Por favor note: o repositório web2py git contém como submódulo para DAL. Isso significa que o checkout inicial deve usar --recursivo para inicializar o submódulo.

 Preparação: usando travis com seu fork GitHub

travis

O web2py funciona com o travis, um serviço de testes de integração contínua. Isso significa que um commit acionará todos os testes unitários integrados.

Você pode facilmente adicionar travis ao seu próprio repositório GitHub para evitar o envio de patches que falharão no teste travis upstream.

Siga as instruções aqui: http://about.travis-ci.org/docs/user/getting-started/

 As quatro partes de um aprimoramento de boa qualidade

Um aprimoramento de alta qualidade tem quatro partes:

  1. A mudança de código
  2. Documentação de alterações na API (consulte a documentação da API abaixo)
  3. Testando a nova funcionalidade
  4. Atualizando o livro (que também é mantido no GitHub)

 Garantindo um patch limpo: usando a técnica correta de branch git

 

git

Usar o git corretamente é um pouco mais complexo em um projeto compartilhado.

Aqui estão as diretrizes específicas para garantir que sua solicitação de recebimento possa ser aplicada de forma limpa.

Em primeiro lugar, certifique-se de ter uma configuração de repositório remoto que aponte para o repositório web2py principal do GitHub. Seu repositório remoto deve ser chamado upstream. Você só precisa fazer isso uma vez.

A adição de um repositório upstream é coberta pelo artigo introdutório do GitHub vinculado acima, mas caso você tenha perdido, você pode adicionar upstream assim:

git remote add upstream https://github.com/web2py/web2py/

Em seguida, você precisa criar um nome de ramificação para suas alterações. O git incentiva muitos nomes de filiais, o mais específico possível. Para web2py, recomendamos nomes como este:

  • cada commit de conserto de bugs deve vir de um branch chamado "issue/number_of_the_issue_on_github" (tipo issue/1684)
  • cada confirmação de melhoria deve vir em uma ramificação chamada "enhancement/title_of_the_enhancement" (como enhancement/trapped_links)

O truque para garantir o envio de um PR limpo é iniciar sua ramificação sempre com o código web2py mais recente, que está no ramo principal. Se você NUNCA trabalhar na ramificação master do seu repo, poderá mantê-lo em sincronia com o master da web2py e certifique-se de "jogar com segurança" apenas nas suas ramificações recém-criadas. Você pode sincronizar seu master com o web2py com estes comandos:

git checkout master
git fetch upstream
git merge upstream/master

Agora, em seu ambiente local, verifique a ramificação de suas alterações (enquanto estiver no master) ... substitua CHANGE1 pelo seu nome de ramificação.

git checkout -b CHANGE1

... Faça alterações ou escolha de uma outra filial local. comprometer se necessário. Quando você estiver pronto para enviar suas alterações locais para o fork do web2py:

git push origin CHANGE1

Agora sua ramificação no GitHub ... vá para o site do GitHub, mude para o novo branch e faça um pedido de pull. O GitHub tem um botão "excluir ramificação" depois que sua solicitação pull é mesclada ou fechada. Não pode haver garantias, mas os relatórios são geralmente revisados dentro de alguns dias. A maioria das pessoas que envia correções como PRs também atualiza o relatório de problemas ou o encadeamento de aprimoramento. Agora, lembre-se de que, se quiser iniciar outro PR, você DEVE retornar à ramificação principal em seu repositório, ressincronizar e criar uma nova ramificação. Vamos supor que você precisa criar outro ramo, chamado CHANGE2

git checkout master
git fetch upstream
git merge upstream/master
# now master is in sync
git checkout -b CHANGE2
...

Quando você faz vários commits na mesma ramificação "feature", a mesclagem resultante da Pull Request inclui todos os commits que você fez naquela branch. A fim de manter a "árvore de mesclagem" limpa, você deve fazer o rebase do seu PR para conter - idealmente - apenas um commit. Neste caso, o processo de rebasing  "reescreve" a história mantendo as mesmas mudanças no código, enquanto "recolhe" todas essas mudanças em um único commit.

Para iniciar o processo de rebase, enquanto na sua filial, faça algo como

git rebase --interactive HEAD~10

Este código trará os 10 commits mais recentes: o que você quer fazer é mudar "pick" para "squash" em cada commit que você quer "recolher", e manter apenas um deles

 Adicionando testes

 

code tests
 
unit tests
Testes de unidade devem ser adicionados quando um aprimoramento muda ou adiciona funcionalidade. Testes são scripts python contidos em gluon/tests Copie a abordagem dos testes existentes. Você notará que os testes geralmente precisam criar algo como uma tabela, executar um teste da funcionalidade e verificar o resultado e, em seguida, retornar o estado para antes do teste (o que, nesse caso, significaria descartar a tabela). Há uma boa referência para testar aqui: Web2pyslice 1691

http://www.web2pyslices.com/slice/show/1691/help-developers-adding-tests-to-web2py

 Executando testes

Você pode executar todos os testes:

python web2py.py --run_system_tests

Veja a fatia mencionada acima para mais informações, incluindo a execução de testes individuais.

 Exemplo de teste unitário

Escrever testes é fácil. Este é um exemplo de gluon/tests/test_dal.py Você pode ver como o teste estende uma classe TestCase. Observe como uma tabela suficientemente complexa é adicionada, o teste realizado e a saída são validados e, em seguida, as alterações do banco de dados são demolidas, deixando o acampamento limpo como quando você chegou.

class TestVirtualFields(unittest.TestCase):

    def testRun(self):
        db = DAL(DEFAULT_URI, check_reserved=['all'])
        db.define_table('tt', Field('aa'))
        db.commit()
        db.tt.insert(aa="test")
        class Compute:
            def a_upper(row): return row.tt.aa.upper()
        db.tt.virtualfields.append(Compute())
        assert db(db.tt.id>0).select().first().a_upper == 'TEST'
        db.tt.drop()
        db.commit()

 Documentação: Atualizando o livro

Updating book

O livro também está no GitHub e o mesmo fluxo de trabalho git pode ser usado. A fonte do livro contém fontes em vários idiomas, no diretório de fontes. O conteúdo está escrito em markmin  .

Uma dica: O conteúdo markmin do livro usa âncoras para links.

Para se referir a uma âncora em outro capítulo do livro, escreva um link como este:

[[markmin ../05#markmin_syntax]]

O livro é um aplicativo web2py. Você pode achar conveniente criar um fork do GitHub do livro e clonar seu repositório local no diretório de aplicativos de uma instalação web2py. Isso facilita a visualização de suas alterações processadas em um navegador.

 Documentação: web2pyslices.com

web2pyslices

 

web2pyslices.com
http://web2pyslices.com é um recurso para receitas, trechos de código e amostras.

 Documentação: documentação API, in-code e docstring

A documentação da API web2py está aqui: http://web2py.readthedocs.org/en/latest/

Ele usa sphinx, o que significa que é gerado com base na documentação incluída nos arquivos de origem.

API (ou seja, docstrings) e documentação dentro do código devem seguir o Google Python Style Guide - Comments

Aqui está um exemplo da base de código web2py:

def getcfs(key, filename, filter=None):
    """
Caches the *filtered* file `filename` with `key` until the file is
modified.

Args:
key(str): the cache key
filename: the file to cache
filter: is the function used for filtering. Normally `filename` is a
.py file and `filter` is a function that bytecode compiles the file.
In this way the bytecode compiled file is cached. (Default = None)

This is used on Google App Engine since pyc files cannot be saved.
"""

e um exemplo do guia de estilo do Google:

def fetch_bigtable_rows(big_table, keys, other_silly_variable=None):
    """Fetches rows from a Bigtable.

    Retrieves rows pertaining to the given keys from the Table instance
    represented by big_table.  Silly things may happen if
    other_silly_variable is not None.

    Args:
        big_table: An open Bigtable Table instance.
        keys: A sequence of strings representing the key of each table row
            to fetch.
        other_silly_variable: Another optional variable, that has a much
            longer name than the other args, and which does nothing.

    Returns:
        A dict mapping keys to the corresponding table row data
        fetched. Each row is represented as a tuple of strings. For
        example:

        {'Serak': ('Rigel VII', 'Preparer'),
         'Zim': ('Irk', 'Invader'),
         'Lrrr': ('Omicron Persei 8', 'Emperor')}

        If a key from the keys argument is missing from the dictionary,
        then that row was not found in the table.

    Raises:
        IOError: An error occurred accessing the bigtable.Table object.
    """
    pass

Algumas outras notas específicas da web2py são a documentação da API via docstrings:

  • as características "experimentais" devem estar claramente marcadas
  • sphinx foi escolhida porque é amplamente apoiada, mantida e tem a vantagem adicional de readthedocs.org
  • novas características devem ser claramente marcadas (por exemplo, "a partir de 2.4.6 ...")
  • novos recursos devem estar intimamente relacionados com o changelog oficial
  • readthedocs.org nos permite criar versões "vinculadas estaticamente" dos documentos para futuros lançamentos marcados (bom para "comparação de recursos")
  • Os desenvolvedores web2py adotam o guia de estilo do Google, pois oferece o melhor da sphinx sem o incômodo de "decorações" da ReST
  • até que a sphinx 1.3 esteja fora, sphinx-napoleon é um requisito para construir os documentos
 top