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 = ‘http://claudiotorcato.wordpress.com’
description = ‘apenas um teste’
def find(self, title, artist):
return artist
#setup.py
from setuptools import setupsetup(
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.