Workshop Produtividade Web 2.0 - Equipes de desenvolvimento de sites produtivas com ferramentas ágeis e padrões web Programadores desanimados? Desmotivados? Sem vontade de cantar uma bela canção?

Arquivos da tag 'Python'

Dicas de shell: testes unitários e commit

12/02/2008

Todas as tarefas relacionadas a contrução, teste e publicação de um desenvolvimento de software[bb] devem ser automatizadas o máximo possível. Escrever software é interar. Você escreve e testa, escreve e testa, escreve e testa dezenas, às vezes centenas de vezes por dia. As tarefas relacionadas a testar o software, de maneira especial, merecem a automatização que for possível dar a elas. Convenhamos, testar é algo muito chato. E se for complicado testar, será uma tentação irresistível para o programador entregar seu código sem testar adequadamente.

Hoje vamos construir um script de commit no subversion[bb] que, antes de enviar o código, executa todos os testes unitários. Vou trabalhar com Python[bb], mas você não deve ter dificuldades em adaptar isso para a sua linguagem de programação predileta.

A primeira coisa importante é que você entenda que todo script executado no shell tem um valor de retorno. Esse valor é retornado pelo comando, e também armazenado na variável especial $?. Veja estes exemplos:

$ echo $?
2
$ ls test
test
$ echo $?
0
$ if ls test2;then echo O arquivo existe.;fi
ls: test2: Arquivo ou diretório não encontrado
$ if ls test;then echo O arquivo existe.;fi
test
O arquivo existe.
$ if ! ls test;then echo O arquivo não existe.;fi
test
$ if ! ls test2;then echo O arquivo não existe.;fi
ls: test2: Arquivo ou diretório não encontrado
O arquivo não existe.

Os testes foram construídos usando o módulo para testes unitários unittest do Python. Cada teste está, no diretório do projeto, junto do arquivo de código que ele testa. E o nome dos arquivos de teste sempre começam com "test". Assim, o arquivo connections.py é testado pelo testconnections.py.

Veja então nosso shell script, salvo com o nome de commit, que será usado durante todo o projeto para rodar os testes antes do commit:

#!/bin/bash
 
# Começamos com um contador de erros em zero
erros=0
 
# Encontramos cada um dos testes
for i in `find -name "test*.py"`;do
echo TESTANDO: $i
echo
 
# Se o teste falhar, incrementamos a variável erros
if ! python $i;then
erros=$(($erros + 1))
fi
 
echo
done
 
# Se os testes passaram, fazemos commit, caso contrário
# avisamos o usuário
if [ $erros == 0 ];then
# Esse $* passa os parâmetros de linha de comando recebidos para o svn.
svn ci $*
else
echo Testes falharam, commit cancelado.
fi

Tendo feito isso, e colocando esse script em /usr/local/bin, o programador vai trocar svn ci por commit, e os testes serão feitos automaticamente antes do commit. Ele também pode passar parâmetros do svn para o script:

commit -m "Criei o link espacial com saturno"

Retornando o último número (script Python)

21/11/2007

Meu amigo DGmike publicou: Retornando o último número (script PHP)

Como eu acho interessante comparar soluções em linguagens diferentes, resolvi escrever o mesmo script em Python[bb]. Veja como ficou:

import re
def ultimoNumero(string):
return re.findall(r"\d+",string)[-1]

Gostou?

Instalando o PSE no Ubuntu 7.10 Gutsy Gibbon

28/10/2007

O novo Ubuntu[bb] 7.10 está maravilhoso. Até o 7.04 eu usava um hack para fazer funcionar minha placa de rede, agora ela funciona sem truques. O compiz já instalado funcionou sozinho, bem direitinho. O resto tudo também funcionou sem dor. Menos o PSE.

Por algum motivo estranho, a versão do mod_python (3.3.1) desse novo Ubuntu reclama de sei lá o que. A versão anterior (3.1.3) funcionava sem problemas. Dei um jeito aqui de colocar para funcionar. Não sei se é uma boa saída, se alguém tiver uma sugestão melhor, por favor.

