Planeta PythonBrasil

March 18, 2010

Flávio Coelho

Converting C code to Python

This may sound like a weird thing to do, but actually, I have craved for something like that every time I have to read C code. Converting C code to Python, can not only help us understand code more easily, but also turn non perfomance-critical code easier to maintain. C can be easy enough to read if well-written and formatted (indented) adequately, however having to move back and forth between .h

por Flavio Coelho (noreply@blogger.com) em 18 de March de 2010 às 12:37

Sidnei da Silva

Javascript Testing and Browser Speed

Just a quick post to get me started at blogging again.

Over the last year (wow, time flies by!) I’ve been working at Canonical, as part of the Landscape team. This is a very diverse team with lots of different skills, and somehow I found myself naturally gravitating towards working more closely on frontend-related issues, of which I could highlight writing YUI3 widgets, speeding up page loading experience and creating a nice testing infrastructure. There’s a ton of things I could write about that, and I really plan to. But today’s entry will be pretty short.

As part of a brain-break task I fixed some of our Javascript tests today so that they would run on Google Chrome. We haven’t been targeting Chrome so far, but that might change soon, driven by Google Analytics stats of people using Landscape.

But, the thing that really caught my attention was the difference in speed between Chrome and Firefox.

For comparison:

Google Chrome 5.0.307.7 beta

$ BROWSER=google-chrome ./bin/test -1vpc --layer=JsTestDriverLayer
Running tests at level 1
Running canonical.testing.javascript.JsTestDriverLayer tests:
Set up canonical.testing.javascript.JsTestDriverLayer in 1.020 seconds.
Running:

Ran 318 tests with 0 failures and 0 errors in 9.545 seconds.
Tearing down left over layers:
Tear down canonical.testing.javascript.JsTestDriverLayer in 0.366 seconds.

Firefox 3.6.3pre

$ BROWSER=firefox ./bin/test -1vpc --layer=JsTestDriverLayer
Running tests at level 1
Running canonical.testing.javascript.JsTestDriverLayer tests:
  Set up canonical.testing.javascript.JsTestDriverLayer in 1.014 seconds.
  Running:

  Ran 318 tests with 0 failures and 0 errors in 15.032 seconds.
Tearing down left over layers:
  Tear down canonical.testing.javascript.JsTestDriverLayer in 0.349 seconds.

Firefox 3.7a3pre

$ BROWSER=firefox-3.7 ./bin/test -1vpc --layer=JsTestDriverLayer
Running tests at level 1
Running canonical.testing.javascript.JsTestDriverLayer tests:
  Set up canonical.testing.javascript.JsTestDriverLayer in 0.804 seconds.
  Running:

  Ran 318 tests with 0 failures and 0 errors in 13.433 seconds.
Tearing down left over layers:
  Tear down canonical.testing.javascript.JsTestDriverLayer in 0.379 seconds.

Disclaimer: Both instances of Firefox were started with the “-safe-mode” flag, which disables all plugins and extensions. Also, as they say around here at Canonical: NOT A METRIC. But interesting still.

If you look closely at this post you might find some hints about things we’ve been working on and which I hope to write about, in addition to general tips and tricks about page speed optimization from experiences in both Landscape and Launchpad.


por Sidnei da Silva em 18 de March de 2010 às 02:30

March 17, 2010

Eduardo Willians

Como Instalar MongoDB no Ubuntu (para iniciantes)

Nem acredito que quebrei a cabeça olhando "how-to" por aí. Não é preciso, tem um pacote apt-get. É fácil.

$  sudo gedit /etc/apt/sources.list

Aberto o arquivo, acrescente a seguinte linha (para Ubuntu 9.10):
deb http://downloads.mongodb.org/distros/ubuntu 9.10 10gen

Se o seu Ubuntu é de outra versão substitua o "9.10" por "9.4" ou por "10.4"

Agora:

$  sudo apt-get update
$  sudo apt-get install mongodb-stable

Pronto!

INSTALANDO O PYMONGO

Primeiro, instale o setuptools caso já não tenha:

$ sudo apt-get install python-setuptools

Depois:

$  sudo easy_install pymongo

Enjoy!


ATUALIZAÇÃO (17/03/10): Alterado a forma de instalar pelo "apt-get". Desde de 5 de março não é mais válido o pacote por nome "mongodb". É preciso escolher entre "mongodb-stable", "mongodb-unstable" e "mongodb-snapshot" -- respectivamente o pacote estável, não-estável e o último git efetivado ao tempo da construção do pacote.

por Eduardo Willians (noreply@blogger.com) em 17 de March de 2010 às 22:41

Elcio Luiz Ferreira

O Linux também fala

Há um tempo eu ensinei aqui como fazer o Mac falar. O Linux também faz. Instala aí:

$ sudo apt-get install espeak

Daí é só mandar:

$ espeak "Luke, I am your father."

E fala português também:

$ espeak -v pt "Luke, eu sou seu pai."

Com -f arquivo.txt, ele lê o texto de um arquivo. Com -w arquivo.wav, ele salva o áudio num arquivo. E pode ser comandado via ssh.

Consegue imaginar utilidades para isso?


por Elcio em 17 de March de 2010 às 16:54

March 16, 2010

Marcos Petry

Boas práticas para um desenvolvedor Django - Parte1 - Evite Hardcodes!

Há um tempo atrás vi um post em um blog que dava algumas dicas para desenvolvedores Django iniciantes, bom aí vai a minha versão, em português, e com alguns comentários que acho interessantes.

Os posts estão ficando bem maiores do que eu imaginei, vou publica-los em partes, para iniciar série, a primeira parte:

Evite hardcodes
Primeiramente, se você não sabe o que é hardcode, clique aqui!

Hardcode no settings.py
É bem comum ver no código especialmente nas variáveis dos settings MEDIA_ROOT e TEMPLATE_DIRS utilizar o caminho absoluto de um diretório do sistema.

TEMPLATE_DIRS = ( "/home/html/project/templates",)
MEDIA_ROOT = "/home/html/project/appmedia/"

Esse tipo de prática dificulta a manutenção do sistema, especialmente quando o projeto está sendo migrado de um servidor para outro, ou simplesmente passando o projeto da máquina de desenvolvimento para a produção, sempre que uma mudança dessas é feita, é necessário alterar o conteúdo destas variáveis.

O ideal é, através do método os.path.realpath, pegar o endereço absoluto do arquivo settings.py, e a partir deste valor, incluir os endereços necessários, como é visto abaixo:

import os
SITE_ROOT = os.path.realpath(os.path.dirname(__file__))
MEDIA_ROOT = os.path.join(SITE_ROOT, 'appmedia')
TEMPLATE_DIRS = ( os.path.join(SITE_ROOT, 'templates'),)

Hardcode em templates
Nos templates, também é possível ver hardcodes nos caminhos de links, imagens, javascript e css.
Embora seja muito tentador (pois é mais rápido) utilizar este caminho, é bem melhor você utilizar a variável MEDIA_URL que foi declarada no settings.py, dentro do seu template. Como fazer isso? Adicione um context processor!

TEMPLATE_CONTEXT_PROCESSORS = ('django.core.context_processors.request',
"django.core.context_processors.auth",
"django.core.context_processors.debug",
"django.core.context_processors.i18n",
"django.core.context_processors.media"
)

Os Context processors, falando a grosso modo, adicionam itens dentro dos templates. Como visto acima, o Django possui uma série de processors, para as mais variadas funcionalidades (autenticação, debug, internacionalização, etc...)
O context processor django.core.context_processors.media adiciona uma variável nos templates chamada MEDIA_URL, ela possui o caminho especificado na constante MEDIA_URL do settings.py, dessa forma ao invés de chamar um css assim:

<img src="/site/midia/imagens/logo.jpg" />

você chama assim:

<img src="{{MEDIA_URL}}imagens/logo.jpg" />


Fica mais bonito? Talvez não, mas vai facilitar a sua manutenção! Isso vai :)

Hardcode em links
Vamos direto a um exemplo mais prático:
Digamos que você tem uma aplicação que exibe os seus produtos:

from django.conf.urls.defaults import *
urlpatterns = patterns('produtos.views',
(r'^$', 'inicio',),
(r'^cadastro/$', 'cadastro'),
(r'^(?P\d+)/$', 'detalhe'),
(r'^(?P\d+)/comprar/$', 'comprar'),
(r'^carrinho/$', 'carrinho'),
)

Até a versão 1.0 do Django o modo de exibir estas urls é colocando o endereço absoluto dela direto no template, algo como:

<a href="/produtos/">Lista</a> - <a href="/produtos/cadastro">Novo</a> - <a href="/carrinho/">Carrinho de compras</a>
<ul>{%for p in produtos%}
<li><a href="/produtos/{{p.id}}/">{{p.nome}}</a></li>
{%endfor%} </ul>

Mas, e se por algum motivo, a seção de produto não estiver em /produtos/ e sim em um outro endereço qualquer? Teremos que alterar "no braço" qualquer vestígio nos templates, caso contrário, enviaremos um erro 404 para o usuário!

Ainda bem, que após a versão 1.0 do Django possuímos urls nomeadas! dessa forma podemos construir nossas urls da seguinte maneira:

from django.conf.urls.defaults import *
urlpatterns = patterns('produtos.views',
url(r'^$', 'inicio', name='produto-home'),
url(r'^cadastro/$', 'cadastro', name='produto-novo'),
url(r'^(?P\d+)/$', 'detalhe', name='produto-exibe'),
url(r'^(?P\d+)/comprar/$', 'comprar', name='produto-compra'),
url(r'^carrinho/$', 'carrinho', name='produto-carrinho'),
)

Reparem que não possuímos mais uma tupla normal, e também foi adicionado um atributo "name" em cada url, cujo objetivo tem justamente nomear as urls, possuímos também uma templatetag chamada "url", que serve para pegar dinamicamente a nossa url {%url nome-da-nossa-url%}. Com este recurso, podemos construir nosso template da seguinte forma:

<a href="{%url produto-home %}">Lista</a> - <a href="{%url produto-novo %}">Novo</a> - <a href="{%url produto-carrinho%}">Carrinho de compras</a>
<ul>
{%for p in produtos%}
<li><a href="{%url produto-exibe p.id %}">{{p.nome}}</a></li>
{%endfor%} </ul>

Também podemos enviar parâmetros para a templatetag url, que foi o que fizemos para a listagem dos produtos. Para mais recursos sobre url nomeadas, acesse a documentação

Bônus: O Método get_absolute_url
No exemplo acima, vimos como listar objetos utilizando a tempaltetag url e passando o id do objeto por parâmetro, no entanto, esta não é uma das melhores práticas, o ideal seria você acrecentar o método get_absolute_url dentro da classe do seu model, como visto abaixo:

class Receita(models.Model):
data_publicacao = models.DateTimeField(auto_now_add=True)
nome = models.CharField(max_length=100)
categoria = models.ForeignKey(Categoria, null=True)
destaque = models.BooleanField(u"Destaque?")
class Meta:
ordering = ['-data_publicacao']
        get_latest_by = 'data_publicacao'
    def __unicode__(self):
return self.nome
    def get_absolute_url(self):
return reverse('produto-exibe', args=[self.id])

O método get_absolute_url retorna a url absoluta do objeto através da função reverse, que possui a mesma função da templatetag "url". Assim podemo listar os objetos de forma um pouco mais elegante:

<ul>
{%for p in produtos%}
<li><a href="{{p.get_absolute_url}}/">{{p.nome}}</a></li>
{%endfor%}
</ul>

Não é regra termos o método get_absolute_url, você pode criar qualquer outro método que faça a mesma função, mas o método get_absolute_url, é necessário para exibirmos no admin, um link para o objeto, como visto abaixo:



por Marcos Daniel Petry (marcospetry@gmail.com) em 16 de March de 2010 às 23:31

March 12, 2010

Gustavo Barbieri

Enlightenment meets BlueZ

In the past weeks ProFUSION coworker Gustavo Padovan was hacking on bluetooth support for Enlightenment ecosystem using the BlueZ stack.

Enlightenment powered and discoverable Bluetooth adaptor.

This module follows my previous ConnMan module and is built upon the same base. Since BlueZ and ConnMan are both developed by almost the same developer group, the DBus APIs are very similar. The current module is quite simple, yet useful and allows pairing devices. The idea is to further extend it to be a full Bluetooth Agent, allowing different authentication and authorization methods, maybe go even further and send files using the OBEX protocol.

Enlightenment powered but hidden Bluetooth adaptor.
Enlightenment popup menu with discovered devices.
Enlightenment bluetooth adapter controls.

The infrastructure is available as ebluez inside e_dbus, so it is easily accessible to all EFL applications. The infrastructure exposes just a handful methods that were required by the module, but it is easily extensible as most methods are similar and the helpers do most of work, just need to specify the method names and convert types.

ProFUSION is also working on oFono support. Stay tuned to see the module João Paulo is cooking, the e_dbus code is already in SVN.

por Gustavo Sverzut Barbieri em 12 de March de 2010 às 23:27

March 11, 2010

Eduardo Willians

(Orientação a Objetos).crítica_sobre( )

O que chamamos de objetos não podem ser considerados objetos na concepção humana, mas apenas na concepção da própria disciplina de programação.

Aliás, lembro que tive certa dificuldade no princípio de compreender o que era a tal iluminada OO porque se nos apresentavam uma explicação segundo a qual a OO se aproximava da concepção humana a respeito de objetos -- premissa que hoje considero parcialmente falsa.

Digamos que eu tivesse ganhado um caderno, mas não soubesse o que é. Então pegaria aquele caderno, e analisando ele como objeto, diria à pessoa que me presenteou: "legal, mas o que eu faço com isso?"

Intuitivamente procuramos alguma coisa para fazer com um caderno, ou, procuramos saber para que ele serve. Todavia, assim concebendo não se pode afirmar que os números seriam objetos no sentido da OO, vez que eles não fazem nada, e sim quem o faria seria o engenheiro que usa de procedimentos matemáticos para com os números.

Note a discrepância. A classe é "Matemática", o procedimento é "soma", e os instrumentos: os números. Quando muito poderíamos asseverar que os números são o objeto da classe matemática, o que nunca implicaria entender que invocaríamos a função "soma" para um número, ao contrário, o parâmetro número é que é passado para o procedimento "soma", a lógica é inversa à da OO.

O único fato da OO que se assemelha ao pensamento humano é a existência de atributos ligados a um objeto. Nesse aspecto, um caderno pode ser verde, pequeno, etc.

Sucede que atributos não podem ser funções de um caderno, pois ninguém que toma o caderno nas mãos requer dele que proceda à sua função "escrever", senão usando o procedimento "escrever" passa-lhe um "caderno".

De modo que não é o paradigma OO que é intuitivo, mas sim o procedural, razão até pela qual um iniciante costuma ter mais facilidade em lidar com funções que com classes e métodos.

A grande idéia da OO é atar a um objeto tudo o que se pode obter dele: desde seus atributos até os procedimentos aplicáveis a ele. É como se um objeto já soubesse o que ele tem, o que ele pode fazer e quais as suas funções. Observe-se, contudo, que saber o que é, o que tem e o que pode fazer é muito mais a característica de um ente consciente que a de um objeto.

Com efeito, seria mais coerente descrever a OO como a orientação a "entes conscientes", já que estão cientes de seus atributos e de suas funções.

Não obstante, o paradigma OO representou um grande avanço na programação, porque realizou que dentro de um universo bastante limitado de possibilidades é mais fácil atrelar atributos e métodos a um ente consciente do que tentar atrelar objetos a centenas de rotinas inconscientes.

Assim, nos parece mais desejável que, p.ex., em Python a função "max( )" fosse um método, pois embora intuitivamente se use primeiro o procedimento max( ) e depois o objeto "list", seria mais simples verificar que um objeto "list" detém a função "max( )", mesmo que "max( )" fosse o mesmo nome para funções semelhantes ligadas a "str" e a "tuple".

De outra lado, não nos parece razoável exigir exclusivamente o uso do paradigma OO. Ele deve ser preponderante, no entanto haverá ocasiões em que um conjunto de funções será mais funcional (por assim dizer), daí uma ampla vantagem de Python que permite o multi-paradigma, mas isso já é outra conversa.

por Eduardo Willians (noreply@blogger.com) em 11 de March de 2010 às 13:48

March 10, 2010

Elton Luís Minetto

Contabilizar espaço usado em FTP usando Python

Aqui na empresa temos duas contas de FTP contratadas no nosso plano de hospedagem para usarmos como espaço de backup. As duas contas tem um espaço limitado e toda semana eu preciso monitorar quanto espaço estamos usando, para evitar erros no script de backup. Para facilitar esse controle eu criei um pequeno script Python para navegar em todas as pastas e me dizer quanto espaço estou usando. O script ficou assim:

  1. import os
  2. from ftplib import FTP
  3.  
  4. def pretty_filesize(bytes):
  5.  if bytes >= 1073741824:
  6.   return str(bytes / 1024 / 1024 / 1024) + ' GB'
  7.  elif bytes >= 1048576:
  8.   return str(bytes / 1024 / 1024) + ' MB'
  9.  elif bytes >= 1024:
  10.   return str(bytes / 1024) + ' KB'
  11.  elif bytes < 1024:
  12.   return str(bytes) + ' bytes'
  13.  
  14. endereco_ftp = 'servidor'
  15. usuario = 'usuario'
  16. senha = 'senha'
  17. conexao_ftp = FTP(endereco_ftp)
  18.  
  19. conexao_ftp.login(usuario,senha)
  20. diretorio_corrente = conexao_ftp.pwd()
  21. soma = 0
  22. for i in conexao_ftp.nlst():
  23.  conexao_ftp.cwd(i)
  24.  for j in conexao_ftp.nlst():
  25.   soma = soma + conexao_ftp.size(j)
  26.  conexao_ftp.cwd('..')
  27.  
  28. print pretty_filesize(soma)

Agora é só colocar no crontab e receber diariamente o espaço utilizado.
Fontes:
http://www.vivaolinux.com.br/script/navegador-ftp
http://code.rivers.pro/python-function-to-convert-bytes-to-kbmbgb/

por elm em 10 de March de 2010 às 14:34

March 09, 2010

Gustavo Niemeyer

Recovering a bootable EBS image

Scott Moser has just announced this week that the new Ubuntu images which boot out of an EBS-based root filesystem in EC2, and thus will persist across reboots, are available for testing.

As usual with something that just left the oven and is explicitly labeled for testing purposes, there was a minor bug in the first iteration of images which was even mentioned in the announcement itself. The bug, if not worked around as specified in the announcement, will prevent the image from rebooting.

Having an bootable EBS image which can’t reboot is a quite interesting (and ironic) problem. You have an image which persists, but suddenly you have no way to see what is inside the image anymore because you can’t boot it. Naturally, even if the said bug didn’t exist in the first place, it’s fairly easy to get into such a situation accidentally if you’re fiddling with the image configuration.

So, in this post we’ll see how to recover from a situation where a bootable EBS image can’t boot.

Getting started

To start this up, we’ll boot one of the EBS images which Scott mentioned in his announcement: ami-8bec03e2. As we see in the output of ec2-describe-images, this is an EBS-based image for i386:

% ec2-describe-images ami-8bec03e2
IMAGE ami-8bec03e2 099720109477/ebs/ubuntu-images-testing/ubuntu-lucid-daily-i386-server-20100305 099720109477 available public i386 machine aki-3fdb3756 ebs
BLOCKDEVICEMAPPING /dev/sda1 snap-f1efd098 15

Let’s run this image. Remember to replace the value passed in the -k command line option with your own key pair name.

% ec2-run-instances -k gsg-keypair ami-8bec03e2
RESERVATION r-9e4615f6 626886203892 default
INSTANCE i-e3e33a88 ami-8bec03e2 pending gsg-keypair 0 m1.small 2010-03-09T20:04:12+0000 us-east-1c aki-3fdb3756 monitoring-disabled ebs

There we go. We got an instance allocated in the availability zone us-east-1c. It’s important to keep track of this information, since EBS volumes are zone-specific.

As part of the above command, we must have been allocated an EBS volume automatically, and it should be attached to the instance we just started. We can investigate it with the ec2-describe-volumes command:

% ec2-describe-volumes
VOLUME vol-edca1684 15 snap-f1efd098 us-east-1c in-use 2010-03-09T20:04:20+0000
ATTACHMENT vol-edca1684 i-e3e33a88 /dev/sda1 attached 2010-03-09T20:04:24+0000

Now, we’ll get into the running instance and do some arbitrary modifications, just as a way to demonstrate that the data we don’t want to lose actually survives the recovering operation. Note that the domain name is obtained with the ec2-describe-instances command.

% ssh -i ~/.ssh/id_dsa_gsg-keypair ubuntu@ec2-184-73-51-147.compute-1.amazonaws.com
(…)

