Morrer Seria o Melhor pra Você

Deve ter sido mais ou menos assim: à medida que o mecanismo lia a longa fita de dados, ia construindo a estrutura, e sendo não se perguntava se as mãos fariam falta, ou as pernas. Mas que mãos e que pernas, não constava nada disso na fita de dados, na verdade, de sua perspectiva ele estava orgulhoso da montagem ter sido perfeita.

Certamente o menino no metrô e sua mãe discordam totalmente da opinião do RNA sobre o que é um “bom trabalho”, tão bom que teve de ser complementado com pernas artificiais – um esforço humano para superar os “bons trabalhos” da natureza – mas ainda nenhuma solução para ele conseguir pegar em sua kombi verde de brinquedo, que a mãe segurava.
Fiquei me perguntando o que uma encarnação da ciência humana diria para ele:

- Filho, fizemos vários avanços na detecção de problemas genéticos como o seu ainda na gestação.
- Para curar?
- Um dia talvez, por hora é para avisar os pais que provavelmente vão matar a criança antes dela nascer.
- Mãe, você teria me matado se soubesse?
- … claro que não meu filho.

Não estou culpando ninguém, nem tendo pena, que é inútil, e se tivesse de ter seria da humanidade toda (começando por mim) que está exposta a todo tipo de mazela. O que fiquei matutando foi a precisão de minha percepção sobre as soluções preferidas serem as rápidas (“ele é só um embrião, nem vai saber o que aconteceu”) em lugar das difíceis (descobrir uma forma de crescer membros novos on-the-fly). Me pergunto se a ciência seria boa em resolver problemas mas ruim em estabelecer um equilíbrio entre as partes afetadas pela “solução”.

Mas… qual o objetivo desse post mesmo? :-|

Planeta PythonBrasil e Plugin (em Python) para o GEdit

Planet Python Brasil

Além de toda facilidade e agradabilidade (!) ao programar, parece que Python também ajuda a fazer amigos! Como Lauro observou num email, parece que fomos sindicados no Planet PythonBrasil. :D

Plugin para Autocompletar Palavras no Gedit
Achei um plugin muito útil (escrito em python) para completar palavras no Gedit. Contudo, atentem que não é pra completar código, ele apenas sugere completar palavras que já constem no arquivo, mesmo assim já é uma boa ajuda quando se trata de código, onde acontece muita repetição.

GEdit word completion

Basta escolher a alternativa e apertar TAB.

Baixe os arquivos

e os copie ambos para ~/.gnome2/gedit/plugins/ (você pode ter de criar o diretório “plugins”), reinicie o gedit, vá em Preferências->Plugins e ative o recém-instalado.

Mais plugins pro gedit em http://live.gnome.org/Gedit/Plugins

LogicParser 0.6

Depois de curto tempo (umas 17 horas), mais um release do LogicParser. Agora é possível atribuir valores às proposições e o resultado da expressão completa é avaliado.

LogicParser 0.6

Para mudar o valor da proposição, basta colocar o cursor sobre o valor na lista da esquerda e segurar o botão esquerdo, então um combobox aparecerá com as opções de valores (True ou False).

Download: logicparser-0.6.tar.gz

Manipulando Documentos ODF com Python

Num post anterior eu falei sobre padrões abertos e o OpenDocument Format em particular. Depois da conversa filosófica veio a vontade prática, e resolvi escrever alguma coisa para manipular um arquivo ODF. Bem, como todos já sabem o ODF usa XML, na verdade distribuído em vários arquivos, compactados junto com figuras e outras coisas; você pode pode dar um unzip algumdocumento.odt pra ver o conteúdo. O arquivo que interessa para este exemplo é o contents.xml, que é onde está o texto num documento. Criei um documento com um título, alguns subtítulos e um bocado de Lorem Ipsum. Os títulos foram feitos direito, informando que aquele componente era do tipo título (heading; veja o destaque no screenshot abaixo) e não usando a “técnica” ancestral e sebosa de negritar e aumentar a fonte.

OOo Lorem Ipsum

Um trecho do XML em contents.xml (coloquei em negrito os trechos que irão interessar):