Segue a receita de bolo para instalar o PSE no novo Ubuntu:

  1. Instale os pacotes necessários: sudo apt-get install apache2 libapache2-mod-python python-profiler build-essential latex2html
  2. Baixe o PSE: wget http://nick.borko.org/pse/PSE-3.0.6.tar.gz
  3. Extraia o código fonte: tar -xzvf PSE-3.0.6.tar.gz
  4. Entre na pasta: cd PSE-3.0.6
  5. Compile e instale: sudo python setup.py install
  6. Edite o arquivo de configuração do Apache: sudo gedit /etc/apache2/apache2.conf
    Acrescente ao final:
    PythonHandler pse_handler
    AddHandler python-program .pt
  7. Aqui vai o hack: sudo gedit /usr/lib/python2.5/site-packages/mod_python/importer.py
    Encontre a linha 303, que deve ser:
    return __import__(module_name, {}, {}, '*')
    E edite para ficar:
    return __import__(module_name, {}, {}) #, '*')
    Cuidado para não quebrar a identação!
  8. Reinicie o Apache: sudo invoke-rc.d apache2 restart

Pronto, deve funcionar. Aqui para mim foi só isso.

Tradutor Português-Portunhol

19/10/2007

Falta uma semana para lo dia internacional de hablarse portuñol. Fica aqui minha contribuição ao ócio e falta do que fazer, fruto de uma tarde de feriado entediante: tradutor automático de sites português-portunhol. Você pode, por exemplo, ver este site traduzido para o portuñol[bb].

Tomara que você ache tão divertido de usar quanto eu achei construí-lo.

Acentuação em Português e Expressões Regulares Python

17/10/2007

Ao utilizar expressões regulares em Python[bb], por padrão, seu texto é interpretado como uma seqüência de caracteres ASCII comum. Assim, caracteres acentuados são considerados sinais gráficos especiais, e não são capturados como letras. Veja este exemplo:


>>> import re
>>> print re.sub(r"\b","|","era uma criança")
|era| |uma| |crian|ç|a|

Como você pode ver, o ce-cedilha não é considerado uma letra, "quebrando" a palavra. Resolver isso é muito fácil, basta compilar a expressão regular passando a flag L, para que ela siga o locale de sua máquina, ou a flag U, para que ela trabalhe com unicode. No meu caso, em que o locale da máquina é unicode, tanto faz. Veja como funciona:


>>> import re
>>> c=re.compile(r"\b",re.U)
>>> print c.sub("|",u"era uma criança")
|era| |uma| |criança|

Só não se esqueça de trabalhar com strings unicode.

Um pouquinho mais da sintaxe do Python

09/10/2007

Um amigo meu está fazendo faculdade, e começando a aprender a programar (com Java[bb].) Ele me mostrou semana passada um exercício que o professor passou:

  • Solicitar que o usuário informe um número inteiro que será usado como limite superior do contador.
  • O programa deverá exibir todos os números pares existentes entre 1 e o limite superior (informado via teclado pelo usuário).
  • Após a exibição dos números o programa deverá perguntar se o usuário deseja executar mais uma vez.

Por curiosidade, eu escrevi uma solução em Python[bb]:

continuar=True
while continuar:
numero=int(raw_input("Informe o valor inicial da repeticao: "))
print str(range(2,numero+1,2))[1:-1]
continuar=raw_input("Continuar? (S/N) ").upper()!="N"

Update: inspirado nos comentários do Rafael Santini, uma solução com break fica mais elegante:

while 1:
numero=int(raw_input("Informe o valor inicial da repeticao: "))
print str(range(2,numero+1,2))[1:-1]
if raw_input("Continuar? (S/N) ").upper()=="N":break

Python X Java X Smalltalk

22/05/2007

Achei muito interessante este artigo comparando a sintaxe de Smalltalk com Java. Implementei os mesmos exemplos em Python, para que você possa comparar a sintaxe:

Problema: cálculo de fatorial

def factorialRecursive(n):
  if n<0:return 0
  if n==0:return 1
  return n*factorialRecursive(n-1)

Ou assim:

def factorialNonRecursive(n):
  if n<0:return 0
  return reduce(lambda a,b:a*b,[1]+range(1,n+1))

A recursividade pode parecer uma solução elegante, mas o consumo de memória é assombroso nesse caso, em qualquer linguagem. Calcular a fatorial de um número grande qualquer pode ser um problema com a recursividade. Por isso, prefira a versão não recursiva.

No novo Python 2.5 você pode fazer:

def fact(x): return (
  0 if x<0 else
  reduce(lambda a,b:a*b,[1]+range(1,x+1))
)

Aqui é difícil dizer qual é mais prática, Smalltalk ou Python. Você pode palpitar sobre qual é mais elegante, uma vez que as soluções são radicalmente diferentes, mas a escolha final é subjetiva.

Problema: imprimir os números de 1 a 10

Eu faria usando os recursos de programação funcional:

print "\n".join(map(str,range(1,11)))

Mas você pode preferir:

for i in range(1,11):
  print i

De qualquer maneira, ponto para o Python[bb] aqui.

Problema: trabalhando com Collections

l=[
  'Em Python,',
  'chamamos as',
  'collections',
  'de "listas"',
]
print "\n".join(l)

Aqui, indiscutivelmente, ponto para o Python.

Problema: mostrar os pares e ímpares entre 1 e 10

for i in range(1,11):
  print i,["is even","is odd"][i % 2]

Novamente, o Python ganha disparado.

Problema: invocar um método via Reflection

É bem fácil:

o=MyClass()
getattr(o,"showMessage")()

Aqui o páreo é duro, Python e Smalltalk correm cabeça-a-cabeça. Na minha opinição, Python ganha por um focinho.


PythonPara saber mais sobre Python recomendo o PythonBrasil.

Além disso, sou professor do Curso de Python da Visie.

Escrevendo um corretor ortográfico

12/04/2007

Um corretor ortográfico de apenas 20 linhas, em Python[bb]:

How to Write a Spelling Corrector

Solução elegante, mostra também o quanto a linguagem é elegante.

Aprendendo a programar, em Python, Ruby, C++, Java ou Logo.

04/02/2007

Eu já tinha lido este excelente livro (e-book grátis):

How to Think Like a Computer Scientist: Learning With Python

Eu costumo recomendar a todo mundo que está tentando aprender lógica de programação, e o uso quando preciso ensinar alguém a programar. Eu já sabia que ele é uma versão em Python[bb] do original, em C++

Mas só hoje fiquei sabendo que o mesmo livro também está disponível nas versões Java, Ruby e Logo.

Agora você pode ensinar seus sobrinhos a programar usando sua linguagem de programação predileta. E, se eles ainda não tiverem idade para coisas como orientação a objeto, e precisarem de algo mais concreto, pode usar Logo.

De novo, boa propaganda faz milagres

31/01/2007

Humanized

É um Katapult, um QuickSilver. Só que rodando em Windows. Ou seja, nada de novo, mais uma vez o Windows tem a mesma coisa que os outros sistemas, com alguns meses ou anos de atraso. E parece maravilhoso porque muito usuário de Windows nunca viu nada parecido.

Assista o vídeo e veja no final, onde aparece o desenvolvedor com a barba engraçada. Na parte em que ele fala sobre como estender o sistema, preste atenção na linguagem de programação que você vai usar se quiser ensinar novos truques.

Antes que alguém venha dizer que o Katapult ou o QuickSilver não fazem todos os truques que o Enso, eu quero lembrá-lo de que estamos falando de sistemas Unix. O shell do Unix é a coisa mais flexível que já se inventou em relação à integração de programas diferentes. Tomei um tempinho agora e escrevi 18 linhas de Python + Shell Script, para tentar fazer algo parecido com o que o Enso faz. Veja o resultado:

Usei o próprio Katapult, o Kmenuedit para criar as entradas e colocar os ícones, e o xvkbd para falar com as aplicações abertas. Levei uns 30 minutos, incluindo a gravação do vídeo. Se gastar mais um tempo nisso, é possível fazer muita coisa legal.