ubuntu@domU-12-31-39-0E-A0-03:~$ echo “Important data” > important-data
ubuntu@domU-12-31-39-0E-A0-03:~$ ls -l important-data
-rw-r–r– 1 ubuntu ubuntu 15 Mar 9 20:15 important-data

ubuntu@domU-12-31-39-0E-A0-03:~$ sudo reboot
Broadcast message from ubuntu@domU-12-31-39-0E-A0-03
(/dev/pts/0) at 20:18 …
The system is going down for reboot NOW!

Note that we didn’t actually fix the problem reported by Scott, so our machine won’t really reboot. If we wait a while, we can even see that the problem is exactly what was reported in the announcement (note it really takes a bit for the output to be synced up):

% ec2-get-console-output i-e3e33a88 | tail -4
mount: special device ephemeral0 does not exist
mountall: mount /mnt [294] terminated with status 32
mountall: Filesystem could not be mounted: /mnt

Alright, now what? Machine is dead.. and can’t reboot. How do we get to our important data?

Fixing the problem

The first thing we do is to stop the instance. Do not terminate it, or you’ll lose the EBS volume! After stopping it, we’ll detach the EBS volume that was being used as the root filesystem, so that we can attach somewhere else.

% ec2-stop-instances i-e3e33a88
INSTANCE i-e3e33a88 running stopping

% ec2-detach-volume vol-edca1684
ATTACHMENT vol-edca1684 i-e3e33a88 /dev/sda1 detaching 2010-03-09T20:04:22+0000

Now, we need to attach this volume in an image which actually boots, so that we can fix it. For this experiment, we’ll pick one of the daily Lucid images, but we could use any other working image really. Just remind that the image must be running in the same availability zone as our previous instance, since the EBS volume won’t be accessible otherwise.

% ec2-run-instances -k gsg-keypair -z us-east-1c ami-b5f619dc
RESERVATION r-967427fe 626886203892 default
INSTANCE i-fd08d196 ami-b5f619dc pending gsg-keypair 0 m1.small 2010-03-09T21:10:11+0000 us-east-1c aki-3fdb3756 monitoring-disabled instance-store

% ec2-attach-volume vol-edca1684 -i i-fd08d196 -d /dev/sdh1
ATTACHMENT vol-edca1684 i-fd08d196 /dev/sdh1 attaching 2010-03-09T21:10:51+0000

With the instance running and the EBS root device attached with an alternative device name, we can then login to fix the original problem which prevented the image from booting correctly. In our case, we’ll simply do what Scott suggested in the announcement.

% ssh -i ~/.ssh/id_dsa_gsg-keypair ubuntu@ec2-204-236-194-196.compute-1.amazonaws.com
(…)
$ mkdir ebs-root
$ sudo mount /dev/sdh1 ebs-root
$ sudo sed -i ’s/^ephemeral0/#ephemeral0/’ ebs-root/etc/fstab
$ sudo umount ebs-root
$ logout
Connection to ec2-204-236-194-196.compute-1.amazonaws.com closed.

Done! Our EBS volume is now correct, and it should boot alright. We’ll detach the volume from the temporary instance we created, and will reattach it back to the old bootable EBS instance which is stopped. Note that we won’t yet terminate the temporary instance, because we may need it in case something else is still wrong, and we are already paying to use it for the hour anyway. We just have to remind ourselves to terminate it once we’re fully done.

% ec2-detach-volume vol-edca1684
ATTACHMENT vol-edca1684 i-fd08d196 /dev/sdh1 detaching 2010-03-09T21:10:51+0000

% ec2-attach-volume vol-edca1684 -i i-e3e33a88 -d /dev/sda1
ATTACHMENT vol-edca1684 i-e3e33a88 /dev/sda1 attaching 2010-03-09T21:24:55+0000

% ec2-describe-volumes vol-edca1684
VOLUME vol-edca1684 15 snap-f1efd098 us-east-1c in-use 2010-03-09T20:04:20+0000
ATTACHMENT vol-edca1684 i-e3e33a88 /dev/sda1 attached 2010-03-09T21:24:55+0000

Okay! It should all be good now. It’s time to restart our instance, and see if it is working. Note that since you stopped and started the instance, the public domain name most probably has changed, and thus we need to find it out again with ec2-describe-instances once the instance is running.

% ec2-start-instances i-e3e33a88
INSTANCE i-e3e33a88 stopped pending

% ec2-describe-instances i-e3e33a88
RESERVATION r-9e4615f6 626886203892 default
INSTANCE i-e3e33a88 ami-8bec03e2 ec2-184-73-72-214.compute-1.amazonaws.com domU-12-31-39-03-B8-21.compute-1.internal running gsg-keypair 0 m1.small 2010-03-09T21:28:43+0000 us-east-1c aki-3fdb3756 monitoring-disabled 184.73.72.214 10.249.187.207 ebs
BLOCKDEVICE /dev/sda1 vol-edca1684 2010-03-09T21:24:55.000Z

% ssh -i ~/.ssh/id_dsa_gsg-keypair ubuntu@ec2-184-73-72-214.compute-1.amazonaws.com
(…)
$ cat important-data
Important data

$ logout
Connection to ec2-184-73-72-214.compute-1.amazonaws.com closed.

It worked, and our important data is still there!

Don’t forget to kill the temporary instance you’ve used to fix it after you’re comfortable with the result:

% ec2-terminate-instances i-fd08d196
INSTANCE i-fd08d196 running shutting-down

Conclusion

Concluding, in this post we have seen how to fix a bootable EBS machine which can’t actually boot. The technique consists of detaching the volume from the stopped instance, attaching it to a temporary instance, fixing the image, and then reattaching it back to the original image. This back and forth of EBS volumes is quite useful in many circumstances, so keep it in your tool belt.

por Gustavo Niemeyer em 09 de March de 2010 às 21:45

March 08, 2010

Inno::Blog

Armadilha de Arco-Íris e o futuro da computação

Em 2007 dois pesquisadores britânicos teorizaram um dispositivo que eles chamaram de  ”alçapão de arco-íris”, sendo um dispositivo composto por uma lenteque seria responsável pela reflexão, dispersão e refração de um feixe de luz para o interior do artefato que teria uma  placa com várias camadas de espelhos de metamateriais que poderia capturar o feixe de luz, não permitindo sua dispersão:

Stopping light in metamaterials: the trapped rainbow

Na época vários grupos ao redor do mundo, acreditando na teoria trabalharam alucinadamente tentando criar um protótipo funcional deste dispositivo e no final de 2009 um grupo de pesquisadores americanos conseguiu obter sucesso e com um aparato muito simples provaram o conceito da “armadilha de arco-íris”, demonstrando que os físicos britânicos estavam certos:

Rainbow trapped for the first time

Quando comentei este feito com um colega pela primeira vez, logo que via a notícia na semana que ela foi publicada na New Scientist, ele fez aquele clássico comentário: este pessoal não tem nada mais importante para fazer?

Bem, esta técnica poderá ser útil para armazenar informações de forma puramente ótica, algo que irá revolucionar a computação (e talvez a vida) no futuro, eliminando a necessidade de conversões de sinais óticos em eletrônicos, facilitando o processo de  manipulação de fótons e proporcionando a criação de  meios de armazenamento de informações revolucionário. E considerando que em 2009 também surgiu o primeiro processador quântico fotônico autêntico podemos elucubrar que parte do futuro da computação está na fotônica e esta nova descoberta é certamento um grande marco.

Quer algo mais útil do que isto? :-)

Ruminando e divagando sobre este assunto com um amigo este final de semana, ele lembrou do filme Minority Report e de um cartão  de armazenamento que parecia que as imagens estavam armazenadas de modo fotônico, visto que elas podiam ser parcialmente vistas sem mesmo estar no seu respectivo driver de leitura.

Com a evolução das pesquisas do grafeno, dos metamateriais e outros daqui a alguns anos silício será coisa do passado, se bobear armazenamento magnético também e por consequencias do entrelaçamento quântico a velocidade da luz irá parecer velocidade tartarugal, imaginou como será a computação e o futuro das telecomunicações?

No final de 2008, escrevi um post onde eu brincava que em 2050 “telepatia sintética” seria coisa do passado, bom, o DARPA tem financiado pesquisas nesta área e isto da tem a ver com ESP, visto que a tecnologia é puramente baseada em neurociência e telecomunicações, sendo-se que o artefato que possibilitará tal feito é puramente um dispositivo de neuroengenharia, área que tende a evoluir muito no futuro e aposto que vários dos “neuroengenheiros” serão nascerão a partir do fascínio pelos brinquedos Mindflex e o Star Wars Force Trainer.

Mas o quê a armadilha de arco-íris e a q-telepatia tem em comum? A resposta é: computação quântica. A neuroengenharia continuará presente, porém o processador quântico será peça fundamental.

E breve, os neurohackers já não serão mais atores da ficção cyberpunk e sim do novo contexto neurotecnológico do balaio de gato que será o admirável mundo novo da computação, fico imaginando a segunda (ou será terceira?) geração que será os q-neurohackers.


por techberto em 08 de March de 2010 às 02:27

March 07, 2010

Ricbit

Mais mágicas com calculadoras

Quando eu era criança, a mágica que eu mais gostava era aquela onde o ilusionista serra a assistente ao meio. Acho que a graça era tentar entender como ele fazia aquilo, levei um tempão para descobrir o truque. Usando uma calculadora também temos um truque parecido, mas ao invés de serrar uma assistente, vamos cortar um número em dois!


Para começar essa mágica, peça para a criança digitar o número mágico 142857 na calculadora:


Agora peça para que ela multiplique esse número por dois:


Olha só! Você cortou o número ao meio e juntou as partes ao contrário, 14-2857 virou 2857-14!

Agora peça para ela digitar novamente o número mágico e multiplicar por três:


Ahá! Novamente você cortou o número ao meio, 1-42857 virou 42857-1.

Você pode continuar a mágica a partir daqui, esse truque funciona com todos os múltiplos até 6:

142857 * 1 = 142857
142857 * 2 = 285714
142857 * 3 = 428571
142857 * 4 = 571428
142857 * 5 = 714285
142857 * 6 = 857142

Aparentemente, a parte díficil desse truque é memorizar o número mágico. Quando você está cercado de crianças barulhentas, não é fácil lembrar 142857! Mas, felizmente, você não precisa decorar o número. É só lembrar que ele é a dizíma periódica de 1/7, e você pode usar a própria calculadora para calcular a dízima:

1/7 = 0.142857142857142857...

A pergunta natural é: tem outras dízimas com essa propriedade, ou o 142857 é especial? Espantosamente, existem sim outros números. Eles tem até nome: são os números cíclicos. Para achar esses outros números, vale a pena entender porque o 1/7 funciona, e para isso é só observar o comportamento da dízima no algoritmo de divisão longa:


Você começa dividindo o número 1, e sempre que o resto é menor que 7, coloca um zero atrás e continua. Note que, quando você divide por 7, só tem sete restos possíveis: 0, 1, 2, 3, 4, 5 e 6. Se o resto for zero em algum momento, a divisão acaba e o resultado é exato. Mas se em algum momento o resto repetir, ou seja, for igual a algum resto que já apareceu antes, então você tem uma dízima.

Os números cíclicos são formados por divisões de período máximo. Como você nunca pode ter um zero de resto, então no caso da dízima de 7, o maior período possível seria seis (felizmente é o caso). Você começa com o resto 1, e quando chega no 1 de novo começa a repetir, como no diagrama abaixo:


Veja como agora dá pra entender porque os números cíclicos funcionam: 142857 é a dízima de 1/7. Se a gente multiplicar 1/7 por dois, teremos 2/7, e a dízima tem que ser o dobro também. Mas se você olhar no diagrama, multiplicar por dois é a mesma coisa que começar a percorrer o diagrama a partir do 2, ao invés de começar no 1. Mas não importa de onde você começa, a seqüência será sempre a mesma, e daí o resultado vai ser uma rotação da dízima original!


Sabendo que os números cíclicos são as dízimas de período máximo, já dá pra começar a procurar propriedades desses números. Quais números, além do 7, geram dízimas de período máximo?

A primeira coisa que a gente nota é que esses números precisam ser primos. O raciocínio é relativamente simples. Vamos chamar esse número que procuramos de k, e fazer a divisão longa de 1 por k. Os restos da divisão longa formam uma recorrência, onde o primeiro termo é 1, e para os seguintes você coloca um zero no final e acha o resto da divisão por k:

R[0] = 1
R[n] = 10*R[n-1] (mod k)

Essa recorrência dá pra resolver de cabeça:

R[n] = 10n (mod k)

Para termos uma dízima de período máximo, o resto precisa ser 1 novamente quando n=k-1, ou seja:

R[k-1] = 10k-1 = 1 (mod k)

Agora, do teorema de Euler-Fermat, nós sabemos que:

10φ(k) = 1 (mod k)

Onde φ(k) é a função totiente. Ora, nós sabemos que, quando k é composto, o totiente é sempre menor que k-1, então k não pode ser composto, e portanto é primo.

Certo, então k precisa ser primo, mas qualquer primo serve? Nope. Tem alguns primos que não funcionam, como por exemplo onze. No caso do 11, é verdade que 1010 deixa resto 1, mas logo 102 já tem resto 1 também, então a dízima é muito mais curta que gostaríamos.

Na verdade, o segredo desses primos que funcionam é que... hum... ninguém sabe qual o segredo. Esse é um problema em aberto. Na verdade, a coisa é tão feia que ninguém sabe nem mesmo se esses primos são finitos ou infinitos. O melhor que podemos fazer é um script que ache os primeiros deles:

Script em python que acha os primeiros números cíclicos

Depois do sete, o primeiro primo que funciona é o 17, e o número cíclico associado é 0588235294117647. Note que esse é um caso onde o zero à esquerda faz diferença! Se a sua calculadora tiver um visor bem grande, dá pra divertir uma criança por um tempão com esse número :)

por noreply@blogger.com (Ricardo Bittencourt) em 07 de March de 2010 às 03:00

March 05, 2010

Kodumaro

Python é capa da TIdigital de Março

Gente,

Segunda-feira todo mundo correndo pras bancas!
TIdigital Março

Em março, Python em foco na revista TIdigital.

Fonte: PythOn Rio.

[]’s
Cacilhας, La Batalema

por noreply@blogger.com (Cacilhας, La Batalema) em 05 de March de 2010 às 18:23

Eduardo Willians

MongoDB é Magnífico!

Pretendia esperar esperar mais uns dias para postar com mais profundidade, mas estou tão deslumbrado com Mongo que vou postar com apenas dois dias de estudo.

Veja-se só as possibilidades, em Mongo podemos:

  • Armazenar diversos objetos/tipos nativos de Python como: int, float, datetime.datetime, list, unicode.
  • Uma vez que ele é "orientado a documentos", ficamos livres de necessariamente criar schemas, mas eles podem ser criados.
  • Pode-se armazenar documentos sem termos que definir tamanho máximo, de modo que facilmente é possível criar registros que contenham arquivos inteiros.
    • A abordagem é tão diferente que nem é necessário criar uma "tabela", basta denominar as chaves e depois determinar valores para elas.
  • Podemos acrescentar "campos" sem sofrer para definir novas regras.
  • O mais extraordinário sobre as regras de consistência / relacionamento / estruturação:
    • Como SQL, podemos criar "referências".
    • Como OO, podemos criar registros HERDADOS com simplicidade. Você pode acreditar nisso????
    • Como OO "Plus", podemos criar documentos EMBEDEDD com facilidade. Incrível!


Quando vi que era possível criar classes-documentos-filhos e também classes-documentos-embededd com consistência e naturalidade fiquei impressionado. Isso vai facilitar nossas vidas. Basta olhar aqui para ver.

Aliás, com tanto tempo no modelo SQL eu tive certa dificuldade no primeiro momento de imaginar outra modelagem de dados.

A propósito, estou usando um ORM para Mongo chamado "mongoengine" que roda em cima do pymongo.

INSTALANDO MONGOENGINE

$ sudo easy_intall mongoengine

Grato ao La Batalema sobre os posts de MongoDB.

por Eduardo Willians (noreply@blogger.com) em 05 de March de 2010 às 13:56

March 03, 2010

Ricbit

Mágicas com calculadoras

Tem um diálogo que sempre acontece quando vou visitar algum amigo que tenha filho pequeno. Eu sou apresentado pelo amigo como "o Ricbit, aquele amigo que gosta de Matemática". Aí a criança, espantada, responde "mas como assiiiiiim ele gosta de Matemática?!". E o amigo responde "ah, mas matemática com o tio Ricbit é divertida. Mostra pra ele, Ricbit!". E aí eu, que nem cheguei direito, já estou com a batata quente na mão!

Felizmente, eu já descobri alguns truques pra lidar com situações assim. Se a criança ainda está na fase de achar que matemática é aritmética, então uma abordagem que funciona bem é pedir uma calculadora emprestada,e falar que você vai usá-la pra fazer mágicas.


Uma das mágicas clássicas funciona assim:

1. Primeiro você pede pra criança digitar 13837, que é um número mágico.


2. Depois, você pergunta quantos anos tem o pai dela, e fala pra ela multiplicar aquele número mágico pela idade do pai. Digamos que o pai tem 42 anos, então o resultado será 581154.


3. Por fim, você fala pra criança multiplicar esse número que está no visor por outro número mágico, 73.


Surpresa! O resultado é 42424242, a idade do pai repetida até encher o visor da calculadora! Crianças adoram isso, eu imagino que o motivo é uma variação da Lei de Clarke. A criança não entende porque isso aconteceu, e qualquer conta suficientemente incompreensível é indistinguível de magia. (Pensando bem, isso funciona com estudantes de engenharia também).

O truque funciona com qualquer valor de idade, é claro. O motivo é simples: se você multiplicar os dois números mágicos, 13837*73 resulta em 1010101. Qualquer número de dois dígitos fica replicado quatro vezes quando você multiplica por 1010101. O ilusionismo do truque é que o par de números mágicos obfusca esse valor.

A pergunta natural nesse caso é: dá pra fazer a mágica com cinco repetições? Seis? Quantas eu quiser?

Isso só é possível se o número 101...01 não for primo. Sendo composto, você sempre pode separar os fatores em dois números mágicos. Vamos fazer um teste rápido. Para duas repetições não dá, 101 é primo. Para três repetições temos 259 e 39, para cinco temos 372731 e 271. Usando o Wolfram Alpha, dá pra checar manualmente que acima de duas repetições todos os números parecem compostos. Mas dá pra provar isso?

Eu achei que esse seria um problema complexo, mas acabou sendo mais fácil do que eu esperava! A prova pode ser feita só com matemática elementar. Suponha que o número que queremos fatorar gera n repetições, então ele pode ser escrito como a soma de uma progressão geométrica finita:



Se você notar que 100n é o mesmo que 102n, então dá pra fatorar o numerador como diferença de quadrados:



Agora é só notar que, para n>2, os dois termos do numerador são bem maiores que 99, então nenhum deles simplifica completamente. Daí, o valor final sempre vai ter pelo menos dois fatores, o que completa a demonstração.

Ainda tem um monte de mágicas que podem ser feitas com calculadoras, mas essas ficam para posts futuros :)

(Obrigado ao Jacques Brancher e ao Fábio Moreira pelas idéias.)

por noreply@blogger.com (Ricardo Bittencourt) em 03 de March de 2010 às 01:27

March 02, 2010

Marco André Lopes Mendes

March 01, 2010

Elcio Luiz Ferreira

utf8_decode em Javascript

Navegando por aí, acabei esbarrando no blog do meu amigo Marcos Rossow (nossa, quanto tempo!)

E encontrei esse post: JavaScript UTF-8 Decode, com um código tirado daqui: JavaScript utf8_decode.

Tem duas coisas que me incomodam nessa abordagem. A primeira é essa mania que muita gente tem, particularmente programadores PHP, de tratar UTF-8 como um "código alienígena" e ISO-8859-1 como normal e padrão. Alô, ISO-8859-1 é usado por parte do mundo. Não dá para escrever hebraico, mandarim, japonês, árabe ou russo com isso. ISO-8859-1 é uma das diversas tabelas de caracteres que existem mundo afora. E Unicode é a única maneira sensata de escrever um sistema que possa ser usado aqui e na China.

A segunda coisa que me incomoda é a quantidade de código. Não testei profundamente, mas tenho a impressão de que o código abaixo resolve o problema:

function utf8_decode(t){
return decodeURIComponent(escape(t))
}


por Elcio em 01 de March de 2010 às 15:40

February 27, 2010

Kodumaro

MongoDB

Logo Há atualmente na Computação uma onda de adoção de bancos de dados não-relacionais, comumente chamados NoSQL.

O foco principal dos bancos NoSQL atuais é a orientação a documentos, uma variação hash da orientação a objetos e alternativa aos RDBMSs, que dominaram a orientação dos gerenciadores de banco de dados por décadas.

O principal banco NoSQL é o CouchDB, DBMS do Projeto Apache baseado em Erlang, porém há uma alternativa bem mais simples e aparentemente tão poderosa quanto: MongoDB.

