Páginas

Thursday, December 10, 2009

Novas línguas do semestre

Neste segundo semestre de 2009 inicei meu contato com diversas novas línguas e linguagens.
Para começar, estou agora morando em Portugal, o que me deixa em contato com um português um bocado diferente do que estava acostumado no Brasil.

Depois, por ter contato com amigos de diversas partes do globo, o inglês é certamente a língua que mais tenho utilizado no dia-a-dia. Para completar, tem o Polonês e o Turco, que podem parecer exóticos mas tem feito parte do meu cotidiano no momento.

Mas, o que tenho feito de novo aqui em Lisboa? Só vida boa? Não, não.
Os trabalhos da faculdade me fizeram desviar da jornada estritamente pythônica para olhar outras linguagens.

No Brasil meus amigos continuam arrasando com as super comunidades, mega encontros, e muita agitação todos os dias da semana. Aqui, encarei um projeto de Inteligência Artificial usando LISP.
O objetivo era resolver automaticamente instâncias do jogo Hidato.

Inicialmente o contato com LISP não foi muito amigável, porém com o tempo fui pegando o gosto e vi muito espaço para aprendizado com esta linguagem. Implementei meu projeto para o ambiente CLISP, e fiquei muito satisfeito pela boa velocidade com que resolvia grandes instâncias do jogo.

Os pontos que me deixaram curiosos no LISP e que ainda não tive a oportunidade de brincar foi o processamento de texto, acesso a dados via Internet, e outros detalhes que não me vêm à cabeça neste momento...

O lado negro foi ter que cursar Programação com Objectos usando Java, linguagem extremamente burocrática, e que nenhum conhecimento interessante me traz. É impressionante a distância entre uma idéia pra solucionar um problema e uma solução implementada em Java. Talvez os mais experientes hackers da terra do cafezinho vão discordar desse meu desabafo sem código, mas aqui o objetivo é só relatar meu descontentamento mesmo :P

Por fim, Matlab. É um ambiente proprietário, de sintaxe muitas vezes esquisita, e que estou utilizando nas aulas de Processamento de Imagens. Não vi ainda vantagens em relação a usar Python + Numpy + Matplotlib... ainda assim, é uma linguagem interpretada e lá temos console e um manual muito bem elaborado.

Acho que as linguagens compiladas tem um ponto a menos nas minhas avaliações por conta da velocidade do "escrever código". Legibilidade e fluxo de desenvolvimento acabam valendo mais que tempo de execução.

Monday, September 21, 2009

Novo blog com histórias e relatos da minha viagem para Portugal

Hoje finalmente comecei o blog para relatar minha viagem, o um ano de intercâmbio em Lisboa.

Aos que quiserem acompanhar a jornada, apontem para Lisboa, Portugal.

Friday, September 11, 2009

Lisboa, Portugal

Eis que cá estou desde segunda-feira. Esta tem sido uma semana muito boa.

Conheci novos países, novas culturas, novas pessoas... sim... PESSOAS muito interessantes. Escrevi algumas coisas em papel nos primeiros dias, depois pretendo postar.

Agora moro aqui em Portugal por um ano, muitas novidades por vir, como o Coding Dojo Lisboa! Aguardem.

Sunday, August 23, 2009

Windows Vista: filtrando visualização no Windows Explorer

Muitas vezes ficamos apenas reclamando dos Sistemas Operacionais, reclamamos do Windows, ele não presta, a Microsoft é má, isso e aquilo...
Bem, depois de ouvir cuidadosamente a palestra do Robert M. Lefkowitz na PyCon 2007, espero que você mude de idéia e comece a entender onde fica o software livre e o proprietário, pois ambos tem seu espaço. Então agora estou escrevendo a favor do Windows Vista, já que acabo de descobrir uma funcionalidade muito bacana, que parece ficar escondida na interface...

Programar no Windows não costuma ser uma tarefa tão divertida quanto ter um Linux bem arrumado, mas em ambos os casos eu sempre fico querendo esconder os arquivos .pyc e ver só o que interessa, os .py.
O que eu descobri é que com o Windows Explorer eu posso fazer isso e um pouco mais!

Aqui está um diretório com alguns arquivos Python e seus respectivos compilados, no modo de exibição "detalhes":

Colocando o mouse sobre qualquer coluna aparece uma seta no canto direito, como pode ser visto abaixo. Clique nesta seta para exibir um menu contextualizado com a coluna. Por exemplo, na coluna "Modificado em", é possível filtrar os arquivos por data. Tem até opções para filtrar os arquivos mais recentes, por semana, mês ou ano. Veja:

E você pode filtrar por nome, neste caso resolvi mostrar apenas os arquivos cujo nome começa com números (ocultando o __init__.py, que neste caso não é tão interessante):

E posso agrupar por tipo de arquivo, assim posso acessar separadamente, como se fossem dois "diretórios virtuais":

Note que desde a segunda tela eu já estava usando o filtro por "Tipo" para exibir apenas "Python file", resolvendo meu problema com os ".pyc" que só distraem!

Python: o print agora se chama raw_input

Opa! Ah? Que? O que que houve? Como assim?

Certo, nada mudou no Python... na verdade mudou, agora no Python 3.0 o raw_input virou input, que não deve ser confundido com o input presente nas versões pre-3.0.

A dica que deixo aqui é apenas um fato que percebi que tenho utilizado há algum tempo... talvez uma nova "técnica", mas que não dei muita bola até que comecei a falar sobre ela com amigos, e pensei que não faria mal relatar aqui.

Às vezes queremos colocar um print no meio do código, naquele processo de depuração (claro, você está fazendo TDD e dificilmente precisa fazer isso) e o que acontece é que, na maioria dos casos, temos que ficar caçando onde o output foi parar, quando você tem muita informação que surge no terminal.

Então, use o raw_input, que terá o mesmo efeito do print, porém o interpretador vai parar logo após exibir o que solicitou. Basta pressionar qualquer tecla para continuar a execução do script.

Outrar opção é parar com AssertionError, fazendo:

assert False, objeto_ou_valor_a_ser_inspecionado

Exemplo:
def get_tweets(user):
   from gluon.tools import fetch
   from gluon.contrib.simplejson import loads as sj_loads
   
   page = fetch('http://twitter.com/%s?format=json' % user)
   return sj_loads(page)['#timeline']

#print get_tweets('ilovetweeting')
raw_input(get_tweets('ilovetweeting'))

Saturday, August 22, 2009

Novo domínio e demais novidades

Olá!

A novidade mais recente é que agora o lifeatmymind.blogspot.com é blog.rodolfocarvalho.net!
Outra é que a partir do próximo mês vou residir em Lisboa, Portugal. Em busca de novas aventuras...

E isso quer dizer que globo.com agora entrou para a história, não estou mais desenvolvendo lá. Excelente experiência que tive nos últimos 8 meses, agora é partir para o desconhecido na Europa.

Dev in Rio 2009

Que Rock in Rio que nada... o evento de 2009 é o Dev in Rio!
Este evento é diferente de tudo que você já viu, e de todos os eventos que já paticipou. E o que me deixa tão confiante para dizer isso? Bem, o foco nas PESSOAS.

Este não é apenas um evento sobre tecnologias e máquinas, e sim um encontro de PESSOAS com um propósito. Ser diferente, a constante busca em fazer o melhor, vontade de mudar o mundo... se você procura pessoas que compatilham deste interesse, vá ao Dev in Rio 2009.

Os créditos vão para os meus amigos Guilherme Chapiewski e Henrique Bastos, dois dos grandes movimentadores de comunidade de software aqui no Rio de Janeiro, e para todos os outros envolvidos que estão tornando o Dev in Rio uma feliz realidade.

O evento será realizado no próximo mês, na segunda-feira dia 14 de Setembro de 2009. É o início da semana com o pé direito.
Infelizmente eu não vou poder participar, pois estarei iniciando outra coisa: minhas aulas em Lisboa!

Então, se não é Dev in Rio em 2009, será Rock in Rio Lisboa em 2010 e Dev in Rio 2010, já apostando na segunda edição!

Além de palestrantes nacionais e internacionais, vai ter uma arena rolando Dojo Rio durante o evento. Já se conscientizou que é imperdível?

Agora é só correr e fazer logo sua inscrição, pois as vagas são limitadas.

Friday, August 14, 2009

Filtros personalizados no admin do Django

Então ontem estava eu pensando na melhor forma de colocar meu próprio filtro naquela caixa lateral da interface padrão da aplicação 'admin' do Django.

Num ModelAdmin você normalmente pode especificar um nome de um campo que faça parte do seu Model, mas não pode fazer por exemplo um filtro por um valor computado.

