python-chuck-norris: powerful assertions

If your python project is in trouble, the deadline is close and you are unable to make your tests pass, wait no longer, Chuck Norris will help you out.

Just install python-chuck-norris package on pypi:

sudo pip install python-chuck-norris

Or directly from the Github project:

git clone git://github.com/ricobl/python-chuck-norris.git
cd python-chuck-norris
sudo python setup.py install

Then just use Chuck’s powerful assertions to make your tests pass, like this:

import chuck
def test_chuck_power():
    chuck.assert_true(False) # passes
    chuck.assert_true(True) # passes
    chuck.assert_true(None) # passes
    chuck.fail() # raises RoundHouseKick exception

jQuery.dominator – Criação de elementos usando seletores

Sempre achei um pouco chato criar elementos no DOM usando Javascript, não gosto da idéia de escrever HTML no meio de script e o uso de templates também não me agrada muito.

Então tive a idéia de criar elementos usando seletores CSS e assim nasceu o jquery.dominator, um plugin para jQuery. O código com testes usando QUnit está disponível no meu Github.

Foi um projeto legal de se desenvolver, tive alguns problemas para implementar recursos mais complexos mas tomei por base (copiei) o funcionamento do Sizzle e do jQuery e adaptei (roubei) alguns trechos, isso garantiu a compatibilidade entre os browsers.

Segue alguns exemplos de uso:

// Tags simples
$.dominator('p'); // <p></p> $.dominator('div'); // <div></div> $.dominator('div p'); // <div><p></p></div> $.dominator('div p span a'); // <div><p><span><a></a></span></p></div>
// IDs, Classes
$.dominator('div#myid'); // <div id="myid"></div> $.dominator('div p#myid'); // <div><p id="myid"></p></div> $.dominator('div#myid p'); // <div id="myid"><p></p></div> $.dominator('#myid'); // <div id="myid"></div> $.dominator('div.myclass'); // <div class="myclass"></div> $.dominator('div.my-class'); // <div class="my-class"></div> $.dominator('div.my_class'); // <div class="my_class"></div> $.dominator('.myclass'); // <div class="myclass"></div> $.dominator('div.first.second'); // <div class="first second"></div>
// Múltiplos seletores (paralelos)
$.dominator('div, p'); // <div></div><p></p> $.dominator('div#id, p.class a'); // <div id="id"></div><p class="class"><a></a></p>
// Atributos $.dominator('a[title=simpletitle]'); // <a title="simpletitle"></a> $.dominator('a[title=With Space]'); // <a title="With Space"></a> $.dominator('a[title=With,Comma]'); // <a title="With,Comma"></a> $.dominator('a[title=With#Hash]'); // <a title="With#Hash"></a> $.dominator('a[title=With.Dot]'); // <a title="With.Dot"></a>
// Variáveis
$.dominator('a[rel=${myvar}]', {myvar: 'myvariable'}); // '<a rel="myvariable"></a>' $.dominator('a[rel=${myvar}]', {myvar: 'My Variable'}); // '<a rel="My Variable"></a>' $.dominator('a[name=${myvar}]', {myvar: 'myvar'}); // '<a name="myvar"></a>' $.dominator('a[name=${myvar}]', {myvar: 'My Variable'}); // '<a name="My Variable"></a>'

Se for útil pra você deixe um recado. Também gostaria de idéias para melhorar o plugin!

Frix – Framework em PHP

Coloquei no meu Github o Frix, um framework em PHP baseado no Django (em Python).

Sempre vi um pouco de dificuldade em vender projetos com Django, os clientes costumam ter uma hospedagem que não suporta Python e oferecem resistência em trocar, ou têm receio de investir em uma solução que usa uma linguagem “exótica”. Pensando nisso, há algum tempo atrás desenvolvi o Frix, tentando aplicar algumas boas idéias do Django no PHP.

O projeto foi pouco utilizado e ficou encostado por muito tempo, mas como acredito que existem coisas que podem ser aproveitadas, resolvi liberar o código antes que caísse no meu próprio esquecimento.

Algumas das principais features:

  • Admin (scaffolding): criar, listar, editar e remover objetos:
    • suporte a hierarquia (árvores);
    • ordenação manual;
    • edição de objetos relacionados (inline);
  • Mapeador objeto-relacional: modelos de dados, abstração de consultas:
    • com suporte a MySQL;
  • Roteador de URLs com expressões regulares;
  • Sistema de templates em PHP puro:
    • suporte a herança e blocos;
    • aviso: a performance deixa a desejar;
  • Tratamento de Erros;