MongoDB combina os melhores funcionalidades de orientação a documentos, hashes e RDBMSs. É um banco de dados orientado a documentos, escalável, livre de esquema, de alto desempenho e código aberto escrito em C++.

Este artigo dá continuidade ao artigo nas Reflexões de Monte Gasppa e Giulia C. sobre a instalação do MongoDB. Aqui você poderá ver um pouquinho do uso de um banco de dados orientado a documentos.

Este artigo é baseado na documentação oficial e entende que você instalou o MongoDB segundo descrito nas Reflexões de Monte Gasppa e Giulia C..

Conexão na base de dados


Para conectar na base basta usar o comando mongo:
bash$ mongo
MongoDB shell version: 1.2.2
url: test
connecting to: test
type "help" for help
>


Caso você tenha configurado uma porta alternativa em /srv/mongodb/etc/mongodb.conf, você pode especificar isso na linha de comando do cliente:
bash$ mongo --port 27018


Você também pode se conectar a um servidor remoto, caso ele esteja habilitado para conexão externa, usando a flag --host.

Para escolher qual base de dados usar, o comando é use:
> use mydb


Autorização


Você pode se autorizar na linha de comando com as opções -u (usuário) e -p (senha), ou já do prompt do interpretador:
> use admin
> db.auth('admin', 'ra35EG/dz');


Comandos básicos


A linguagem de interação com MongoDB é Javascript, mas há alguns comandos úteis no interpretador.

Para listar comandos úteis:
> help


Listar recursos uteis da base atual:
> db.help();


Listar recursos uteis de uma coleção (levemente equivalente a tabela de um banco relacional), no exemplo foo:
> db.foo.help();


Para listar as bases instaladas:
> show dbs


Para listar as coleções da base atual:
> show collections


Listar usuários da base atual:
> show users


Criar usuário na base atual:
> db.addUser('admin', 'ra35EG/dz');


Autenticar-se:
> db.auth('admin', 'ra35EG/dz');


Listar o conteúdo de uma coleção:
> db.foo.find();


Apagar uma coleção:
> db.foo.drop();


Apagar a base de dados atual:
> db.dropDatabase();


Armazenamento de dados


Repare que o MongoDB é livre de esquema, portanto uma coleção pode conter estruturas de dados radicalmente diferentes, sempre no formato JSON.

Por exemplo, vamos inserir dois dados distintos na coleção foo da base mydb:
> use mydb
> var j = { name: 'mongo' };
> var t = { x: 3 };
> db.foo.save(j);
> db.foo.save(t);
> db.foo.find();
{ "_id" : ObjectId("4b8949d9cd50237b8573833b"), "name" : "mongo" }
{ "_id" : ObjectId("4b8949dbcd50237b8573833c"), "x" : 3 }


Você não precisa predefinir a coleção, que é criada automaticamente no salvamento da primeira estrutura. O campo _id é criado automaticamente e é a chave primária.

Para apagar o objeto j:
> j = db.foo.findOne({ name: 'mongo' });
> db.foo.remove(j);


Para apagar todos os objetos basta remover a coleção:
> db.foo.drop();


Vamos usar um pouco mais de lógica:
> for (var i=0; i<100; ++i) db.foo.save({ x: i, y: i*i });


Esse loop cria cem registros, com x variando de zero a noventa e nove e y igual a seu quadrado:
> db.foo.find();
{ "_id" : ObjectId("4b894c05cd50237b8573833e"), "x" : 0, "y" : 0 }
{ "_id" : ObjectId("4b894c05cd50237b8573833f"), "x" : 1, "y" : 1 }
{ "_id" : ObjectId("4b894c05cd50237b85738340"), "x" : 2, "y" : 4 }
{ "_id" : ObjectId("4b894c05cd50237b85738341"), "x" : 3, "y" : 9 }
{ "_id" : ObjectId("4b894c05cd50237b85738342"), "x" : 4, "y" : 16 }
{ "_id" : ObjectId("4b894c05cd50237b85738343"), "x" : 5, "y" : 25 }
{ "_id" : ObjectId("4b894c05cd50237b85738344"), "x" : 6, "y" : 36 }
{ "_id" : ObjectId("4b894c05cd50237b85738345"), "x" : 7, "y" : 49 }
{ "_id" : ObjectId("4b894c05cd50237b85738346"), "x" : 8, "y" : 64 }
{ "_id" : ObjectId("4b894c05cd50237b85738347"), "x" : 9, "y" : 81 }
{ "_id" : ObjectId("4b894c05cd50237b85738348"), "x" : 10, "y" : 100 }
{ "_id" : ObjectId("4b894c05cd50237b85738349"), "x" : 11, "y" : 121 }
{ "_id" : ObjectId("4b894c05cd50237b8573834a"), "x" : 12, "y" : 144 }
{ "_id" : ObjectId("4b894c05cd50237b8573834b"), "x" : 13, "y" : 169 }
{ "_id" : ObjectId("4b894c05cd50237b8573834c"), "x" : 14, "y" : 196 }
{ "_id" : ObjectId("4b894c05cd50237b8573834d"), "x" : 15, "y" : 225 }
{ "_id" : ObjectId("4b894c05cd50237b8573834e"), "x" : 16, "y" : 256 }
{ "_id" : ObjectId("4b894c05cd50237b8573834f"), "x" : 17, "y" : 289 }
{ "_id" : ObjectId("4b894c05cd50237b85738350"), "x" : 18, "y" : 324 }
{ "_id" : ObjectId("4b894c05cd50237b85738351"), "x" : 19, "y" : 361 }
has more


Consultas (queries)


É possível fazer consultas simples ou bem complexas assim como em modelos relacionais usando MongoDB.

Vamos obter uma contagem de objetos:
> db.foo.find().count();
100


Só os cinco primeiros objetos:
> db.foo.find().limit(5);
{ "_id" : ObjectId("4b894c05cd50237b8573833e"), "x" : 0, "y" : 0 }
{ "_id" : ObjectId("4b894c05cd50237b8573833f"), "x" : 1, "y" : 1 }
{ "_id" : ObjectId("4b894c05cd50237b85738340"), "x" : 2, "y" : 4 }
{ "_id" : ObjectId("4b894c05cd50237b85738341"), "x" : 3, "y" : 9 }


Agora os cinco seguintes:
> db.foo.find().skip(5).limit(5);
{ "_id" : ObjectId("4b894c05cd50237b85738343"), "x" : 5, "y" : 25 }
{ "_id" : ObjectId("4b894c05cd50237b85738344"), "x" : 6, "y" : 36 }
{ "_id" : ObjectId("4b894c05cd50237b85738345"), "x" : 7, "y" : 49 }
{ "_id" : ObjectId("4b894c05cd50237b85738346"), "x" : 8, "y" : 64 }
{ "_id" : ObjectId("4b894c05cd50237b85738347"), "x" : 9, "y" : 81 }


Para obter o elemento com valor de x vinte e quatro:
> var e = db.foo.findOne({ x: 24 });
> print(e.y);
576
> print(tojson(e));
{ "_id" : ObjectId("4b894c05cd50237b85738356"), "x" : 24, "y" : 576 }


Consultas avançadas


Vamos complicar um pouco…

Para obter todos os registros com x maior que cinquenta:
> db.foo.find('this.x > 50');
{ "_id" : ObjectId("4b894c05cd50237b85738371"), "x" : 51, "y" : 2601 }
{ "_id" : ObjectId("4b894c05cd50237b85738372"), "x" : 52, "y" : 2704 }
{ "_id" : ObjectId("4b894c05cd50237b85738373"), "x" : 53, "y" : 2809 }
{ "_id" : ObjectId("4b894c05cd50237b85738374"), "x" : 54, "y" : 2916 }
{ "_id" : ObjectId("4b894c05cd50237b85738375"), "x" : 55, "y" : 3025 }
{ "_id" : ObjectId("4b894c05cd50237b85738376"), "x" : 56, "y" : 3136 }
{ "_id" : ObjectId("4b894c05cd50237b85738377"), "x" : 57, "y" : 3249 }
{ "_id" : ObjectId("4b894c05cd50237b85738378"), "x" : 58, "y" : 3364 }
{ "_id" : ObjectId("4b894c05cd50237b85738379"), "x" : 59, "y" : 3481 }
{ "_id" : ObjectId("4b894c05cd50237b8573837a"), "x" : 60, "y" : 3600 }
{ "_id" : ObjectId("4b894c05cd50237b8573837b"), "x" : 61, "y" : 3721 }
{ "_id" : ObjectId("4b894c05cd50237b8573837c"), "x" : 62, "y" : 3844 }
{ "_id" : ObjectId("4b894c05cd50237b8573837d"), "x" : 63, "y" : 3969 }
{ "_id" : ObjectId("4b894c05cd50237b8573837e"), "x" : 64, "y" : 4096 }
{ "_id" : ObjectId("4b894c05cd50237b8573837f"), "x" : 65, "y" : 4225 }
{ "_id" : ObjectId("4b894c05cd50237b85738380"), "x" : 66, "y" : 4356 }
{ "_id" : ObjectId("4b894c05cd50237b85738381"), "x" : 67, "y" : 4489 }
{ "_id" : ObjectId("4b894c05cd50237b85738382"), "x" : 68, "y" : 4624 }
{ "_id" : ObjectId("4b894c05cd50237b85738383"), "x" : 69, "y" : 4761 }
{ "_id" : ObjectId("4b894c05cd50237b85738384"), "x" : 70, "y" : 4900 }
has more


Outra opção é usar o operador condicional $gt:
> db.foo.find({ x: { $gt: 50 } });


Da mesma forma outros operadores. Por exemplo, todos os elementos com x entre vinte e três e vinte e seis, inclusive:
> db.foo.find('23 <= this.x && this.x <= 26');


Ou:
> db.foo.find({ x: { $gte: 23, $lte: 26 } });


Os principais operadores são:
  • $lt – menor que
  • $gt – maior que
  • $lte – menor ou igual a
  • $gte – maior ou igual a
  • $ne – diferente de
  • $in – está em (recebe uma lista)
  • $nin – não está em
  • $mod – resto igual a (recebe uma lista onde o primeiro valor é o divisor e o segundo o resto)
  • $exists – contém ou não o atributo
  • $not – negação de uma condição


Ordenação


A ordenação é feita usando o método sort. Por exemplo, para ordenar de modo descrescente pelo atributo y:
> db.foo.find().sort({ y: -1 });


Expressões regulares

Quando há campos com valor string, é possível usar expressões regulares:
> db.foo.find({ name: /^mon.o$/i });


Índices

Quando você faz muitas consultas baseadas em um determinado atributo, é interessante criar um índice para ele. Por exemplo, se quisermos criar um índice para nosso atributo x:
> db.foo.ensureIndex({ x: 1 });


Obs.¹: o atributo _id possui índice por padrão.

Obs.²: é possível criar índices compostos.

Agregação


Não vou entrar nesse mérito, mas é possível criar agregações, como GROUP_BY de SQL. Para tanto veja a documentação oficial.

Módulos de conexão com linguagens de programação


Há módulos para várias linguagens, que podem ser encontrados na lista de APIs.

O módulo que pude e me fascinou foi para Python. Sua instalação usando easy_install foi muito simples:
bash$ sudo easy_install -U pymongo


E seu uso extremamente fácil devido à similiaridade entre dicionários de Python e JSON. A única reclamação que faço é o fato do método db.auth() do MongoDB ter sido traduzido como db.authenticate() em Python, o que me fez perder alguns segundos tentando entender por que não funcionava.

**


Espero que este artigo seja mais do que útil e incite o uso dessa intrigante ferramenta.

[]’s
Cacilhas, La Batalema

por noreply@blogger.com (Cacilhας, La Batalema) em 27 de February de 2010 às 17:44

February 26, 2010

Eduardo Willians

Notícias do Fronte de ZODB

Alguns vislumbres de ZODB:

.Me admira que ele receba tão pouca atenção
.Me admira que, além do Zeo, ele não venha empacotado com Zcatalog (indexador)
.Me admira que ninguém fale dele
.Me admira que ainda usemos Python com BDs relacionais

por Eduardo Willians (noreply@blogger.com) em 26 de February de 2010 às 15:17

Flávio Coelho

Utopia

Interesting post, But hoping to invert those proportions, i.e., making the smarter guys the 80% is harder that having a society where everyone earns more money than they can spend... Pretty next to impossible...;-)in reference to: Coding Horror: The Two Types of Programmers (view on Google Sidewiki)

por Flavio Coelho (noreply@blogger.com) em 26 de February de 2010 às 11:16

February 25, 2010

Kodumaro

Kodumaro no Twitter

Twitter Kodumaro agora no Twitter!

@kodumaro


A conta será usada para divulgar novos artigos e para troca de ideias com os leitores.

[]’s
Cacilhas, La Batalema

por noreply@blogger.com (Cacilhας, La Batalema) em 25 de February de 2010 às 17:38

February 22, 2010

Lauro Moura

“Pegadinha”: Cuidado ao encadear múltiplas chamadas de métodos


Num dos testes antigos do PySide, havia uma inocente linha de código com QFile().metaObject().methodCount(), que na nova versão estava causando uma falha de segmentação dentro da Qt. O que estava acontecendo era que o QMetaObject retornado pelo metaObject() estava sendo apagado pelo QFile() criado, invalidando a área de memória que methodCount() tentava acessar. Agora por que diabos ele estava sendo deletado, já que eu chamava o método direto nele? A resposta está no modo como o CPython é implementado, sendo uma máquina virtual de pilha.

Usando o módulo dis nessa linha, temos o seguinte resultado:

0 LOAD_GLOBAL              0 (QFile)
3 CALL_FUNCTION            0
6 LOAD_ATTR                1 (metaObject)
9 CALL_FUNCTION            0
12 LOAD_ATTR                2 (foo)
15 CALL_FUNCTION            0
18 POP_TOP
19 LOAD_CONST               0 (None)
22 RETURN_VALUE

Dissecando instrução por instrução e seus efeitos na pilha, vamos assumir que esteja inicialmente vazia. Apenas as 4 primeiras instrução são necessárias:

  • LOAD_GLOBAL (QFile) – Topo da pilha é a classe QFile
  • CALL_FUNCTION – Remove QFile do topo e coloca o resultado da chamada, no caso, a nova instância de QFile, com refcount 1
  • LOAD_ATTR(metaObject) – Remove a instância de QFile do topo (decrementa o refcount) e coloca o resultado de getattr(instância, ‘metaObject’) no topo. Nesse caso, o resultado é um “bound method” A chamada a getattr incrementa a referência da instância de QFile, logo ela não morre.
  • CALL_FUNCTION – Remove o metodo metaObject do topo e coloca o resultado, no caso a instância de QMetaObject retornada. Ao remover o método, a referência à instância de QFile é removida, chegando a 0. Então o destrutor do binding chama o destrutor de C++, que por sua vez deleta o objeto C++ do QMetaObject, invalidando o ponteiro usado pelo binding.

Ou seja, devido essas instruções, não se pode garantir que um objeto criado anonimamente numa chamada de metodo e usado imediatamente irá estar “vivo” em chamadas subsequentes.

Vale notar que esse problema aparece em outras implementações de Python baseadas no CPython, como o Stackless e o Unladen Swallow. Implementações que usam outros tipos de máquina virtual como o Jython, IronPython e Pypy não sofrem desse problema.

por lauro em 22 de February de 2010 às 16:37

February 20, 2010

Christiano Anderson

MongoDB e Python


Em novembro de 2009 publiquei minhas impressões sobre o CouchDB, já que estou desde então estudando banco de dados NoSQL para aplicações bem específicas. Permaneci por alguns meses estudando o CouchDB, que é mantido pela Apache Foundation e realizei diversos testes. O banco de dados se demonstrou bem eficiente para o modelo de aplicação que estou trabalhando, no caso a performance foi bem superior ao MySQL, já que tenho um volume de informações enorme e o fato de trabalhar com documentos — para esta minha aplicação específica — foi o que me chamou a atenção para um banco de dados estilo NoSQL.

Resolvi dar uma espiadinha em outro banco de dados no mesmo estilo, o MongoDB. Instalei no meu ambiente e realizei os mesmos testes. No CouchDB demorei muito tempo para realizar algumas operações simples, enquanto que no MongoDB, realizei  os mesmos procedimentos de maneira mais rápida e sem me enroscar nas configurações e na manutenção do banco. Em termos de performance — no caso da minha aplicação — os dois bancos se mostraram praticamente iguais.

Embora o CouchDB também tenha bibliotecas para trabalhar em Python, a do MongoDB parece ser mais simples e direta. Pelo menos me identifiquei melhor com sua biblioteca e consegui adaptar minha aplicação rapidamente para trabalhar com o MongoDB, descartando o tempo que levei para o aprendizado e leitura das documentações, demorei menos tempo para desenvolver um script totalmente funcional para MongoDB do que para CouchDB. Isso não quer dizer que o CouchDB seja ruim e ainda não tenho o volume de informações necessárias para fazer um benchmark ou dar opinião sobre qual é melhor.

É muito simples trabalhar em Python com o MongoDB, veja um exemplo:

#!/usr/bin/python

from pymongo import Connection
import datetime

con = Connection('localhost', 27017)
db = con['teste01']

user = {"nome":"Fulano",
        "sobrenome":"de Tal",
        "email":"fulano@detal.net",
        "data_inclusao": datetime.datetime.now()}

# Insere
users = db.users
users.insert(user)

O código acima cria um banco no MongoDB (veja as instruções para instalação e veja também a documentação Python para MongoDB) e insere um registro no dict user para o banco de dados. Como o trabalho é feito em um banco de dados não relacional, não há necessidades de definir o layout da tabela. O layout é definido à medida que os documentos são definidos e é flexível, podendo ser alterada a qualquer momento.

A pesquisa na base de dados pode ser feita com o seguinte código:

#!/usr/bin/python

from pymongo import Connection

con = Connection('localhost', 27017)
db = con['teste01']

# Pesquisa um só
users = db.users
a = users.find_one({"email":"fulano@detal.net"})
print a

# Pesquisa varios
for u in users.find():
    print u['nome'], u['email']

Entre o CouchDB e o MongoDB eu me identifiquei mais com o segundo. Consegui fazer as tarefas de forma mais rápida e eficiente. Mas o primeiro também é um ótimo banco, merece ser estudado. Provavelmente continuarei meus estudos e desenvolvendo a pesquisa em cima do MongoDB, pois tem uma documentação um pouco melhor e mais ferramentas para trabalhar na base de dados.

O próximo passo é integrar uma aplicação Django no MongoDB. Mas isso é motivo para outro post! :-)

por Christiano Anderson em 20 de February de 2010 às 19:13

February 19, 2010

Eduardo Willians

Estudando ZODB

Resolvi estudar ZODB (sem Zope). O próprio wiki de ZODB diz que ZODB trabalha independente de Zope, vamos ver.

Nosso foco por enquanto é Desktop (e não Web), mas nunca vi ninguém comentar algum projeto baseado em ZODB sem Zope para Desktop. Será que seria uma boa idéia?

Do jeito que costumo ser meio radical, se der certo vou abandonar a minha então preciosa fórmula Storm-Postgres, mudando para pure-python-zodb.

PS. Por enquanto só não gostei do nome "zodb" porque nunca saberemos como realmente pronunciar isso, parece aquele nome transcendental "GNU" cuja a pronúncia, segunda as más línguas, só pode ser feita corretamente por Richard Stallman.

por Eduardo Willians (noreply@blogger.com) em 19 de February de 2010 às 18:42

February 10, 2010

Elcio Luiz Ferreira

Hein?

Trecho de código legado (ASP) que pegamos aqui:

if len(request("price")) = 3 then
    valorTotal = left(request("price"),1)
elseif len(request("price")) = 4 then
    valorTotal = left(request("price"),2)
elseif len(request("price")) = 5 then
    valorTotal = left(request("price"),3)
end if

Jênio.


por Elcio em 10 de February de 2010 às 20:03

Eduardo Willians

O Tal Banco de Dados Relacional

Acreditem eu só entendi o que deveras era um BD relacional quando tentei montar um BD orientado a objetos.

Em algumas horas livres rascunhei na mente o projeto de BD orientado a objetos. Um dia sentei e fiz a modelagem de dados começando por Python, usando Storm. Até aí perfeito: a classe pai ia dando o rumo aos filhos que além de necessariamente herdar os atributos do pai criavam outros filhos ou se relacionavam com outros filhos numa hierarquia angelical.

Legal. Passei para o Postgres. Daí o primeiro problema: as tabelas-filho estranhamente herdavam fisicamente as colunas da tabela-pai. Beleza, esqueci que tem esse detalhe. Mas não muda muito as coisas. Em seguida as "tabelas-filhas-netas" (herdavam da tabela pai e filho) se relacionavam com a segunda geração e tudo mais.

Tudo sincronizado em python-storm. Vamos para os testes e... saltam resultados estranhíssimos.