Eu já tinha começado por uma abordagem bem rasteira de estender os templates padrão e colocar meu filtro logo abaixo dos outros filtros (guardado numa shelf do Bazaar :P). Mas eis que a melhor solução até agora foi a do Marinho Brandão e do Semente no DjangoSnippets.

Fiz algumas poucas alterações para pegar do banco apenas valores distintos, e apesar de ser um ponto que pode prejudicar o desempenho, gero a lista a cada requisição -- caso contrário, a lista só será recomputada quando o servidor for reiniciado. Talvez fosse mais interessante gerar um lista fixa de opções (implicando nenhum acesso ao banco), ou mesmo ao invés de consultar N linhas do banco e remover valores duplicados, poderia partir de uma lista fixa e chegar se o banco contém resultados para o valor da lista.

# meu_projeto/minha_app/admin/filterspecs.py
from django.contrib.admin.filterspecs import FilterSpec, ChoicesFilterSpec
from django.utils.encoding import smart_unicode
from django.utils.translation import ugettext as _


class AlphabeticFilterSpec(ChoicesFilterSpec):
"""
Adds filtering by first char (alphabetic style) of values in the admin
filter sidebar. Set the alphabetic filter in the model field attribute
'alphabetic_filter'.

my_model_field.alphabetic_filter = True

Based on http://www.djangosnippets.org/snippets/1051/
"""

def __init__(self, f, request, params, model, model_admin):
super(AlphabeticFilterSpec, self).__init__(f, request, params, model,
model_admin)
self.lookup_kwarg = '%s__istartswith' % f.name
self.lookup_val = request.GET.get(self.lookup_kwarg, None)
self.model = model

def choices(self, cl):
yield {'selected': self.lookup_val is None,
'query_string': cl.get_query_string({}, [self.lookup_kwarg]),
'display': _('All')}

f = self.field
values_list = self.model.objects.distinct().values_list(f.name, flat=True)
# getting the first char of values
lookup_choices = sorted(set(val[0].lower() for val in values_list if val))

for val in lookup_choices:
yield {'selected': smart_unicode(val) == self.lookup_val,
'query_string': cl.get_query_string({self.lookup_kwarg: val}),
'display': val.upper()}


# registering the filter
FilterSpec.filter_specs.insert(0, (lambda f: getattr(f, 'alphabetic_filter', False),
AlphabeticFilterSpec))


E para ativar seu filtro para algum campo:

# meu_projeto/minha_app/models.py
# [...]

class Empresa(models.Model):
nome = models.CharField(max_length=64)
nome.alphabetic_filter = True
# [...]


# meu_projeto/minha_app/admin/__init__.py
# [...]
class EmpresaAdmin(admin.ModelAdmin):
list_display = ('nome', 'cnpj', 'inicio_convenio',
'_termino_convenio', 'natureza')
list_display_links = ('nome', 'cnpj')
list_filter = ('natureza', 'termino_convenio', 'inicio_convenio', 'nome')


# meu_projeto/urls.py
# Chama o código que registra o filtro personalizado
import sgtce.admin.filterspecs
# [...]

Wednesday, August 12, 2009

Web2py hack day



Na última sexta-feira realizamos um encontro em um dos laboratórios da Peta 5 na UFF.
O tema foi o framework desenvolvimento de aplicações web web2py, escrito em Python, e que conta com uma crescente comunidade -- boa parte dela aqui no Brasil.

Este post serve como uma continuação da história sobre o que estamos fazendo aqui no Rio.
Como conversamos depois do último dojo na quarta-feira passada, "estamos procurando por melhores formas de desenvolver software fazendo e ajudando outros a fazer o mesmo..." e por aí vai o Manifesto Ágil. Só que, para fugir da imagem enganosa estabelecida pelas buzzwords -- os conceitos deturpados de o que é fazer software, cunhamos o termo framps como a nossa palavra para descrever o que somos e fazemos.




Estão foi isso, tivemos o web2py hack day framps. Juntamos membros do Dojo Rio, PythOnRio, INPI, UFF, etc. Alguns computadores, disposição e as dicas e orientações do Álvaro Justen, e rapidinho fomos desenvolvendo nosso produto: o web2itter!

Se virem esse nome em qualquer outro lugar, não se enganem, fui eu quem inventei! Apesar do escopo amplo, o primeiro release foi apenas uma aplicação concorrente do Twitter, com a diferença de suportar muito mais requisições por segundo que o original.

Depois, só porque a UFF tinha que fechar as portas e porque nossos estômagos estavam vazios, paramos de programar e fomos para o Vestibular do Chopp encarar uma picanha... e algumas horas de bate-papo sobre os mais variados temas, incluindo a história do projeto GNU e o papel do Linus Torvalds e seu kernel, as opções de controle de versão de código-fonte: git, mercurial (hg) e bazaar (bzr), e mais um monte de coisas que sinceramente eu já nem lembro :P.

E pra isso tudo não poderiam faltar fotos! Vejam as fotos do I Web2py Hack Day Framps.

Saturday, August 8, 2009

If-else em uma linha de Python

Hoje aprendi mais uma forma [tosca] de fazer condicional com Python.

Depois do truque lógico do "condicao and valor_caso_verdadeiro or valor_caso_falso", o que descobri navegando na Internet hoje foi:

>>> x = 5
>>> ["menor que 10", "maior que 10"][x > 10]
'menor que 10'

Isso funciona porque o tipo bool (valor booleano) é um subclasse do tipo int, tipo requerido em indices de sequências.

>>> ["menor que 10", "maior que 10"]['not an integer']
TypeError: list indices must be integers

>>> issubclass(bool, int)
True

>>> ["menor que 10", "maior que 10"][True]
'maior que 10'


Mas é claro que isso é só um "acidente" e não deve ser usado normalmente. A partir do Python 2.5 temos a sintaxe:

valor_caso_verdadeiro if condicao else valor_caso_falso

Sunday, July 5, 2009

O que nós estamos fazendo aqui no Rio?

Após ver o post do Tapajós, deu vontade de espalhar mais pela rede o que temos feito por aqui na Cidade Maravilhosa...

Ultimamente a turma do Rio de Janeiro anda bastante agitada e muita gente está sem entender o que é Hora Extra, Coding Dojo Rio, Hack Framps e outros encontros. A explicação é simples, basicamente nós criamos uma certa rotina, com pequenos encontros onde a gente se diverte, bebe cerveja e ainda aprende muito.

Que eventos são esses?

Hora Extra

Trata-se do nosso choppinho semanal que acontece todas as segundas-feiras no Bar Antigamente a partir das 19:30h. Apesar do objetivo ser apenas jogar conversa fora e beber, é impossível juntar mais de três nerds e não rolar muita discussão sobre trabalho, tecnologias, frameworks e todas essas coisas.

Veja algumas fotos:

(Hora Extra)

O objetivo era chegar com a mesa até os táxis, mas dessa vez não deu.

(Hora Extra)

Casa cheia!

(Hora Extra)

Edição especial do Hora Extra na Intelitiva.

Coding Dojo Rio

O Coding Dojo Rio acontece todas as quartas-feiras no CEFET-Rio, a partir de 18:30. Começou do final de 2008 e já conta com a bagagem de 22 encontros realizados, média de 10 participantes e mais de 60 inscritos na lista de discussão.

(Coding Dojo Rio)

Hack Framps

A Hack Framps é o mais restrito desses eventos. Infelizmente não é possível divulgar publicamente onde ele ocorre e convidar a todos pois ele é realizado na casa do Vinícius. Em geral quem participa dos outros eventos é automaticamente incluído nesse também.

A Hack Framps é uma espécie de RejectConf, onde cada um faz uma breve apresentação sobre algum assunto que domina, ou não, e depois a gente troca algumas figurinhas. A idéia desse evento é difundir conhecimento aproveitando as diferentes habilidades que cada um de nós temos e a grande diversidade de áreas que a nossa profissão oferece.

Veja algumas fotos:

(Hack Framps)

(Hack Framps)

(Hack Framps)

(Hack Framps)

Festa Framps

A Festa Framps é mais um evento restrito lá na casa do Vínicius e é o momento da gente se redimir com as esposas. Trata-se de uma festinha para toda a familia e a coisa mais nerd que a gente faz é jogar Wii!

Então...

Esses eventos todos são uma forma que a gente encontrou de manter a galera unida, trocar idéias e se divertir muito.

Mas então, o que vocês estão fazendo na sua cidade? Como vocês estão aproveitando o talento de cada um?

Saturday, July 4, 2009

Exceptional Software Explained: Embrace Error