<text:h text:style-name=”Heading_20_1″ text:outline-level=”1″>
Título
</text:h>
<text:h text:style-name=”Heading_20_2″ text:outline-level=”2″>
Seção A
</text:h>
<text:p text:style-name=”Standard”>
<text:bookmark text:name=”lipsum1″/>
Lorem ipsum dolor (…)
</text:p>

text.h indica um título (heading), assim como text:p indica um parágrafo, e text:outline-level diz o nível do título. Assim, text:h e text:outline-level=”1″ juntos significam que o texto contido no tag é do tipo “Header 1″.

O objetivo do script é encontrar os títulos contidos no documento e imprimí-los, identando de acordo com o nível do título. Usei a biblioteca zipfile para abrir o odt e minidom para parsear o XML numa árvore. Ambos já vêm numa instalação Python padrão.

import zipfile
from xml.dom.minidom import parseString

def get_titles(odf_filename):

dom = parseString(component)
odf_file = zipfile.ZipFile(odf_filename, 'r')
contents = odf_file.read('content.xml')
odf_file.close()

dom = parseString(component)
title_elements = dom.getElementsByTagName('text:h')
titles = []
for t in title_elements:

level = int(t.attributes['text:outline-level'].value
title = t.childNodes[0].data
titles.append((level, title))

dom.unlink() return titles

if __name__ == '__main__':

titles = get_titles('teste.odt')
for title in titles:

for a in range(title[0] - 1):

print ' ',

print title[1]

A função get_titles extrai o arquivo contents.xml do odt, seu conteúdo é parseado e o método dom.getElementsByTagName('text:h') retorna todos os elementos de título e os adiciona numa lista junto com seu nível no documento. Em seguida, os títulos são escritos na tela com uma identação equivalente ao nível.

O exemplo deu nisso:

Título

Seção A

Subseção A.1
Subseção A.2
Subseção A.3

Seção B
Seção C

Subseção B.1
Subseção B.2

É bem simples, mas é preciso conhecer o formato, o que não é um problema já que este é claro e bem documentado. Contudo, acabei de achar uma biblioteca chamada odfpy, que quando tiver tempo vou dar uma olhada, mas já adianto que tem coisas como

from odf.opendocument import OpenDocumentText
from odf.style import Style, TextProperties
from odf.text import H, P, Span

…o que parece muito promissor.

Uma série de artigos que valem uma olhada é Dr. ODF: Examining OpenDocument Format with Python, na qual este post é inspirado. E qualquer dúvida sobre XML em Python veja o Capítulo 9 de Dive Into Python.

Arquivos:

Gerador de Glade Loaders para Python

Quando estou fazendo programa com gui usando Python + GTK, depois de desenhar a interface no Glade tenho de escrever o carregador, que é uma tarefa bem monótona. Daí escrevi uma utilitariozinho em Python que parseia um arquivo Glade e gera um script python para carregá-lo, associando widgets à variáveis e sinais à funções callback.

Fiz essa tela para um exemplo:

Exemplo de GUI

O arquivo originário é exemplo.glade, o nome da janela é janelaExemplo, os nomes das caixas de texto são nomeEntry e emailEntry, e o botão, chamado botao, ao receber um evento clicked chamará a função callback botao_pressionado.

Para gerar o código carregador basta passa o arquivo glade para o gladeloader.py e redirecionar a saída para um arquivo. Assim:

./gladeloader.py exemplo.glade > exemplo.py

Eis o exemplo.py gerado:

#!/usr/bin/python
#-*- coding:utf-8 -*-
import sys
try:

import pygtk
pygtk.require('2.0')
import gtk
import gtk.glade

except:

sys.exit(1)

class appWindow:

def __init__(self):

self.widgetTree = gtk.glade.XML('exemplo.glade')
#Get the Main Window, and connect the 'destroy' event
self.window = self.widgetTree.get_widget('janelaExemplo')

if (self.window):

self.window.connect('destroy', gtk.main_quit)

#Widgets -------
self.emailEntry = self.widgetTree.get_widget('emailEntry')
self.nomeEntry = self.widgetTree.get_widget('nomeEntry')

#Autoconnect Signals and Callbacks
self.widgetTree.signal_autoconnect(self)
self.window.show_all()

# Callbacks ---------------------------------------------------------------
def botao_pressionado(self, widget):

print 'botao_pressionado'

if __name__ == '__main__':

app = appWindow()
gtk.main()

Como deu pra perceber é um utilitário bem simples, não espere que ele escreva seu código, ele dá apenas ajuda a dar aquele pontapé inicial e espantar a preguiça.

Arquivos:

Update: colocar código-fonte no wordpress é um saco. Muito mesmo.

Padrões Abertos: OpenDocument vs OpenXML e o que a Dinamarca tem com isso?

Para todos os advogados de Software Livre que estejam passando, uma declaração: Padrões Abertos são mais importantes que Software Livre. Paciência, continue lendo e acabarei com seu ultraje Stallmaniano.

Primeiro, S.L. é feito de pessoas: deve haver um interesse de uma certa quantidade de usuários e programadores para que estes últimos queiram dispor de seu tempo para codificar as aplicações necessárias. Isso se traduz com as aplicações mais populares tendo maior quantidade de desenvolvedores (voluntários ou “doados” por empresas interessadas) do que as mais obscuras ou menos desejadas pelo público.

Suponhamos então que uma diversidade de negócios vêm usando uma aplicação proprietária para manipular seus dados (digamos documentos com aquela extensão, como é mesmo? .doc!) até que um belo dia surge uma aplicação com recursos satisfatórios a ponto de uma troca ser considerada. Apenas um problema: “e meus zilhares de documentos cruciais para meu negócio? Vou poder vê-los?” Se você está no negócio de migração para Linux (ou pelo menos para OpenOffice.org) então já ouviu isso milhares de vezes, e teve de explicar o que são formatos e suas diferenças (e o que significa uma compatibilidade de 90 e tantos por cento) o dobro de vezes, e o cliente compreendeu metade, sendo otimista.

É por isto que padrões abertos são mais importantes que, ou melhor seria dizer, tem precedência sobre, software livre. As pessoas só usarão software livre na medida que poderão continuar de onde pararam. Imagino que ninguém jamais migrou para Linux um escritório que usasse Autocad.

Estou tocando nesse assunto por causa da recente disputa entre os formatos para documentos de escritório, OpenDocument Format (ODF) e Microsoft OpenXML. O primeiro é um formato padronizado pela ISO, o segundo é a resposta da Microsoft à pressão de vários governos por clareza no armazenamento dos dados públicos, por exemplo, o estado americano de Massachussets declarou que só compraria aplicativos que usassem padrões abertos, apontando o ODF como preferido. Note bem que eles não disseram que desejavam usar software livre em detrimento de qualquer outro modelo de negócio, é apenas um caso do consumidor especificando como deseja seu produto.

Observando rápidamente você poderia até dizer que a Microsoft fez a lição de casa: garantiu que a documentação de seu novo formato seria aberto e financiou um plugin livre para conversão do ODF. Mas como diz minha mãe “quem não te conheça que te compre”, o plugin de conversão causa perdas de dados, e o formato, será mesmo aberto?

Um olhar ingênuo diria que basta a documentação técnica estar disponível para ser considerado um padrão aberto, mas a vida é mais complicada, certo? Veja esse comparativo das documentações técnicas dos dois formatos:

OpenDocument Format
700 páginas
3MB especificação
Reusa padrões existentes (como SVG e XLink).

MS OpenXML
4,000 páginas
24.4MB especificação
Reinventa a roda.

Além disso a especificação da Microsoft exige compatibilidade com seus formatos fechados anteriores, alguns com licenças restritivas. Existe uma página com as objeções ao OpenXML como padrão aberto: EOOXML objections. Na prática tudo isso significa que o OpenXML pode entrar nas licitações como formato aberto, mas na vida real continuaria sendo tão fechado quanto seus antecessores.

Sabe qual o ponto crucial da coisa toda? Definições. Como podemos julgar que um padrão é aberto, sem definirmos o que é um padrão aberto. Existem algumas definições com pontos em comum, mas vou falar aqui de uma definição dinamarquesa que cobre os pontos mais importantes. São eles:

  1. Ele é bem documentado com a especificação completa disponível publicamente.

  2. Ele pode ser implementado livremente sem limitações economicas, políticas ou legais sobre a implementação ou o uso.

  3. Ele é padronizado e mantido por um fórum aberto (também chamado “organização de padronização”) via um processo aberto.

O item 1 é o mais óbvio para o público, e com o qual a MS quer vender seu peixe. Com o item 2 a coisa complica: a MS se compromete a nunca usar suas patentes envolvendo o OpenXML contra implementações concorrentes? Não? Sim? Nada a declarar? Surpresa!!!

Mesmo que eles deixassem em aberto, criando assim aquele clima de medo, incerteza e dúvida, aliás, mesmo que eles se comprometessem a nunca processar nem mesmo um concorrente que esteja lhes comendo 60% de mercado, ainda resta a coisa mais querida da Microsoft ao longo de sua história: controle. Por isso o item 3 é o mais aterrorizante. Imagine que o OpenXML satisfaz os itens 1 e 2, e a concorrência está dando trabalho à Microsoft, qual a solução? Ora, passar 1 ano desenvolvendo e implementando a próxima versão do pardrão “aberto”, lançar o produto no mercado e deixar a concorrência lutando por 2 anos pra implementar a nova versão, ou ter seu produto taxado de incompatível.

Ponto para Dinamarca pela definição. E a conclusão desse artigo você mesmo tira. ;)