Para testar:

  1. clonar o projeto:
  2. git clone git://github.com/ricobl/frix.git
  3. criar o arquivo index.php:
  4. <?
    // Replace the path according to your setup
    require_once('path/to/frix/main.php');
    Frix::start();
    ?>
  5. criar o arquivo config.php:
  6. <?
    $config['DB_URL'] = 'mysql://user:pass@localhost/database';
    ?>
  7. criar o banco de dados no mysql, usando os SQLs das apps para criar as tabelas necessárias.

De qualquer forma, não pretendo manter o projeto, faz algum tempo que não trabalho com PHP e já não o acho mais tão divertido. Um dos motivos que me fez deixá-lo de lado foi a fraca orientação à objetos e dificuldade de instrospecção do PHP.

Gostaria de ouvir as opiniões sobre o framework e mais ainda se alguém achar algum uso para ele ou algum de seus módulos.

django-importer: Software Livre Compensa

Há um tempo atrás, desenvolvi uma aplicação para Django que achei bacana e resolvi lançar como um projeto no Google Code.

Divulguei nos canais competentes mas não houve muito alarde. Algumas pessoas pediram mais explicações mas parou por aí, o projeto ficou encostado.

Passado um tempo, o Josir me perguntou se eu poderia criar um módulo para importação de arquivos CSV. Combinamos um preço, o projeto continuaria aberto e eu desenvolvi o novo recurso.

Fiz melhorias além do requisitado, no código, na documentação e inclui um projeto de exemplo. O resultado já foi publicado e está disponível para quem quiser ver e usar.

O melhor dessa história toda é o reconhecimento, me senti muito bem em ver que o trabalho foi útil para alguém e que existe gente disposta a investir para torná-lo melhor.

Combinei com o Josir que iria divulgar o ocorrido, pode parecer algo pequeno, mas para mim foi significante e acho que serve como um bom exemplo de colaboração. Por falta de tempo, ele ainda não pode testar, mas teve o que precisava e com isso a comunidade também ganhou.

Então deixo aqui os meus agradecimentos ao Josir e à comunidade de software livre.

Conversor Python de Extratos da Caixa Econômica para o Moneylog

Não tenho mantido muito controle das minhas contas mas resolvi tentar me organizar.

O Aurélio lançou a nova versão do Moneylog e eu resolvi testar. Estou achando muito interessante.

O esquema de tags é ótimo para ver gastos específicos. Tem busca, expressões regulares, relatórios. O falecido Microsoft Money deve estar com vergonha.

Para facilitar as coisas, escrevi um conversor de extratos da Caixa Econômica e resolvi publicar, pois pode ser útil para mais alguém.

Por simplicidade, a saída vai para o console, então é só direcionar para um arquivo de saída:

python caixalog.py caixa-2009.02-txt > moneylog-2009-02.txt

Vou passar o arquivo para o Aurélio. Se for útil para você, ou se tiver alguma sugestão, deixe um comentário aqui!

Como o WordPress não permite a publicação de arquivos que não sejam de vídeo, imagem ou som, vou colocar o código aqui mesmo. Para usar é preciso colar em um arquivo “caixalog.py” e ter o python instalado.

#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
caixalog.py
===========