Depois de ouvir um keynote do Robert M. Lefkowitz (aka. r0ml) na PyCon 2007 sobre The Importance of Programming Literacy, virei fã desse cara...


PDF com os slides sobre The Importance of Programming Literacy

Sua forma de conduzir seus discursos é fantástica, fora o "meta-discurso", já que na maior parte do tempo ele faz justamente o que está sendo pregado no discurso, seguindo as diversas etapas da retórica.

Hoje encontrei um vídeo da OSCON 2008 no qual ele fala sobre sua metodologia de desenvolvimento, baseada nas comunidades de software open source.

Lefkowitz compara MSF, XP, e sua metologia de software Excepcional de forma muito bem humorada e com profundos desdobramentos:

Coding Dojo Rio

Não tenho escrito muito nas últimas semanas, mas algo que gostaria de destacar agora é o nosso Coding Dojo Rio.

Não só chegamos a marca de 20 sessões realizadas, como também na última quarta-feira tivemos o prazer de reunir 14 pessoas no dojo.

Já foram 22 encontros, temos 65 pessoas no grupo de emails, e temos um grupo bastante estável e coeso. Tem sido uma experiência maravilhosa compartilhar código e ideias com essa galera...

Você que está lendo aqui deveria procurar mais as práticas Ágeis, experimentá-las, não ter medo de mudar!
Não deixe essa falsa impressão de "não mudo time que está ganhando", por que isso esconde as melhorias que seriam conquistadas quando damos um passo de coragem.

Mude, dê espaço para você mesmo se tornar uma pessoa melhor!

Hmm, depois do devaneio, links para os últimos posts do Dojo Rio, com muitas fotos do grupo:

Tuesday, June 30, 2009

Morte ao email do BOL e UOL

Depois de o blog da PythOnRio ter sido bombardeado pelo filtro anti-spam do BOL e UOL, eis que surge a campanha "Morte ao email do BOL e UOL":

Qual o melhor jeito de se evitar spam via email? Um filtro bayesiano? Educação do usuário?

Não! Simplesmente DESATIVE O EMAIL DO USUÁRIO! É isso mesmo! Quando você recebe uma mensagem, o BOL e o UOL simplesmente não levam a mensagem até o destinatário. O servidor responde o remetente dizendo: “Você mandou uma mensagem para Fulano, se você não for um spammer clique aqui e prove sua boa intenção digitando o captcha.”

Isso significa que se o remetente não tomar as medidas impostas pelo BOL e o UOL, o destinatário simplesmente não receberá o email.

Agora imagine se o usuário do BOL e o UOL preenche algum formulário em um site e este site envia um email automático como feedback desta ação? Resultado: 1600 mensagens pedindo confirmação de que o site não é um spammer.

Este é um caso clássico de quando TI significa Totalmente Imbecil! E que fique claro que não digo isso para as pessoas técnicas destas empresas. Pois tenho certeza que este workflow absurdo foi imposto por algum “Gerente” ou “Diretor” que não faz idéia das consequências dessa decisão.

Seria ótimo se o pessoal das campanhas “Morte ao IE 6″ iniciassem uma nova: “Morte ao email do BOL e UOL”, afinal, o GMail ganha de goleada.

Thursday, June 11, 2009

Pós-PythOnCampus Gama Filho Piedade no Outback Norte Shopping

Esse post está bastante atrasado... já postei sobre a 3ª PythOnCampus sem antes ter publicado as fotos da 2ª PythOnCampus.

Na verdade não tenho fotos do evento, mas sim do pós-evento. Fomos almoçar no Outback do Norte Shopping.

Várias horas de descontração, comida e bate-papo.

PythOnCampus UVA Cabo Frio

No último sábado (06/06/2009) a comunidade PythOnRio realizou mais uma edição do PythOnCampus, evento itinerante que visita as universidades.
Menos de um mês desde a edição da Universidade Gama Filho campus Piedade, visitamos a Universidade Veiga de Almeida em Cabo Frio, onde fomos muito bem recebidos.

Realizamos palestras, e um mini-curso de Python. Este deixou os alunos sedentos por um curso de extensão ou alguma outra forma de disseminar a linguagem na faculdade.
Todo o evento foi focado em como os alunos podem e devem correr atrás das oportunidades, fazer o mercado acontecer, como a mentalidade em voga pode e deve ser alterada. E os alunos tem como exemplo a ser seguido o seu coordenador, o Fábio Licht.

Mais do que promover um linguagem, estamos lá para promover um espírito de colaboração, uma idéia de comunidade, de como podemos ter academia e mercado sintonizados, de forma sempre a valorizar o profissional como pessoa.

São as práticas, os valores, os princípios, que nos fazem nos deslocar do Rio para Cabo Frio num sabadão para ver o brilho nos olhos dos alunos que compareceram ao evento.

Foram horas super agradáveis na companhia de pessoas excelentes. Tirei algumas fotos para registrar o evento e o pós-evento numa churrascaria em Cabo Frio.

Já estamos nos preparando para novos destinos, fiquem atentos para saber sobre o próximo PythOnCampus.

Se você é aluno ou professor de alguma instituição de ensino e quer nossa presença, entre em contato.

Não deixem de acompanhar o site oficial da comunidade PythOnRio, e o grupo de emails da PythOnRio.



Fotos paisagísticas do campus da UVA Cabo Frio:
Universidade Veiga de Almeida - campus Cabo Frio

20 edições de Coding Dojo - comemoração com direito a bolo

É com grande satisfação que anúncio que o Coding Dojo Rio é um sucesso.
Depois de seis meses temos um grupo consolidado, que se encontra todas as quartas para programar, trocar conhecimento, se divertir.

Para quem não acreditou, cá estamos nós, comemorando as pequenas conquistas.

E ontem não só comemoramos nosso vigésimo encontro como também o aniversário do Cláudio Berrondo. Tivemos 9 pessoas presentes, um papo muito bom sobre as entranhas do Python, bolo, ... sim, tivemos bolo!

Em breve vamos liberar um post mais detalhado no blog oficial do Dojo, mas por enquanto já adianto as fotos de ontem:

Saturday, May 30, 2009

Como usar code-completion no console Python

É muito conveniente poder autocompletar comandos e propriedades de objetos Python no prompt de comando. Espero que a maioria de vocês já conheça o IPython, que cumpre muito bem não só esse papel, mas também tem outras funcionalidades muito boas. Confira! Vale a pela instalar, esteja você no Linux, Windows ou Mac...
Dentre as "melhorias" que o IPython traz, cito: autocompletar, indentação automática, sintaxe colorida (syntax highlight), macros, guarda todos os inputs e outputs dos comandos, gerenciamento de sessão, histórico avançado, debugger, etc.

De qualquer forma, para os momentos em que o IPython não está disponível, podemos nos virar com o console Python padrão e usufruir de autocompletar!
Use o seguinte código para ativar essa funcionalidade:

# .pythonrc.py
import readline, rlcompleter
readline.parse_and_bind("tab: complete")


Você pode rodar esse código direto no console ou salvar em um arquivo, digamos ~/.pythonrc.py, e usar a variável de sistema PYTHONSTARTUP para que o Python execute o arquivo na inicialização. (Exemplo: colocar "export PYTHONSTARTUP=$HOME/.pythonrc.py" no arquivo ~/.bashrc)

Note que isto não substitui o IPython!

Friday, May 29, 2009

Coding Dojo Rio #18 no CEFET

Na última quarta-feira tirei fotos do dojo!

Foi um dia muito engraçado, comecei ficando preso dentro da sala com o Israel antes de começar o dojo... felizmente logo fomos salvos :)
Depois resolvemos mudar bastante do que vinhamos fazendo... usamos JavaScript para testar a cantiga infantil "Atirei o pau no gato". Eu já tinha indicado como isso poderia ser feito nos posts Dojo Lúdico, TDD em cantigas de roda - parte 1 e TDD em cantigas de roda - parte 2.

Usamos o QUnit para nos apoiar nos testes em JavaScript.

Tivemos muitas guloseimas! E comemos tudo... o registro fotográfico:

Wednesday, May 6, 2009

ESEJ Londrina 2009: Vídeo e Fotos

Começando a sequencia de fotos e vídeos por vir, disponibilizo as fotos da última festa do ESEJ, na boate Vega, no sábado 02/05/2009.

De Boate Vega Londrina


E aqui o vídeo da primeira noite, pessoal perto da piscina cantando:



Em breve mais fotos e vídeos do evento!

Tuesday, May 5, 2009

PythonCampus na Universidade Gama Filho no campus da Piedade

Neste próximo sábado, dia 9 de maio, das 9h às 13h, será realizada a 2a. edição da PythonCampus na Universidade Gama Filho no campus da Piedade.