..:|:.. A chave primária da classe pai fora francamente violada sem que o Postgres reclamasse. Hmm... Teria feito alguma coisa errada? Reviso as restrições. Tudo certo. Como os Postgres havia aceitado aquilo?

..:|:.. Dados inconsistentes, as restrições haviam sido sumariamente ignoradas.

..:|:.. O próprio BD obrigava os dados a serem inconsistentes. Se tentasse consertar manualmente os problemas das chaves primárias e estrangeiras, o BD impunha novos dados inconsistentes. Que loucura era aquela?

O que estaria errado então? Fui ao Google e finalmente encontrei a chave-primária da questão: o Postgres é relacional e tentar fazê-lo orientado a objetos é amplamente desencorajado.

O neǵocio é que o que eu considerava inconsistente não era assim tão inconsistente, apenas que havia uma meia lógica objeto-relacional que justificava aqueles dados.

Final das contas: Usando um BD relacional seja apenas relacional, que funciona muito bem. A propósito, a idéia de OO é ótima, mas não é tudo.

por Eduardo Willians (noreply@blogger.com) em 10 de February de 2010 às 11:17

February 07, 2010

Ricbit

Single-Person Pair Programming

Dia desses me perguntaram no twitter o que eu achava de Pair programming. Não apenas eu gosto, como sou entusiasta! Pair programming tem um monte de vantagens, sendo que a principal delas é que o programa será escrito com dois pares de olhos. E como nos lembra a Lei do Beholder Lei de Linus: dados olhos suficientes, todos os bugs são fáceis.


Minha técnica predileta de pair programming é o Ping-Pong Pair Programming, que eu aprendi com o Miško. A idéia é mesclar as idéias do pair programming com o test-driven development. Você começa colocando dois teclados no computador, aí um parceiro escreve um teste, e o outro escreve o código que faz aquele teste passar. A vantagem desse método é que funciona mesmo se um dos programadores for preguiçoso, e, de fato, funciona até melhor assim!

Por exemplo, vamos supor que Alice e Bob querem escrever um programa bem simples: uma função que incrementa um número. Digamos que a assinatura dessa função será int increment(int value). Alice escreve um teste que valida essa função:

void teste1() {
  assertEquals(2, increment(1));
}

Um teste bem razoável. Se entrar um, tem que sair dois. Agora Bob vai escrever o código que faz esse teste passar:

int increment(int value) {
  return 2;
}

FAIL? O Bob é um cara preguiçoso, então ele escreveu um código que sempre retorna dois. Isso faz o teste passar, mas não era isso que a Alice tinha em mente!

Surpreendentemente, essa é a vantagem do ping-pong. Suponha que esse teste fosse o único teste que o código tinha. Agora digamos que alguém, anos depois, foi refatorar o código, mas fez uma bobagem no processo e agora a função que incrementa um número está retornando sempre 2. Nesse caso, o teste não vai detectar o erro!

A conclusão é que o teste inicial não era robusto o suficiente. Pra melhorar isso, Alice escreve um segundo teste:

void teste2() {
  assertEquals(3, increment(2));
}

Agora o código original do Bob não funciona, e ele precisa refatorar pra criar um código que passe os dois testes:

int increment(int value) {
  if (value == 1)
    return 2;
  else
    return 3;
}

E agora, FAIL? Não há dúvidas de que o conjunto com dois testes é mais robusto que apenas o primeiro teste, mas esse processo não parece prático. Afinal, os dois poderiam ficar no ping-pong até exaurir todos os valores do int, o que levaria um bocado de tempo.

Mas isso não acontece! Como sabemos, o Bob é preguiçoso. Na verdade, ele é tão preguiçoso, que atingiu o nível supremo da preguiça: a meta-preguiça. O Bob sabe que se ele continuar nesse ping-pong, ele vai ficar trabalhando até depois das seis, e ele quer ir pra casa ver a novela. Se a Alice escrever testes o suficiente, ela vai acabar forçando o Bob a escrever o código correto, porque é o código mais simples que resolve o problema.

void teste3() {
  assertEquals(4, increment(3));
}


int increment(int value) {
  return value + 1;
}

Agora sim! O resultado final é duplamente bom, nós temos um conjunto de testes robustos, e um código que é o mais simples possível (o que é sempre uma vantagem, esse código é o mais fácil de entender, tem o menor custo de manutenção, etc.)

Esse método me fascinou por dois motivos. Primeiro, ele é uma aplicação da Navalha de Occam em software: você parte de uma série de observações e deduz a teoria mais simples que modela o sistema. Segundo, o método é um indicativo de que é possível fazer um conjunto de testes que define a operação em questão.

Juntando as duas observações, a pergunta natural que faz é: pra que eu preciso do Bob? Eu poderia construir uma máquina que, dado um conjunto de testes, encontre o programa mais simples que os satisfaçam. Se a máquina conseguir jogar o ping-pong de maneira ótima, então acabamos de inventar o Single-Person Pair Programming!


Antes de tentar resolver esse problema, precisamos escolher alguma definição para "programa mais simples". Por exemplo, vamos escolher que o programa mais simples é o menor programa que resolve o problema. Uma maneira de achar esse programa é fazer um brute force: basta testar todos os programas possíveis!

Isso é fácil de visualizar em assembly. O conjunto de opcodes do processador é limitado, então a quantidade de programas em assembly com um único opcode é finito. Eu testo todos eles pra ver se algum satisfaz os testes: se algum passar, ele é a solução, senão, eu repito o procedimento com todos os programas de tamanho dois, e assim por diante. Esse algoritmo garantidamente acha o menor programa que satisfaz os testes.

Um problema teórico com essa abordagem é que ela está sujeita ao problema da parada de Turing. Eventualmente, algum desses programas que você está testando pode entrar num loop infinito e você não tem como detectar isso. Uma solução é sair pela tangente: a maioria dos problemas da vida real podem ser resolvidos com modelos computacionais mais fracos que a máquina de Turing. Em assembly, nós poderíamos proibir os saltos pra trás, o que resolve essa limitação.

Essa técnica para achar o programa mínimo se chama Superotimização, e hoje em dia há vários papers sobre o assunto. Em 2003 eu escrevi um superotimizador para assembly Z80, então foi fácil adaptá-lo para fazer Single-person Pair Programming.

Single-person Pair Programming escrito em C

Vamos testar. Se eu tenho um único teste, 1->2, o programa acha três soluções mínimas, sendo uma delas ADD A,A. É claro, com esse único teste, ele não sabe se estamos somando um ou multiplicando por dois. Colocando dois testes, 1->2 e 2->3, ele já converge para a solução única INC A.

Complicando: e se quisermos um incremento módulo 8 (ou seja, a=(a+1)%8)? Podemos definir isso com os testes 1->2, 2->3 e 7->0. Colocando essa suite no programa, temos o resultado abaixo:

INC A
AND 7

Ou seja, o Single-person Pair Programming funciona direitinho!

Bônus!

O vencedor do Ricbit Jam #1 foi o Davi Costa, parabéns! Por uma questão de logística que envolve a China eu ainda não tive como compilar os resultados, mas fiquem de olho lá no meu twitter que em breve eu farei uma página com soluções e comentários.

por noreply@blogger.com (Ricardo Bittencourt) em 07 de February de 2010 às 18:16

February 04, 2010

Elcio Luiz Ferreira

Exportando MySQL para CSV

Criei agora um pequeno script para resolver um problema meu, um exportador de base de dados MySQL para arquivos CSV. Resolvi compartilhar:

MySQL2CSV

Para baixar, você vai precisar do git. No Ubuntu, para instalar, faça:

$ sudo apt-get install git-core

Depois, para baixar:

$ git clone git@github.com:elcio/mysql2csv.git

Isso vai criar a pasta mysql2csv, com o script dentro. Você pode copiá-lo para a pasta /usr/local/bin/ e dar permissão de execução se for usar com muita freqüência:

$ cd mysql2csv
$ sudo cp mysql2csv.py /usr/local/bin/mysql2csv
$ sudo chmod +x /usr/local/bin/mysql2csv

Se fizer isso, vai poder chamar, em qualquer diretório:

$ mysql2csv host user passwd dbname


por Elcio em 04 de February de 2010 às 18:14

February 01, 2010

Elcio Luiz Ferreira

Rodando comandos do sistema operacional com cache no Python

Código simples, mas que pode ser útil para alguém não ter que escrevê-lo de novo (arquivo runcached.py):

import os,time
cachepath='cache'
timeout=360
 
def runcached(cmd):
  filename=os.path.join(cachepath,str(hash(cmd)))
  if os.path.isfile(filename):
    if time.time()-os.path.getmtime(filename)<timeout:
      return open(filename).read()
  t=os.popen(cmd).read()
  open(filename,'w').write(t)
  return t

A função runcached roda comandos do sistema operacional, e faz cache do resultado por 6 minutos. Para alterar o tempo do cache, basta mudar a variável timeout. Por exemplo, para cachear por 10 horas:

import runcached
runcached.timeout=36000
r=runcached('lynx --source http://www.tableless.com.br')


por Elcio em 01 de February de 2010 às 16:41

January 31, 2010

Inno::Blog

MRNN Brasil – Para discussão de soluções MRNN ( N1NF | NoSQL – NotOnlySQL )

Apesar de extremamente prazeroso (ou às vezes nem tanto) acompanhar mailists e foruns nem sempre é tarefa fácil, seja pelo rumo que certas discussões geram, pela falta de tempo  ou às vezes pela questão do foco. Acredito eu, que eventualmente todos vêem um assunto que é meio (ou inteiramente) off-topic sendo tratado com certo pudor, mas que você gostaria que a discussão evoluísse mas a própria lista e a netiqueta não permite.

Alguns dizem que a relação entre arquiteto e programador é de confiança e compreensão, arquitetos não confiam em programadores e estes não compreendem os arquitetos!

Esta afirmação pode parecer exagerada (como de fato é) mas recentemente identifiquei exatamente esta situação numa reunião onde o foco era NoSQL, atritos à parte, na hora pensei que este é um assunto que merece ser profundamente e adequadamente discutido e difundido e ver ele restrito a censura ou limite dos off topics era algo cruel, e isto me fez lembrar de algumas conversas que tive, sendo uma delas com o Pedro Lamarão (figura carimbada do grupo C & C++ Brasil) num happy hour e outra com o Jack Ganssle (quando ele esteve no Brasil para o workshop que o Portal Embarcados promoveu sobre Engenharia de Software) no qual o foco de ambas conversas foi o estímulo e a iniciativa. Pra ser sincero, foi com este foco que convidamos o Felipe Tonello para palestrar no VI Encontro de Programadores do grupo C & C++ Brasil (que vai ocorrer no próximo sábado dia 06/02/2010) para falar sobre seu projeto RoboQT, é com esta abordagem em mente pensei que era necessários fazer algo em ralação ao NoSQL…

Como muitos sabem:

DBMS != SQL
SQL != Evil
NoSQL != Paraíso

Para aqueles que apreciam o assunto e desejam discuti-los sem a preocupação de criar “OFF TOPICS”, com o  propósito de criar um canal
independente (de linguagens de programação e DBMS) destinada para a discussão de Banco (não bando) de Dados não relacionais - NF², NF2, N1NF (non first normal form) , MRNN (Modelo Relacional Não-Normalizado) também conhecidos como nested relational, dimensional, multivalue, free-form, schemaless porém mais populares como NoSQL (Not Only SQL) criei a lista MRNN-Brasil:

http://groups.google.com/group/MRNN-Brasil

O foco é tratar o assunto sem pudores de abordagens acadêmicas,
profissionais ou produtos podendo ser tratado tanto BigTable (???),
Dynomite, Riak, Cassandra, CouchDB,  HBase, Sherpa, Voldemort, Tokyo
Cabinet, MongoDB como as bibliotecas das mais diversas linguagens, sejam elas C, C++, Python, ERlang, Go, Haskell, Ruby, Brainfuck ou Whitespace ou até novas iniciativas; seja do ponto de vista de arquitetura, programação, segurança ou o que for, mas obviamente relacionado com MRNNs.

Talvez eu não tenha procurado direito, mas como eu não havia encontrado nada semelhante em Pt-BR, resolvi tomar esta iniciativa.

A escolha de um nome do vernáculo foi em razão de que NoSQL não intui muito para o que ele realmente representa (Not Only SQL) e esta NÃO é uma lista não para aqueles que relacionam SQL com algo do mal e NoSQL dá impressão de ser  uma campanha anti-SQL; mesmo que no fundo esta ”buzzword” não (?!?!) signifique  isto e após estímulo (indireto) do Luciano Ramalho (que é um entusiasta do assunto tanto quanto ele é de Python) acabei adotando o nome MRNN-Brasil ao invés de NoSQL-Brasil.

Espero que  iniciativa possa ser útil para a comunidade.


por techberto em 31 de January de 2010 às 17:18

January 26, 2010

Christiano Anderson

Livro Python para Desenvolvedores – Baixe a segunda versão

Não posso deixar de divulgar a grande iniciativa do Luiz Eduardo Borges em disponibilizar a segunda versão do livro Python para Desenvolvedores sob licença Creative Commons. Ainda não li todo o livro, mas pelo índice já dá para perceber que é um grande material, leitura indispensável para programadores de outras linguagens que desejam conhecer Python ou até mesmo programadores Python que desejam aperfeiçoar seus conhecimentos.

Uma leitura técnica como esta, além de revigorante é bastante inspiradora. Por mais experiência que alguém tenha sobre uma determinada tecnologia, ao ler um ótimo material como este, é possível aprender novas técnicas ou melhorar procedimentos já utilizados. Então vale muito a leitura, além de tudo está sob licença CC.

O download do livro pode ser feito na página Python para Desenvolvedores no próprio site do Ark4n ou se tiver alguma dificuldade no download, fiz um mirror do livro. Clique aqui para baixar do mirror.

por Christiano Anderson em 26 de January de 2010 às 15:52

January 25, 2010

Inno::Blog

Luminescência, meu tio José e Avatar

Final de ano, num rancho a beira-rio, curtindo o feriadão com a família, meus primos tiveram a idéia de fazer uma festa (que para minha surpresa havia sido preparada com boa antecedência) com direito a vários badulaques e inclusive com lightsticks (à volonté como diria os franceses ou à la vonté como nós abrasileiramos e gostamos de dizer) que sempre dá um tom alegre a festas noturnas e sempre leva a criançada (e inclusive vários marmanjos) a brincar diante das lâmpadas ultra-violetas, devido aos agradáveis efeitos visuais que tal combinação produz, sendo sempre um bom elemento para complementar a diversão.

Após a festa e em momento oportuno, meu sábio tio José, que tem uma curiosidade que eu muito aprecio,  me fez a seguinte pergunta:

- O que faz estas pulseiras brilharem? Elas são realmente de neon?

Estes são um daqueles momentos que você sente imenso prazer, afinal perguntaram algo do que eu sabia responder e pelo qual naquele momento eu estava pensando por razões que vocês irão descobrir abaixo.  Sem contar que com certas pessoas é sempre prazeiroso compartilhar um pouco de erudição  ou como alguns preferem chamar, um pouco de cultura inútil para desopilar o fígado; apesar que se tratando de cultura eu nunca a acho inútil, mesmo que seja para filosofar sobre o  bater de asas das borboletas  do ponto de vista entomológico, neural, da física tratando da teoria do caos, da perspectiva cinematográfica comentando sobre criativo filme “efeito borboleta” ou poético lembrando por exemplo da famosa pretensão de Mhuammad Ali de “float like a butterfly, sting like a bee“. Mas dependendo do contexto isto pode ser um porre para quem está participando e ninguém gosta de ser desagradável, mas este não era o caso.

O neon é um gás nobre incolor, abundante no universo, mas presente em pequena quantidade no ar atmosférico, ele foi descoberto pelos químicos britânicos Morris Travers (que eu sempre confundo com Tavares) e William Ramsay no século 19, os mesmos que descobriram o gás xenônio e o criptônio;  que apesar do nome krypton nada tem a ver com a saga de Kal-EL.

Segundo gás nobre mais leve, com um alto poder de refrigeração, 40 vezes maior que do hélio líquido e três vezes maior que o hidrogênio líquido, ele não está presente no light-stick!!!

A tradução de ligh-stick é “bastão luminoso”, mas sei lá por que cargas d’água (talvez pela mesma razão que vulgarizaram a expressão francesa à volonté para à la vonté) o mercado abrasileirou  o nome para bastão de neon ou pulseira de neon,  devido a sutil semelhança com as lâmpadas de neon, porém não é o gás nobre o responsável pela fonte de energia luminosa deste artefato, mas sim uma reação que ocorre com o cyalume (que está no bastão) similar e mais barato que ao luminol. No caso do luminol, ele reage com cobre e ferro, e como há ferro na hemoglobina, o luminol é vastamente empregado por equipes de investigação forense (como de CSI) para investigações criminais.

O que presenciamos no ligh-tstick (e nas cenas de CSI quando eles encontram sangue em algum local ou objeto) é o efeito conhecido como luminescência (nome com origem no latim “lumem”) que é a emissão de luz através por estímulo de radiação ionizante, luz ou reação  onde uma energia química  é transformada em energia luminosa. Na realidade quando o efeito é obtido através de algum composto químico sintético, como no caso do light-stick, ele é chamado de quimiluminescência e, apesar de não ser o caso, se fosse produzido por um organismo vivo ele seria chamado de bioluminescência sendo-se que há vários outros tipos de luminescência.

Voltando ao bastão.

No caso deste, normalmente há um solução de cyalume com uma ampola de vidro contendo uma solução de peróxido de hidrogênio (água oxigenada  35%) e quando o bastão é dobrado a ampola é quebrada, as soluções são misturadas o luminol começa a ser oxigenado e a quimiluminescência começa a ocorrer e fazer a alegria da galera. A duração do efeito depende da  temperatura do local, sendo-se que temperaturas baixas são mais propícias  para sua durabilidade, portanto colocar a pulseira na geladeira tende a prologar o efeito mas ele não se eternizará ou fará a efeito ocorrer novamente.

Vale lembrar que apesar de ser um efeito estudado a centenas de anos, com grandes evoluções no último século, este é um fenômeno não totalmente compreendido plenamente ainda sendo alvo de estudos e pesquisas.

No caso da bioluminescência, normalmente o substrato de uma proteína denominada luciferina (nome com origem no latim “lucifer” que significa “que ilumina”) é oxidada por uma enzima, denominada luciferase. Nesta reação há o consumo de uma molécula de trifosfato de adenosina (ATP) que excita energéticamente a luciferina e proporciona a geração de energia luminosa através da liberação da energia química.

A luminescência tem atraído o interesse do homem desde o princípio de sua existência, visto que do Pernambuco à China, os primeiros registros e pirilampos, fenômeno que Aristóteles (384 – 322 A.C)  descreveu como “luz fria”. Em 1669, o médico H. Brandt criou a “phosphorus mirabilis”, que era uma reação que utiliza uma propriedade do fósforo quando exposto ao oxigênio do ar em certas circunstâncias e por esta reação ele obtia a “quimiluminescência” (termo que fui criado 200 anos depois),  mas  Brandt que era um alquimista na época não compreendia exatamente o que ele estava fazendo, apenas o que ele estava conseguindo; o fascínio das pessoas para quem ele apresentava seu experimento alquimista.

Talvez seja este fascínio (o a intenção de fascinar) que fez James Cameron

inserir na história de Avatar,  a luminescência e a bioluminescência em Pandora como uma propriedade de todo organismo deste planeta, dos animais aos pequenes Woodsprites, as sementes de Utraya “Mokri”, e a Árvore das Almas, com propriedades místicas.

Quando meu tio Zé perguntou-me sobre o bastão de luz, a pouco eu estava lembrando da carinha de alegria de minhas sobrinhas ao brincar com os bastões de luz, sobre o fascínio da luminescência na humanidade e sobre o belo efeito que James Cameron conseguiu com Avatar, portanto nem preciso dizer o quanto achei oportuno a pergunta dele; porém confesso que na hora puxei um pouco o freio de mão e não externei toda minha viagem.

E por falar em viagem e para finalizar, vejam só o que este maluco fez com um bocado destes bastões:

Alerta, Cyalume é tóxico e além disto como comentei acima, há vidro nos bastões, portanto não façam isto em casa!

Namastê!


por techberto em 25 de January de 2010 às 19:52

January 22, 2010

Inno::Blog

VI Encontro de Programadores C & C++

O core de organização de eventos do grupo C & C++ Brasil, com colaboração da  Liga dos Programadores Indepentes mais alguns colaboradores e com apoio da galera do hashtag #ccppbrasil_meetings estão trabalhando na remotada dos eventos do grupo C & C++ Brasil para 2010, sendo-se que o primeiro evento será o encontro de programadores que está programado para o dia 06 de fevereiro de 2010 em São Paulo.

A programação ainda não está fechada mas há propostas de palestras sobre concorrência para C++, robótica, programação segura entre outras.