Update: traduzi a definição dinamarquesa e coloquei no site do CInLUG.
Outras referências:

The Diamond Age, breve!

The Diamond Age é um livro de Neal Stephenson sobre nano-tecnologia, educação infantil e choque de culturas, e pode apostar que é uma das melhores coisas de se ler. A maior parte da história se passa em Xangai, mas não na China, já que ela, assim como todos os outros estados nacionais, não existe na época em que se passa a história, em seu lugar temos a corrupta “República Costeira” e o ancestral e confunciano “Reino Celestial”.

Na Era do Diamante, ou você faz parte de uma tribo, ou dificilmente morrerá de velhice. E uma tribo não é aquele bando de Emos andando em shopping centers e vestindo as mesmas roupas, a tribo do Reino Celestial corresponde a população da China Continental, por exemplo. Os laços tribais podem consistir em partilhar da mesma filosofia e visão de mundo, como os neo-Vitorianos, líderes em nanotech, ou ser afinidades genéticas e históricas, como os Nipponeses, número dois em nanotech.

A história começa com um lorde neo-Vitoriano, Alexander Chung-Sik Finkle-McGraw, encomendando a John Percival Hackworth, Artifex de sua Majestade Rainha Victoria II, um livro para educar sua neta, melhor do que seus filhos foram educados, algo com um toque subversivo. Não um livro comum, é claro, todos acessam informação via papéis eletrônicos (que se dobram sozinhos, graças às nano-máquinas), este livro, “A Cartilha Ilustrada da Jovem Dama”*, deveria contar uma história fictícia, porém baseada em todos os acontecimentos da vida da menina, ao mesmo tempo que ensina sobre os mais diversos campos de conhecimento: alfabetização, artes marciais, etiqueta, astronomia, cozinha, máquinas de turing e, claro, nanotecnologia. A cartilha é capaz de conhecer o ambiente e mesmo os processos biológicos de quem estiver ao redor usando nano-sondas e integrar esses dados nas histórias com sua pseudo-inteligência. (Aparentemente na Era do Diamante eles desistiram do termo inteligência artificial.)