A PythonCampus é um evento promovido pela PythOnRio (Comunidade Python do Rio de Janeiro) com o objetivo de levar conhecimentos de Python, Software Livre e Métodos Ágeis ao público universitário.

Com um formato de caravana, a PythonCampus visita as universidades integrando estudantes, professores e profissionais do mercado sob o movimento de Software Livre no Rio de Janeiro.

No evento são promovidos mini-cursos, open spaces, dojos e palestras. As atividades são realizadas por profissionais, especialistas e pesquisadores da área tecnológica, abordando tendências e o estado da arte do Software Livre. Veja a grade de programação.

A entrada é franca e as inscrições são para controle da organização. Inscreva-se já!

Estarei coordenando uma edição especial do Coding Dojo Rio, de
09:00h às 11:00h.

Monday, May 4, 2009

ESEJ Londrina 2009

Do dia 30 de Abril a 3 de Maio foi realizado o XVII Encontro Sul de Empresas Juniores, na cidade de Londrina no Paraná — o ESEJ Londrina 2009.


O ESEJ deste ano teve como tema "O Empresário Júnior como ator estratégico para o Desenvolvimento Sustentável".





Eu, tendo participado do Movimento Empresa Junior (MEJ) através da Fluxo Consultoria, compareci ao evento e trouxe diversas idéias para mudar o mundo [para a melhor, claro]. Foi uma excelente oportunidade para divulgar nosso trabalho e aprender com outros jovens do Brasil todo.

Tive inclusive a oportunidade de falar sobre Scrum (e sua aplicação na Globo.com) com outros empresários juniores! E também de divulgar o trabalho que tenho feito com a Elaine Mitie visando promover boas atitudes para com o mundo, o Deixe Para Seus Filhos.

Nos próximos dias escreverei sobre os pontos marcantes do evento. Se você veio até aqui procurando pelas fotos do evento, aguarde, pois muito em breve elas serão divulgadas!

Saturday, April 25, 2009

FLISOL 2009

Terminada a versão 2009 do FLISOL, tenho algumas fotos para compartilhar.
Mas não são fotos do evento principal, e sim da reunião da PythonRio, que rolou em paralelo ao evento na UERJ, na tarde do último sábado.

Discutimos sobre algumas ações como a criação de uma ementa "padrão" para cursos de Python que eventualmente venhamos criar, e como tornar estes cursos uma realidade muito em breve.
Falamos do nosso evento PythonRio, e sobre o Python Campus (evento "ambulante" nas universidades divulgando e fomentando o uso da linguagem).

Por fim, tratamos de nossa ida ao FISL, e como será a logística do grupo.

Coding Dojo #13

Na última quarta tivemos mais um Coding Dojo muito produtivo. Desta vez com direito a fotos!



Não vou escrever os detalhes aqui, pois já está tudo no post do Blog Oficial do Coding Dojo Rio.

Tuesday, April 21, 2009

Planeta Globo.com

Há muuuuito tempo o Meyer deu uma idéia da fazer uma coisa que eu também sempre quis fazer mas nunca arrumava um tempo. Mas agora foi. Acabo de criar para nós o Planeta Globo.com: http://planeta-globo.com/

A idéia é criar um agregador de todos os blogs pessoais da galera que trabalha na Globo.com. Já tivemos uma experiência de criar um blog corporativo [...], mas acabou ficando um pouco abandonado porque as pessoas não gostaram de ter que blogar em dois lugares diferentes (eu inclusive). Então, a idéia do Planeta é que todos os posts que nós escrevermos em nossos blogs pessoais vão automaticamente para lá sem dar trabalho adicional. [...]

Outra coisa importante é que a idéia principal é falar sobre coisas técnicas que fazemos na Globo.com (desenvolvimento de software, desenvolvimento client-side, user experience, design, arquitetura de inf., administração de sistemas, etc.). [...] A idéia é que o Planeta seja um blog técnico sobre coisas envolvidas no processo de criação de produtos para Internet.

Guilherme Chapiewski, em 11 de Abril, 2009

E foi assim que o GC introduziu a idéia do Planeta Globo.com! Agora todos podem acompanhar os diversos blogs do pessoal da globo.com, tudo agregado em planeta-globo.com!

E o LifeAtMyMind está presente lá/aqui, apenas com posts selecionados por relevância.

Monday, April 20, 2009

Palestra de Python e Desenvolvimento Web no FLISOL Rio de Janeiro

No dia 25 de abril de 2009, sábado, acontecerá o Festival Latino Americano de Instalação de Software Livre (FLISOL) na Universidade Estadual do Rio de Janeiro. O evento reunirá grupos locais de expressão na área de Software Livre que conjuntamente disseminarão a filosofia, cultura e conhecimento sobre o movimento de Software Livre.
Com uma recheada grade de palestras, o FLISOL contará também com a presença da PythOnRio representada por Luiz Guilherme Aldabalde que apresentará a palestra técnica "Entendendo Framework Web com Python".
Definitivamente esta é uma grande oportunidade para aprender e experimentar o que há de mais interessante e inovador em matéria de Software Livre. Compareça! E não deixe de levar o seu computador!