StayValid

30/01/2007

O caso é muito comum: você cria um site com um gerenciador de conteúdos qualquer. Por exemplo, um blog Wordpress. Você valida o código e o site passa perfeitamente pelo validador. Mas, depois de algum tempo, alguém, você, seu cliente, seu colega, seu cachorro ou seu papagaio fazem um post no blog, ou alteram um conteúdo no CMS e isso quebra a validação. E você só vai descrobir sabe-se lá quanto tempo depois.

Como resolver este problema? Validar todos os seus sites, todos os dias?

O StayValid valida seu site para você, todos os dias, de hora em hora. Insira o endereço de seu site e o StayValid vai criar um feed RSS[bb] onde você pode acompanhar os resultados da validação. Se tudo correr bem, você vai receber apenas uma notícia por dia, do StayValid dizendo que validou seu site. Se ele encontrar um ou mais erros, ou se o resultado da validação mudar (por exemplo, você tinha três erros e agora só tem dois) o StayValid vai validar de hora em hora e te avisar via RSS.

Em tempo: o StayValid nasceu de uma necessidade nossa, e se tornou possível porque o código de resultados do validador do W3C é XHTML válido. Bastou então escrever um arquivo XSLT que transformasse os resultados num RSS.

Um passo além do Akismet

29/01/2007

Qualquer um que tenha um blog com comentários dos usuários conhece o problema: spam de comentários. Este blog recebe centenas de comentários por dia sobre assuntos tão diversos quanto viagra ou tramadol, fotos de angelina jolie e britney spears nuas, encontros, jogos online e uma série de outras coisas que não tem absolutamente nada a ver com o assunto desse blog.

Quem usa Wordpress certamente conhece o Akismet, um plugin com um filtro de spam, semelhante ao de Gmail, que acerta mais de 97% das vezes neste humilde blog. É fabuloso. Mas de vez em quando erra.

Se o Akismet deixa passar um comentário que deveria ter sido considerado spam, tudo bem, eu modero isso manualmente. Mas quando ele coloca na caixa de spam um comentário legítimo, o risco de que esse comentário se perca no meio das centenas de spam que recebo todos os dias é muito alto. Verificar a caixa de spams é um trabalho extremamente chato.

Foi pensando nisso que eu criei o Navalha do Spam, um pequeno script Python[bb] que eu fiz em cinco minutos, e que você pode baixar aqui. O navalha funciona através da antiquìssima idéia de se ter uma blacklist de palavras. É simples, a esmagadora maioria dos spams que recebo contém nomes de remédio ou de doenças, como viagra, cialis, phentermine, lexapro, acyclovir, mesothelioma ou prozac, nomes de celebridades escandalosas como britney spears, angelina jolie, briana banks, referências a pornografia ou outras palavras muito manjadas, como ringtone, insurance, refinancing ou wallpapers. E os comentários em meu blog, devido aos assuntos que abordo e ao idioma, raramente contém uma dessas palavras.

Então o que o Navalha faz é ler uma lista de expressões, uma por linha, no arquivo keywords, e excluir todos os comentários que estiverem na caixa de spam e contiverem qualquer uma dessas palavras.

Para usá-lo, você vai precisar apenas de Python e MySQLdb. Coloque os dados de sua conexão no arquivo settings.py. Depois basta executar, dentro do diretório do script:

$ python spamkill.py

E pronto. Aqui para mim o resultado é que geralmente sobra meia dúzia de comentários. Dois ou três legítimos, que eu vou restaurar. Se ainda sobrar muito spam depois de rodar o script, é hora de olhar o que sobrou e incluir novas palavras chaves no arquivo de keywords.

Auto-completar no shell interativo do Python

29/01/2007

Tentei o IPython, mas não consegui acostumar com ele. É diferente demais do shell padrão.

Mas hoje, encontrei nos comentários deste artigo, a dica. Ao abrir o shell interativo, rode:

import readline
import rlcompleter
readline.parse_and_bind("tab: complete")

Pronto, isso te dá auto-completar no shell.

Navegando

12/01/2007