Outra idéia empolgante (para programadores, pelo menos) é o Compilador de Matéria (M.C.), capaz de materializar qualquer coisa criada pelos engenheiros nanotecnológicos, de cavalos robôs a computadores, até mesmo cartilhas… O caso é que o senhor Hackworth faz uma cópia ilegal da invenção que foi contratado para desenvolver para sua própria filha. Contudo, todos os compiladores tiram a matéria de uma fonte central, que denunciaria sua cópia imediatamente, e ele provavelmente seria expulso da tribo. Ele então recorre ao Dr. X, um mandarin do Reino Celestial que possui um rústico compilador com fonte própria. Na volta pra casa é atacado por uma gangue, a mando do Dr. X, que tinha interesse próprios na cartilha e no próprio Sr. Hackworth. Não reconhecendo o livro como um objeto de valor a gangue não percebe quando um dos membro guarda a cartilha.

Harv, dá a Cartilha a Nell, sua irmã de quatro anos, que passa a maior parte do tempo conversando com o livro, ouvindo suas histórias e aprendendo. No tempo restante ela e Harv são ignorados pela mãe e espancados pela sucessão de namorados truculentos.

No de correr da trama são levantadas questões sobre a superioridade de uma cultura sobre as outras, o que realmente funciona na educação de crianças, e como conhecimento e instrução podem mudar a vida de uma pessoa, embora em um dado momento a protagonista se veja numa situação onde a filiação a um grupo social teria sido sua melhor chance de segurança.