[Original em http://pythonrio.org/palestra-de-python-e-desenvolvimento-web-no-f]

Friday, April 10, 2009

Coding Dojo Rio #11

Essa semana tivemos mais um dojo que rendeu até altas horas!

Depois de programarmos um bocado, partimos para um lugar meio bar, meio restaurante, meio qualquer outra coisa, onde comemos uns aperitivos e trocamos muitas ideias legais.

Já escrevi um bocado sobre o acontecido no blog oficial do dojo, confiram:
http://dojorio.wordpress.com/

Sunday, April 5, 2009

Yes, Python rocks - Multitouch to the masses

Hoje o Ronald me mostrou um vídeo que demonstra mais um dos super-poderes do Python.
Desta vez nosso herói entre em cena como um framework para aplicações "multi-touch" (interfaces sensíveis a vários toques simultâneos, como a tela do iPhone).

Com um número de linhas inimaginavelmente pequeno dá para escrever coisas muito legais... hmm falei em inimaginável? Bem, acho que com Python já dava para imaginar que seria rápido e fácil e sem burocracia :P

"Idolatria" a parte, o vídeo:


pymt demo reel from Thomas Hansen on Vimeo.

Existe muito mais nesse mundo, e um bom começo é aqui: http://nuigroup.com/

Saturday, April 4, 2009

Desligar o computador automaticamente quando offline (usando Python)

Já faz um tempo que estou tendo problemas com minha conexão ADSL. Frequentemente acontece alguma bizarrice na minha linha telefônica e preciso fazer alguns procedimentos manuais para reconectar.

Como não compensa montar um robô para realizar a reconexão, passou a ser interessante ao menos desligar o PC quando ele estiver offline...

Então, um dia desses antes de dormir escrevi um curto script Python, que só funciona em Linux, para desligar o computador quando não conseguir acessar uma URL.

#!/usr/bin/env python
import os
from time import sleep, strftime
from urllib2 import urlopen, URLError

TEST_URL = "http://www.google.com"

while 1:
try:
urlopen(TEST_URL)
print '%s [OK] %s' % (strftime("%c"), TEST_URL)
except URLError:
# I am liked offline, halt!
os.system("shutdown now -h")
break
sleep(180)


O que faço depois é, antes de ir dormir, rodar sudo ./halt_when_offline.py > hwo.log.

Wednesday, April 1, 2009

Coding Dojo Rio #10

Nesta quarta, 1ᴼ de Abril, realizamos o Coding Dojo Rio de número 10!
Já foram dez encontros desde Dezembro do ano passado.

Foi uma noite chuvosa e muito legal, com novos participantes no Dojo, e com pizza para comemorar!
Para não me alongar muito, fica o link para o post que fiz no blog do dojo:

http://dojorio.wordpress.com/2009/04/02/coding-dojo-rio-10/

Sunday, March 29, 2009

Como falar muito sem dizer nada

Essa semana um professor nos enviou um documento bem humorado dizendo como se comportar em reuniões / apresentações.
Trata-se de uma tabela em que você pode formar frases sintaticamente corretas, porém sem nenhum conteúdo, bastando pegar um trecho de cada coluna.

Coluna 1 Coluna 2 Coluna 3 Coluna 4
Caros colegas, a execução deste projeto nos obriga à análise das nossas opções de desenvolvimento futuro.
Por outro lado, a complexidade dos estudos efetuados cumpre um papel essencial na formulação das nossas metas financeiras e administrativas.
Não podemos esquecer que a atual estrutura de organização auxilia a preparação e a estruturação das atitudes e das atribuições da diretoria.
Do mesmo modo, o novo modelo estrutural aqui preconizado contribui para a correta determinação das novas proposições.
A prática mostra que o desenvolvimento de formas distintas de atuação assume importantes posições na definição das opções básicas para o sucesso do programa.
Nunca é demais insistir que a constante divulgação das informações facilita a definição do nosso sistema de formação de quadros.
A experiência mostra que a consolidação das estruturas prejudica a percepção da importância das condições apropriadas para os negócios.
É fundamental ressaltar que a análise dos diversos resultados oferece uma boa oportunidade de verificação dos índices pretendidos.
O incentivo ao avanço tecnológico, assim como o início do programa de formação de atitudes acarreta um processo de reformulação das formas de ação.
Assim mesmo, a expansão de nossa atividade exige precisão e definição dos conceitos de participação geral.

Então resolvi fazer um rápido script Python para formar frases pra mim, algo como "Quote-of-the-day".

# -*- coding: utf-8 -*-
# phrases.py
from random import choice
from textwrap import dedent

try:
from itertools import product
except ImportError:
# http://docs.python.org/library/itertools.html#itertools.product
def product(*args, **kwds):
# product('ABCD', 'xy') --> Ax Ay Bx By Cx Cy Dx Dy
# product(range(2), repeat=3) --> 000 001 010 011 100 101 110 111
pools = map(tuple, args) * kwds.get('repeat', 1)
result = [[]]
for pool in pools:
result = [x+[y] for x in result for y in pool]
for prod in result:
yield tuple(prod)


_COLUNAS_ = [[u"Caros colegas,",
u"Por outro lado,",
u"Não podemos esquecer que",
u"Do mesmo modo,",
u"A prática mostra que",
u"Nunca é demais insistir que",
u"A experiência mostra que",
u"É fundamental ressaltar que",
u"O incentivo ao avanço tecnológico, assim como",
u"Assim mesmo,"],
[u"a execução deste projeto",
u"a complexidade dos estudos efetuados",
u"a atual estrutura de organização",
u"o novo modelo estrutural aqui preconizado",
u"o desenvolvimento de formas distintas de atuação",
u"a constante divulgação das informações",
u"a consolidação das estruturas",
u"a análise dos diversos resultados",
u"o início do programa de formação de atitudes",
u"a expansão de nossa atividade"],
[u"nos obriga à análise",
u"cumpre um papel essencial na formulação",
u"auxilia a preparação e a estruturação",
u"contribui para a correta determinação",
u"assume importantes posições na definição",
u"facilita a definição",
u"prejudica a percepção da importância",
u"oferece uma boa oportunidade de verificação",
u"acarreta um processo de reformulação",
u"exige precisão e definição"],
[u"das nossas opções de desenvolvimento futuro.",
u"das nossas metas financeiras e administrativas.",
u"das atitudes e das atribuições da diretoria.",
u"das novas proposições.",
u"das opções básicas para o sucesso do programa.",
u"do nosso sistema de formação de quadros.",
u"das condições apropriadas para os negócios.",
u"dos índices pretendidos.",
u"das formas de ação.",
u"dos conceitos de participação geral."]]

frases_vazias = list(product(*_COLUNAS_))
print dedent('''\
De %d frases vazias, escolhi:
"%s"''') % (len(frases_vazias), ' '.join(choice(frases_vazias)))

##for frase in product(*_COLUNAS_):
## print ' '.join(frase)

Sunday, March 22, 2009

Web Frameworks

Essa semana eu compilei uma lista de diversos frameworks para desenvolvimento web.
Não me limitei a Python, (quase) todas as linguagens foram consideradas e ainda tentei "separar o joio do trigo" marcando os frameworks mais 'badalados' em cada linguagem.

Eu fiz o original em um mapa mental no MindManager, mas como o formato é proprietário, fica aqui o PNG com o mapa completo exportado.



A lista é a seguinte:

  1. ActionScript
    • Flex
  2. ASP.NET
    • ASP.NET MVC
    • DotNetNuke
    • MonoRail
    • BFC
    • CSLA
    • Umbraco
  3. ColdFusion
    • ColdSpring
    • Fusebox
    • Model-Glue
    • onTap
  4. Groovy
    • Grails
  5. Java
    • Apache Struts 2
    • JavaServer Faces
    • JBoss Seam
    • Spring
    • Stripes
    • Tapestry
    • Apache
      • Click
      • Cocoon
      • Wicket
    • AppFuse
    • Aranea
    • Google Web Toolkit
    • Hamlets
    • ItsNat
    • IT Mill Toolkit
    • OpenLaszlo
    • OpenXava
    • Reasonable Server Faces
    • RIFE
    • Shale
    • SmartClient
    • Sofia
    • ThinWire
    • WebObjects
    • WebWork
    • ztemplates
  6. JavaScript
    • Ajile
    • Axiom Stack
    • WaveMaker
  7. Lua
    • Orbit
    • Kepler
  8. Perl
    • Catalyst
    • Interchange
    • Mason
    • Maypole
  9. PHP
    • CakePHP
    • Prado
    • Symfony
    • Zend
    • CodeIgniter
    • Drupal
    • Akelos
    • eZ Components
    • FUSE
    • Horde
    • Kohana
    • LISA
    • Midgard
    • Nette
    • PEAR
    • Orinoco
    • Qcodo
    • Simplicity
    • SilverStripe (Sapphire)
    • SPIP
    • Tigermouse
    • Zoop
  10. Python
    • Django
    • TurboGears
    • Pylons
    • Zope
    • Grok
    • web2py
    • CherryPy
    • CubicWeb
    • Enamel
    • Gizmo(QP)
    • Glashammer
    • Karrigell
    • notmm
    • Porcupine
    • Pyroxide
    • QP
    • SkunkWeb
    • Spyce
    • web.py
    • Webware
    • Werkzeug
  11. Ruby
    • Ruby on Rails
    • Merb
    • Camping
    • Nitro
  12. Smalltalk
    • Seaside
    • AIDA/Web

Saturday, March 21, 2009

Python tricks: locals(), globals() e keyword arguments (kwargs)

Nessa semana durante uma sessão de pair programming lá na globo.com chegamos a um código que começava a se repetir... um bom momento para melhora, e lá introduzi uma "técnica" muito legal: usar o um dicionário que contém o escopo local para dinamizar o acesso a variáveis/nomes.

Esse dicionário já existe builtin no Python, apesar de eu acreditar que muita gente não saiba ou não o use...
Trata-se do locals() (e seu irmão globals()).

Uso:
def preencher_mensagem(id_mensagem, titulo=None, subtitulo=None, link=None):
id_titulo = MENSAGENS[id_mensagem]['titulo']
id_subtitulo = MENSAGENS[id_mensagem]['subtitulo']
id_link = MENSAGENS[id_mensagem]['link']

if titulo is not None:
preencher_titulo(id_titulo, titulo)

if subtitulo is not None:
preencher_subtitulo(id_subtitulo, subtitulo)

if link is not None:
preencher_link(id_link, link)


Abstraim o resto do código, e pensem nos if's.
Com mais e mais parametros para preencher, isso fica muito repetitivo.
Por que não um loop?
def preencher_mensagem(id_mensagem, titulo=None, subtitulo=None, link=None):
id_titulo = MENSAGENS[id_mensagem]['titulo']
id_subtitulo = MENSAGENS[id_mensagem]['subtitulo']
id_link = MENSAGENS[id_mensagem]['link']

for parte in 'titulo subtitulo link'.split():
texto = locals()[parte]
id = locals()['id_%s' % parte]
preencher = globals()['preencher_%s' % parte]

if texto is not None:
preencher(id, texto)

Notem que com o locals() podemos acessar o dicionário de nomes locais e usar seus valores tanto para leitura quanto para escrita (não recomendada), chamar métodos, etc. O equivalente para o escopo global é o globals().
Ainda poderíamos fazer melhor e usar um dicionário dos parâmetros passados para a função/método, ao invés de 'apelar' para o escopo local.
Basta colocar um argumento que leve ** na frente, e ele será um dicionário de todos os parâmetros passados por nome. Melhor definição, formalismo e mais exemplos na documentação oficial do Python.
def preencher_mensagem(id_mensagem, **partes):
for parte, texto in partes.iteritems():
id = MENSAGENS[id_mensagem][parte]
preencher = globals().get('preencher_%s' % parte)

if preencher is not None:
preencher(id, texto)

Agora, para os que querem rodar alguma coisa que funcione, fiz um script completo que pode ser executado.
Fiz um "banco de dados" fictício só para fins de demonstração.

# -*- coding: utf-8 -*-
# Exemplo usado no meu blog em lifeatmymind.blogspot.com
# Rodolfo Carvalho 2009-03-21

#----- Meu "Banco de Dados" ------------------
MENSAGENS = {1: {'titulo': 4,
'subtitulo': 3,
'link': 1},
2: {'titulo': 1,
'subtitulo': 4,
'link': 2},
3: {'titulo': 2,
'subtitulo': 2,
'link': 4},
4: {'titulo': 3,
'subtitulo': 1,
'link': 3}}

TITULOS = {1: '', 2: '', 3: '', 4: ''}
SUBTITULOS = {1: '', 2: '', 3: '', 4: ''}
LINKS = {1: '', 2: '', 3: '', 4: ''}
#---------------------------------------------

def preencher_titulo(id_titulo, titulo):
TITULOS[id_titulo] = titulo

def preencher_subtitulo(id_subtitulo, subtitulo):
SUBTITULOS[id_subtitulo] = subtitulo

def preencher_link(id_link, link):
LINKS[id_link] = link

#---------------------------------------------

def preencher_mensagem1(id_mensagem, titulo=None, subtitulo=None, link=None):
id_titulo = MENSAGENS[id_mensagem]['titulo']
id_subtitulo = MENSAGENS[id_mensagem]['subtitulo']
id_link = MENSAGENS[id_mensagem]['link']

if titulo is not None:
preencher_titulo(id_titulo, titulo)

if subtitulo is not None:
preencher_subtitulo(id_subtitulo, subtitulo)

if link is not None:
preencher_link(id_link, link)

def preencher_mensagem2(id_mensagem, titulo=None, subtitulo=None, link=None):
id_titulo = MENSAGENS[id_mensagem]['titulo']
id_subtitulo = MENSAGENS[id_mensagem]['subtitulo']
id_link = MENSAGENS[id_mensagem]['link']

for parte in 'titulo subtitulo link'.split():
texto = locals()[parte]
id = locals()['id_%s' % parte]
preencher = globals()['preencher_%s' % parte]

if texto is not None:
preencher(id, texto)

def preencher_mensagem3(id_mensagem, **partes):
for parte, texto in partes.iteritems():
id = MENSAGENS[id_mensagem][parte]
preencher = globals().get('preencher_%s' % parte)

if preencher is not None:
preencher(id, texto)

#---------------------------------------------

def imprimir_mensagens():
def print_linha(conteudo=''):
print '| %s |' % conteudo.center(76)

for id, msg in MENSAGENS.iteritems():
print
print '(%d)' % (id,)
print '-' * 80
print_linha('* %s *' % TITULOS[msg['titulo']])
print_linha('%s' % SUBTITULOS[msg['subtitulo']])
print_linha()
print_linha('%s' % LINKS[msg['link']])
print '-' * 80

if __name__ == '__main__':
preencher_mensagem = preencher_mensagem3

preencher_mensagem(id_mensagem=1,
titulo=u'Olá mundo!',
subtitulo=u'Veja como é divertido usar Python',
link='http://lifeatmymind.blogspot.com')
preencher_mensagem(id_mensagem=2,
titulo=u'Esta é a segunda mensagem cadastrada',
link='http://lifeatmymind.blogspot.com')
preencher_mensagem(id_mensagem=3,
subtitulo=u'Eu não tenho título...',
link='http://lifeatmymind.blogspot.com')
preencher_mensagem(id_mensagem=4,
titulo=u'Última mensagem',
subtitulo='Sou uma mensagem sem link')
imprimir_mensagens()



Um outro exemplo de uso interessante seria:

def tell_story(king, princess, action):
print ('There was a King called %(king)s that had a beautiful daughter. '
'Her name, %(princess)s, would have to be shout in order to make '
'her %(action)s.' % locals())

tell_story("Peter", "Fiona", "ride a horse")
tell_story("Allan", "Britney", "dance")


No trecho acima tem duas coisas interessantes:
  1. Você pode escrever strings grandes sem poluir seu código com linhas super extensas. Siga a recomendação de manter no máximo 80 caracteres por linha. Para escrever strings longas, use-se do artifício da continuação de linha implícita por causa dos parênteses e da concatenação automática de strings postas lado a lado.
>>> "Eu sou uma string" " que continua em outra parte"
'Eu sou uma string que continua em outra parte'

>>> ("Eu sou uma string" " que continua em outra parte"
... " e tambem em outra linha!")
'Eu sou uma string que continua em outra parte e tambem em outra linha!'

  1. Você pode usar o locals() como dicionário para formatação de strings!

O código original é equivalente a:
def tell_story(king, princess, action):
print ('There was a King called %(king)s that had a beautiful daughter. '
'Her name, %(princess)s, would have to be shout in order to make '
'her %(action)s.' % dict(king=king, princess=princess, action=action))

tell_story("Peter", "Fiona", "ride a horse")
tell_story("Allan", "Britney", "dance")

Porém, o original é bem mais sucinto :)

