Python com Eggs – Parte II

Construções relevantes do Setuptools

Considero Setuptools um projeto tão importante para a comunidade Python que eu preciso citar mais informações sobre ele antes de entrar realmente no tópico sobre plugins. Para ter uma idéia da quantidade de projetos em Python, pequenos ou grandes, vale a pena visitar o site do Cheese Shop. Ele é um repositório de projetos escritos em Python. A maioria dos projetos já é distribuído usando o formato Egg, principalmente para facilitar a verificação de dependências.

Projetos que ainda não usam os recursos do Setuptools, ainda assim, quando baixados via EasyInstall são transformados em Eggs antes da instalação, automaticamente.

Recursos mais importantes (retirados daqui):

  • Automaticamente encontra/baixa/instala/atualiza dependências em tempo de construção usando a ferramenta EasyInstall, que suporta donwload via HTTP, FTP, Subversion e ainda SourceForge, além de rastrear automaticamente páginas “linkadas” no PyPI para encontrar links de downloads. Como o autor mesmo cita: é o mais próximo que temos do CPAN em Python.
  • Criação de Python Eggs – formato de distribuição importável em um único arquivo.
  • Incluir arquivos de dados em seus diretórios de pacotes.
  • Capaz de automaticamente incluir todos os pacotes da sua árvore-fonte sem a necessidade de declarar individualmente cada pacote no setup.py.
  • Suporta o envio de fontes ou eggs para o PyPI.
  • Instala seu projeto em modo de desenvolvimento. Assim seu projeto fica disponível para importação e você ainda poderá editá-lo e quaisquer modificações são automaticamente visíveis.
  • Facilmente estende o distutils com novos comandos ou argumentos para a função setup() e distribui/reusa suas extensões para cada projeto sem copiar código.
  • Cria aplicações e frameworks extensíveis que automaticamente descobrem extensões usando simplesmente “entry points” declarados no script setup.py do projeto.

Esse último item é o que nos interessa. Ele vem fazendo a mágica em vários projetos, inclusive em favor do próprio Setuptools.

Entry Points

Entry Points é uma lista de objetos públicos numa distribuição. Vejamos um exemplo:

# setup.py

setup(…
entry_points = “””
[lyricsearch.search]
terra = lyricsearch.terrasearch:LyricsTerra
[console_scripts]
lyse = lyricsearch.lyse:command
“””
)

Os objetos são ordenados em grupos. No caso do exemplo, lyricsearch.search é um grupo para objetos que fazem busca de letras para a aplicação LyricSearch.

Já existem nomes de grupos convencionalizados:

– [console_scripts] para scripts de linha de comando
– [paste.app_factory] aponta para uma função que constrói uma aplicação WSGI.
– [distutils.command] aponta para um comando do distutils (ex.: setup.py sdist)
– [python.template.plugin] é uma classe que representa uma sistema de template.

Um objeto público possui um nome. Em nosso exemplo, o plugin de busca de letras no site do Terra chama-se ‘terra’. Nomes simplesmente apontam para objetos Python. As duas declarações abaixo são equivalentes:

lyricsearch.terrasearch:LyricsTerra

from lyricsearch.terrasearch import LyricsTerra

Essa aplicação de exemplo realmente existe e sou seu autor. Fiz especialmente para essa matéria. Atualmente o LyricSearch é composto de um simples script de linha de comando para realizar consulta de letras e mais um plugin. Passamos para ele o título da música e o artista. O script procura por plugins e tentará utilizar cada um deles até encontrar um que devolva a letra desejada. Fiz somente um plugin. O plugin consulta o site letras.terra.com.br em busca da página da letra. Ele devolve o texto em HTMl. Todos os plugins do grupo [lyricsearch.search] devem ser uma classe que implemente dois atributos url, description e um método público, find(title, artist), para retornar uma string contendo o texto da letra ou uma string vazia caso não encontre nada.

Fazendo nosso primeiro plugin

Vamos fazer um simples plugin para o LyricSearch na finalidade de mostrar o poder dos Entry Points do Setuptools. Façamos a seguinte estrutura de arquivos:

TestePlugin
+– testeplugin.py
+– setup.py

Agora o código:

#testeplugin.py

class TestePlugin:

url = ‘https://claudiotorcato.wordpress.com’

description = ‘apenas um teste’

def find(self, title, artist):

return artist

#setup.py
from setuptools import setup

setup(

name = ‘TestePlugin’,
version = ‘0.1’,
py_modules = [‘testeplugin’],
entry_points = “””
[lyricsearch.search]
teste = testeplugin:TestePlugin
“””

)

Nosso plugin não fará nada útil, apenas devolverá o nome do artista.