Maiores detalhes em http://www.ccppbrasil.org/wiki/Grupo:Encontro_VI

Está em planejamento também um encontro do pessoal de Porto Alegre.

Em breve será divulgado uma previsão de  agenda para 2010.

Bons códigos e nos vemos lá!

Namastê!


por techberto em 22 de January de 2010 às 11:43

January 20, 2010

Inno::Blog

Lei de Stigler, ressaca de pan-galactic gargle blaster, a vida, o universo e tudo mais

Epónymos era a figura que atribuía o nome a uma cidade na grécia clássica.  Eponímia é o nome que dela deriva.  Este conceito generalizou-se ao batismo de  técnicas, objetos, atributos, invenções seja por vias diretas ou indiretas, sendo considerada a forma suprema de reconhecimento da atividade de um pesquisador.

Quando eu era adolescente e morava lá em Santa Fé do Sul (proporcionalmente 105.18 Km mais distante de São Paulo e 3.7840092199092412 vezes menor que Barbarcena)  numa época em  que eu realizava um curso técnico em eletrônica,  com grande  freqüência eu conversava com o (bom amigo) Batata sobre física, eletricidade, válvulas raras, RF, a vida, o universo e tudo mais; num destes bate-papo logo após uma desopilação hepática  ele me comentou que quem deveria ser creditado pelo invento do rádio deveria ter sido o Padre Landell, um gaúcho que foi  padre católico e um notável inventor e não Marconi ; físico italiano que plagiando estudos apresentandos pelo Nikola Tesla em 1899 apresentou ao mundo que Pe.Landell já havia apresentado em 1893 para um pequeno público em Campinas.  Também foi o Batata que me revelou que o verdadeiro inventor do telefone teria sido Elisha Gray e não Alexander Graham Bell, quando eu solicitei suas “fontes” ele sacou de seu arquivo duas revistas  Saber Eletrônica que relatavam estes fatos.  Quando terminei de ler os artigos comentei: “Isto sim é pilantragem” e o Batata soltou uma que (na época)  eu  não entendi:

- “Isto sim é a apoteose da irresponsabilidade consciente”  e tomei nota desta frase  na hora,  pois achei um “insight” muito inspirado…

Fiquei bastante curioso sobre estes fatos, infelizmente naquela época (década de 80) minhas fontes de pesquisas mais confiáveis diziam que os inventores da primeira aeronave havia sido os  irmãos Orville e Wilbur Wright.  Estas informações não mudaram minha vida, mas me tornaram um assíduo leitor na revista Saber Eletrônica por alguns anos como também me  estimularam a pesquisar (eventualmente)  sobre a história das invenções e das ciências.

Nestas primeiras pesquisas,  percebi que muitas invenções passaram por disputas de paternidade, mas nem sempre a disputa tinha motivações financeira, como por exemplo foi o caso de Bob Kearn retratado no filme Flash of Genius. Um caso mais popular  foi o exemplo da lâmpada que teve como primeiro inventor Joseph Swan mas  Thomas Edison levou os créditos, porém foi quem melhor explorou a invenção, tendo inventado o sistema elétrico com rede de distribuição de energia, geradores de energia e todo um universo que viabilizou a comercialização da eletricidade,  conseguindo explorar melhor a invenção. Caso similar ao  telefone visto que Bell explorou muito bem “sua” invenção e as redes telefônicas. Porém, no caso dele vamos dizer que se aplica a máxima do batata visto que Bell se inspirou no trabalho de Johann Philipp Reis,  descobriu o trabalho de Stephen Gray (que em 1729 teorizou um telefone funcional) comprou (a preço de banana) protótipos de Antonio Meucci, ouviu boatos do aparelho de Christian Ørsted e quando ficou sabendo que   Elisha Gray (que era alguém com quem ele sabia que devia-se preocupar) iria registrar a patente de um telefone funcional, Bell subornou um funcionário do escritório de patentes e “conseguiu” registrar a patente do telefone primeiro, mas em 2002 a suprema corte americana reconheceu o trabalho de Antonio Meucci por ter sido o verdadeiro inventor do telefone;  decisão  justa mas tardia, afinal Meucci faleceu no século 19. No caso do rádio, entre aqueles que se proclamaram pais da invenção havia Nikola Tesla, Alexander PopovReginald Fessenden, Pe.Landell de Moura;  em 1943 a Suprema Corte dos Estados Unidos concedeu a Tesla a Patente 763,772 creditando a ele a invenção do rádio, talvez porque era o único que ainda havia algum representante ativo nesta luta, pois analisando historicamente o Pe.Landell Moura foi quem conseguiu primeiro. Felizmente hoje Landell é mais conhecido no Brasil, sendo patrono dos radiamadores brasileiros sendo conhecido como um dos pioneiros na invenção da TV, ele foi o inventor do telefone sem fio,  da comunicação via portadora ótica e entre outros campos ele é conhecido mundialmente por seu pioneirismo na bioeletrografia porém quanto ao rádio…

Numa destas pesquisas encontrei a palavra  eponímia (acho que)  pela primeira vez.  Um exemplo de eponímia é a  Salmonella, que tem origem do sobrenome do  Dr.Daniel Elmer Salmon, mas que na realidade ela foi descoberta por  Theobald Smith. Ué, como assim? De forma simplista, olha a máxima do batata aí novamente.

Num acaso, em 1992  li uma nota que Joel Cohen havia escrito um artigo no qual ele revelava que a “lei da eponímia de Stigler” foi muitas vezes formulada antes de Stigler a ter sequer nomeado. Mas o que era esta tal lei? Infelizmente era 1992,  não consegui encontrar nada nas bibliotecas que eu tinha acesso e eu estava procurando nos lugares errados.

Poucos anos depois, ao acaso, descobri que a chamada Lei – da  mesonímia ou eponímia – de Stigler afirmava que “no scientific discovery is named after its original discoverer” (nenhuma descoberta científica é designada com o nome do seu descobridor original)   bem, neste momento comecei a pensar, nenhuma?  Stigler chegou a esta conclusão observando várias descobertas, na área de economia e ciências, sendo-se que este trabalho proporcionou a ele o Nobel de Economia em 1982. Porém, se Cohen estava correto, até a lei de Stigler era vítima dela própria; ao menos ela era coerente. E ali senti que eu estava començando a aprender os nomes dos bois.

E eu ainda tinha aquela dúvida: todas? Obviamente que não podia ser todas, mas o quanto ela se aplicava? Qual ciência era mais suscetível? Porque esta tipo de situação era tolerada? Não há uma única resposta, cada caso é um história.

Alguns anos depois, felizmente já com a internet, resolvi pesquisar a origem de algo que a muito tempo eu tinha curiosidade e o que descobri foi interessante:

Em 1949, John Paul Stapp,  um  Ph.D, médico e coronel da  USAF (nascido na Bahia em 1910)  pioneiro nos estudos dos efeitos das forças de aceleração e desaceleração no organismo humano, que havia sido selecionado dois anos antes como “cobaia” de testes para medir a resistência humana a grandes acelerações,  consegui bateu o recorde mundial de aceleração mas não pôde  festejar o feito. Isto porquê os acelerômetros do trenó-foguete simplesmente não funcionaram. P. da vida, Stapp  solicitou ao engenheiro responsável pelas medições -  o então capitão Edward Murphy Jr. -  uma análise para identificar a falha. Logo eles descobriram que  um técnico ligara os circuitos do veículo ao contrário. No relatório de análise do problema,  Murphy anotou: “Se há mais de uma forma de fazer um trabalho e uma dessas formas redundará em desastre, então alguém fará o trabalho dessa forma”.

Dr. Stapp popularizou a expressão ao comentar em uma entrevista a jornalistas, o diagnóstico de Murphy, atribuindo ao fato de que ninguém saiu ferido dos testes por levarem em conta a Lei de Murphy e explicou as variáveis que integravam a assertiva, ante ao risco de erro e consequente catástrofe.

Enfim, quem a popularizou  foi Stapp e o seu autor (mesmo que atormentado por isto) sempre recebeu os méritos. Assim quando tive contato com as origens da folclórica e emblemática a Lei de Murphy minha primeira observação  foi que a Lei de Stigler não se aplica a ela. Imagino que esta seja uma daquelas citações desgastadas que ninguém mais aguenta,  mas como já dizia Nelson Rodrigues “toda unaminidade é burra”. Mas o que mostrou-se mais evidente é que a Lei de Murphy é mais poderosa que a Lei de Stigler! rs

Outro dia, já em 2010, lendo o post Newton e os Universos Paralelos vi uma referência ao clássico embate Newton vs Hooke, que sempre me faz lembrar do embate Newton vs  Leibniz . Muitas vezes a fama indevida ou a prova da Lei de Stigler ocorre de forma involuntária, no caso do Cálculo, não há eponímia, mas houve literalmente “a apoteose da irresponsabilidade consciente”, enfim, houve a pilantragem de Newton. Com o tempo descobri que o Batata não havia sido original, que a frase que me deslumbrou era do Carlos Imperial e ele omitiu, mas comparado ao que Newton fez isto não foi nada!

Apenas para contextualizar:

Isaac Newton fez descobertas elementares em gravitação, óptica, mecânica, dinâmica celeste e matemática!  Era um cientista. Já Leibniz, pai do termo função, era um filósofo e se interessava  por lingüística, história, direito, diplomacia, política, economia, teologia,  biologia, geologia,  matemática, filosofia e metafísica, sendo considerado  como o último gênio universal e inclusive um virtuoso atleta.

Leibniz publicou o seu trabalho sobre Cálculo antes de Newton.  Quando Newton teve acesso, ele ficou bastante irritado e temendo críticas, principalmente advindas de Robert Hooke, com quem não tinha muita afinidade desde quando ele publicou seu trabalho sobre ótica e que na ocasião era o presidente da Royal Society, Newton preferiu adotar uma estratégia vitriólica para “defender” seus interesses.

Quando  Hooke faleceu, Newton tornou-se uma espécie de presidente vitalício da Royal Society, da qual Leibniz também era membro. Desta forma, ainda inconformado por ter perdido o bonde do Cálculo, com um aliado escocês, John Kell,  começou a provocar Leibniz como plagiador.  Muito irritado com esta história, ele enviou ofícios violentos à Royal Society para provar que ele, sim, inventara o Cálculo Diferencial e Integral (até hoje são usadas as notações de Leibniz – por exemplo, o famoso dy/dx). Diante daquela querela entre titãs e como sói acontecer, criou-se um comitê para investigar a questão. Esse comitê foi formado em quase sua totalidade por membros pró Newton. Em tempo recorde ficou pronto um relatório conferindo a Newton a prioridade da invenção. Mais tarde foi descoberto um rascunho desse relatório manuscrito por Newton! Na realidade, com o tempo descobriu-se que quase todos os artigos que foram escritos ” atacando” Leibniz foram apenas publicados em nomes de outros cientistas da época, mas foram escritos por Newton (tsc).  Newton recebeu o título de Sir, faleceu em 31 de março de 1727 e foi sepultado na Abadia de Westminster, em Londres, entre os reis do Império Britânico.  Apesar de suas mentiras e desvios de caráter, ele foi  evidentemente um gênio, preguiçoso e ardiloso, porém sagaz e extremamente inteligente.

Todavia, a filosofia de Leibniz contribuiu para o que hoje chamamos de física moderna. Ele trabalhou com lógica simbólica, aperfeiçoou uma primitiva máquina de calcular e foi precursor da aritmética binária, base dos atuais computadores. Leibniz morreu em Hanover no dia 14 de novembro de 1716.

A melhor síntese desta história que eu já encontrei, do qual me apropriei de parte do texto está no trabalho Newton vs Leibinniz de Adalberto Nascimento, porém esta história é contada em vários livros.

Comentando sobre alguns destes assuntos  no twitter com o @AlanJumpi e o @Feutestoun, surgiu um insight de escrever este post (ou algo parecido) foi quando comentei da Lei de Stigler e logo alguém me comentou que a @cyberdecker havia escrito a pouco tempo o post breve panorama da estatística e lei de Stigler que li gostei muito, sinceramente recomendo.  Na sequência surgiu a idéia de debatermos tudo isto com mais algum tempero de nerdices num bar, numa divagação imaginei que o local ideal seria o bar & restaurante no fim do universo, logo pensei:  como será uma ressaca  de Pan-Galactic Gargle Blaster? :-)

Saideira: por falar em aritmética binária, grandes gênios, inventores, absurdos e polêmicas sobre patentes, lembrei de uma clássica história onde em 1948 quando tentaram patentear as portas lógicas digitais, a U.S.Patents a negaram  pois Nicola Tesla já a detinha  desde a virada do século.  Esta foi uma contribuição indireta de Tesla extremamente valiosa, visto que  este  monopólio certamente iria gerar um absurdo atraso tecnológico.

Ps: Ainda pensando nestes sci-fi drinks,  como será uma ressaca de “Romulan Ale“?  Bom, esta divagação incidental e um pouco (ou muito mais) sobre curiosidades sobre Tesla,  Landell e história da ciência  ficam para outro(s) post(s) que após quebrar o jejum, nas próximas aplicarei as técnicas de jack.

Namastê!


por techberto em 20 de January de 2010 às 12:59

January 19, 2010

Luciano Ramalho

Django-Brasil ultrapassa Zope-PT

Conforme eu previa, em algum momento de 2009 a lista django-brasil ultrapassou em número de assinantes a lista zope-pt. Alguém sabe exatamente quando foi?

Na minha palestra-relâmpago na PyCon 2009 em Chicago eu mostrei números que indicavam que isso estava prestes a acontecer.

Então por esse critério o Django é hoje o mais popular framework Web da linguagem Python no Brasil.

Parabéns a todos que ajudaram isso a acontecer, como usuários, consultores, tradutores, autores, instrutores e evangelizadores!

A simplicidade, a praticidade e o poder do Django combinam com o jeito Python de programar. Assim como Python, Django faz bem para a auto-estima do principiante (como diz o Marco André).

Ao mesmo tempo, Python e Django vêm com pilhas incluídas (componentes prontos para usar), e não se limitam a soluções simples, pois oferecem ferramentas e extensibilidade para programadores experientes produzirem sistemas muito sofisticados, flexíveis e robustos.

O sucesso do Django foi a melhor coisa que aconteceu para o Python nos últimos anos.

por Luciano Ramalho (noreply@blogger.com) em 19 de January de 2010 às 06:23

January 18, 2010

Luciano Ramalho

Três perguntas sobre Python

Desde quando o Google e o Youtube usam Python?

Desde o início. Os algoritmos inovadores do Google foram criados em Python e em C, e até hoje Python é usada em todos os milhões de servidores do Google. O Youtube já era feito em Python antes de ser adquirido pelo Google. Veja a página About Google de 1998 e o depoimento de Peter Norvig, diretor de pesquisa do Google e co-autor do livro Inteligência Artificial: uma abordagem moderna. Ah sim: a primeira linguagem suportada no Google App Engine foi Python.

Porquê o MIT está usando Python?

O Massachussetts Institute of Technology, a mais famosa escola de engenharia do mundo, está usando Python em sua principal disciplina introdutória de computação. Python foi adotada porque possui bibliotecas muito versáteis (redes, robôs, computação gráfica, etc.) e permite explorar conceitos avançados de orientação a objetos e meta-programação, mas tem uma curva de aprendizagem suave. O livro-texto adotado pelo MIT já foi traduzido pela comunidade Python brasileira: Aprenda Computação com Python.

Existe emprego para programadores Python?

Sim. Hoje existem mais vagas para .Net, Java e PHP do que para Python, mas as vagas para programadores Python são mais atraentes. O motivo é que Python não é uma opção "default", mas é uma escolha consciente feita por empresas que se preocupam com qualidade e buscam inovação, e isso se reflete em melhores condições de trabalho, salários maiores e ambientes mais estimulantes para a pesquisa e a aprendizagem. O programador milionário Paul Graham blogou sobre isso: The Python Paradox.

Para quem tem um perfil mais empreendedor: vários programadores Python brasileiros atendem clientes no exterior, vivendo no Brasil e recebendo em dólar ou euros. Outros tantos foram convidados para trabalhar no exterior. A demanda de especialistas em Python é muito maior que a oferta, e isso cria grandes oportunidades profissionais.

por Luciano Ramalho (noreply@blogger.com) em 18 de January de 2010 às 14:57

January 17, 2010

Ricbit

Tatuagens em cadeia

Uma classe de artistas que eu admiro muito são os tatuadores, e por um motivo simples: eles não podem errar. Um desenhista pode usar borracha, um arte-finalista pode cobrir o erro com tinta branca, um artista digital pode apertar control-Z, mas o tatuador não pode fazer nada disso. Um escultor, se erra, tem a opção de jogar fora o bloco de pedra e começar de novo, mas o tatuador nem essa opção tem.

Exatamente por isso, tem um tatuador que eu conheço que se recusa a tatuar nomes de namorados. Tatuagens são permanentes, mas namoros são efêmeros: imagine namorar alguém que tem uma tatuagem com o nome do ex? Nesse caso, uma solução prática é reciclar a tatuagem e namorar alguém que tenha o mesmo nome do seu ex. Não é elegante, mas funciona.



Isso leva a conclusões curiosas. Veja o meu caso, por exemplo. Se eu tatuar ILA e minha esposa tatuar RICARDO, aparentemente ela estaria levando vantagem. É muito mais fácil arrumar outro Ricardo que arrumar outra Ila. Por outro lado, eu não precisaria procurar apenas Ilas, eu poderia arranjar uma Priscila ou uma Camila, bastando adicionar mais letras na tatuagem!

Isso naturalmente leva à pergunta: qual é o máximo de namoradas que um Serial Tatuator pode ter? Por exemplo, uma pessoa poderia ir de Ana para Iana e depois Fabiana. Será que dá pra achar uma cadeia de tatuagens de tamanho quatro? Cinco? Hora de fazer uma simulação!

Antes de começar, precisamos de um corpus de nomes. O jeito mais fácil de conseguir o corpus é escrevendo um crawler para um desses sites com nomes de bebês. Uma busca rápida e eu achei o Babyhold, que tem a vantagem de separar os nomes por sexo.

Script python para fazer crawling de nomes de meninas

O script retornou mais de 7100 nomes de meninas. Agora é só fazer um outro script que calcule a máxima cadeia de nomes. Como a quantidade de nomes não é tão grande assim, um algoritmo cúbico bobo dá conta do recado:

Script python para achar cadeias máximas

O script acabou achando várias soluções de tamanho seis, mas sem dúvida a seqüência mais curiosa foi a abaixo :)


Li -> Lin -> Elin -> Elina -> Angelina -> Angelina Jolie

Bônus!

Embora o algoritmo cúbico funcione bem para 7100 nomes, certamente há como otimizá-lo. Ao invés de fazer uma solução mais rápida, dessa vez eu vou abrir para os leitores enviarem suas soluções! Clicando no link abaixo você vai para o primeiro Ricbit Jam, feito com a engine do spoj. Ganha quem enviar a solução mais rápida nos próximos quinze dias. Não tem prêmio, mas o vencedor terá seu nome divulgado no próximo post :)

Ricbit Jam #1

Não adianta tentar mandar o programa em python acima, ele não acha todas as soluções e vai dar TLE no servidor do spoj. Mas você pode usar como base pra fazer a sua solução.

por noreply@blogger.com (Ricardo Bittencourt) em 17 de January de 2010 às 22:32

January 15, 2010

Kodumaro

FizzBuzz (No Stairway to Heaven)

Glider Hoje um amigo meu veio falar comigo de uma brincadeira velha – e que eu não conhecia – chamada FizzBuzz.

[update 2010-01-15]
Sugestão de apontador do Cesar Barros: If something is worth doing….

A propósito, atualizei o código Lisp.
[/update]

A brincadeira consiste em imprimir uma sequência de números, tradicionalmente de 1 a 100. Porém os números múltiplos de 3 devem ser substituídos por fizz e os números múltiplos de 5 por buzz. Os números que são divisíveis por 3 e por 5 devem ser substituídos por fizzbuzz.

No Stackoverflow você pode encontrar as versões mais loucas, como LOLCODE, Brainf*ck, Ook, assembly de 8051, 6502 e Linux IA-32, Hebreu Estruturado, Cobol e Forth, como destaque para o poético código em Perl.

Aqui quero postar algumas soluções que achei interessantes.

**

Em Haskell:
putStr (concat [if (mod x 15)==0 then "fizzbuzz\n" else if (mod x 3)==0 then "fizz\n" else if (mod x 5)==0 then "buzz\n" else (show x) ++ "\n" | x <- [1..100]])


Em Python:
print "\n".join('fizzbuzz' if x%15==0 else 'fizz' if x%3==0 else 'buzz' if x%5==0 else str(x) for x in xrange(1, 101))


Em Perl:
print +(fizz)[$_%3] . (buzz)[$_%5] || $_, $/ for 1..100;