Wednesday, March 18, 2009

Provérbio do dia

"O maior dos erros é a pressa antes do tempo, e a lentidão ante a oportunidade"
- Provérbio árabe


Do (excelente) livro "Do Fortran à Internet: no rastro da trilogia Educação, Pesquisa e Desenvolvimento", de Tércio Pacitti.

Saturday, March 14, 2009

Escreva menos, use Python

Ontem vivenciei uma situação em que tivemos que manter um código legado para inserir mais uma pequena funcionalidade.
Uma "regra" aqui é não se desviar do que você tem que fazer (que possui mais valor de negócio) para cuidar de outras coisas. Outra "regra" é não deixar débito técnico.
A grande dificuldade é encontrar o balanço adequado entre esses dois objetivos, e ainda assim implementar sua nova funcionalidade.

Bem, livre de qualquer "regra", vou aproveitar esse post para introduzir 3 recursos do Python que nem sempre são lembrados, e que nos permitem economizar linhas de código, escrevendo de forma clara e concisa o que queremos fazer.

  1. Método get dos dicionários;
  2. Método split das strings;
  3. Função builtin/global setattr.
Vamos partir do seguinte código legado:

#...
from django.shortcuts import render_to_response
from model import Cadastro
#...

def tratar_cadastro(request):
post = request.POST
#...
cadastro = Cadastro()
#...

if post.has_key('nome'):
cadastro.nome = post['nome']

if post.has_key('endereco'):
cadastro.endereco = post['endereco']

if post.has_key('telefone'):
cadastro.telefone = post['telefone']

if post.has_key('email'):
cadastro.email = post['email']

return render_to_response('cadastro/index.html', {"cadastro": cadastro})


É um esboço de uma View do Django. Como podem ver, espera-se que a view seja requisitada via HTTP POST, com a passagem de diversos parâmetros, que ficam armazenados no dicionário Python request.POST. Esse papo de cadastro, nome, telefone, etc é só para ilustrar.
Então o código que temos é uma sequência de if's que setam atributos de uma instância de Cadastro que é posteriormente passada para o template.

Podemos imaginar que temos um formulário numa página que, ao ser submetido, exibe as informações preenchidas para confirmação.

Agora temos que adicionar mais um campo ao cadastro. Digamos que nosso cliente pediu para guardar também o campo "idade". Por simetria, acabaria acontecendo o seguinte:
#...
from django.shortcuts import render_to_response
from model import Cadastro
#...

def tratar_cadastro(request):
post = request.POST
#...
cadastro = Cadastro()
#...

if post.has_key('nome'):
cadastro.nome = post['nome']

if post.has_key('idade'):
cadastro.idade = post['idade']


if post.has_key('endereco'):
cadastro.endereco = post['endereco']

if post.has_key('telefone'):
cadastro.telefone = post['telefone']

if post.has_key('email'):
cadastro.email = post['email']

return render_to_response('cadastro/index.html', {"cadastro": cadastro})


Pra que mudar o que já funciona? Bem, vamos então ao primeiro dos tópicos.
Usar o dict.has_key é ruim e desnecessário. Esse método é deprecated no Python 2.6 e já foi removido da linguagem no Python 3.0, em favor da forma chave in dicionario. No lugar dele e do if deveríamos usar o dict.get.
Mas o que esse método faz? Ele retorna o valor de dict['key'] se o dicionário tem a chave 'key', senão retorna None ou outro valor padrão que o programador especificar.
Ficaria assim:
#...
from django.shortcuts import render_to_response
from model import Cadastro
#...

def tratar_cadastro(request):
post = request.POST
#...
cadastro = Cadastro()
#...

if post.has_key('nome'):
cadastro.nome = post['nome']