Antes de continuar, precisamos instalar o setuptools em nossa máquina caso não o tenhamos. Baixe o script ez_setup.py e o execute. Ele baixará e instalará a versão estável mais recente do setuptools. Agora vamos instalar em nossa máquina o LyricSearch. Usuários do Linux que não tenham permissão de root para a instalação há essa alternativa [1].

easy_install LyricSearch

Agora, testemos a aplicação que foi baixada:

lyse “o vencedor” “los hermanos”

Obs.: Usuários do Windows não devem esquecer de colocar o caminho do interpretador Python e dos scripts na variável de ambiente PATH: c:\python24\;c:\python24\scripts.

Felizmente nossa aplicação já vem com pelo menos um plugin de pesquisa. É interessante, ela não usa diretamente o plugin, mas requere para a API Python que trata dos Entry Points o determinado objeto. Desejamos que nosso plugin de teste funcione da mesma forma, ou seja, seja localizado pela aplicação e executado.

O próximo passo é instalar TestePlugin. Na raiz do pacote digite e execute:

python setup.py develop

A opção develop cria um arquivo em site-packages que aponta para nosso diretório de desenvolvimento. Assim nossas modificações nesse ambiente repercutem na biblioteca automaticamte. De modo mais simples: a atualização da biblioteca é instantânea.

O outro modo seria ‘python setup.py install’ que realmente grava nosso pacote na árvore de diretórios do Python. Na verdade, é o modo comum de instalar pacotes.

Se a instalação ocorreu sem problemas, vamos testar agora nosso plugin.

lyse –list

Este comando mostrar os plugins do grupo lyricsearch.lyric. Deveriam ser encontrados dois: terra e teste. Aparecendo, vamos ver se ele realmente devolve o nome do Artista.

lyse -p teste “o vencedor” “los hermanos”

Partindo do mesmo exemplo de consulta, porém forçando o plugin, esperamos que retorne a palavra “los hermanos”!

Tamanha a flexibilidade dos Plugins em Python, cada vez mais desenvolvedores se voltam para esse modo de criar aplicações e ferramentas extensivas de modo mais simples. No próximo material, trataremos de assuntos tais como Paste entre outros.

Parte I

Tempfile no Windows

Bom, senhores, o tempfile ao contrário do que eu imaginava, não funcionou bem no Windows. O método flush() que forçava escrita não funcionou e o browser não encontrou texto nenhum. Tive de apelar para o processo normal em que eu mesmo tenho de fechar o arquivo após o browser já ter sido aberto e lido o mesmo.

Lancei o LyricSearch 0.1.9, mas breve lançarei uma correção de um bug. Foi um erro por ter esquecido a existência da variável sys.plataform e usado algo que não era legal para testar em qual plataforma o lyse está rodando.

lyse -bp terra "o vento” “los hermanos”

Apesar de ainda não ter disponibilizado a versão 0.2.0 do LyricSearch por está fazendo refatorações no código, comprovei o funcionamento da biblioteca tempfile e webbrowser tratadas no último post.

Agora podemos usar a opção -b ou –browser para abrir um navegador/janela/aba para mostrar a letra da música. Função bem útil uma vez que meu plugin de busca devolve o texto com formação HTML.

Futuramente, pretendo criar uma API e plugins correspondentes para tipos de saídas possíveis. Assim, é possível que essa opção não dure muito. Só o futuro dirá.

Em breve anunciarei a nova versão do LyricSearch. Aguardem.

technorati tags:

Santa Biblioteca!

“Python vem com baterias incluídas!”

A frase acima já é consagrada na comunidade Python. Ela significa que ao instalar o Python na sua máquina você já tem uma biblioteca poderosa e variada à sua disposição.

Essa verdade eu já sabia mas somente hoje resolvi me expressar escrevendo um post sobre o tema. O motivo é que eu desejo acrescentar uma nova funcionalidade ao script de busca de letras, lyse, que é abrir uma janela num navegador web para mostrar a letra encontrada. Para isso eu preciso criar um arquivo temporário. Como fazer isso independente da plataforma? Resolvi ir atrás mas por onde começar? Na própria biblioteca do Python! O que eu encontrei foi o módulo tempfile.

Ainda não escrevi essa parte do código mas já sei que vai dar certo porque além deste módulo existe o webbrowser! Vai ser uma tarefa divertida porque é com Python!

Deseja conhecer a biblioteca de Python? Visite a sua documentação que é muito boa.

Atualização: O módulo tempfile no Windows não funciona como eu esperava. Uma pena. Tive de criar um arquivo comum para ter o mesmo efeito que acontece no Linux.