Em Common Lisp:
(format t "~{~A~%~}" (loop for x from 1 to 100 collect (if (= (mod x 15) 0) "fizzbuzz" (if (= (mod x 3) 0) "fizz" (if (= (mod x 5) 0) "buzz" x)))))


[]’s
Cacilhas, La Batalema

por noreply@blogger.com (Cacilhας, La Batalema) em 15 de January de 2010 às 00:13

January 13, 2010

Noticias da APyB

PythonBrasil[6]: Curitiba, 2010

Definido o local do sexto encontro brasileiro da comunidade Python.

por ramiroluz em 13 de January de 2010 às 02:05

January 11, 2010

Elcio Luiz Ferreira

Porque meu GPS não fala com a web?

Passei a última semana no IPAE, aqui. É o colégio em que fiz o segundo grau (faz tempo!), um lugar fantástico, ao pé de uma montanha, região com paisagens inacreditáveis. Me hospedei no colégio com minha família, para matar saudades, e todos os dias saíamos para visitar algum lugar em Petrópolis ou Teresópolis.

Há catorze anos, quando estudei lá, telefonava para minha família uma vez por semana apenas, pois os interurbanos eram muito caros. Dessa vez, estava conectado via rede 3G o tempo todo. O mundo mudou muito rápido em catorze anos. Ponto para o 3G da Claro, que funcionou em todo lugar onde fui, inclusive em todo o trajeto paulista (Dutra, Carvalho Pinto, Ayrton Senna) e em boa parte do estado do Rio de Janeiro. Na região de Itatiaia virou 2G, mas continuou funcionando.

Antes de sair para viajar, usávamos o Google Maps e a Wikimapia para encontrar os pontos de interesse. O problema? Depois de encontrar o ponto de interesse, meu sobrinho tinha que digitar os endereços no GPS para obter a rota. E quando o ponto de interesse ficava no meio de uma estrada, o jeito era navegar à mão no GPS até o lugar, arrastando o mapa para cá e para lá.

Será que só eu sofri com isso? Vocês, meus bem informados leitores, conhecem algum aparelho de GPS que fale com a web, através de alguma integração maluca? O ideal seria GPRS. Seria muito interessante se, enquanto estou dirigindo, um passageiro pudesse pegar o GPS e ver a navegação acontecendo sobre a Wikimapia, por exemplo. Alguém já viu isso? Alguma idéia de como fazer?


por Elcio em 11 de January de 2010 às 13:00

January 09, 2010

Kodumaro

Ajude a mostrar a PythonBrasil na PyCon 2010

Meu amigo Henrique Bastos publicou hoje um artigo entitulado Ajude a mostrar a PythonBrasil na PyCon 2010.

A proposta é muito legal e já preenchi o formulário para reunir informações sobre a Comunidade Python no Brasil.

Segue uma reprodução do artigo:
Salve Pythonistas!

De 19 a 21 de fevereiro será realizada a PyCon, em Atlanta nos Estados Unidos. Como alguns de vocês já sabem, participarei do evento apresentando a palestra #78 entitulada «Small acts make great revolutions».

Esta apresentação será uma evolução da palestra relâmpago que fiz na PythonBrasil[5] em Caxias do Sul, onde tento difundir os conceitos por trás das iniciativas que vêm movimentando a comunidade no Rio de Janeiro.

No entanto, falar só do que acontece no Rio me parece muito pouco para uma oportunidade dessas. Quero muito aproveitar a PyCon para mostrar o grande desenvolvimento da Comunidade Python no Brasil. Pessoasfantásticas estão fazendo as coisas acontecerem em Terras Brasilis. E a exemplo do que fiz no FISL 10, pretendo continuar na linha de tentar evidenciar que na nossa comunidade, o todo é muito maior do que a soma das partes. Mas para isto, eu preciso da ajuda de vocês.

Para poder falar com propriedade sobre a Comunidade Python no Brasil, precisamos traçar o perfil do nosso grupo. Por isso, preparei um rápido questionário online que ajudará a levantar informações sobre nossa comunidade. Ele está disponível em: http://henriquebastos.wufoo.com/forms/vamos-divulgar-nossa-comunidade-python-na-pycon/

É muito importante que o maior número de pythonistas respondam à pesquisa. Isso vai ajudar muito! Portanto, não economizem nos retweets e espalhem o link da pesquisa por todas as listas de email no Brasil, relacionadas com Python.

Além disso, também estou buscando links para boas fotos em alta resolução, como as tiradas na escadaria da PUC-RS durante o FISL 10 e as fotos «aéreas» da PythonBrasil[4] na UVA etc. Basta publicarem os links para as fotos nos comentários deste post ou me enviar por email.

Obrigado à todos, e vamo que vamo!

[]’s!


Já andei tuitando e divulguei nas Reflexões de Monte Gasppa e Giulia C. também. Convido todos então a ler o artigo e preencher o formulário, ajudando assim o Henrique a revelar e expor a Comunidade Python no Brasil ao Mundo!

[]’s
Cacilhas, La Batalema

por noreply@blogger.com (Cacilhας, La Batalema) em 09 de January de 2010 às 02:07

January 02, 2010

Gustavo Barbieri

Enlightenment meets ConnMan

I’m proud to present you with my last Enlightenment module: ConnMan!

ConnMan module popup.

For those unfamiliar with ConnMan, it is a solution to configure and manager your network connections. Unlike NetworkManager, it is very simple and fast, specially for users of it’s DBus API. It will manage everything, including DNS proxy to avoid messing with your /etc/resolv.conf. It also handles WiFi, Ethernet, WiMax, Bluetooth and even Cellular connections easily. For developers using it, it is very simple to use and you just need to use the high level “Service” interface.

ConnMan module tooltip

In order to make it more useful, I created econnman inside e_dbus that abstracts the DBus API as a nice C interface that matches it perfectly and optimally, keeping objects in sync with server and emitting Ecore_Event whenever things change.

The module is quite simple, yet useful. As seen in the above screenshots, it will list the current status and service name (if module is bigger than 32px), when you mouse over it will show a fancy popup with more details, including error messages and IPv4 addresses. If you click it, you get a simple popup with the current connected service selected and clicking it will disconnect, while clicking a new one will connect to that one. Services requiring password will automatically ask for it, while those that failed to connect will also re-ask your password.

The module nicely exposes the offline mode feature to turn off radios. It integrates well with E17 mode: whenever you change E17 or ConnMan, they will sync with the other.

There is still work to do, mainly focus on the cellular specific needs and also create static services. And I also plan to have an application to allow managing your services, reorder them (that defines the priority) and even switch technologies that are available.

por Gustavo Sverzut Barbieri em 02 de January de 2010 às 23:05

Ricbit

Newton e os universos paralelos

Neste último Natal fomos passar o feriado no sítio. Não precisei de muito tempo pra notar que eu não funciono muito bem nesse ambiente. Além de ser alérgico a quase todos os insetos, eu tinha apenas uma pequena noção de coisas básicas de quem vive por lá (como andar a cavalo, por exemplo). Isso nem me chateia, porque em compensação eu tenho outras habilidades que o pessoal do sítio não tem, como saber usar o Google Sky Map pra identificar as estrelas no céu.

Enquanto eu descansava numa rede, eu comecei a pensar como seria um universo paralelo onde o Ricbit é um matuto que entende tudo da vida no campo. Mas o pensamento não durou muito. Que coisa batida isso, se for pra imaginar um universo paralelo, vamos imaginar um mais original!

Sempre que pensamos em universo paralelos, tendemos a imaginar um muito semelhante ao nosso, onde apenas alguns detalhes mudam. E se imaginássemos um universo tão diferente que até as leis físicas são distintas da nossa? Por exemplo, como seriam as órbitas planetárias num universo onde a Lei da Gravidade não variasse com o quadrado da distância, mas sim com alguma outra expressão qualquer?



Esse exemplo é bacana por causa da sua importância histórica. Vamos voltar para o tempo do Isaac Newton, que o Asimov considerava o maior de todos os cientistas. É inegável que o Newton era um gênio, mas o que nem todo mundo sabe é que ele era briguento, vingativo, e costumava cometer o maior pecado que um cientista pode fazer: não citar as fontes.

Isso aconteceu com a Lei da Gravidade. Naquela época ainda não existiam as listas de discussão, então os cientistas conversavam por cartas escritas à mão. Certa vez, Newton recebeu uma carta do Robert Hooke, aquele que hoje é conhecido pela lei da molas. Nessa carta, Hooke dizia que suspeitava da existência de uma força da gravidade, que seria central (dependendo apenas da distância), e provavelmente proporcional ao inverso do quadrado da distância. Na carta ele ainda dizia que não sabia como provar essa suspeita.

Hoje em dia a razão para o Hooke não saber provar é clara. Pra conseguir provar, você precisa saber Cálculo, que o Newton já tinha inventado, mas ainda não tinha contado pra ninguém. Se o Newton fosse gente boa, ele teria respondido algo do tipo "eu sei provar, chega mais e vamos resolver juntos". Ao invés disso, ele ficou na miúda, e anos depois publicou o Principia Mathematica, onde ele usava o Cálculo para mostrar que a tal força central inversamente quadrática implica em órbitas que são seções cônicas.

O Hooke, compreensivelmente, ficou puto, e foi reclamar com o editor do livro, o Halley (o cientista, não o cometa). Depois de muito bate-boca, o Halley convenceu o Newton a colocar um prefácio onde ele dizia que a lei da gravidade tinha sido sugerida informalmente pelo Hooke, mas sem demonstração. Numa carta posterior ao Hooke, Newton ainda diria "se enxerguei mais longe, foi porque estava sobre o ombro de gigantes". Não era humildade, era trollagem. Conta-se que Hooke era baixinho e corcunda.

Mas o Newton não parou por aí. Certa vez, ele ficou como responsável pela mudança de prédio da Royal Society. Entre os quadros que precisavam ser mudados, estavam os retratos de todos os membros do grupo. Por uma coincidência não-explicada, o quadro do Hooke foi o único que se perdeu no caminho. Hoje em dia, ninguém sabe como era o rosto do Hooke, esse quadro perdido era o único retrato dele.



Nada disso teria acontecido se o Hooke soubesse Cálculo. E nós, para calcularmos nossas órbitas em universos paralelos, vamos fazer exatamente as contas que o Hooke desconhecia! Se você também não sabe cálculo, pule a caixa azul e vá direto pro resultado.

Consideremos um sistema com duas massas pontuais no vácuo. As contas em coordenadas cartesianas são meio chatas, então vamos usar coordenadas polares, centradas numa das massas. Nesse tipo de conta, o normal é usar um sistema de versores r e θ que giram junto com o planeta, mas a engenharia me deixou vícios difíceis de largar, então eu vou usar exponenciais complexas. A posição do planeta é a seguinte:

p=re^{j\theta}

Note que r e θ na verdade são r(t) e θ(t), eu vou omitir o tempo pra não poluir as equações. A aceleração da partícula é a segunda derivada:

p'=r'e^{ j\theta}+rj\theta'e^{j\theta}
p''=r''e^{j\theta} +r'j\theta'e^{j\theta}+r'j\theta'e^{j\theta}+rj \theta''e^{j\theta}+rj^{2}\theta'^{2} e^{j\theta}

Agrupando os termos e lembrando que j2 = -1, temos:

p''=(r''-r\theta'^{2})e^{j\theta}+(2r'\theta'+r\theta'')je^{j\theta}

Até aqui tudo genérico. Vamos impor agora que a força seja central. Nesse caso, a componente transversal vale zero. Note que, com uma pequena manipulação algébrica, dá pra isolar uma derivada:

2r'\theta'+r\theta''=\frac{1}{r}(2rr'\theta'+r^{2}\theta'')=\frac{1}{r}\frac{d}{dt}(r^{2}\theta')=0

Aqui temos duas soluções. A primeira é sem graça, 1/r=0 se as duas massas estiverem infinitamente distantes, aí naturalmente a força transversal é zero. O segundo caso é mais legal:

\frac{d}{dt}(r^{2}\theta')=0 \Rightarrow r^{2}\theta'=k

Se a derivada é zero, então a integral é uma constante. Se você lembrar que r2θ é o dobro da área de um setor circular, então o que essa fórmula diz é que a taxa de variação da área de um setor é constante, ou seja, para um dado intervalo de tempo, ele percorre sempre a mesma área. Ora, essa é a segunda lei de Kepler! Pelo que concluímos, ela funciona pra qualquer força central, não só pra gravidade.

Vamos lidar com a componente radial agora. As massas são todas constantes, então vale que F=ma. Além disso, vamos introduzir uma variável u pra facilitar as contas:

\frac{F}{m}=r''-r\theta'^{2}
r=\frac{1}{u}\Rightarrow u=\frac{1}{r}

Nós podemos isolar o tempo e deixar o raio em função do ângulo, usando uma mudança de váriaveis com a regra da cadeia.

r^{2} \theta'=k \Rightarrow \frac{d\theta}{dt}=\frac{k}{r^{2}}=ku^{2}
r'=\frac{dr}{dt}=\frac{dr}{d\theta}\frac{d\theta}{dt}=\frac{d}{d\theta}(\frac{1}{u})ku^{2} =-\frac{1}{u^{2}}\frac{du}{d\theta}ku^{2}=-k\frac{du}{d\theta}
r''=\frac{dr'}{dt}=\frac{dr'}{d\theta}\frac{d\theta}{dt}=\frac{d}{d\theta}(-k\frac{du}{d\theta})ku^{2}=-k^{2}u^{2}\frac{d^{2}u}{d\theta^{2}}

Agora é só substituir na equação original:

\frac{F}{m}=r''-r(\frac{d\theta}{dt})^{2}=-k^{2}u^{2}\frac{d^{2}u}{d\theta^{2}}-\frac{1}{u}(ku^{2})^{2}=-k^{2}u^{2}(\frac{d^{2}u}{d\theta^{2}}+u)
-\frac{F}{mk^{2}u^{2}}=\frac{d^{2}u}{d\theta^{2}}+u

Pronto! Esta é a equação geral das órbitas com força central. Para conferir se está certo, vamos colocar uma força inversamente quadrática. Note que as forças precisam ser negativas, pois, na nossa orientação, forças atrativas são negativas. Aliás, como eu não estou interessado em unidades, vou escolher constantes que cancelem.

F=-\frac{mk^{2}}{r^{2}}=-mk^{2}u^{2}
1=\frac{d^{2}u}{d\theta^{2}}+u

Para resolver a equação diferencial, somamos a solução particular com as homogêneas. Uma particular é fácil, u=1. A homogênea todo mundo sabe de cabeça, é cos(θ) (vezes uma constante que depende das condições de contorno). Afinal, é a mesma solução do sistema massa-mola, do oscilador LC, e assim por diante.

u=1+e.cos(\theta) \Rightarrow r=\frac{1}{1+e.cos(\theta)

Ahá! Esta é equação da seção cônica em coordenadas polares. Dependendo do valor de e, a órbita pode ser circular (e=0, como Vênus, aproximadamente), elíptica (e<1, como a Terra), parabólica ou hiperbólica (e=1 ou e>1, como os cometas).

Vamos tentar outro tipo de força, por exemplo, uma inversamente cúbica. Nesse caso:

F=-\frac{mk^{2}}{r^{3}}=-mk^{2}u^{3}
u=\frac{d^{2}u}{d\theta^{2}}+u \Rightarrow \frac{d^{2}u}{d\theta^{2}} =0 \Rightarrow u=\theta \Rightarrow r=\frac{1}{\theta}

Ou seja, a órbita agora é uma espiral.

Agora que temos a equação geral, podemos colocar a força que quisermos, e analisar a órbita resultante. O problema é que muitas fórmulas geram equações que não tem solução analítica, então eu fiz um scriptzinho em python pra resolver numericamente mesmo. Abaixo o script e os resultados para várias funções:

Script em python para resolver órbitas em universos paralelos


Para uma força inversamente quadrática, a órbita é circular, como esperado pela Lei da Gravidade.


Já uma força inversamente cúbica gera uma espiral. Essa força é fraquinha demais pra manter uma órbita, e o planeta vai aos poucos se afastando.


Uma força inversamente linear demora para estabilizar, mas acaba fazendo uma órbita circular também.


E uma força constante, independente da distância? Ela também termina numa órbita circular, o que pra mim faz sentido. O planeta se move até o ponto onde a força constante é igual à centrípeta.


Agora vamos sacanear e colocar uma força senoidal só pra ver o que acontece. Ele não diverge, mas faz uma órbita muito doida. Provavelmente é um atrator estranho.

por noreply@blogger.com (Ricardo Bittencourt) em 02 de January de 2010 às 03:45

December 25, 2009

Leonardo Gregianin

National Geographic Wallpaper


National Geographic Wallpaper is a software adapted to Desktop Wallpaper Love with enhancements such as:

  1. It really puts the image on the desktop.
  2. Watermark of link the photo of National Geographic Photo of the Day
  3. Schedule for implementation of the NG Wallpaper 1 minute after turning on the computer.
  4. Installation All-in-One: Python 2.6, Python Imaging Library, PyWin32 and settings of National Geographic Wallpaper.
  5. User friendly

A fun afternoon of Christmas :-)

por leogregianin em 25 de December de 2009 às 21:55

December 22, 2009

Kodumaro

Seaside

Squeak Seaside é um arcabouço (framework) para desenvolvimento de aplicações web para Smalltalk. É descrito pelo próprio autor como um arcabouço herético, por quebrar todas as regras dos gurudons atuais.

Pessoalmente gosto muito de coisas heréticas ou subversivas. Sou um apaixonado por subversão. =D

Olhando a documentação, podemos ver que Seaside é suportado pelas máquinas virtuais Cincom VisualWorks, GNU Smalltalk, VA Smalltalk, Squeak e seus derivados Pharo e GLASS.

GNU Smalltalk


A máquina virtual recomentada é Squeak, da qual gosto muito e que é ótima para aplicações desktop, no entanto Squeak é uma plataforma muito pesada, consome muitos recursos da máquina, por isso, para Seaside, optei por uma plataforma mais leve: GNU Smalltalk.

GNU Smalltalk sofre porém de um mal extremamente irritante: a sintaxe da linguagem é muito irregular – para ser eufémico.

Teoricamente GNU Smalltalk suportaria a sintaxe correta de Smalltalk-80, mas não funciona bem assim… ele é muito chato e levanta erros de sintaxe para códigos perfeitamente corretos, mas que diferem do que o GNU Smalltalk espera de Smalltalk-80. Então é preciso experimentar algumas formas diferentes – mas regulares – de fazer as coisas antes de encontrar uma que funcione (às vezes ele implica até com nomes de argumentos).

Vou usar aqui a sintaxe Smalltalk-80 precisa – e que funciona no GNU Smalltalk –, mas colocarei o mesmo código na sintaxe peculiar do GNU Smalltalk ao final deste artigo apenas por curiosidade.

Preparação da imagem


Para criar a imagem para nosso exemplo usei o comando:
bash$ gst-load -iI seaside.im Seaside Seaside-Development Seaside-Examples


Isso cria uma imagem seaside.im com os pacotes Seaside (Seaside em si), Seaside-Development (ferramentas de desenvolvimento) e Seaside-Examples (exemplos).

Usei então o exemplo de componente da própria documentação: MyCounter.st.
  • O método de classe #canBeRoot diz se o componente pode ser registrado como uma aplicação autónoma ou não.
  • Na inicialização (#initialize) o atributo count é zerado.
  • O método #states retorna uma coleção de estados que podem ser retrilhados (backtracked).
  • O método #renderContentOn: é usado para renderizar a página.
  • Ao final a mensagem #registerAsApplication: registra o componente como aplicação.


O código fica então (se copiar e colar, substituia por ^):
" See: http://www.gnu.org/software/smalltalk/manual/html_node/Seaside.html "

Seaside.WAComponent subclass: #MyCounter
instanceVariableNames: 'count'
classVariableNames: ''
poolDictionaries: ''
category: 'Seaside Examples'
!

!MyCounter class methodsFor: 'testing'!

canBeRoot
↑true
!

!

!MyCounter methodsFor: 'initializing'!

initialize
super initialize.
count := 0.
!

!

!MyCounter methodsFor: 'accessing'!

states
↑{ self }
!

!

!MyCounter methodsFor: 'rendering'!

renderContentOn: html
html heading: count.
html anchor
callback: [ count := count + 1 ];
with: '++'.
html space.
html anchor
callback: [ count := count - 1 ];
with: '--'.
!

!

MyCounter registerAsApplication: 'mycounter'.


Para carregar o componente na imagem usei o comando:
bash$ gst -I seaside.im -S MyCounter.st


Rodar a aplicação


O seguinte comando levanta a máquina virtual no modo servidor:
bash$ gst-remote -I seaside.im --daemon


Depois disso você poderá ver a máquina virtual ouvindo na porta 12345/TCP:
bash$ netstat -ln4 | grep 12345
tcp 0 0 0.0.0.0:12345 0.0.0.0:* LISTEN


É possível obter o PID do processo da máquina virtual com seguinte comando:
bash$ gst-remote --pid


Porém o Seaside não está rodando. Para rodar o serviço web use o comando:
bash$ gst-remote --start=Seaside


É possível também iniciar a máquina virtual já rodando o Seaside com o seguinte comando:
bash$ gst-remote -I seaside.im --daemon --start=Seaside


Por padrão o serviço web Seaside estará escutando na porta 8080/TCP.

Para acessar a aplicação que acabamos de criar use o endereço http://localhost:8080/seaside/mycounter.

Parar a aplicação


Para parar a aplicação use o comando:
bash$ gst-remote --stop=Seaside


Repare que, apesar do serviço web ter parado, a máquina virtual continua rodando. Para pará-la:
bash$ gst-remote --kill


Para comparação


A título de comparação, segue o código usando a sintaxe bizarra e esdrúxula peculiar do GNU Smalltalk:
Seaside.WAComponent subclass: MyCounter [
| count |

<category: 'Seaside Examples'>
<comment: nil>

MyCounter class >> canBeRoot [
<category: 'testing'>
^true
]


initialize [
<category: 'initializing'>
super initialize.
count := 0
]

states [
<category: 'accessing'>
^{ self }
]

renderContentOn: html [
<category: 'rendering'>
html heading: count.
(html anchor)
callback: [count := count + 1];
with: '++'.
html space.
(html anchor)
callback: [count := count - 1];
with: '--'
]
].

MyCounter registerAsApplication: 'mycounter'.


[]'s
Cacilhas, La Batalema

por noreply@blogger.com (Cacilhας, La Batalema) em 22 de December de 2009 às 22:28

December 14, 2009

Flávio Coelho

LaTeX Tikz examples

I am currently working on a presentation where I have to include a lot of mathematical graphs, so instead of plotting using matplotlib and inserting the result as a figure, I am considering using specialized LaTeX packages to create the graphs. While searching for documentation, I found this great repository of examples for the Tikz package.referente a: http://www.texample.net/tikz/examples/ (ver

por Flavio Coelho (noreply@blogger.com) em 14 de December de 2009 às 09:27

December 08, 2009

Andrews Medina

Testando aplicações django com nose-django.

O nose-django é um plugin para o nose com o objetivo rodar testes de aplicações Django.

Com ele é possível criar testes em uma estrutura de arquivos menos engessada que a estrutura imposta pelo Django, sem perder as funcionalidades de testes do framework como fixtures, client e etc.

Outra vantagem do nose-django é a possibilidade de utilizá-lo em conjunto com outros plugins para o nose como o coverage por exemplo.

Mais informações sobre o projeto: http://www.assembla.com/spaces/nosedjango

08 de December de 2009 às 20:28

December 07, 2009

Elcio Luiz Ferreira

Navegação rápida com o Google Public DNS

Uma coisa que sempre me espantou é a ineficiência dos servidores de DNS dos provedores de hospedagem brasileiros. Já testei ADSL, cabo coaxial, 3G e, aqui em São Paulo, de maneira geral as conexões são boas. Mas como o servidor de DNS dos provedores é ruim, a navegação é muito lenta.

Eu vinha usando OpenDNS, cuja performance é muito boa. Mas hoje resolvi testar o Google Public DNS. Deixa o OpenDNS no chinelo!

Como o Google conseguiu isso? Um mega sistema de cache, com cobertura global, e um inovador sistema de prefetching. Se você não está usando ainda, vale a pena testar.

Para facilitar a vida dos usuários de Linux, segue meu /etc/resolv.conf:

nameserver 8.8.8.8
nameserver 8.8.4.4

Sim, são esses IPs mesmo ;-) Não é fantástico?


por Elcio em 07 de December de 2009 às 18:48

Pythonologia

[jabá] Treinamento Python e Django

A Triveos está lançando o seu treinamento de Desenvolvimento Web Ágil com Python e Django e por isso pega carona nesse conceituado blog (que por coincidência é um dos sócios da Triveos) para anunciar este lançamento.

Imagem ilustrativa do treinamento com a apostila e o texto 'Aprenda Python e Django em apenas 5 dias'

Eu não costumo fazer esse tipo de post (jabá) por aqui mas este é um caso especial por dois motivos: o produto anunciado foi criado pela minha empresa (como eu já havia dito); e porque que até o momento são poucas as empresas que ministram esse curso no Brasil.

Esse treinamento é o primeiro entre muitos que planejamos desenvolver no próximo ano sempre com algumas características:

  • treinamentos in-company — isso nos dá mobilidade e permite que o treinamento seja ministrado em qualquer lugar do Brasil e não somente no eixo Rio-São Paulo.
  • treinamentos de curta duração — achamos que tecnologias precisam ser simples e que se elas forem realmente simples não seria necessário investir meses num treinamento. O treinamento de Python e Django precisa de 5 dias apenas para ser ministrado com grande tranquilidade para pessoas que já desenvolvem em alguma linguagem OO.
  • treinamentos personalizáveis — a linha principal do treinamento é mantida mas algumas modificações podem ser feitas para adequar o treinamento aos requisitos das empresas. Exemplos: dedicar um tempo do treinamento à implantação do Django, apresentar alguma biblioteca Javascript para desenvolvimento de RIAs, ministrar só o módulo Django, etc.
  • materiais de qualidade — nada de apostilas contendo só slides impressos. Disponibilização de todo o material usado em aula (Slides, repositório de códigos, etc).
  • instrutores qualificados — não posso falar muito mais sobre isso. Sou um dos instrutores :D

Quem tiver interesse no treinamento pode entrar em contato com a gente através do site ou diretamente comigo.

Update: Pessoal, não tinha ficado claro mas, a Triveos só trabalha com treinamentos in-company, ou seja, não temos infra-estrutura para ministrar esse treinamento em nossa empresa. Fazemos isso dentro da sua empresa (ou da empresa onde você trabalha). De qualquer maneira estamos avaliando um modo de atender às demandas que estão surgindo.


por Osvaldo Santana em 07 de December de 2009 às 13:19

December 06, 2009

Kodumaro

Mais sobre reiteração

Glider A reiteração ou iteração é um dos mais efetivos algoritmos para para processamento de sequências, mas sua eficiência não se limita a processamento de conjuntos prontos, essa técnica de algoritmo também pode ser usada para processamento de amostragens em plena coleta.

Vamos a um algoritmo bem simples, a média aritmética:
mean_x=sum_x/n


O algoritmo reiterativo pode ser expresso da seguinte forma:
(defun mean ((a-list list))
(/
(apply #'+ a-list)
(length a-list)))


Agora imagine que você tem o registro contínuo do comportamento de um dado específico ao longo do tempo e gostaria de manter sua média sem preocupação como os valores em si (acho um caso pouco provável, mas…).

Se reparando bem, há dois dados importantes para o cálculo da média aritmética: a própria média e a quantidade de elementos. Basta que a função receba esses valores além dos novos valores que serão usados para atualizar a média anterior.

Assim é possível armazenar apenas a média atual e a quantidade de elementos avaliados:
(defun update-mean ((the-mean hash-table) (a-list list))
(let ((*count* (+ (gethash 'count the-mean) (length a-list))))
(setf (gethash 'mean the-mean)
(/
(+
(apply #'+ a-list)
(* (gethash 'mean the-mean) (gethash 'count the-mean)))
*count*))
(setf (gethash 'count the-mean) *count*)
the-mean))


Então, além de receber a lista com os dados mais recentes (segundo parâmetro), a função recebe como primeiro parâmetro um hash com os dados de média anteriores.

O formato inicial do hash deve ser:
#s(hash-table :test fasthash-eql (count . 0) (mean . 0))


Ou seja, 'mean zero (0) e 'count zero (0). O hash será atualizado e retornado:
(setq *mean*
(make-hash-table
:initial-contents (list
(cons 'count 0)
(cons 'mean 0))))


Na próxima falarei em variância on-line.

[]'s
Cacilhas, La Batalema

por noreply@blogger.com (Cacilhας, La Batalema) em 06 de December de 2009 às 15:42

Marco André Lopes Mendes

Meu roteiro de instalacao do Ubuntu 9.10




Introdução


Este artigo descreve o meu roteiro de atualização dos meus computadores
pessoais com o Ubuntu 9.10 Karmic Koala. Eu costumo instalar muitos
programas, seja para testar ou mesmo para usar nas aulas que ministro.
Assim, a cada seis meses, quando sai uma versão nova do Ubuntu, costumo
fazer uma reinstalação completa desses computadores. Eu também costumo
adaptar esses computadores ao meu gosto, e sempre que os reinstalo,
preciso sair à procura das modificações que havia feito.


Sendo
assim, resolvi anotar cuidadosamente cada modificação feita na
instalação. Estes roteiro foi criado pensando nas minhas necessidades,
mas pode ser adaptadopara satisfazer outras pessoas. Percebi também que
a cada versão nova do Ubuntu, algumas configurações que eu fazia antes,
passaram a vir por padrão nele.

Tentei deixar as dicas curtas.
Se você cosiderar alguma dica incompleta, entre em contato, que eu
tentarei explicar melhor. Para correções a fazer ou outras
configurações a sugerir, envie um comentário. Terei prazer em ler e
responder.


Iniciando a instalação




Não vou descrever a instalação. Recomendo deixar uma partição de cerca
de 25 GB pro sistema uma de swap do tamanho da sua RAM e uma partição
de dados separada. A instalação pelo pen drive é muita mais rápida do
que pelo CD. Recomendo deixar um de 1 GB só pra isso.


Configurando a placa de vídeo Sis 771


No meu caso, um Positivo com placa Sis 771/671, siga o tutorial, para instalar o driver da placa de vídeo:


http://pequenotux.blogspot.com/2009/10/sis-771-671-no-ubuntu-karmic-koala.html


Adicione estas linhas no seu arquivo /etc/X11/xorg.conf:

Section "Device"
   Identifier   "Configured Video Device"
   Driver "sis671"
EndSection

Modificando os repositórios


Para gerar a lista de reposítórios, estou utilizando o Ubuntu Source List Generator:


http://repogen.simplylinux.ch/

No site, você define o país e os repositórios desejados e ele cria um arquivo sources.list. Basta copiar e colar no seu computador. Pra fazer isso, abra um terminal ou digite Alt+F2 (executar aplicação) e digite ou cole esta linha:

gksu gedit /etc/apt/sources.list

Depois de criada a nova lista de repositórios, atualize o sistema. Num terminal, digite:

sudo aptitude update && sudo aptitude safe-upgrade

Isto fará com que seus sistema seja atualizado para a sua versão mais nova. Ele deve baixar e atualizar algumas centenas de megabytes, dependendo da data da instalação.

Meu sources.list, depois de gerado e modificado ficou assim:

http://paste.pocoo.org/show/155162/

A partir desse ponto, você pode instalar outros programas, fontes, drivers, codecs e tudo mais.

Instalando o pacote ubuntu-restricted-extras


O pacote ubuntu-restricted-extras instala uma série de codecs, aplicativos, fontes e drivers que possuem algum tipo de restrição e que por isso não fazem parte da instalação padrão. Entre eles, podemos citar: Máquina virtual Java (usada por sitesde bancos, por exemplo) flash (sem ele, o youtube não funciona) fontes true type (do windows), codecs de áudio e vídeo (wmv, divx, mp3, rmvb, etc.) e outros. Para instalar este pacote, digite num terminal:

sudo aptitude install ubuntu-restricted-extras

Configurando o ambiente de trabalho



- Retirar ícone de Help

- Menu Gnome Padrão
- Adicionar:
  • Menu Principal do Gnome (reduzido)
  • Lista de Janelas
- Retirar barra inferior
- Mudar tema e papel de parede
- Habilitar efeitos

- Instalar o Gnome Global Menu (descrito mais abaixo)

Configurando o Firefox

Eu costumo modificar o Firefox da seguinte forma:

  1. - Tirar barra de favoritos
  2. - Mudar ícones para ícones pequenos
  3. - Colocar ícone de "Nova aba"
  4. - Definir página inicial: http://google.com.br/ig
  5. - Adicionar Pesquisas: http://mycroft.mozdev.org/
  • MercadoLivre
  • Youtube Brasil








Instalando extensões do Firefox

No Firefox, menu Ferramentas, Complementos:

- Adblock Plus
- Colt
- Delicious
- Download Helper
- Forecastfox
- Search Preview
- Echofon
- FireGPG
- Fission
- Power Twitter

Screenlets

Instale o pacote screenlets. Não tenho mais usado, mas fica a dica de alguns screenlets interessantes:

- Relogio, Calendário

Fonte Monaco

A Fonte Monaco é a fonte monoespaçada padrão do Mac OS. Ela é muito bonita, e  a utilizo no Gedit, Terminal e X-chat, entre outros programas.

Baixar a fonte: http://blog.siverti.com.br/2008/05/22/fonte-monaco-no-ubuntugedit/

Instalar a fonte:

cd /usr/share/fonts/truetype; sudo mkdir myfonts ; cd myfonts ; sudo cp /dados/downloads/Monaco_Linux.ttf . ; sudo chown root.root *.ttf ; sudo mkfontdir ;

cd .. ; fc-cache

Aparentemente é preciso iniciar a sessão novamente para que a fonte fique disponível.

Tempo de boot


Pra diminuir o tempo de boot, siga este tutorial:

http://pastie.org/676730

Eu cheguei a 80 segundos, do boot frio até todo o sistema carregado, wifi conectada, firefox com gmail, reader e calendar completamente carregados e pidgin conectado. Faça a medição e me envie nos comentários.

Gnome-Global-Menu

O Gnome Global Menu faz com que os menus da aplicações passem a aparecer na barra superior, no estilo do Mac OS. Junto com um Dock, o sistema começa a ficar parecido com o Mac OS.

Acrescente as seguintes linhas no seu sources.list:

#Gnome Global Menu
deb http://ppa.launchpad.net/globalmenu-team/ppa/ubuntu jaunty main

Depois adicione o Global Menu pela opção de Adicionar ao Painel. Para mais detalhes, procure por tutoriais, como este:

http://nancib.wordpress.com/2009/11/24/update-the-globalmenu-in-ubuntu-9-10/

Um monte de programas de uma vez

O Ubuntu vem com um desktop corporativo padrão, mas eu sinto falta de várias aplicações. Não vou explicar pra que serve cada uma. Instale todas, experimente e crie a sua lista. Se não gostar, é só remover depois:

sudo aptitude install ubuntu-restricted-extras mplayer nautilus-dropbox nautilus-open-terminal vlc virtualbox gnome-do gnome-do-plugins banshee audacious amule vim-full gedit-plugins picasa gparted htop pidgin xchat skype

Ubuntu Perfeito


Por mais que o Ubuntu tenha evoluído em termos de configurações, o Ubuntu Perfeito continua sendo uma importante aplicação para instalar e configurar o sistema. Baixe e instale-o daqui:

http://sourceforge.net/projects/ubuntu-perfeito/files/ubuntu-perfeito-9.10/ubuntuperfeito-9.10.1_all.deb/download

Depois, vá em Sistema - Administração - Ubuntu Perfeito e o execute. Paa configurar diversas opções dele, vá em Sistema - Preferências - Menu de Serviços do Ubuntu Perfeito

Configurações de Terminal


Histórico do bash: adicionar em ~/.bashrc:

export HISTSIZE=5000

- Alias: descomentar linhas de  ~/.bashrc:

if [ -x /usr/bin/dircolors ]; then
    eval "`dircolors -b`"
    alias ls='ls --color=auto'
    alias dir='dir --color=auto'
    alias vdir='vdir --color=auto'

    alias grep='grep --color=auto'
    alias fgrep='fgrep --color=auto'
    alias egrep='egrep --color=auto'
fi

alias ll='ls -lh'
alias la='ls -A'
alias l='ls -CF'
alias ..='cd ..'
alias grep='ack-grep'



- Adicione no arquivo ~/.inputrc:



set completion-ignore-case On
"\e[B": history-search-forward
"\e[A": history-search-backward

ack - em grep melhorado

Eu uso este programa para substituir o grep tradicional:

http://betterthangrep.com/

sudo aptitude install ack-grep

coloque o alias no ~/.bashrc:

alias grep='ack-grep'

Gerenciador de inicialização

Para modificar opções de boot:

sudo aptitude install startupmanager

Latex


sudo aptitude install texlive texlive-humanities texlive-lang-portuguese babel latex-beamer \
abntex aspell-pt-br gedit-plugins gedit-latex-plugin rubber texmaker

Webcam


sudo aptitude install cheese


Páginas de manual (man) coloridas


sudo aptitude install most && sudo update-alternatives --config pager

Python


sudo aptitude install ipython bpython python-django python-sqlite


Gedit


Instalar plugins:
sudo aptitude install gedit-plugins gedit-latex-plugin

Ativar plugins e modificar configurações. O Gedit pode se tornar um excelente editor de programas, páginas web e arquivos de configuração. Faça as seguintes configurações:

  • Editar - Preferências - Visão: Marque todas as opções
  • Editar - Preferências - Editor:
    • Defina a largura da tabulação para 4
    • Marque "Inserir espaços em vez de tabulações"
    • Marque "Habilitar recuo automático"
  • Editar - Preferências - Fontes e cores:
    • Escolha a fonte de sua preferência. Eu uso a fonte Monaco com tamanho 11
  • Editar - Preferências - Plugins. Habilite os seguintes plugins:
    • Abertura rápida
    • Alterar maiusculização
    • Comentar código
    • Desenhar espaços
    • Espaços inteligentes
    • Fechamento de parênteses (verifique se você gosta deste recurso)
    • Painel do navegador de arquivos (habilite o painel com F9)
    • Trechos
    • Verificador ortográfico

Configurar fonte Monaco
: No Gedit, vá em Editar - Preferências - Fontes e Cores - Fonte do editor

Instalar outros plugins manualmente de http://live.gnome.org/Gedit/Plugins:

latex open_terminal better_python_console

Gnome-do


sudo aptitude install gnome-do gnome-do-plugins

Nautilus


sudo aptitude install nautilus-open-terminal

Baixar e instalar:

  • nautilus-send-gmail_0.1.1-1_all.deb
  • nautilus-rename-exif-date_0.1.1-1_all.deb

- trocar linhas:

-- Alterar o programa /usr/lib/nautilus/extensions-2.0/python/nautilus-rename-exif-date.py
    def menu_activate_cb(self, menu, names):
        """Called when the user selects the menu. Rename the selected files."""
        for path in names:
            img_file = open(path, "rb")
            tags = EXIF.process_file(img_file)
            date = str(tags["EXIF DateTimeOriginal"]).replace(":", "-", 2)
            date = date.replace(":", "", 1)
            date = date.replace(":", "", 1)
            date = date.replace(":", "",1)
            date = date.replace(" ", "-",1)

            dir_name = os.path.split(path)[0]
            file_name = os.path.split(path)[1]
            parts = file_name.split(".")
            if len(parts) == 1:
                extension = ""
            else:
                extension = "." + parts[-1].lower()
            os.rename(path, dir_name + "/" + date + extension)

Adicionar scripts a ~/.gnome2/nautilus-scripts (menu de contexto)

Criar links simbólicos para pastas


Padrão: ln -s destino

sudo rm -Rf /usr/local/bin && ln -s /dados/downloads/scripts /usr/local/bin
cd
sudo rm -Rf Documentos Imagens Modelos Música Público Vídeos
ln -s /dados/Dropbox/aulas/
ln -s /dados/imagens/
ln -s /dados/videos/
ln -s /dados/videos/filmes/
ln -s /dados/musicas/
ln -s /dados/series/

Ativar o CTRL+ALT+BACKSPACE para reiniciar o X

Se você não sabe o que é, provavelmente não precisa. Isto habilita uma combinação de teclas pra derrubar e reiniciar o servidor gráfico,conhecido por "X":

gksu gedit /etc/X11/xorg.conf

Adicione as seguintes linhas:


Section "ServerFlags"
        Option          "DontZap"               "false"
EndSection

Instalar impressoras


Existem duas opções:

  1. No Menu: Sistema - Administração - Impressão
  2. No navegador: http://localhost:631/


DVD

sudo aptitude install dvdrip devede


Jpilot


sudo aptitude install jpilot jpilot-plugins jpilot-backup jppy-jpilot-plugins


Diff


sudo aptitude install meld


Aplicativos e jogos para crianças


sudo aptitude install gcompris gcompris-sound-ptbr tuxpaint tuxpaint-plugins ktuberling



IRC

sudo aptitude install xchat

- Modificar encoding para utf-8
- Usar fonte Monaco


Cópia de segurança com sincronização


rsync -acruz --progress --rsh=ssh /dados/ usuario@servidor.com.br:/home/usuario/


LED da rede sem fio


sudo aptitude install linux-backports-modules-jaunty

Gmail como cliente padrão de email


Criar script (/usr/local/bin/gmail.sh, por exemplo)

gksu gedit /usr/local/bin/gmail.sh

Colocar as seguintes linhas no arquivo:

#!/bin/sh
firefox -remote "openurl(https://mail.google.com/mail?view=cm&tf=0&to=`
echo $1 | sed 's/mailto://'`,new-tab)"


Tornar executável:

sudo chmod +x /usr/local/bin/gmail.sh

Atribuir o script em Sistema - Preferências - Aplicativos Preferenciais - Leitor de email:



por Marco André Lopes Mendes (noreply@blogger.com) em 06 de December de 2009 às 12:27

Gustavo Niemeyer

Breaking into an Android password manager – Practice

In the last post, we’ve seen some security issues which exist in the Android password manager gbaSafe version 1.1.0a, by analyzing the security description provided in its web site. As described there, even though the system depends on a “master key” which might be secure, the security of the system is seriously compromised by the encouragement of very weak keys (a few digits only) in what is named an “unlock key”, used to encrypt the master key itself. All of that in an application which claims to strongly protect people’s data from unwanted eyes.

In this post, we will play a bit with the Linux-based Android OS to actually explore these security deficiencies, demonstrating that such issues are very real, and that the claims of being hard to unveil the data is unfounded. Since the most serious weakness lies in the key itself, we’ll run a simple brute force attack to try to find arbitrary unlock keys.

This procedure is actually mentioned by the author of gbaSafe himself in the web page, except he overestimates the work involved in producing such a mechanism:

Theoretically, somebody could write a program that tries to decrypt the master key by trying all possible values of the short key (with 4 digits there are only 10000 possibilities), but this would still be much work, as more information about the crypting algorithm is needed (e.g. salt bytes, iteration count).

So let’s get started.

As a first step, we’ll need the Android SDK with a working emulator (I’ve used API level 5, revision 1), and a copy of the application itself. I got a trial version of the application from AndAppStore.com.

The application downloaded is bundled within that .apk file, which is really a .zip file that may be opened up normally with any tool which understands this file format.

Once that’s done, we get access to all the information needed to run the application, including icons, interface layouts, and most importantly in this case, the bytecode which targets the Dalvik VM. This bytecode is the end result of a sequence of translations which happen when the program’s Java source code is compiled, so that’s what we’ll have to fiddle with to figure details of the application we want to investigate.

The bytecode is located inside the classes.dex file, and as expected it’s not easy to read in its native format. Luckily, though, a smart guy has already written a couple of tools, smali and baksmali, which allow people to decompile and recompile that bytecode format to/from something that is much easier to understand.

After downloading these tools, the following command should decompile the file:

$ java -jar baksmali.jar –output classes classes.dex

We now have a classes/ directory full of .smali files.

Before going any further, let’s ponder for a moment about what we want to do. A brute force attack is when we attempt sequentially many possible keys, and given the context already presented, what we’re looking after is to attempt different “unlock keys”. With that in mind, we’ll introduce a very small modification in the application so that it will attempt to enter the unlock key automatically, rather than reporting an error when the key entered in the unlock dialog is invalid.

With that in mind, after some quick research, it looks like the onClick() method within the DlgUnlock.smali file is a pretty good candidate. This is supposedly called when the button in the unlock dialog is clicked, so something interesting about the password being correct or not must happen there.

Before doing anything there, I’ve increased the number of registers in the function to 12, to get some additional registers to play with, and then initialized a register with the value zero, to serve as a monotonically increasing number (our keys!):

.method public onClick(Landroid/view/View;)V
- .registers 9
+ .registers 12
.parameter “view”
+ const/16 v9, 0×0

Then, we have to instruct the program to use these keys rather than whatever is typed in the dialog box. Some lines down, we’ll see a call to the checkUnlockKey() method, which is certainly what we’re looking after. Let’s do this now:

+ :mykey
+ invoke-static {v9}, Ljava/lang/String;->valueOf(I)Ljava/lang/String;
+ move-result-object v2
invoke-static {v2}, Lcom/gbizapps/safeA/Crypt;->checkUnlockKey(Ljava/lang/String;)I

Now, what if this key is wrong? We don’t want the master key to be removed as mentioned in the software description. We want to simply attempt the next key. With some analysis, we see that in case of errors, the next couple of lines below the above code will instruct the VM to jump to an error branch. Rather than following up with the normal error logic, we’ll increment the key, and jump back to the above code:

:cond_6c
+ add-int/lit8 v9, v9, 0×1
+ goto :mykey

Now we just have to rebundle this and put it into the emulator. I won’t go over it in too much detail here, since there’s plenty of information available online, but the steps to do that are:

  1. Recreate a modified classes.dex with smali
  2. Recreate a modified .apk file by just zipping the modified content
  3. Sign and zipalign the new .apk file
  4. Install it

And that’s it, seriously! This would be enough to break the software security if it was working correctly.

Interestingly, though, the software wasn’t working correctly with this change. Instead, it was Force Closing on certain keys. To test it out, use the master key “master key”, and the unlock key “999999″, and then once you close and open the application again, try to unlock it with the key “1175″. Instead of showing an error message, it will break badly.

Now, for the proof of concept to work, I actually had to fix the bug, which felt a bit funny to do given the context.

Looking at the traceback trough adb logcat, I found out that there was a null being dereferenced in the file Crypt.smali, so I fixed the problem by injecting some error checking at this position and jumping the flow into an existing error branch:

+ if-eqz v3, :cond_5a
const-string v4, “ucpmhkexov85MDKhdfdfFGQPYxywq7209fcrqhghjkuiopy”

With this in place came the biggest surprise of the experiment. The keys which were crashing the application were special, in the sense that they actually decode the master key successfully! That’s right: whatever the algorithm is doing, that six-digit “999999″ encrypts the master key in such a way that attempting the “1175″ key works, so even big keys are rendered extremely weak with the logic used to encrypt the master key.

At this point, I added some trivial logic to display the key found with a Toast, just to ensure the whole thing was working correctly:

Toast displaying unlock key found

Note that the key generation implemented above is a bit simplistic, in the sense that it doesn’t attempt keys with leading zeros, but this would be trivial to implement, and my intention here isn’t to actually break any keys for real, but just to show how the promised security in this application is not to be trusted at all. Just the logic above will already be enough for a brute force attack against the application, and has broken all the keys I’ve tried in mere seconds, in a slow emulator.

As a conclusion, if you want to put your data in a secure place, rather than picking an application which promises security because the salt is hidden somewhere or because it’s too much work to figure its logic, pick an open source application with logic which is publicly verifiable and has already had many eyes over it. Chances are that doing something like what was described in this post won’t be so trivial. Then, choose your keys wisely! The most secure application won’t be enough if you pick a bad key.

por Gustavo Niemeyer em 06 de December de 2009 às 00:38

December 04, 2009

Rodrigo Amaral

amaral


A versão 1.2.8 do Google App Engine SDK já está disponível para download. O novo release traz muitas melhorias no serviço de Task Queue e no Admin Console, além de várias pequenas correções.

Para mais detalhes:

por Rodrigo Amaral em 04 de December de 2009 às 13:02

December 02, 2009

Gustavo Niemeyer

Breaking into an Android password manager – Theory

For some time now I’ve been wanting to research more deeply about the internals of Android. Until now, though, this was just a sentiment. Then, a couple of weeks ago I’ve finally managed to replace my iPhone for an Android phone, and that was the final motivator for me to actually get into learning more about the inner workings of the Linux-based OS.

Now, I just had to pick an actual task for digging into. The Dalvik VM is certainly one of the most innovative and advertised technical details about the OS, so something around it would be a nice start.. some kind of bytecode fiddling perhaps, but what? Luckily, even without trying too hard, I eventually stumbled upon an interesting case for researching upon.

The “victim” of this research is the application gbaSafe version 1.1.0a, which claims to protect user passwords using unbreakable algorithms (how’s that for a hint of a Snake oil case?).

Before we get into some hacking, let’s see some words on the software security by the author himself, and then render some analysis on conceptual issues on it:

The confidential data can only be decrypted if the master key is known. You should choose a long key (at least 16 characters) with mixed case and unreadable text. Of course you cannot enter this key each time you want to access the confidential data, so it is stored in the user settings encrypted with a shorter key (4 to 6 digits) and normally you only have to enter this unlock key. Theoretically it is possible to try all possible values (brute force attack), but then you must use another program, since gbaSafe deletes the encrypted master key from the user settings when you enter the unlock key wrong three times repeatedly, and then you must enter the master key. If you wrote a program to decrypt the master key, you would have to know the algorithm used, the salt bytes and iteration count (used to augment the short unlock key), which are very hard to extract from the binary program module gbaSafe.

If you have some security background, I’m sure that by now you’re already counting the issues on this single paragraph.

The most obvious issue is the fact that there’s a “strong key” and a “weak key”, and the strong key is encrypted with the weak one. This is a very common cryptography sin, as would say my friend and coworker Andreas Hasenack (a security researcher himself). A security system is only as secure as its weakest spot. It obviously makes little difference for an attacker if he has to attempt decrypting a master key or the actual data, since decrypting the master key will give access to the data.

Then, it mentions en passant that the software enforces the use of digits for the weak key. This ensures that the weak key is really weak! Four digits is basically ten thousand attempts, which is absolutely nothing for nowadays’s hardware. This number would move up to about 15 million by simply allowing upper and lowercase letters as well (which isn’t great either, but a few orders of magnitude never hurt in this scenario).

It follows up encouraging people to think that it’s actually hard to figure the algorithm and other implementation details. Considering that there’s absolutely nothing preventing people from getting their hands in the implementation itself, this is in fact asserting that the security mechanism is based on the ignorance of the attacker. Counting on the ignorance of people is bad at all times, and in a security context it’s a major error.

There’s a final security issue in this description which is a bit more subtle, but further analysis on the logic used leaves no doubt. In cryptography, the salt is supposed to increase the work needed in a brute force attack by strengthening the number of bits of the actual passphrase, in a case where the salt is actually unavailable, or at least prevent that a single large word dictionary can be used to attack several encryptions or hashes at once, in a case where the salt is known but variable. In the latter case, it helps because encrypting a single key with two different salts must be done twice, rather than once, so it increases the computational task when attacking multiple items. A salt which is known and does not change across all processed items is worth pretty close to nothing.

So, indeed, considering the many security issues here, this isn’t something I’d store my passwords or credit card numbers on, and I suggest you don’t do it either.

In my next post on this topic I’ll actually implement a trivial brute force attack to prove that these issues are very real, and that, actually, it’s not even hard to break into a security system like this.

The application author has been contacted about this blog post, since he’ll likely want to fix some of these issues.

por Gustavo Niemeyer em 02 de December de 2009 às 01:33

December 01, 2009

Arthur Furlan

Creating the urllist.txt with your sitemaps configuration

In Django, you can configure the sitemap of your website using the sitemaps framework and then use this configuration to generate the sitemap.xml. Notwithstanding, the Yahoo! used to support only the urllist.txt type of sitemap and, because of that, I still use to have both (urllist.txt and sitemap.xml) available on my websites.

But, once you have your sitemap configured, why not use it to generate the urllist.txt? I created a view which generates the urllist.txt based on your sitemap configuration, as follows:

# -*- coding: utf-8 -*-

from django.conf import settings
from django.http import HttpResponse
from django.contrib.sites.models import Site

def urllist_from_sitemaps(request, sitemaps):
        urllist = []
        protocol = getattr(settings, 'PROTOCOL', 'http')
        baseurl = u'%s://%s' % (protocol, Site.objects.get_current().domain)
        for cls in sitemaps.values():
                instance = object.__new__(cls)
                for item in instance.items():
                        urllist.append(baseurl + item.get_absolute_url())
        return HttpResponse(u'\n'.join(urllist), mimetype='text/plain')

And now, you just need to configure the urls.py and add the urllist.txt entry:

sitemaps = {
    'entries': EntrySitemap,
    'tags': TagSitemap,
    'archive': ArchiveSitemap,
}

urlpatterns = patterns('',
    ...
    (r'^sitemap.xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': sitemaps}),
    (r'^urllist.txt$', 'myproj.apps.myapp.views.urllist_from_sitemaps', {'sitemaps': sitemaps}),
    ...
)

And I think that is all for now...

Update 1: I submitted a patch to be added into the official Sitemaps framework of the Django. The patch is very different of the code in this post and, if you'd like to see it and its code, here it is.

As always: if you found some english bug, warn me and I'll be glad to fix it. :)

01 de December de 2009 às 16:42

Inno::Blog

Droplet: Um Twitter & Google Reader em C++ para Arduino

 

Esbarrei com este projeto que achei bastante interessante, como um link às vezes é mais verboso do que mil palavras:

- Droplet

 


por techberto em 01 de December de 2009 às 00:34

November 26, 2009

Noticias da APyB

As fotos e vídeos da PythonBrasil[5] estão disponíveis!

A Associação Python Brasil liberou os vídeos da última edição da PythonBrasil, ocorrida em Caxias do Sul.

por mdpetry em 26 de November de 2009 às 16:40

November 25, 2009

Stiods Palace

Make e Makefile

Você que utiliza algum *nix da vida já deve ter passado pelo momento mágico de ter executado o comando make em algum código fonte, não?

O make (GNU make) é uma ferramenta que executa os comandos inclusos dentro de um arquivo. É normalmente utilizado na compilação e instalação de programas.

Uma das vantagens do make é que ele identifica quais partes do programa devem ser recompiladas de acordo com as mudanças efetuadas desde a última compilação.

Dependendo do tamanho do programa pode-se economizar minutos ou horas entre as recompilações, pois não será necessário recompilar o programa inteiro.

Exemplo de uso:

$ make -f arquivo_com_os_comandos

Se você chamar o comando make sem passar nenhum parâmetro ele tentará utilizar o arquivo com nome de Makefile do diretório atual.

É o que normalmente acontece quando você precisa compilar e instalar um programa pelo código fonte.

  • Descompactar o código fonte (se for um "*.tar.gz").
  • Entrar na pasta descompactada. Haverá um arquivo Makefile dentro.
  • Executar o comando "make" para compilar.
  • Executar o comando "make install" como root para instalar.

Makefile

Se você quiser utilizar o comando make só é necessário criar um arquivo Makefile e dentro dele colocar as instruções que o make deve executar.

Formato do Makefile:

regra: dependências...
	comandos
	...

Os comandos são comandos normais do shell (bash). Pode-se colocar vários comandos, porém devem estar identados com tabulações. Isto é importante, não utilize espaços pois não irá funcionar.

A regra é só um nome para identificar um bloco de comandos. Fazendo uma analogia com programação, a "regra" seria semelhante a uma função.

As dependências são os arquivos necessários para a execução dos comandos da regra, o make irá fazer a verificação deles. Também podem ser outras regras que serão chamadas antes da execução dos comandos. Se houver mais de uma dependência elas devem ser separadas com espaços.

Aqui vai um exemplo de um Makefile que compila um programa em C:

program:
	gcc -o meuprograma meuprograma.c

Um exemplo com dependências:

program: cod1.c cod2.c lib1.a
	gcc -c cod1.c cod2.c
	gcc cod1.o cod2.o lib1.a -o program

lib1.a: lib1.c cod3.c
	gcc -c lib1.c cod3.c
	ar rcs lib1.a lib1.o cod3.o
	ranlib lib1.a

Pode-se utilizar variáveis também. A declaração é simples, mas devem ser chamados com a notação "$(variável)". Repare também que elas podem ser concatenadas:

CC=gcc
CFLAGS=-O2
CFLAGS=$(CFLAGS) -Wall

program:
	$(CC) $(CFLAGS) -o program program.c

Olha que legal no Makefile a seguir, advinha o que acontece ao executar o comando `make clean' no terminal?

program: program.c
        gcc -o program program.c

clean:
        rm *.o
        rm program

O que aconteceria também se houvesse um arquivo no diretório atual que se chamasse "clean"? O `make clean' não iria executar a lista de comandos da regra. Para evitar este tipo de conflito utilize a regra ".PHONY":

program: program.c
        gcc -o program program.c

.PHONY: clean
clean:
        rm *.o
        rm program

Agora a regra "clean" será executada mesmo se houver um arquivo no diretório atual com mesmo nome.

por Yoshio Iwamoto em 25 de November de 2009 às 14:43

Gustavo Niemeyer

The last 4 years (and the next N?)

Some interesting changes have been happening in my professional life, so I wanted to share it here to update friends and also for me to keep track of things over time (at some point I will be older and will certainly laugh at what I called “interesting changes” in the ol’days). Given the goal, I apologize but this may come across as more egocentric than usual, so please feel free to jump over to your next blog post at any time.

It’s been little more than four years since I left Conectiva / Mandriva and joined Canonical, in August of 2005. Shortly after I joined, I had the luck of spending a few months working on the different projects which the company was pushing at the time, including Launchpad, then Bazaar, then a little bit on some projects which didn’t end up seeing much light. It was a great experience by itself, since all of these projects were abundant in talent. Following that, in the beginning of 2006, counting on the trust of people which knew more than I did, I was requested/allowed to lead the development of a brand new project the company wanted to attempt. After a few months of research I had the chance to sit next to Chris Armstrong and Jamu Kakar to bootstrap the development of what is now known as the Landscape distributed systems management project.

Fast forward three and a half years, in mid 2009, and Landscape became a massive project with hundreds of thousands of very well tested lines, sprawling not only a client branch, but also external child projects such as the Storm Object Relational Mapper, in use also by Launchpad and Ubuntu One. In the commercial side of things it looks like Landscape’s life is just starting, with its hosted and standalone versions getting more and more attention from enterprise customers. And the three guys which started the project didn’t do it alone, for sure. The toy project of early 2006 has grown to become a well structured team, with added talent spreading areas such as development, business and QA.

While I wasn’t watching, though, something happened. Facing that great action, my attention was slowly being spread thinly among management, architecture, development, testing, code reviews, meetings, and other tasks, sometimes in areas not entirely related, but very interesting of course. The net result of increased attention sprawl isn’t actually good, though. If it persists, even when the several small tasks may be individually significant, the achievement just doesn’t feel significant given the invested effort as a whole. At least not for someone that truly enjoys being a software architect, and loves to feel that the effort invested in the growth of a significant working software is really helping people out in the same magnitude of that investment. In simpler words, it felt like my position within the team just wasn’t helping the team out the same way it did before, and thus it was time for a change.

Last July an external factor helped to catapult that change. Eucalyptus needed a feature to be released with Ubuntu 9.10, due in October, to greatly simplify the installation of some standard machine images.. an Image Store. It felt like a very tight schedule, even more considering that I hadn’t been doing Java for a while, and Eucalyptus uses some sexy (and useful) new technology called the Google Web Toolkit, something I had to get acquainted with. Two months looked like a tight schedule, and a risky bet overall, but it also felt like a great opportunity to strongly refocus on a task that needed someone’s attention urgently. Again I was blessed with trust I’m thankful for, and by now I’m relieved to look back and perceive that it went alright, certainly thanks to the help of other people like Sidnei da Silva and Mathias Gug. Meanwhile, on the Landscape side, my responsibilities were distributed within the team so that I could be fully engaged on the problem.

Moving this forward a little bit we reach the current date. Right now the Landscape project has a new organizational structure, and it actually feels like it’s moving along quite well. Besides the internal changes, a major organizational change also took place around Landscape over that period, and the planned restructuring led me to my current role. In practice, I’m now engaging into the research of a new concept which I’m hoping to publish openly quite soon, if everything goes well. It’s challenging, it’s exciting, and most importantly, allows me to focus strongly on something which has a great potential (I will stop teasing you now). In addition to this, I’ll definitely be spending some of that time on the progress of Landscape and the Image Store, but mostly from an architectural point of view, since both of these projects will have bright hands taking care of them more closely.

Sit by the fireside if you’re interested in the upcoming chapters of that story. ;-)

por Gustavo Niemeyer em 25 de November de 2009 às 04:16

November 23, 2009

Gustavo Barbieri

And more EFL news out there!

Wow! Just after my last week post about companies supporting EFL, we were pleased with two more announcements:

  • Ardy, a tool that brings together EFL and Arduino using Python
  • Free.fr, the second biggest ISP in France opened up the development of their Freebox HD set-top box using Enlightenment Foundation Libraries and Mozilla JavaScript library. This is pretty amazing as it’s the biggest deployment of EFL out there, an uncertain number that ranges from 2 to 3 million devices.

por Gustavo Sverzut Barbieri em 23 de November de 2009 às 12:03

November 19, 2009

Flávio Coelho

Developing a Wave Robot in Python

I have been so busy lately that I almost forgot to write about my lightning venture into writing a Google Wave robot: Trendy.For those of you living under a rock in the last several months, Google Wave offers an API for the development of robot, which are... well, robots, which when added to waves, do automated tasks with its contents. There are robots for translating, do syntax highlighting on

por Flavio Coelho (noreply@blogger.com) em 19 de November de 2009 às 07:45