cadastro.idade = post.get('idade', u'Campo não preenchido')

if post.has_key('endereco'):
cadastro.endereco = post['endereco']

if post.has_key('telefone'):
cadastro.telefone = post['telefone']

if post.has_key('email'):
cadastro.email = post['email']

return render_to_response('cadastro/index.html', {"cadastro": cadastro})


Além de economizar linhas, temos um código menos redundante e seguindo o princípio de "It's better to beg forgiveness than to ask permission".
Vamos refatorar o resto do código:
#...
from django.shortcuts import render_to_response
from model import Cadastro
#...

def tratar_cadastro(request):
post = request.POST
#...
cadastro = Cadastro()
#...

cadastro.nome = post.get('nome')
cadastro.idade = post.get('idade')
cadastro.endereco = post.get('endereco')
cadastro.telefone = post.get('telefone')
cadastro.email = post.get('email')

return render_to_response('cadastro/index.html', {"cadastro": cadastro})


Assim, caso um dos campos não venha no POST, será atribuído o valor None ao atributo do objeto cadastro.
Notem que, assim como antes, existe bastante duplicação de código (por razões práticas, fiz um exemplo com poucas chaves do dicionário, mas o caso que me deparei eram mais que dez...).
Agora então é a hora de introduzir os outros dois conceitos, o split e o setattr.
O primeiro transforma uma string em lista através de um separador. Exemplo:
>>>  print "um, dois, tres".split(", ")
['um', 'dois', 'tres']

Isso pode ser usado para declararmos uma lista sem precisar de muitas aspas e vírgulas... basta colocar todos os itens da lista em uma string e usar o split.
O outro faz o mesmo que objeto.atributo = valor, porém atributo pode ser algo dinâmico, definido em tempo de execução.
Com essas mudanças, nosso código ganha uma tremenda compressão, sem perder legibilidade:
#...
from django.shortcuts import render_to_response
from model import Cadastro
#...

def tratar_cadastro(request):
post = request.POST
#...
cadastro = Cadastro()
#...

for attr in 'nome idade endereco telefone email'.split():
setattr(cadastro, attr, post.get(attr))


return render_to_response('cadastro/index.html', {"cadastro": cadastro})

Wednesday, March 11, 2009

Psicologia Junguiana

Recebi isto hoje por email e acho que parece bastante com minha 'rotina' corrente.
Apesar da ralação, tem sido muito bom. Não me contento com molezinha :P

Exigências da vida moderna (quem agüenta tudo isso??)


Dizem que todos os dias você deve comer uma maçã por causa do ferro.
E uma banana pelo potássio.
E também uma laranja pela vitamina C.

Uma xícara de chá verde sem açúcar para prevenir a diabetes.
Todos os dias deve-se tomar ao menos dois litros de água.
E uriná-los, o que consome o dobro do tempo.
Todos os dias deve-se tomar um Yakult pelos lactobacilos (que ninguém sabe bem o que é, mas que aos bilhões, ajudam a digestão).

Cada dia uma Aspirina, previne infarto.
Uma taça de vinho tinto também.
Uma de vinho branco estabiliza o sistema nervoso...
Um copo de cerveja, para... não lembro bem para o que, mas faz bem.
O benefício adicional é que se você tomar tudo isso ao mesmo tempo e tiver um derrame, nem vai perceber.

Todos os dias deve-se comer fibra.
Muita, muitíssima fibra.
Fibra suficiente para fazer um pulôver.
Você deve fazer entre quatro e seis refeições leves diariamente.
E nunca se esqueça de mastigar pelo menos cem vezes cada garfada.
Só para comer, serão cerca de cinco horas do dia.

E não esqueça de escovar os dentes depois de comer.
Ou seja, você tem que escovar os dentes depois da maçã, da banana, da laranja, das seis refeições e enquanto tiver dentes, passar fio dental, massagear a gengiva, escovar a língua e bochechar com Plax.
Melhor, inclusive, ampliar o banheiro e aproveitar para colocar um equipamento de som, porque entre a água, a fibra e os dentes, você vai passar ali várias horas por dia.

Há que se dormir oito horas por noite e trabalhar outras oito por dia, mais as cinco comendo são vinte e uma.
Sobram três, desde que você não pegue trânsito.

As estatísticas comprovam que assistimos três horas de TV por dia.
Menos você, porque todos os dias você vai caminhar ao menos meia hora (por experiência própria, após quinze minutos dê meia volta e comece a voltar, ou a meia hora vira uma).

E você deve cuidar das amizades, porque são como uma planta: devem ser regadas diariamente, o que me faz pensar em quem vai cuidar delas quando eu estiver viajando.

Deve-se estar bem informado também, lendo dois ou três jornais por dia para comparar as informações.

Ah! E o sexo.
Todos os dias, tomando o cuidado de não se cair na rotina.
Há que ser criativo, inovador para renovar a sedução.
Isso leva tempo e nem estou falando de sexo tântrico.

Também precisa sobrar tempo para varrer, passar, lavar roupa, pratos e espero que você não tenha um bichinho de estimação.

Na minha conta são 29 horas por dia.

A única solução que me ocorre é fazer várias dessas coisas ao mesmo tempo!!!

Tomar banho frio com a boca aberta, assim você toma água e escova os dentes. Chame os amigos e seus pais.
Beba o vinho, coma a maçã e dê a banana na boca da sua mulher.

Ainda bem que somos crescidinhos, senão ainda teria um Danoninho e se sobrarem 5 minutos, uma colherada de leite de magnésio.

Agora tenho que ir.

É o meio do dia, e depois da cerveja, do vinho e da maçã, tenho que ir ao banheiro.

E já que vou, levo um jornal...

Tchau....

Se sobrar um tempinho, me manda um e-mail.

Luís Fernando Veríssimo

Friday, March 6, 2009

Como abrir o gnome-terminal com múltiplas abas

Para abrir o gnome-terminal com diversas abas, cada uma em um diretório, podemos usar o comando:

gnome-terminal \
--tab --working-directory=/home/user/project1 \
--tab --working-directory=/home/user/another_dir \
--tab --working-directory=/home/user/project1/src/main \
--tab --working-directory=/home/user


Outros dois parâmetros interessantes são " --command='comando a ser executado' " e " --title='titulo da aba' ", porém nenhum dos dois funcionou satisfatoriamente pra mim.

Wednesday, March 4, 2009

Mozilla Bespin: web text editor and collaboration tool

Hoje eu conheci o Bespin, graças a meu amigo Flávio Amieiro.

Depois do Coding Dojo Rio de hoje, movimentação na lista e uma possível integração com o pessoal da SEA Tecnologia de Brasília, o Flávio citou o Bespin como ferramenta para fazermos um dojo remoto colaborativo.

Comecei vendo um introdução nesse vídeo:

Introducing Bespin from Dion Almaer on Vimeo.


Basicamente é mais um experimento/projeto em estado alfa de desenvolvimento da equipe do Mozilla Labs. É um editor de código-fonte, atualmente com suporte a sintaxe colorida em Javascript, CSS e HTML.

O Bespin é escrito em Java, Python, e bastante Javascript, HTML e CSS.

Tem suporte experimental a edição colaborativa.

Esta é a interface de "dashboard", com um navegador de arquivos no estilo do Mac OS X.
Na parte de baixo eu dei o comando "help" para receber uma lista dos comandos disponíveis.


Esta é a interface de edição mais a área de colaboração, que no momento parece estar desativada.


Tem um demo do projeto rodando em:
http://bespin.mozilla.com/

Você pode se registrar ou usar um login genérico daqui:
http://www.bugmenot.com/view/bespin.mozilla.com

O código-fonte do Bespin é aberto, e está em um repositório do Mercurial:
http://hg.mozilla.org/labs/bespin/


Vale a pena dar uma olhada neste e outros projetos do Mozilla Labs, a exemplo do Ubiquity e do Prism.

Saturday, February 28, 2009

Brincando com o Bazaar (bzr)

Nesse carnaval tirei um tempo para ver como funciona o Bazaar.

Mas o que é isso? Bem, o Bazaar é um DVCS - Distributed Version Control System -, um software que, simplificadamente, serve para guardar diversas versões de arquivos. Em geral, esses "arquivos" estão relacionados a código-fonte, mas podem ser qualquer coisa, como imagens, pdfs, executáveis, etc.

Um sistema de versionamento famoso é o Subversion (svn), que é um sucessor do CVS. Entretanto, o Bazaar, assim como outros DCVSs, são essencialmente diferentes desses dois.

O SVN e o CVS são sistemas centralizados, com pouco suporte para operações offline, e possibilidades (facilidade) de colaboração limitadas. As operações de controle de versão ocorrem num repositório central, necessitando conexão de rede/Internet.