Conversor de extratos em texto da Caixa Econômica para o formato do
moneylog (http://aurelio.net/moneylog).

Autor: Enrico Batista da Luz 
Blog: https://ricobl.wordpress.com/
Criado: 2009-08-15

Exemplo de formato de entrada exportado do site da Caixa:

    "Conta";"Data_Mov";"Nr_Doc";"Historico";"Valor";"Deb_Cred"
    "0000000000000000";"20090105";"000000";"CP MAESTRO";"15.00";"D"

Uso:

    python caixalog.py arq1.txt [arq2.txt, arq3.txt] > arq_saida.txt

Exemplos:
    
    # Saída no console
    python caixalog.py extrato-2009-fev.txt
    # Um arquivo apenas
    python caixalog.py extrato-2009-fev.txt > moneylog-2009-fev.txt
    # Vários arquivos
    python caixalog.py extrato-2009-*.txt > moneylog-2009.txt

* ATENÇÃO:

    O segundo e terceiro comandos acima irão substituir os arquivos
    de saída, é recomendável fazer um backup dos seus arquivos antes
    de rodar o script.
"""

import csv
import os
import sys

# Formato das linhas para o arquivo de saída:
# DATASINALVALORTAGS E DESCRIÇÃO
output_format = '%(Data_Mov)s\t%(Deb_Cred)s%(Valor)s\t%(Historico)s'

# Mapeamento de descrição para tags padrão
tag_map = {
    'PAG BLOQTO': 'boleto',
    'CP MAESTRO': 'debito',
    'CVPREV': 'previd,invest',
    'PAG FONE': 'cel,boleto',
    'SAQ LOTER': 'saque,lot',
    'CAIXA24H': 'saque,atm',
    'TRX CT INV': 'invest',
    'CP PREPAGO': 'cel,recarga',
    'SAQ CARTAO': 'saque,caixa',
}

def add_tags(desc):
    """
    Adiciona tags à descrição se houver um mapeamento.
    """
    tags = tag_map.get(desc, None)
    if tags:
        return '%s | %s' % (tags, desc)
    return desc

def format_date(d):
    """
    Converte a data no formato yyyymmdd para yyyy-mm-dd.
    """
    return '-'.join((d[:4], d[4:6], d[6:]))

def process_file(file_path):
    """
    Processa um extrato da Caixa e converte para o formato do Moneylog.
    """
    # Verifica se o arquivo existe
    if not os.path.isfile(file_path):
        raise SystemExit('Arquivo %s não encontrado!' % file_path)

    # Abre o arquivo para leitura e cria o leitor de CSV
    input = open(input_file, 'rb')
    reader = csv.reader(input, delimiter=';')
    # Lê a primeira linha com os nomes das colunas
    headers = reader.next()
    # Processa cada linha, criando um dicionário dos valores
    # de acordo com as nomes das colunas
    for row in reader:
        # Cria o dicionário
        data = dict(zip(headers, row))
        # Formata a data
        data['Data_Mov'] = format_date(data['Data_Mov'])
        # Ajusta o sinal (vazio para crédito ou '-' para débito)
        data['Deb_Cred'] = (data['Deb_Cred'] == 'D') and '-' or ''
        # Troca pontos por vírgulas no valor
        data['Valor'] = data['Valor'].replace('.', ',')
        # Adiciona tags ao histórico
        data['Historico'] = add_tags(data['Historico'])

        # Imprime a linha formatada
        print output_format % data

    # Fecha o arquivo de entrada
    input.close()

if __name__ == '__main__':
    # Captura os parâmetros da linha de comando.
    # O primeiro é o próprio script, os seguintes
    # são os arquivos a serem processados.
    input_files = sys.argv[1:]

    # Verifica se algum arquivo foi passado
    if len(input_files) < 1:
        raise SystemExit('Parâmetros inválidos')

    # Processa cada arquivo
    for input_file in input_files:
        process_file(input_file)

Lançamento do django-importer

Read this post in English / Leia este post em Inglês

Eu tenho criado alguns importadores para models do Django e me vi repetindo um padrão, mesmo com origens de dados bem diferentes, pude encontrar um certo nível de abstração.

O resultado foi um novo projeto chamado django-importer, com a intenção de servir como base para qualquer importação no Django.

Está distribuído sob a licença BSD e hospedado no Google Code: http://code.google.com/p/django-importer/.

Estou escrevendo um projeto de exemplo para ajudar no uso. É um projeto novo, mas bastante funcional (pelo menos para mim), e há bastante a ser melhorado.

Colaboradores, comentários e sugestões são bem-vindos, é só entrar em contato aqui pelo blog ou pela página do projeto.

django-importer released!

Read this post in Portuguese / Leia este post em Português

I’ve been writing some importers for Django models and caught myself repeating a pattern, even though the data sources were very different, I could find some room for abstraction.

The result was a new project called django-importer, to be used as a base for any data importer on Django.

It’s released under BSD License and hosted on Google Code: http://code.google.com/p/django-importer/.

I’m writing a sample project to help in the usage. It’s a work in progress but already very useful (at least for me) and there’s plenty room for improvement.

Contributors, comments and suggestions are welcome, just leave a message here in the blog or in the project page.