Para minha profunda felicidade e indescritível (e sua também, pode acreditar) fiquei sabendo que o SciFi Channel vai filmar The Diamond Age como série de 6 horas, com produção de George Clooney e roteiro do próprio Neal Stephenson, o que me deixa curioso, pois embora seus dialógos sejam muito bons, partes extensas do livro sejam descritivas, mas provavelmente várias páginas se tornarão cenas de 10 segundos.

Por que Era do Diamante, você pergunta? Ora, porque as Eras históricas costumam ser definidas pelos materiais que a raça humana é capaz de manipular. No começo do livro alguns personagens estão voando sobre o mar num luxuoso avião com chão de diamante, o mesmo diamante que qualquer pessoa poderia produzir nos compiladores de matéria caseiros que todos possuem.

Seek The Alchemist!

* Minha livre tradução para “The Young Lady Illustrated Primer”.

Cygwin, C, Python, SWIG, Wrappers & Sofrimento em Win32

Existem muitos tipos de sofrimento, e a disciplina do “Projetão” desse período está me trazendo uma grande variedade deles. Contudo, vou falar apenas do sofrimento de ser obrigado a ficar próximo do que é desagradável. Esse está representado pelo uso do Windows como S.O., já que o tablet PC que conseguimos pro projeto, assim como o cérebro de muitos professores desse centro, roda Windows.

Mas onde existe sofrimento, existe algum paleativo! O projeto usa as linguagens Python e C, e minha parte foi fazer a integração das duas, no sentido de Python chamando funções em C. Primeiro precisei exorcisar o ambiente: instalei o Cygwin, que me dá o direito de usar GCC, Make e um terminal bash perfeitamente funcional. Quando apertava CTRL+R pensava estar no gnome-terminal.

Pra tarefa de criar os wrappers Python sobre a lib em C usei o SWIG. É bem simples: você cria um arquivo.i, roda o SWIG que por sua vez gera um arquivo_wrap.c mais um arquivo.py (e várias outras linguagens), depois disso um Makefile pra criar as DLLs, aí você pode importar e aproveitar a alta performance de uma função em C. Meu problema é que compilava as DLLs e wrappers no Cygwin e quando o povo usava com o Python instalado no windows, ele pedia a libpython2.4.dll, e depois de copiada do /bin do Cygwin para o diretório onde seria usada, eu descobri que ela estava linkada com o cygwin1.dll, quando coloquei mais esse a aplicação travava para sempre e sempre.

Me informando melhor descobri que compilar coisas no Cygwin faz seu código precisar do runtime do bicho, que a princípio não é nada mal, já que ele emula umas posix-coisas legais. Mas estava sem saco pra ver descobrir qual o problema, possivelmente não relacionado com o Cygwin, além disso não tinha mais castanhas-do-pará então resolvi matar o cyg, ou melhor, suas DLLs. Descobri a diretiva do gcc -mno-cygwin, que evita o uso das dlls do cygwin, mas também nada mais estava compilando. Resolvido algumas horas depois, quando troquei o endereço dos includes e libs de Python, tirando os do cygwin (que estavam linkados com o cygwin1.dll) e colocando os da instalação de Python no Windows, em c:\Temp\Python24.

PYTHON_LIB_PATH = /cygdrive/c/Temp/Python24/libs
PYTHON_INC_PATH = /cygdrive/c/Temp/Python24/include

E a compilação de um dos DLLs ficou mais ou menos assim