Já os sistemas distribuídos, possuem diversos repositórios; repositórios locais, onde o desenvolvedor pode salvar (commit) seu trabalho, e repositórios remotos onde ocorre a integração (merge) das partes.

Bem, a minha intenção aqui não é explicar como funciona o SVN nem o CVS, nem dar detalhes do que eles são. O trecho acima foi só para tentar nivelar os desentendidos :)

Mais informações nos links que apontam para a Wikipedia!


Voltando ao Bazaar, existem outros "concorrentes" por aí, boas opções também. Dentre as principais: Mercurial e Git.
Tenho usado o Git no meu estágio, e achei ele um pouco "fora do meu estilo". Também tem um ponto chato que é rodá-lo no Windows -- um grande problema. E como meu dia a dia é Linux pra cá, Windows acolá, então é uma limitação relevante pra mim.

Meu orientador Carlo me deu uma amostra grátis do Bazaar algumas semanas atrás, lá no NCE/UFRJ, e achei por bem tirar um tempo pra brincar com ele por minha conta. E foi o que fiz em algum momento do feriadão de carnaval. Instalei o Bazaar no Ubuntu e passei a usá-lo em um projeto pessoal.

A instalação foi muito fácil. Nos repositórios padrão do Ubuntu 8.10, a versão do Bazaar não era a mais recente, portanto, adicionei ao meu sources.list o repositório do Bazaar no Lauchpad.

Conforme diz aqui bastou eu abrir o gerenciador de pacotes e pedir para adicionar essas duas linhas:

deb http://ppa.launchpad.net/bzr/ppa/ubuntu intrepid main
deb-src http://ppa.launchpad.net/bzr/ppa/ubuntu intrepid main
Depois de atualizar a lista de pacotes disponíveis, lá estava o Bazaar 1.12, assim como o pacote bzr-gtk que traz uma interface gráfica pro mesmo.

Agora enquanto escrevo, vou instalar no Windows...
Extremamente fácil: só baixar e executar. Instalado e funcionando muito bem.
Desta forma, instalei o Bzr standalone, isso é, não está instalado junto ao meu Python do sistema.

Pois é, o Bazaar é escrito em Python, é muito fácil de usar, e é uma mão na roda para por exemplo manter o pendrive, notebook, e outros pcs sincronizados. E de quebra um local faz backup do outro...

A idéia do Bazaar é de ser um software fácil de usar, e com pouco tempo de uso já me sinto confortável para fazer diversas tarefas. Sua documentação é boa, funciona em qualquer lugar que rodar Python, o que significa umm... qualquer lugar...

Também é muito legal usar o bazaar interfaceando com outros sistemas de controle de versão. O Bazaar, até onde sei, é o único que pode ser usado com o SVN, Git, Mercurial, tudo ao mesmo tempo. Existem plugins que integram o bzr com cada um destes outros projetos, de forma que pela linha de comando do bzr posso fazer checkout e commits em repositórios svn... ou git...

Por fim, li uma dica muito bacana sobre como colaborar em projetos usando o bzr. O projeto pode estar usando qualquer controle de versão, ou mesmo usando nenhum :)

A idéia é a seguinte:
    # criar um diretório para guardar seu trabalho
mkdir projeto
cd projeto
# Criar um repositório do bzr (para otimizar o uso de espaço em disco)
bzr init-repo --trees .
# Pegue o codigo oficial do projeto
svn co http://url/do/repositorio/oficial/do/projeto original

Então agora temos um diretório contendo o código original do projeto. A idéia é deixar o diretório "original" intocado, sendo este apenas uma referência.

Agora vamos criar alguns branches no Bazaar para organizar o trabalho:
    # Criando um branch do bzr para o codigo original
cd original
bzr init
bzr add .
bzr ci -m'Importação do projeto'
# Criando um branch principal
cd ../
bzr branch original main

No branch main, podemos fazer as modificações necessárias para fazer o projeto rodar no nosso sistema, se for necessário. Essas modificações não serão enviadas de volta ao repositório original.

    cd main
# Faça as alterações locais e prossiga
bzr ci -m'Adicionando mudanças locais'

Agora, sempre que for trabalhar em um patch/funcionalidade, crie um novo branch para ela. Isso faz com que as mudanças no projeto original sejam independentes.

    # Criando um branch para trabalho em uma funcionalidade
cd ..
bzr branch main algumafuncionalidade
cd
algumafuncionalidade
# Implemente a fucionalidade e então
bzr ci -m'Adicionada funcionalidade xyz'

Agora, certifique-se que o código está atualizado em relação ao original para que seu patch seja limpo (atualize frequentemene para evitar uma grande quantidade de conflitos a serem resolvidos).

    cd ../original
svn update

Isso trará as mudanças do repositório SVN oficial do projeto (pode ser outro comando, de acordo com o controle de versão usado no projeto...). Não deve haver nenhum conflito nesse momento, já que nada foi feito localmente em 'original'. Note que podem haver novos arquivos (linhas com um A na saída do svn update). O comando bzr unknowns pode te ajudar agora. Se houver algum arquivo novo, adicione-o ao bzr:

    bzr add arquivonovo
# ou bzr add $(bzr unknowns)
bzr ci -m'Mesclando com original do svn revisão 1234'

Isso significa que seu branch original está atualizado no bzr. Agora é hora de propagar as novidades para os branches com cada nova funcionalidade. Mas antes vá ao branch main para manter suas alterações de funcionamento local.

    cd ../main
# Mesclar com as alterações em original
bzr merge
# Se houver algum conflito, solucione e então
bzr resolve file
# Quando tudo estiver ok (bzr status e bzr diff podem
# ajudar nessa hora)
bzr ci -m'Mesclando com original do svn revisão 1234'

E agora o mesmo para os branches de cada funcionalidade.

    cd ../algumafuncionalidade
bzr merge
# 'bzr resolve' se necessário
bzr ci -m'
Mesclando com original do svn revisão 1234'

Pode parecer muito trabalho (é mais simples que o Git :P), mas isso é feito bem rápido, especialmente se o desenvolvimento for feito "um passo de cada vez". Entretanto, os benefícios dessa forma de trabalhar superam essa trabalheira.

Como comparado ao svn o bzr é superior na hora de fazer merge, trabalhando desta forma reduzirá a quantidade de trabalho manual necessária para resolver conflitos.

Agora que você tem um nova funcionalidade implementada em um branch, você pode enviá-la para o repositório oficial do projeto!

É muito fácil. Já que separamos as funcionalidades em branches, os diffs sempre serão limpos, e para criá-los:

      bzr diff -r branch:../main > ../funcionalidade.diff

Agora você pode revisar o diff e enviar para os mantenedores do projeto como um patch.

Você pode deixar seu branch de lado, e criar novos branches se quiser trabalhar mais. Se os mantenedores pedirem alguma alteração no seu patch para a funcionalidade que enviou, basta voltar ao branch e fazer as alterações, e enviar um novo diff.

Se o patch for aceito, então suas alterações irão parar na próxima atualização do código no repositório svn, e irão se propagar para todos os seus branches bzr. Não haverá nenhum conflito.

Se o patch não for aceito, mas mesmo assim você qe manter suas alterações localmente, é também fácil. Simplesmente faça um merge do seu branch com o main branch, que então vai propagar para os outros branches de funcionalidade.
    cd ../main
bzr merge ../algumafuncionalidade
bzr ci -m'Adicionando funcionalidade'

Agora, quando você atualizar os outros branches de funcionalidade, eles vão receber a funcionalidade, sem que seus diffs a contenham, mantendo os patches separados.

Se quiser implementar um funcionalidade em várias etapas, você pode criar branches de funcionalidade que dependam um do outro.
     bzr branch main pequena.mudanca
bzr branch
pequena.mudanca grande.mudanca

Agora, as mudanças de pequena.mudanca se propagam para grande.mudanca, e você pode gerar três patches:

   # Diff para implementar pequena.mudanca
cd pequena.mudanca
bzr diff -r branch:../main
# Diff para implementar grande.mudanca
cd grande.mudanca
bzr diff -r branch:../main
# Criar diff para implementar grande.mudancao que é dependente de
# pequena.mudanca. Útil se a segunda parte da mudança ainda precisar
# ser discutida, ou se for aceita em etapas.
cd grande.mudanca
bzr diff -r branch:../pequena.mudanca

Portanto, fica aqui uma amostra de como o bzr pode trazer flexibilidade para trabalhar em um projeto, não importa qual controle de versão que seja usado oficialmente.


E eu, super feliz com o bzr :)