gcc -c blah.c -mno-cygwin
gcc -c -I$(PYTHON_INC_PATH) blah_wrap.c -mno-cygwin
gcc -L$(PYTHON_LIB_PATH) -shared -mno-cygwin $(OBJS) -lpython24 -o _blah.dll

Referência:

Lógica de Predicados com Python

Ultimamente tenho me divertido revendo algumas coisas de lógica e no momento estou em predicados e quantificadores. Resolvi testar esses conceitos (de forma bem simples) usando Python, assim vou compartilhar minha idéia de diversão com o mundo.

Considere a frase “Marcelo dorme 4 horas por noite”, “Marcelo” é o sujeito e “dorme 4 horas por noite” é o predicado, a lógica de predicados expressa o predicado da afirmação como uma função proposicional onde uma variável representa o sujeito. Estabelecemos que P(x) significa “x dorme 4 horas por noite”, e podemos substituir x por qualquer sujeito, bem não qualquer sujeito e sim algum que esteja no universo de discurso, que nesse caso poderia ser “todos os alunos de computação”. A função P(x) pode ser verdadeira ou falsa, dependendo da qualidade de vida do aluno de computação que substituir x na função.

A outra parte são os quantificadores, que são o universal e o existencial. Usando a função P(x) e o universo de discurso declarados acima, com o quantificador universal posso afirmar que todos os alunos de computação dormem 4 horas por noite”, ou usar o existencial e afirmar que existe pelo menos um aluno de computação que dorme 4 horas por noite”. Para ser verdadeira a proposição quantificada universalmente precisa ser verdade para todos os casos do universo de discurso, já para a proposição quantificada existencialmente, basta que exista um caso verdadeiro para tornar verdadeira a proposição. Pelo menos essa semana posso afirmar que a segunda proposição é verdadeira, infelizmente. :-\

Agora vamos à programação. Em termos algorítmicos a verificação das proposições quantificadas é feita com um loop sobre os elementos do universo de discurso, se a proposição testada for quantificada universalmente o loop pára quando encontrar um resultado falso, que invalida a proposição, se for quantificada existencialmente, ele pára ao encontrar um resultado verdadeiro, que valida a proposição.

Vou usar um exemplo matemático pra facilitar. Considere a função P(x) significando

px

Em Python fica assim:

def P(x):
... return x**2 - 4*x <= 0

Vamos considerar o universo de discurso

xez4×5.png

Agora afirmo que

ax

que é lida como “para qualquer valor de x (dentro do universo de discurso) P(x) é verdadeira”. Ora, P(x) é falsa para x=-1, o que torna falsa a proposição de que P(x) é verdadeira para qualquer valor de x. Expresso logicamente para o universo de discurso declarado acima fica:

ands.png

A avaliação de “para todo” em Python:

def avaliaParaTodo(univ):
... res = True
... for x in univ:
...... res = res and P(x)
...... if not res:
......... return False
... return res

Daí testamos para o universo de discurso (usando range)

>>> avaliaParaTodo(range(-4,5))
False

Vejamos agora o existencial

ex

que é lida como “existe ao menos um valor de x para o qual P(x) é verdadeira”. Com apenas um caso verdadeiro, como x=2, provamos a veracidade da expressão. Também pode ser expresso como:

ors.png

Em Python:

def avaliaExiste(univ):
... res = False
... for x in univ:
...... res = res or P(x)
...... if res:
......... return True
... return res

Avaliando:

>>> avaliaExiste(range(-4,5))
True

Vamos mudar o universo de discurso um pouco, passando a usar o números naturais em lugar dos inteiros:

xen1.png

Agora o teste de ambos os casos, universal e existencial, resulta em verdade:

>>> avaliaParaTodo(range(0,5))
True

>>> avaliaExiste(range(0,5))
True

A coisa pode ficar mais elaborada com funções proposicionais com mais de um argumento, permitindo quantificações como “para todo x existe um y”, que algorítmicamente seria expressa com dois loops aninhados.

Depois disso tudo você pode querer mandar para sua namorada uma representação em lógica de predicados de “x ama y” ou algo assim. As mulheres adoram.

Referências:

Ah, e as fórmulas foram produzidas no OpenOffice.org Math