Planeta PythonBrasil

September 03, 2010

Kodumaro

Torne-se excelente

Glider Este é um artigo que meu amigo Argentino me apresentou, do Klaus Wuestefeld, autor do manifesto da Computação Soberana.

O artigo original – ou pelo menos o endereço que me foi apresentado – se encontra no GitHub e aconselho todos a lerem.

Mas antes, no artigo original os comentários tenderam para discussão sobre a importância do curso superior. O foco do texto não é esse! Não é criticar a faculdade ou sua importância. O foco é mais na prioridade que damos às coisas.

Em outras palavras: um curso académico é importante, mas possui menor prioridade do que a experiência profissional, ainda mais na Computação, curso que no Brasil ainda não está academicamente bem definido e em muitas faculdades tende a ser regido por interesses empresariais no lugar de pelo conhecimento.

Segue o artigo:

Torne-se excelente


Seja realmente bom em alguma coisa. Não fique só choramingando ou querendo progredir às custas dos outros. Não pense que, porque você sentou 4 anos numa faculdade ouvindo um professor falar sobre software, você sabe alguma coisa. Jogador de futebol não aprende a jogar bola tendo aula. Ele pratica. Instrumentistas geniais não aprendem a tocar tendo aula. Eles praticam. Pratique. Chegue em casa depois do trabalho e da aula e pratique. No final de semana, pratique.

Crie seu próprio vírus, seu proprio jogo, seu proprio SO, seu proprio gerenciador de janelas, seu proprio webserver, sua propria VM, qualquer coisa. Várias coisas.

Não precisa ser só programação. Pode ser networking, vendas, etc. Só precisa ser bom mesmo. Tenha paixão pela coisa.

As melhores práticas do mercado são polinizadas primeiro nos projetos de software livre. Aprenda com eles.

Discípulo, Viajante, Mestre: Primeiro seja um discípulo, tenha mestres locais, aprenda alguma coisa com alguem realmente bom, qualquer estilo. Depois viaje, encontre outros mestres e aprenda o estilo deles. Por fim, tenha o seu estilo, tenha discípulos, seja um mestre.

Vou fazer o curso da Mary Poppendieck em SP semana que vem e quando tiver o curso de Scrumban do Alisson e do Rodrigo quero fazer também.

«Torne-se excelente» também pode ser chamado de «Melhoria Continua» ou Learning.

Não seja deslumbrado


Desenvolvimento de software é a mesma coisa há 60 anos: modelo imperativo. Há 30 anos: orientação a objetos. Bancos de dados relacionais: 30 anos. («Web», por exemplo, não é uma tecnologia ou um paradigma. É meramente um conjunto de restrições sobre como desenvolver e distribuir seu software).

Não corra atras da ultima buzzword do mercado. Busque a essência, os fundamentos.

Busque na Wikipédia e Grokke: determinismo, complexidade de algoritmos O(), problema de parada de Turing. Pronto, pode largar a faculdade. Falando sério.

Trabalhe com software livre. Não dê ouvidos a grandes empresas, grandes instituições ou grandes nomes só porque são grandes.

Você acha que vai aprender mais, ter mais networking e mais chance de alocação no mercado trabalhando em par comigo no Sneer por um ano, 8h por semana, ou passando 4 anos na faculdade, 20h por semana, pagando sei lá quanto por mês?

Você acha que vai aprender mais trabalhando em par com o Bamboo 6 meses na linguagem Boo e na engine do Unity ou fazendo um ano de pós em «a buzzword da moda»?

«Não seja deslumbrado» também é conhecido como Coolness.

Mantenha-se Móvel


Com a demanda que temos hoje no mercado, se você é desenvolvedor de software e não consegue negociar um contrato com uma empresa onde você é pago por hora e pode trabalhar quantas horas quiser com um mínimo de meio período, você precisa rever a sua vida.

É melhor ter dois empregos de meio período que um de período integral, porque você pode largar um deles a qualquer momento.

Você nunca vai conseguir nada melhor se não tiver tempo, se não tiver disponibilidade pra pegar algo melhor quando aparecer.

Você sustenta seus pais e 7 irmãos? Não. Então pare de ser ganancioso e medroso no curto prazo, para de pagar facu, mestrado, pós, MBA, sei-lá-o-quê e vai aprender e empreender.

Trabalhe remoto. Não é o mais fácil, mas é perfeitamente possível.

Não fique reclamando que está trabalhando demais. Aumente seu preço e trabalhe menos.

Emparceire-se Promiscuamente


Participe de dojos, de congressos, de projetos de software livre. Tenha amigos, colegas, conhecidos. Seja conhecido. Não faça ruído em seis projetos e doze fóruns. Ajude de verdade em um ou dois projetos de cada vez. Ao longo do tempo, você terá ajudado em varios projetos, trabalhado em várias empresas.

Mentalidade de Abundância


Ajude seus amigos sem cobrar (a «camaradagem» do Vinícius). Dê palestras gratuitas. Cursos gratuitos. Participe de projetos de software livre.

Pare as vezes uma tarde pra receber um amigo seu e explicar seu projeto. Vá visitar seus amigos nos projetos deles. Viaje com algum amigo seu pra visitar um cliente dele, só pra conversar e fazer companhia.

Você tem um espaço onde dá cursos? É uma Aspercom, Caelum da vida? Chama os brothers para dar curso. Porra, bola um modelo em que as pessoas podem se inscrever para cursos variados, pagando um sinal, e mantém tipo uma agenda pré-combinada: «Será numa terça e quinta à noite, avisadas com duas semanas de antecedencia». Se rolar, beleza, se depois de meses não der quórum, devolve o sinal. Pode ser curso de Prevayler, de Kanban, de Scrum, de Lean, de Comp Soberana, de Restfulie, de Cucumber, de Rails, de Teste Automatizado Mega-Avançado, qualquer coisa.

Chame amigos seus pra dar curso em dupla com você. Divida clientes. Divida projetos, mesmo que não precise de ajuda.

Dizia o pai de um brother meu de infância: «Tudo que custa dinheiro é barato».

Busque modelos de custo zero


Trabalhe em coisas que tem custo administrativo/ burocrático/ manutenção zero. Por menos ganho que tragam, depois de prontas, estarão tendo uma relação custo/benefício infinitamente vantajosa.

Ganhe notoriedade


Faça coisas massa. Participe de projetos de software livre. Dê palestras gratuitas. Promova eventos (dojos, debates, grupos de usuários, etc).

By Dairton Bassi:

Não tenha medo!


Meta a cara. Arrisque empreender. Arrisque inovar. O que você tem a perder? No máximo um emprego, mas isso pode ser revertido facilmente em um mercado aquecido como o atual. O pior que pode acontecer é não dar certo. Mesmo assim você terá aprendido muito mais do que batendo cartão.

Saia da zona de conforto. Se o seu trabalho estiver fácil e sob controle, isso significa que ele não está mais agregando para a sua evolução técnica e pessoal.

Não desperdice a chance de trocar de função se a nova oportunidade for mais desafiadora. Isso fará você crescer tecnicamente e o preparará para desafios maiores ainda. Conhecer pessoas novas é tão importante quanto manter-se em contato com código.

Não se detenha por insegurança ou pela sensação de despreparo. Como você acha que vai ganhar experiência em alguma coisa se sempre adiá-la?


[]’s
Cacilhας, La Batalema

por noreply@blogger.com (Cacilhας, La Batalema) em 03 de September de 2010 às 01:00

Aprenda Python

Aprenda Python com o MIT

Mais dois cursos gratuitos de Python. Dessa vez no MIT: A Gentle Introduction to Programming Using Python (de 2008) Introduction to Electrical Engineering and Computer Science I (de 2009) A Gentle Introduction to Programming Using Python (de 2010) Os vídeos você encontra no Youtube.

por Vinicius Assef (noreply@blogger.com) em 03 de September de 2010 às 01:40

September 02, 2010

Aprenda Python

Aprenda Python com um curso do Google

Tem gente que ainda duvida que Python é uma linguagem muito usada. Depois que li o texto Google Python Style Guide, tenho repassado para várias pessoas. Na seção "Background", está escrito que Python é a principal linguagem de script usada pelo Google. Vale lembrar que o Guido van Rossum, criador da linguagem, também trabalha lá. Recentemente descobri que o Google disponibilizou gratuitamente

por Vinicius Assef (noreply@blogger.com) em 02 de September de 2010 às 23:47

August 31, 2010

Kodumaro

Blogagem Coletiva em repúdio ao AI5 Digital – 31/08

AI5 Digital

Veja também no blog do gutocarvalho.net:

Blogagem Coletiva em repúdio ao AI5 Digital – 31/08



Amigos, os adoradores do AI5Digital e da ditadura, os amantes do vigilantismo, os defensores dos direitos econômicos em detrimento dos direitos civis que formam o tripé do atraso, estão se movimentando para aprovar o famigerado e monstruoso AI5Digital que há muito deveria ter sido fulminado, destruído e acabado.

A turma do Grande Irmão: Azeredo, Febraban, Fecomercio e outros do mesmo quilate estão fazendo uma força tremenda para nos empurrar o AI5Digital guela abaixo de qualquer forma, vamos aos fatos:
  1. A mídia continua repetindo o Mantra da Irracionalidade contra a Internet
  2. No dia 05/08/10 O Deputado Pinto Itamaraty do PSDB apresentou parecer favorável ao AI5Digital, ignorando todos os argumentos e movimentos sociais dos últimos três anos.
  3. Seis dias depois aparece uma matéria dizendo que os Deputados buscarão acordo para votar a lei de crimes na Internet.
  4. E agora um evento para lá de esquisito organizado pela revista Decision Report, uma publicação que parece estar à serviço do Azeredo e do vigilantismo, se anuncia para o dia 31/08 com o título oportuno (para o tripé do atraso) de: Crimes Eletrônicos – A urgência da lei. O curioso e que este evento conta com 19 palestrantes para falarem em 2:30h, o que dá um pouco mais de 7 minutos para cada um.

Por estas e por outras que estamos convocando uma blogagem coletiva para o dia 31/08/10, justamente no dia do tal evento à serviço do Azeredo e do AI5digital, vamos fazer uma blogagem coletiva contra o AI5Digital para lembrar a todos que queremos a Internet como um espaço livre e democrático!!!

Fonte:
http://meganao.wordpress.com/2010/08/27/blogagem-coletiva-de-repudio-ao-ai5-digital/

Participe do MEGANÃO, acesse agora:

http://meganao.wordpress.com/o-mega-nao/quem-esta-participando/


[]’s
Cacilhας, La Batalema

por noreply@blogger.com (Cacilhας, La Batalema) em 31 de August de 2010 às 13:24

August 30, 2010

Inno::Blog

Leptoniando: Toda computação é sempre física

Seja C, C++, Python, Java, Ruby ou Brainf*ck, independente de sua linguagem preferida, durante a análise léxica, sintática, semântica, geração do código executável ou em qualquer outra operação, na execução de programas, independente da arquitetura de run-time e dependência que ela tenha, seja instruções bare-metal ou dependente de algum sistema operacional, rodando na CPU de um ignorado microcontrolador presente em seu relógio, celular ou na CPU do seu idolatrado (ou cobiçado) notebook ou nas células de uma cloud computing, não há o que discutir, a computação é sempre um fluxo de partículas, sejam léptons do tipo elétron ou bósons de calibre como o fóton. Tudo bem que seja por influência de algum fenômeno eventualmente não se comportam como nós esperamos, porém sabendo disto determinamos faixas de tolerância e assim os mal comportados acabam sendo desprezados e vamos levando a vida praticamente sem perceber estes rebeldes e a física flui, ou tenta, nos favorecendo neste admirável mundo computacional.

E como você já sabe, ou deveria saber, a física não é exclusiva da computação, aspectos físicos estão na fundamentação de vários fenômenos, como por exemplo a sua vida e a natureza.

Tudo bem que o termo “físico”  pode ser empregado para outros contextos e com outros significados que não seja a ciência que estuda os fenômenos naturais como a interação da matéria e da energia, mas sinceramente é muito estranho quando você emprega-o de forma indevida tentando substituir um termo consagrado.

Por exemplo, temos Embedded Systems (ou sistemas embarcados em português) que é um termo que já existe desde a década de 60, quando o pai dos sistemas de navegação inercial – Charles Stark Draper – criou o Apollo Guidance Computer, que era um sistema computacional de controle e comando do módulo Lunar  da missão Apolo. O termo então é coroa e está mais atual do que nunca, principalmente porque hoje as pessoas estão se dando conta do universo computacional onde elas vivem onde há computação embarcada em máquinas de levar, forno microondas, relógios e até em tênis.

Obviamente que qualquer um com direitos suficientes, pode ter a liberdade de atribuir qualquer nome para qualquer coisa, mas isto costuma ser mais apropriado quando o universo onde este “apelido” é utilizado seja bem íntimo e restrito ao domínio daquele que o emprega ou a obra ou a criatura ainda não possui um nome devidamente registrado ou consagrado. Rebatizar sem nexo é uma ação sempre passível de represália, principalmente quando o termo não agrada por não ser muito elegante. Quando é um termo empregado por uma comunidade é ela que poderá estranhar a nova nomenclatura, principalmente se o nome é ligeiramente desprovido de propósitos adequados.

No caso de Sistemas Embarcados, este nome está bastante maduro e bastante conhecido no meio industrial, acadêmico e na sociedade, que é o nome dado aos sistemas digitais microprocessados no qual o computador é encapsulado ou dedicado a um sistema controlado, sendo assim diferente de computadores de propósito geral. Obviamente que há categorias de sistemas embarcados, e alguns sistemas são mais flexíveis do que outros, porém o tipo de computação realizado com eles, seja num marca-passo ou num celular é computação embarcada, sendo um tipo de computação empregado numa grande variedade de domínios e aplicações. Na realidade, se você for analisar bem, você convive a maior parte do dia com dispositivos que realizam computação embarcada do que computação genérica, por razões óbvias! Suas CPUs muitas vezes são especializadas e o próprio processador atende um determinado propósito por concepção, podendo assim ser muito mais eficiente. Dentro deste guarda-chuva, ainda há a computação pervasiva e ubíqua, porém analisando cada um dos conceitos pode-se entender que cada terminologia é bem coerente, e apesar de parecer confusa dependendo da perspectiva de análise, se corretamente analisado percebe-se que ela é inteligente.

Recentemente, surgiu uma nova terminologia chamada “computação física” que designa exatamente  um subset da “computação embarcada” mas empregando seus atributos principais. Este termo é aplicado para os sistems embarcados direcionado para artes, ensino, e no geral para um grupo quase leigo em eletrônica, que sabe apenas o suficiente para realizar suas experimentações. Por um lado, é muito interessante que este público faça uso de sistemas embarcados desta forma, pois com a propagação da informação e das técnicas de desenvolvimento, a chance da tecnologia ser melhor empregada cada vez mais é sempre maior.  Porém, estes não deixaram de desenvolver sistemas embarcados, mas estão rebatizando um termo amplamente conhecido e ignoram outros que tem sido claramente empregados.  Assim como muitos colegas da comunidade industrial, aprecio muitíssimo estas atividades mas algumas terminologias como esta são de doer! Neste caso em específico por uma razão óbvia: toda computação é física, então o que há de diferente nela?

E então vieram me dizer:  mas você entendeu errado! Computação Física são aquelas aplicações que você consegue tocar, interagir.

Vamos lá, fisicamente um bit , de uma maneira geral, é uma carga elétrica acima ou abaixo de uma faixa de  nível padrão. Para se tocar uma aplicação seria necessário entrar em contato com um fluxo de elétrons, então Computação Física é a arte de desenvolver máquinas de eletrochoque? Nem isto, pois o fluxo de elétrons de uma tensão padrão de mensuração digital não costuma ser percebida pelos seres humano normais.

Ah, não é isto! A interação são com sensores como botões, acelerômetros e atuadores como leds, motores, auto-falantes. Curioso, estes componentes e estas propriedades também são utilizados por embedded systems e a computação presente  é a embedded computing. Isto me lembra o estranho termo NoSQL; afinal, uma bicicleta não é SQL então é NoSQL, mas este termo se refere aos modelos de persistência baseado em banco de dados não relacionais e de alta performance com “novos paradigmas”, alguns existentes desde a década de 60 e 70, sei…

Como o termo incomoda, alguns “gurus” desta nova categoria de projetos de interação, controle, mecatrônica e robótica adoram empregá-lo,  como no caso do NoSQL. Este tipo de artifício pode ser muito útil quando se precisa chamar a atenção, mas os Sistemas Embarcados desenvolvidos com OSHW (Open Source Hardware) por hobby, aprendizado, atividade artística ou qualquer outro objetivo, já chama a atenção por si só, pela massificação de uma cultura que já existia, mas que foi repaginada de uma forma muito vigorosa dentro do contexto Open Source, ramo da computação e da eletrônica que antes era muito restrita e pela própria interação cibernética agradável que ela acaba gerando. Tornando-se um movimento extasiante, inebriante, contagiando e atraindo cada vez mais pessoas para este mundo. Portanto, a cultura OSHW não precisa reinventar terminologias e uma integração maior com a indústria, empregando os termos já existentes e caldo de galinha não faz mal a ninguém.

Rebatizar tem se mostrado não apenas uma prática, mas uma característica da subcultura Arduino, onde se analisarmos a plataforma é uma nova versão da Wiring mas tornou-se Arduino, o IDE que era o Processing foi rebatizado de Arduino, a linguagem virou Arduino, o termo “coreboard” tem sido substituído por Arduino, a DaughBoard virou “Shield”, a arquitetura de stack virou “expansão Arduino” e até o microcontrolador tem sido chamado de Arduino por respeitáveis revistas formadoras de opinião.

Tudo bem que spin-offs são comuns e forks fazem parte da cultura Open Source, sendo até muito bem vindos em alguns casos. Certos projetos de sucesso dificilmente teriam ganhado a projeção que eles alcançaram se estivessem atrelados aos projetos originais, mas tentar utilizar e substituir terminologias e nomes consagrados numa indústria mostra-se agressivo se o novo nome não tem nexo, visto que substituir o termo “sistemas embarcados” por “computação física” é algo que não faz sentido, pois toda computação é física e esta justifica da interação é tão inocente que chega ser constrangedora. E não adianta vir dizer que é o termo mais apropriado pois designa a interação de circuitos digitais e analógicos, pois este processamento de sinais além de ser característica dos circuitos integrados também era conhecido como sinal misto (mixed signal), e qualquer significado que se tentar encontrar para justificar este nome estranho certamente esbarrará na definição de algum outro termo já existente.

No caso do microcontrolador AVR, que já existe desde 1996 e tinha todo um ferramental open source que é empregado pelo Arduino, e da terminologia “sistemas embarcados”, isto é até uma falta de respeito por seu legado.

Entendo que todo este movimento é extasiante e inebriante, assim como somos ilhados por incoerências, ilusões e irradiação de campos de distorção da realidade, porém no que tange a nossas possibilidades devemos sempre colaborar com bom senso.

Na minha humilde opinião, aderir a  terminologias impróprias além de incoerente não é falta de etiqueta, e inclusive tem sido observado por várias pessoas da comunidade, sendo-se que alguns até aprova o movimento Open Source Hardware que é uma repaginação do que já ocorria a décadas, mas que quando abrem certas revistas de “renome” ou navegam por algumas páginas na internet torcem o nariz para estas bobagens que são escritas e propagadas.

Costumo atuar em favor da comunidade Open Hardware, mas certas situações me colocam em situação tão delicada, que realmente não há como negar: alguns sub-grupos desta comunidade precisa de um pouco de maturidade, não há mais o que dizer.

Obviamente, cada um faz aquilo que o torna mais feliz e se quiser chamar celulares de computação falante, afinal por eles se falam;  as máquinas de lavar microcontroladas de computadores lavadores; assim como as catracas de metrô de computadores porteiros, fiquem a vontade! Mas são todos dispositivos com sistemas embarcados, seja aviônica, automotiva, telecom, automação e controle, consumo ou arte digital. Estes sempre foram e a indústria continuará chamando-as assim, então esta é uma opção de cada um: ser coerente ou não.

E por enquanto é isto.

Namastê!


por techberto em 30 de August de 2010 às 02:47

August 27, 2010

Kodumaro

Paradigmas de programação

Glider Muito mais empolgante do que aprender uma nova linguagem de programação é aprender um novo paradigma de programação.

A parte mais louca é perceber como o paradigma funciona. Isso acontece de modo intuitivo, muito parecido com como quando se aprende uma língua nova: nada faz sentido no começo, tudo é muito mecânico; de repente um estalo e tudo faz sentido!

Há muitos paradigmas de programação, já andei falando disso antes, mas muitos são variações dos mesmos tipos básicos: paradigmas imperativo, funcional e declarativo.

Programação imperativa


É o primeiro paradigma com o qual a maioria dos programadores trava contato.

Na programação imperativa, o programa se parece com uma receita de bolo: uma sequência de ordens, chamadas comandos ou instruções (statements em inglês), que devem ser executadas.

A partir desse conceito, derivam diversos paradigmas secundários. O principal é a programação estruturada ou procedimental (procedural em inglês), onde os comandos são organizados em grupos, chamados funções, que podem ser evocados em momentos diferentes.

As funções podem receber ou não parâmetros, que alteram seu comportamento, e podem retornar valores. Em algumas linguagens, quando o grupo de comandos não recebe parâmetros nem retorna valores, ele é chamado subrotina.

Para exemplificar o funcionamento da programação imperativa, vamos implementar fatorial em C – mais simples impossível.

Para quem não sabe, fatorial consiste em uma função recursiva cuja parada é:
0! = 1


E o passo é:
n! = n * (n - 1)!


Outra forma de entender é reiterativamente:
n! = 1 * 1 * 2 * 3 * … * (n - 2) * (n - 1) * n


Vamos implementar a função reiterativa em C para ilustrar melhor o paradigma:
#include <stdlib.h>
#include <stdio.h>

int factorial(int);


int main(int argc, char **argv) {
printf("O fatorial de 5 é %d\n", factorial(5));
return EXIT_SUCCESS;
}


int factorial(int x) {
int result = 1;
int i;
for (i=1; i<=x; ++i)
result *= i;
return result;
}


Cada comando é uma ordem dada ao sistema: atribua 1 à variável result; para cada i de 1 até o valor do argumento x, multiplique o valor de result pelo valor de i; retorne o valor de result.

São ordens dadas ao sistema.

Orientação a objetos


Orientação a objetos não passa de um variante da programação imperativa, mas um variante digno de citação.

Na orientação a objetos, as ordens não são dadas a um sistema abstrato, mas objetos recebem as ordens e as executam.

O conceito de objeto é bem genérico: qualquer coisa pode ser um objeto, um número, uma janela na tela, uma coleção…

Na orientação a objetos as ordens dadas a um objeto são chamadas mensagens e a definição de como o objeto reage a cada mensagem é chamada método.

O exemplo será a versão recursiva de fatorial implementada em Smalltalk:
!Integer methodsFor: 'arithmetic'!

factorial
(self = 0) ifTrue: [
↑ 1
].

↑ self * ((self - 1) factorial).
!
!!


Transcript
show: 'O fatorial de 5 é ', (5 factorial printString);
cr.


O princípio é parecido com o anterior, mas em vez de dar uma ordem ao sistema – calcule o fatorial de 5 –, é dada ao próprio número – número 5, qual seu fatorial?

Observação: a orientação a objetos pode ser aplicada também à programação funcional.

Programação funcional


Enquanto na programação imperativa ordens são dadas ao sistema ou a objetos, no paradigma funcional são definidas funções, como as matemáticas, e o programa nasce da interação entre as funções: o resultado de umas funções é passado como parâmetro para outras.

O mesmo exemplo, fatorial, em Common Lisp:
(defun factorial ((x integer))
(if (zerop x)
1
(* x (factorial (- x 1)))))


(format t "~%O fatorial de 5 é ~A~&" (factorial 5))


O conceito é ligeiramente difente: a função factorial, que recebe um parâmetro inteiro nomeado x, é definida como o resultado da função if; a função if recebe como primeiro parâmetro o resultado da função zerop, que é verdadeiro quando x é igual a zero; o segundo parâmetro de if, 1, é o resultado caso o primeiro parâmetro seja verdadeiro; o terceiro parâmetro é o resultado caso seja falso; o terceiro parâmetro é o resultado da função de multiplicação. Entendendo até aqui, o resto é autoexplicativo.

Programação declarativa


Este paradigma é um dos mais complicados para pescar

O programa consiste em uma lista de declarações de verdades.

Nos paradigmas anteriores havia variáveis, que sofriam atribuições. Na programação declarativa há incógnitas, que não sofrem atribuições! O valor de cada incógnita é constante e inicialmente desconhecido. O que o programa faz é cruzar as consultas (queries) com as declarações que formam o conjunto verdade para deduzir o valor das incógnitas.

O exemplo consiste no fatorial implementado em Prolog:
factorial(0, 1).

factorial(N, F) :-
N > 0,
N1 is N - 1,
factorial(N1, F1),
F is N * F1.


O que este conjunto verdade diz é que o fatorial de 0 é 1 e que o fatorial de N é F quando:
  1. N é maior que zero;
  2. N1 é N menos 1;
  3. o fatorial de N1 é F1;
  4. e F é igual a N vezes F1.


Para a consulta:
| ?- ['factorial.pro'].
fatorial.pro compiled, 7 lines read - 869 bytes written, 7 ms
(1 ms) yes
| ?- factorial(5, X),
write('O fatorial de 5 é '),
write(X),
nl.


Para entender como funciona, há um applet em Java em um tutorial que demonstra o chinês. É só encontrar o applet na página, ir clicando em Step e ver acontecer.

A linguagem declarativa da vez é Erlang.

[]’s
Cacilhας, La Batalema

por noreply@blogger.com (Cacilhας, La Batalema) em 27 de August de 2010 às 01:24

August 24, 2010

Noticias da PyConBrasil

Ajude a divulgar a PythonBrasil

A PythonBrasil[6] é o maior evento da comunidade brasileira de Python. Serão 3 dias com palestras e treinamentos de altíssimo nível ministradas por profissionais nacionais e internacionais. Ajude a divulgar!

por taniaa em 24 de August de 2010 às 18:39

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:

você chama assim:


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 24 de August de 2010 às 16:45

Noticias da PyConBrasil

Novo recorde no envio de trabalhos

Ano após ano, a comunidade Python brasileira mostra a sua força e pela sexta edição consecutiva, foi quebrado o recorde de envio de trabalhos. No total foram enviadas 73 propostas de trabalho. Elas estarão em avaliação nos próximos dias e a grade oficial do evento sai no dia 6 de Setembro.

por dorneles em 24 de August de 2010 às 07:31

August 23, 2010

Linil

Proxy Pattern – Java e Python

Recentemente venho dedicando boa parte do meu tempo na implementação da minha dissertação de mestrado. O meu trabalho consiste em modelar/desenvolver um middleware para redes de sensores sem fio. Apesar de ser um pythonista de carteirinha não consegui achar nenhuma plataforma de sensores baseadas em python então a minha escolha para o mestrado ficou com o SunSPOT. Para os desavisados, o SunSPOT trabalha com j2me. Dessa forma, precisei deixar o python de lado e voltar a programar em “Java”.

O middleware que venho implementando tem como principal requisito ser extremamente flexível. O objetivo é tornar o middleware bastante customizável, permitindo que os interessados possam modificá-lo. Além disso, outra característica dele é permitir a troca on-the-fly de alguns componentes visando atender os requisitos da aplicação. No intuito de solucionar o problema da troca de componentes uma das escolhas realizadas foi a de utilizar o padrão proxy. Quando um componente é solicitado como requisito de outro componente, o middleware entrega um proxy para a  implementação real, assim um componente sempre tem uma referência opaca ao componente. Através da utilização de proxies, o middleware pode realizar a troca de componentes ajustando apenas a referencia do proxy e todos os objetos que fazem uso dele terão a referência ao novo componente automaticamente. Assim, o uso do padrão ajuda a controlar as referências para um determinado componente que precisa ser trocado.

No entanto, um “problema” da abordagem adotada é que eu necessito implementar um novo proxy para cada interface dos componentes. O middleware em questão possui vários componentes que podem ser modificados de acordo com a escolha da aplicação, por exemplo, gestores de bateria, roteamento e etc. Nesse cenário, para cada componente que é permitido a troca, é necessário ao programador desenvolver pelo menos 3 classes/interfaces. A interface do componente, a implementação real e o proxy.

Olhando a definição do padrão contida na wikipedia isso fica mais claro ao leitor. Podemos ver a definição da interface, da implementação real e do proxy.

import java.util.*;

interface Image {
    public void displayImage();
}

class RealImage implements Image {
    private String filename;
    public RealImage(String filename) {
        this.filename = filename;
        loadImageFromDisk();
    }

    private void loadImageFromDisk() {
        System.out.println("Loading   " + filename);
    }

    public void displayImage() {
        System.out.println("Displaying " + filename);
    }
}

class ProxyImage implements Image {
    private String filename;
    private Image image;

    public ProxyImage(String filename) {
        this.filename = filename;
    }
    public void displayImage() {
        if (image == null)
        {
           image = new RealImage(filename);
        }
        image.displayImage();
    }
}

Agora imagine que você tenha umas 15 interfaces para fazer isso ? Começa a ficar tedioso. Esse é o tipo de código em que um proxy em si não é código duplicado mas sua lógica sim, eles fazem sempre a mesma coisa, possuem uma referência ao objeto real e delegam todos os seus métodos para o objeto. Atualmente as IDEs for Java já permitem gerar esse tipo de código automaticamente, o que me facilitou muito o trabalho. Inicialmente eu passei mais tempo pedindo ao netbeans para produzir código do que de fato programando. Porém, apesar da IDE gerar o código, a sua manutenção ainda fica por conta do programador. O que acontece quando um método novo entra na interface? Outro precisa ser renomeado? Mudança de parâmetros e etc. Todos nós sabemos, mudanças na interface afetam todas as implementações, nesse caso os proxies também.

Como programador Python, pensei desde o princípio: “esse é o tipo de código que pode ser feito de forma muito mais inteligente em Python do que me Java”. Em Python eu posso definir um único proxy para todas as interfaces. Ou seja, onde eu teria 15, 20 implementações eu passo a ter só uma. Isso é redução de código válida, não estamos falando de one-liners. Dessa forma é menos código para manter, um único ponto para consertar, refatorar, testar. Quanta mágica se precisa para definir esse proxy genérico em Python?

class Proxy(object):
    def __init__(self, obj):
        self.obj = obj
    def __getattr__(self, attr):
        return getattr(self.obj, attr)

Pronto, ai está nosso “incrível” “super” proxy. Isso teria me poupado mais de uma centena de linhas de código. Como esse código funciona? Simples, em python nós temos um método, denominado de __getattr__, o qual é invocado quando não é encontrado um determinado atributo na instância. O nosso Proxy implementa o __getattr__ na linha 4, e na 5 nós definimos que quando um atributo não for encontrado dentro do proxy deve ser procurado na referência que o mesmo detém. Pequeno e elegante. Outro detalhe é que não estamos amarrados a nenhuma interface e não precisamos escrever vários métodos apenas delegando tarefas.

Os programadores rails vão achar semelhante ao method_missing do ruby. A idéia é a mesma, porém funciona também para atributos. Não sei dizer se ruby possui isso para acesso a atributos também, acredito que sim.


por fenrrir em 23 de August de 2010 às 16:47

August 22, 2010

Flávio Coelho

Python in the Clouds

Consegi 2010 is over. It was a great meeting! I was happily suprised to realize how far the adoption of free software has come in the last few years. Congratulations to the Free Software community for such a successful lobby!Big thanks are due to Giuseppe (@gsromag) , Luiz Guilherme (@aldabalde) and their colleagues from SERPRO, who where responsible for the or ganization of this amazing

por Flavio Coelho (noreply@blogger.com) em 22 de August de 2010 às 19:51

August 18, 2010

Noticias da APyB

August 17, 2010

Kodumaro

Diversão com ANTLR

ANTLR – Another Tool for Language Recognition – é uma ferramenta para construção de analisadores léxico (lexer) e sintático (parser) de linguagens formais para JVM.

A grosso modo, é uma ferramenta para implementação de linguagens de programação.

E ANTLRWorks é um IDE gráfico para ANTLR.

Para entender como funciona ANTLR, vou explicar o exemplo do próprio sítio. Então instale o ANTLRWorks e mãos à obra!

Avaliador de expressões


Quando iniciar o ANTLRWorks, crie uma gramática chamada Expr.g.

O código já vai aparecer com a seguinte linha:
grammar Expr;


A ideia aqui é criar um interpretador que avalie expressões matemáticas simples, inclusive com variáveis.

Para suportar variáveis, precisamos de algum lugar para armazenar seus valores. Para isso usamos Java:
@header {
import java.util.Map;
import java.util.HashMap;
}

@members {
Map<String, Integer> memory = new HashMap<String, Integer>();
}


Isso criará o contentor memory, que é um mapa de chaves string e valores inteiros.

ANTLR funciona definindo regras. Nossa primeira regra é programa (prog) e precisamos defini-la:
prog:   stat+;


Então nosso programa é um grupo (+) de comandos (stat), o que nos leva à próxima regra.

Definimos comando como:
stat:   expr NEWLINE { System.out.println($expr.value); }
| ID '=' expr NEWLINE
{ memory.put($ID.text, new Integer($expr.value)); }
| NEWLINE
;


Calma, vou explicar!

Um comando pode ser uma expressão (expr) seguida de uma mudança de linha (NEWLINE). Neste caso, será impresso na saída padrão (System.out) o valor da expressão ($expr.value);

Um comando também pode ser (| significa OU) um identificador (ID) seguido de um sinal de igual ('='), uma expressão e uma mudança de linha. Neste caso o valor da expressão ($expr.value) será armazenado no contentor memory na chave igual ao texto do identificador ($ID.text).

Um comando ainda pode ser uma mudança de linha, que não fará nada.

Agora precisamos definir uma série de regras: expr, NEWLINE e ID. Vamos começar por expr:
expr returns [int value]
: e=multExpr { $value = $e.value; }
( '+' e=multExpr { $value += $e.value; }
| '-' e=multExpr { $value -= $e.value; }
)*
;


Quer dizer que expr retorna um valor inteiro (int value) e consiste de uma expressão múltipla (multExpr) seguido de nenhuma, uma ou mais repetições (*) do que estiver entre parêntesis. O valor retornado é igual ao valor da expressão múltipla.

A atribuição e= é necessária por haver mais de uma ocorrência de multExpr.

Entre parêntesis tempos o sinal de adição ('+') seguido de uma multExpr ou (|) um sinal de subtração ('-') seguido de uma multExpr. No primeiro caso o valor da multExpr é adicionado ao valor retornado, no segundo é subtraído.

A regra multExpr é definida como:
multExpr returns [int value]
: e=atom { $value = $e.value; } ('*' e=atom { $value *= $e.value; })*
;


Uma multExpr retorna um valor inteiro e consiste de um ou mais atómicos (atom). Os valores dos atómicos são multiplicados.

Definindo um atómico:
atom returns [int value]
: INT { $value = Integer.parseInt($INT.text); }
| ID
{
Integer v = memory.get($ID.text);
if (v != null) $value = v.intValue();
else System.err.println("undefined variable " + $ID.text);
}
| '(' expr ')' { $value = $expr.value; }
;


Então um atómico pode ser um inteiro (INT, o valor é o corpo do inteiro: $INT.text), um identificador (ID, o valor é o relacionado à chave no contentor memory – se não existir, gera um erro) ou o resultado de uma expressão (expr), que deve estar entre parêntesis.

Falta definir as regras ID, INT e NEWLINE:
ID  :   ('a'..'z'|'A'..'Z')+;
INT : '0'..'9'+;
NEWLINE: '\r'? '\n';


Ou seja: identificador é uma sequência de letras, inteiro uma sequência de números e mudança de linha é CRLF ou LF.

Para finalizar, para ignorar espaços em branco:
WS  :   (' '|'\t')+ { skip(); };


Testando


Para testar, clique em Debug e preencha a caixa Text com:
x = 1
y = 2
3 * (x + y)


Os parêntesis e a mudança de linha na última linha são importantíssimos!

Clique Ok e divirta-se acompanhando o debugger! Repare que, ao final da execução, vai mostrar 9 na aba Output.

[]’s
Cacilhας, La Batalema

por noreply@blogger.com (Cacilhας, La Batalema) em 17 de August de 2010 às 01:24

August 16, 2010

Elcio Luiz Ferreira

Dica de Python: glob

Um módulo Python pequeno, com uma única função muito simples, mas que você precisa conhecer é o glob. O que ele faz é obter uma listagem de diretório:

import glob
files=glob.glob('*')

O que equivale a:

import os
files=os.listdir('.')

Porém o glob é muito poderoso. Podemos fazer:

glob.glob('*.mad')

Ou:

glob.glob('../pasta/*')

Fica a dica.


por elcio em 16 de August de 2010 às 04:36

August 13, 2010

Marco André Lopes Mendes

SCIFC-2010: Semana da Computação do Instituto Federal Catarinense Araquari 2010

De 16 a 20 de agosto de 2010, acontecerá na Instituto Federal Catarinense, campus de Araquari/SC, a Semana de computação do IFC-Araquari (SCIFC2010). A programação inclui palestras com profissionais da área de Computação e personalidades da comunidade de software livre. A programação acontecerá no período das 13:30 às 17:00, no auditório do IFC. A Semana Acadêmica é aberta ao público e todos são convidados a participar.

Quero destacar a participação de alguns amigos: Rodrigo Curvêllo, Júlio Monteiro, Giuliano Vicente e Osvaldo Santana Neto. Só por eles, já valeria a pena participar do evento. Mas tem muitas outras palestras de alto nível.

Quem quiser acompanhar ou comentar o evento pelo Twitter, utilize a tag #scifc2010. Como sempre, devemos ter as fotos e vídeos das palestras disponibilizados depois do evento.

Abaixo, a programação do evento:
Para chegar, siga o mapa.

Serviço:
O que: Semana de Computação do IFC 2010
Quando: de 16 a 20 de agosto de 2010 (segunda a sexta-feira), de 13:30 até 17:00
Onde: Instituto Federal Catarinense, Campus Araquari, BR 280, Km 27, Araquari - SC
Quanto: gratuito
Quem pode participar: aberto ao público
Informações: 47 3803-7240 ou semana.bsi@ifc-araquari.edu.br

por Marco André Lopes Mendes (noreply@blogger.com) em 13 de August de 2010 às 13:54

SCS2009 - Semana de Computação da SOCIESC 2009

De 18 a 21 de maio de 2009, acontecerá na SOCIESC, Campus Marquês de Olinda, em Joinville/SC, a Semana de computação da SOCIESC (SCS2009). A programação inclui palestras com professores, profissionais da área de Tecnologia da Infomação e personalidades da comunidade de software livre. Teremos ainda apresentações de acadêmicos e egressos dos cursos. Na quarta-feira, a noite será reservada para minicursos. Para se inscrever nos minicursos, basta preencher o formulário. A SCS2009 é aberta ao público e todos são convidados a participar.

Quem quiser acompanhar ou comentar o evento pelo Twitter, utilize a tag #scs2009.

Abaixo, a programação do evento:



Para se inscrever nos minicursos, preencha o formulário abaixo:



Serviço:
O que: Semana de Computação da SOCIESC 2009
Quando: de 18 a 21 de maio de 2009 (segunda a quinta-feira), de 19:15 até 22:45
Onde: SOCIESC, Campus Marquês de Olinda, Rua Gothard Kaesemodel, 833, Joinville - SC
Quanto: gratuito
Quem pode participar: aberto ao público
Informações: 47 3461-0517

Leia outros textos publicados aqui sobre a SOCIESC.

por Marco André Lopes Mendes (noreply@blogger.com) em 13 de August de 2010 às 13:25

August 12, 2010

Noticias da PyConBrasil

Palestrantes internacionais confirmados

A comissão de organização da PythonBrasil[6] tem o prazer de confirmar os nomes dos palestrantes internacionais que estarão presentes na UFPR, em Curitiba/PR, para participar da sexta edição do Encontro Brasileiro da Comunidade Python.

por ramiroluz em 12 de August de 2010 às 07:42

August 10, 2010

Noticias da APyB

Python no TDC 2010

A quarta edição do TDC, The Developer's Conference, terá uma trilha dedicada a Python com palestras do Google, Yahoo, Globo.com e IG, entre outras.

por dorneles em 10 de August de 2010 às 12:29

July 29, 2010

Ricbit

Aritmética com Regexp

Dia desses eu descobri que o SPOJ agora tem uma seção só para problemas pontuados por shortest code, e fiquei super animado! Mas não demorou muito até eu notar a maior constante desse tipo de concurso: você pode até participar usando Python e Haskell, mas, para competir, só usando Perl.

Então lá fui eu aprender Perl. Apanhei um pouco no começo, mas acabei descobrindo o segredo para conseguir uma boa colocação: basta resolver todos os problemas usando regexp. Os regexps originais do Posix são apenas autômatos finitos, mas a engine do Perl é bem mais poderosa que isso.

Naturalmente, eu fiquei tentado a ver quais são os limites do regexps do Perl. Por exemplo, dá pra fazer aritmética com eles? Depois de pensar um pouco, acabei concluindo que dá sim!



Antes de mostrar como eu fiz, uma revisão de Perl. O único comando que eu vou usar é o s///g (substituição com regexp). O primeiro argumento é uma regexp que será procurada na sua string de input, e o segundo é um string, possivelmente interpolada, que vai substituir o match. A opção g permite múltiplas substituições, recomeçando do ponto onde a última terminou. Por exemplo:

input: "kkkkkk Restart kkkk sacanagem"
regexp: s/k+/LOL/g
output: "LOL Restart LOL sacanagem"

Antes de fazer qualquer conta, precisamos também definir a representação numérica. Na escola nós aprendemos a fazer contas em decimal, que tem dez símbolos, de 0 a 9. Mais tarde, computeiros aprendem binário, que tem só dois símbolos: 0 e 1. Eu vou agora fazer contas em unário, que tem um símbolo só: I (eu escolhi o símbolo I para ficar parecido com os números romanos).

No sistema unário, o número é representado por repetições do símbolo único. Por exemplo:

1  = I
4 = IIII
10 = IIIIIIIIII

Por fim, para as regexps não ficarem muito grandes, eu vou me restringir apenas às operações definidas nos inteiros positivos (ou seja, tanto os argumentos quanto os resultados precisam ser inteiros positivos). Vamos lá então:

Adição

s/\+(I+)=/$1/g

A adição é a operação mais simples, basta tirar os sinais de mais e igual. O resultado é a concatenação dos operandos. Vamos ver, por exemplo, como ficaria 4+7.

"IIII+IIIIIII="
s/\+(I+)=/$1/g

"IIIIIIIIIII"

Como esperado, o resultado é 11.

Subtração

s/(I+)-\1=//g

Para fazer a subtração, nós usamos o recurso de backreference. Se ele achar um conjunto no lado direito, pode apagar esse conjunto e um outro igual no lado esquerdo. Sobram só os caracteres que estavam no primeiro mas não estavam no segundo, ou seja, a subtração deles. Vejamos o exemplo de 7-4:

"IIIIIII-IIII="
s/(I+)-\1=//g

"III"

Multiplicação

s/(I)(?=I*\*(I+))(\*I+=)?/$2/g

A multiplicação é um pouco mais complexa, agora precisamos usar o operador (?=), que serve para fazer positive lookahead, ou seja, ele faz o match, mas não consome o input. Como resultado, o operador /g pode passar várias vezes pela mesma string, e cada I que ele encontra no lado esquerdo é trocado pela string inteira do lado direito. Vejamos um exemplo passo-a-passo de 3*6 (mas note que o Perl faz isso num passo só, eu estou fazendo em vários passos só pra ficar mais claro).

"III*IIIIIII="
s/(I)(?=I*\*(I+))(\*I+=)?/$2/g

"IIIIII""II*IIIIIII="
s/(I)(?=I*\*(I+))(\*I+=)?/$2/g

"IIIIIIIIIIII""I*IIIIIII="
s/(I)(?=I*\*(I+))(\*I+=)?/$2/g

"IIIIIIIIIIIIIIIIII"

Divisão

s/(I+)(?=I*\/\1\=)(\/I+=)?/I/g

A divisão é similar à multiplicação, mas, ao invés de somas sucessivas, nós usamos subtrações sucessivas. Vejamos o exemplo de 12/4:

"IIIIIIIIIIII/IIII="
s/(I+)(?=I*\/\1\=)(\/I+=)?/I/g

"I""IIIIIIII/IIII="
s/(I+)(?=I*\/\1\=)(\/I+=)?/I/g

"II""IIII/IIII="
s/(I+)(?=I*\/\1\=)(\/I+=)?/I/g

"III"

GCD

s/gcd\((I+)\1*,\1+\)=/$1/g

Por que parar nas quatro operações? É bem simples fazer também o gcd (máximo divisor comum). Nesse caso basta mandar repetir a backreference, o resultado é que os matches sempre vão ser múltiplos do tamanho dela. Como o primeiro grupo é greedy, ele vai tentar fazer o maior match possível, e daí temos como resultado o gcd. Vejamos para 15 e 9:

"gcd(IIIIIIIIIIIIIII,IIIIIIIII)="
s/gcd\((I+)\1*,\1+\)=/$1/g

"III"

Embora brincar com regexps desse jeito seja divertido, vale a recomendação de sempre: faça isso apenas acompanhado de adulto responsável :)

por Ricardo Bittencourt (noreply@blogger.com) em 29 de July de 2010 às 13:34

July 26, 2010

Elton Luís Minetto

July 25, 2010

Ricbit

O algoritmo mais lento do oeste

Por que as pessoas aprendem complexidade computacional? Para achar os algoritmos mais rápidos, é claro. Dada uma lista de algoritmos equivalentes, você pode ordená-los pela complexidade, e o primeiro da lista é o mais eficiente.

Uma brincadeira divertida é fazer isso ao contrário: dada uma especificação, qual o algoritmo determinístico mais lento que a resolve? Por exemplo, qual o algoritmo mais lento para decompor um número em fatores primos?


O algoritmo mais rápido que resolve esse problema é o algoritmo de Shor, que roda em O((log n)3) e requer um computador quântico. Meu candidato a algoritmo mais lento é o abaixo, que na falta de nome melhor eu chamei de Fatoração Bozo:

import itertools

def factor(n):
solutions = []
for f in itertools.product(range(1,1+n),repeat=n):
if reduce(lambda x,y: x*y, f) == n:
solutions.append(filter(lambda x:x>1, list(f)))
solutions.sort(key=len, reverse=True)
return solutions[0]

Parece complexo, mas o funcionamento é bem simples. Vamos pensar no nosso objetivo: queremos achar uma lista de fatores primos, que multiplicados resultam no número desejado (vamos chamá-lo de N).

Nós sabemos que os primos dessa lista são menores ou iguais a N, e sabemos também que essa lista nunca vai ter mais que N elementos. A primeira coisa que fazemos no algoritmo é gerar todas as possíveis listas candidatas, que são o produto cartesiano do intervalo de 1 a N com N repetições. Por exemplo, para N=3, teríamos 27 combinações:

111 112 113 121 122 123 131 132 133
211 212 213 221 222 223 231 232 233
311 312 313 321 322 323 331 332 333

Em python o jeito mais fácil de gerar essa lista é usando itertools.product(), que faz o serviço sozinho. Mas, dessas listas, só interessam aquelas cujo produto seja igual a N. Por exemplo, se N=4, então as listas interessantes são:

1114 1122 1141 1212 1221
1411 2112 2121 2211 4111

Python não tem um operador para multiplicação de listas como tem o sum() para adições, mas pra isso que serve o reduce() né. As listas selecionadas até agora estão boas, mas elas têm um monte de elementos 1 que não contribuem em nada. Usando o filter() podemos jogar fora os uns. Para N=4:

4 22 4 22 22 4 22 22 22 4

Várias listas repetidas, mas tudo bem. O truque agora é notar que, de todas essas listas, a fatoração em primos é a lista de comprimento máximo. É fácil provar isso: se a lista máxima tivesse um elemento composto, então você poderia fatorá-lo, e trocar o número composto pela sua fatoração. Logo, você estaria gerando uma lista maior que a lista máxima, o que é uma contradição.

Pedindo para que o Python ordene as listas por tamanho, basta pegar a primeira lista da seqüência e temos então a nossa fatoração!

E qual a complexidade dessa solução? Ela é dominada pelo número de listas que geramos no primeiro passo, então a complexidade da Fatoração Bozo é maior que O(nn). Se você não tem noção de como isso é lento, veja o tempo que esse código leva para fatorar alguns números:

N=6 - 0.2 segundos
N=7 - 2.1 segundos
N=8 - 45.8 segundos
N=9 - 20 minutos

A função cresce tão rapidamente que, para fatorar N=18, você levaria mais tempo que a idade do universo até agora! Como exercício para o leitor, tente calcular quanto tempo levaria para fatorar o RSA-704, que em decimal tem 212 dígitos :)

por Ricardo Bittencourt (noreply@blogger.com) em 25 de July de 2010 às 21:29

July 22, 2010

Noticias da APyB

July 21, 2010

Noticias da PyConBrasil

Aberta a chamada de trabalhos

Está aberto o período para envio de trabalhos para a PythonBrasil[6]. Essa é a sua chance de mostrar para a comunidade o que você tem feito com Python!

por dorneles em 21 de July de 2010 às 19:14

Elcio Luiz Ferreira

Servindo vídeos Ogg Teora com o Content Type correto

Semana passada participei de um curso sobre HTML5 ministrado pela w3c Brasil. Nesse curso o Elcio Ferreira foi o instrutor, eu fiquei com uma duvida e fiz uma pergunta para ele sobre a necessidade de incluir a extensão do arquivo na tag <video> para que o mesmo funcione no firefox. Ele me mostrou uma forma utilizando PHP mas infelizmente não consegui obter o codigo.

Os servidores web, quando servem um arquivo, enviam ao navegador a informação de tipo de conteúdo. O header enviado do servidor, para um arquivo Ogg Vorbis, deve ser:

Content-type: application/ogg

Se o servidor não enviar esse header, o vídeo não vai tocar no Firefox. O Apache sabe fazer sozinho, basta que esteja configurado para isso. No Ubuntu, por exemplo, ele já vem configurado para servir ogg.

A saída de scripts PHP é servida com outro tipo de conteúdo. Geralmente “text/html”. Se você serve seu vídeo do PHP, precisa enviar um header no início do script avisando o navegador que esse conteúdo é vídeo. Você pode fazer:

<?php
header('Content-type: application/ogg');
?>

Já se você serve os vídeos como arquivos estáticos, não deve usar PHP para processá-los só para que sejam servidor com o tipo correto. O jeito certo é configurar corretamente o servidor. Se for um hosting compartilhado, eu tentaria um chamado ao suporte pedindo para que configurem isso corretamente antes de fazer com PHP. Ou estudaria mudar de hosting ;-)


por elcio em 21 de July de 2010 às 09:46

July 19, 2010

Marco André Lopes Mendes

O que eu carrego na minha mochila


O efetividade.net está com com a promoção "O que você carrega na sua mochila (ou bolsa...) de trabalho? Abaixo, a foto do conteúdo da minha mochila hoje, junto com a descrição.

Clique na foto para vê-la em tamanho maior

Vou fazer a descrição de cima pra baixo, da esquerda pra direita. Atrás está a mochila, um modelo simples que ganhei da minha irmã, que tinha ganhado num evento que ela participou. Nada sofisticado, mas ela possui duas repartições maiores, com subdivisões internas e uma repartição menor, com porta canetas, além das duas bolsas laterais. O tamanho é o ideal pra meu notebook de trabalho, de 14 polegadas, mas deve caber um de 15 sem problemas. Já carreguei este mesmo notebook junto com um EEE PC de 7 polegas e seus carregadores de bateria sem problemas.

Abaixo, está o notebook Positivo de 14 polegadas que eu uso no trabalho, e sobre ele alguns agrupamentos de objetos, que descreverei em seguida. No canto superior esquerdo estão: um pendribe mini de 4 GB com o instalador do Lubuntu 10.04, um Kingston de 4 GB que uso pra transporte de dados e um outro de 24 GB (com a cordinha enrolada) que tem sempre o instalador da última versão do Ubuntu (no momento, o 10.04). Logo abaixo, um leitor de cartão SD, um adaptador de Micro SD para SD, um cartão SD de 4 GB (com músicas) e um cartão SD de 64 MB (com um boot DOS). Abaixo destes, sobre um pacote plástico com sip lock, um micro SD de 2 GB (com músicas) e um de 4 GB (com vídeos), um leitor de cartão micro SD e um cartão SD de 128 MB (com um drive criptografado com o True Crypt).

No lado esquerdo, em cima, várias canetas: destaca texto, caneta com tinta invisível, caneta vermelha (para corrigir provas e trabalhos), canetas de ponta fina e grossa para escrever em CD/DVD, pincel pra quadro branco e uma caneta azul.

Abaixo das canetas: um chaveiro multi-uso Swiss Inox, um conjunto de esferas imantadas, um elástico que uso pra prender as canetas que uso menos, um cabo de rede retrátil e um outro pacote plástico com zip lock que uso pra guardar os pen drives.

Logo abaixo do notebook, no centro, está o fone do meu celular. Logo abaixo à esquerda, estão o pano de limpeza do monitor, pastilhas contra azia, um fone de ouvidos com microfone e o saquinho de pano branco onde guardo o fone). Ao lado deste grupo está o carregador do notebook e abaixo dele, uma autorização pra dirigir os carros oficiais do trabalho, junto com os horários de ônibus. À direita disso, um mouse Microsoft sem fio.

Pra finalizar, bem embaixo, uma lata com um pacote de Club Social e o carregador do celular.

Não sei o que foi pior, tirar tudo da mochila, organizar as coisas de modo a aparecerem claramente na foto, tirar a foto ou guardar tudo de novo no lugar. De qualquer forma, Aí está o conteúdo da minha mochila.














por Marco André Lopes Mendes (noreply@blogger.com) em 19 de July de 2010 às 14:13

July 18, 2010

Leandro Lameiro

Deixando o interpretador Python maluco por diversão e lucro, ou Como se livrar de um colega de trabalho desenvolvedor Python

Você está lá, em apenas mais um dia comum de trabalho (ou diversão), debugando um sistema complexo e tentando entender porque diabos algo que deveria acontecer não acontece. Você consegue reduzir o seu problema a uma linha de código, que não se comporta como você espera:

>>> print 42 == 0
True

O resultado foi verdadeiro, ou seja, 42 realmente é igual a 0 no momento em que esta comparação roda! Mas como assim?! Em Python não é possível reabrir a classe dos números (int), reescrever os métodos de comparação para fazer isso dar certo.
Lembre-se que esta comparação estranha está no meio de um sistema complexo. Assim:

algo_que_deixa_interpretador_maluco()
print 42 == 0

Explicação: A função algo_que_deixa_interpretador_maluco está modificando o objeto “número inteiro 42″ (mesmo os números são objetos). Mas os números são objetos imutáveis, como assim você modificou o valor de 42? Um número inteiro em Python (na verdade, CPython) é representado por uma struct do C, que entre outras coisas, contém um long do C com o mesmo valor  – o atributo ob_ival.

Simplificando uma longa história, quando temos uma comparação de números, ela é repassada para o nível do C, e os atributos ob_ival da struct C são comparados com o operador == do C. Basta então mudarmos o ob_ival do objeto “número 42″ que podemos influenciar na comparação.

E para mudar o valor de ob_ival? Como é possível acessar e modificar o estado interno e a memória do interpretador? Com o módulo ctypes, da biblioteca padrão, podemos acessar do Python os tipos do C. Basta então conseguirmos achar na memória a struct do número 42. Mas isso é fácil, a função builtin id retorna exatamente o lugar na memória onde o objeto está. Com isso, temos tudo que precisamos.

import ctypes

if hasattr(ctypes.pythonapi, 'Py_InitModule4'):
    Py_ssize_t = ctypes.c_int
elif hasattr(ctypes.pythonapi, 'Py_InitModule4_64'):
    Py_ssize_t = ctypes.c_int64
else:
    raise TypeError("Cannot determine type of Py_ssize_t")

class PyObject(ctypes.Structure):
    pass # incomplete type

class PyObject(ctypes.Structure):
    _fields_ = [('ob_refcnt', Py_ssize_t),
                ('ob_type', ctypes.POINTER(PyObject))]

class PyIntObject(PyObject):
    _fields_ = [('ob_ival', ctypes.c_long)]

forty_two_object = PyIntObject.from_address(id(42))
forty_two_object.ob_ival = 0

print 42 == 0

Neste código, estamos primeiro conseguindo o endereço do objeto 42 (linha 20), depois criando a struct do ctypes (ponte entre o Python e a struct C), depois alteramos o ob_ival do 42 para 0, na memória do interpretador (linha 21).

A partir daí, quando o Python fizer a comparação entre o número 42 e 0 (linha 23), ela será verdadeira, já que seus ob_ival são iguais.

Extensões em C ou mesmo código Python com ctypes mal testados podem causar consequências imprevisíveis e bugs dificílimos de reproduzir, mesmo onde parece impossível. Mas também tem usos interessantes: Pense em um dos inúmeros jogos que suportam Python como Civilization IV, Battlefield 2 e Piratas do Caribe Online. É possível fazer um script usando o mesmo princípio que modifica, por exemplo, as variáveis de controle de vidas do jogador, posição etc.


Filed under: C, hack, Python Tagged: C, hack, Python

por Leandro Lameiro em 18 de July de 2010 às 22:47

July 16, 2010

Noticias da PyConBrasil

PythonBrasil[6]: Inscrições abertas

O período de inscrições para a PythonBrasil[6], a ser realizada na UFPR, em Curitiba, está aberto. Não espere mais, garanta logo a sua presença no maior evento nacional sobre Python, faça sua inscrição até o dia 31 de Julho e aproveite o desconto máximo!

por dorneles em 16 de July de 2010 às 09:06

July 15, 2010

Elcio Luiz Ferreira

Amanhã, Café com Browser sobre HTML5

Durante esta semana estive no escritório do W3C Brasil, ministrando um treinamento de HTML5. Para encerrar o treinamento, o W3C organizou uma edição do Café com Browser.

Nós e o pessoal da Agência Click vamos mostrar um pouco do que já estamos fazendo com HTML5, e você pode assistir ao streaming ao vivo, cujo link será disponibilizado na hora.

Para tuitar, use a tag #cafecombrowser.


por elcio em 15 de July de 2010 às 15:52

Flávio Coelho

Consegi 2010

I have been invited to give a talk on the 3rd International Congress on Free Software and E-Government -- Consegi, taking place in Brasilia on 18-20 of august. It is a massive event bringing together Leading professionals from all over the world. Last year's event had 6000 participants from 19 countries!This year's theme is cloud computing and I'll bee talking about Google AppEngine (GAE). Since

por Flavio Coelho (noreply@blogger.com) em 15 de July de 2010 às 11:57

July 09, 2010

Gustavo Niemeyer

Python has a GIL, and lots of complainers

I’ve just read a post by Brett Cannon where, basically, he complains about complainers.

If you don’t know who Brett is, you’re probably not a heavy Python user. Brett is a very important Python core developer which has been around for a while and who does a great job at it. His post, though, makes me a bit sad.

Brett points out that there are two types of personalities which do not contribute to open source. The first one he defines as:

The first type is the “complainer”. This is someone who finds something they don’t like, points out that the thing they don’t like is suboptimal, but then offers no solutions.

And the second one is defined as:

(…) This is someone who, upon finding out about a decision that they think was sub-optimal, decides to bring up new ideas and solutions. The person is obviously trying to be helpful by bringing up new ideas and solutions, thinking that the current one is simply going to flop and they need to stop people from making a big mistake. The thing is, this person is not helping. (…)

This, on itself, is already shortsighted. If you’re tired of hearing the same arguments again and again for 10 years, from completely different people, there’s a pretty good chance that there’s an actual issue with your project, and your users are trying in their way to contribute and interact with you in the hope that it might get fixed.

This is really important: They are people, which use your project, and are trying to improve it. If you can’t stand that, you should stop maintaining an open source project now, or pick something which no one cares about.

The other issue which took my attention in his post is his example: the Python GIL. Look at the way in which Brett dismisses the problem:

(I am ignoring the fact that few people write CPU-intensive code requiring true threading support, that there is the multiprocessing library, true power users have extension modules which do operate with full threading, and that there are multiple VMs out there with a solution that have other concurrency solutions)

Brett, we can understand that the GIL is hard to remove, but it’s a fundamental flaw in the most important Python implementation, and being dismissive about it will either draw further complaints at you, or will simply drive users away from the language entirely.

I can understand why you think this way, though. Guido presents the same kind of feeling about the GIL for a very long time. Here is one excerpt from a mail thread about it:

Nevertheless, you’re right the GIL is not as bad as you would initially think: you just have to undo the brainwashing you got from Windows and Java proponents who seem to consider threads as the only way to approach concurrent activities.

Just Say No to the combined evils of locking, deadlocks, lock granularity, livelocks, nondeterminism and race conditions.

I apologize, but I have a very hard time reading this and not complaining.

In my world, the golden days of geometric growth in vertical processing power is over, multi-processed machines are here to stay, and the amount of traffic flowing through networks is just increasing. It feels reasonable to desire a less naïve approach to deal with real world problems, such as executing tasks concurrently.

I actually would love to not worry about things like non-determinism and race conditions, and would love even more to have a programming language which helps me with that!

Python, though, has a Global Interpreter Lock (yes, I’m talking about CPython, the most important interpreter). Python programs execute in sequence. No Fork/Join frameworks, no coroutines, no lightweight processes, nothing. Your Python code will execute in sequence if it lives in the same process space.

The answer from Brett and Guido to concurrency? Develop your code in C, or write your code to execute in multiple processes. If they really want people to get rid of non-determinism, locking issues, race conditions, and so on, they’re not helping at all.

I know this is just yet another complaint, though. I honestly cannot fix the problem either, and rather just talk about it in the hope that someone who’s able to do it will take care of it. That said, I wish that the language maintainers would do the same, and tell the world that it’s an unfortunate problem, and that they wished someone else would go there and fix it! If, instead, maintainers behave in a ridiculously dismissive way, like Guido did in that mail thread, and like Brett is doing in his post, the smart people that could solve the problem get turned down. People like to engage with motivated maintainers.. they like to solve problems that others are interested in seeing solved.

Perhaps agreeing with the shortcomings won’t help, though, and no one will show up to fix the problem either. But then, at least users will know that the maintainers are on the same side of the fence, and the hope that it will get fixed survives. If the maintainers just complain about the users which complain, and dismiss the problem, users are put in an awkward position. I can’t complain.. I can’t provide ideas or solutions.. I can’t fix the problem.. they don’t even care about the problem. Why am I using this thing at all?

Would you rather have users, or have no complainers?

por Gustavo Niemeyer em 09 de July de 2010 às 19:15

Sidnei da Silva

Call for testers: lxml 2.2.6/py2.6 Windows Binaries

Hi everyone,

After several months of silence, I finally managed to get all the needed pieces back together to build lxml again. More than once people asked over on the lxml mailing list about what happened to the said eggs. The good news is that an unnoficial release of lxml 2.2.6 for Python 2.6 on Windows is now available for testing, in 32 and 64 bit flavors. The 64 bits version was compiled without iconv support because that’s the only thing I haven’t figured out how to compile.

In case you didn’t hear about what happened, this delay was caused by a robbery that occurred on the same day I arrived in Houston, November of last year. I was with my wife and we left for a couple hours for dinner, and when we came back the place we were staying at (Robin’s Nest) had been broken into my backpack was taken, with my laptop, two cameras (with all the pictures we had taken in New York) and two cellphones. We have already replaced everything that was robbed and moved on. Thankfully Robin had insurance, which covered about half of our losses.

That was the bad news. The good news is completely unrelated to all of this: my wife is pregnant, and the babies are due in somewhere between late November/early December. Note I said babies. Yes. Twins. Apparently two girls (last ecography was a little bit to early to say, but the doctor gave us about 90% confidence). We’ve tentatively picked Laura and Rafaela for her names.

So if you’re as happy as we are about the news and want to show some gratitude, we’ve set up a Baby Registry at Babies’R'Us, and the shipping address is set to Enfold System’s office in Houston. I will be visiting my old friends there around September 10, on my way back from another Landscape sprint in Montreal to pick up the gifts and to say Hi.

Thanks everyone for your patience!


por Sidnei em 09 de July de 2010 às 04:16

July 03, 2010

Gustavo Niemeyer

Support for Launchpad and Bazaar in goinstall

The patch submitted last weekend to support Launchpad and Bazaar in goinstall went in!

This means that once the next release of Go is out (or you sync up with the tip code) you’ll be able to host modules for Go in Launchpad and people will be able to install it by running something similar to:

goinstall launchpad.net/yourproject

Then, you can simply use that in your source code as:

import “launchpad.net/yourproject”

The following URLs are supported:

import “launchpad.net/project”
import “launchpad.net/project/series”
import “launchpad.net/project/series/sub/directory”

import “launchpad.net/~user/project/branch”
import “launchpad.net/~user/project/branch/sub/directory”

import “launchpad.net/~user/+junk/branch”
import “launchpad.net/~user/+junk/branch/sub/directory”

Where you see sub/directory above, it means the module to be compiled, installed, and used, may be inside a subdirectory in the Bazaar branch itself. This is a convention used in all supported backends of goinstall.

por Gustavo Niemeyer em 03 de July de 2010 às 19:17

Pythonologia, o blog da Triveos » python

Interface Admin do Django: um baita quebra-galho.

Já faz algum tempo que nós aqui na Triveos estamos usando Django e Python. Também tenho apresentado palestras e ministrado cursos de Django em vários lugares. Temos até mesmo um curso online de Python e Django à venda em um site desenvolvido em Django.

A Interface Admin do Django

A Interface Admin do Django

Todos os programadores Django adoram falar sobre um dos grandes diferenciais desse framework: A Interface Admin.

Realmente, só quem desenvolve aplicações Web a bastante tempo e perdeu tempo precioso fazendo “telinhas de cadastro” sabe como essa tarefa é chata e pouco desafiadora. E todos que desenvolvem com Django agradecem a existência dessa funcionalidade.

A interface Admin do Django é prática, fácil de ser usada, e bonitinha. Uma mão na roda. Um baita quebra-galho. Até mesmo… mágica! A diferença entre um projeto entregue e um projeto atrasado.

Mas isso termina por aqui.

A interface de Admin do Django tem uma função clara: administrar o sistema. Tanto que ela foi feita para ser acessada só por usuários do “staff“.

Ela foi feita para que os desenvolvedores do site não percam tempo fazendo cadastros “bobinhos” que precisam ser mantidos só pelos funcionários da empresa.

O Django nasceu no mercado editorial e o primeiro projeto desenvolvido nele foi um gerenciador de conteúdo (CMS). A interface de Admin do Django servia (serve?) para que os editores, jornalistas, autores, etc. inserissem conteúdo nos sites dos jornais do grupo The World Company.

A interface Admin não foi feita para você desenvolver toda a sua aplicação nela. Ela é muito poderosa e até faz algumas coisas além de permitir somente a inclusão, visualização, alteração, e exclusão de conteúdo. Ela permite ordenar registros, efetuar buscas, definir ações, etc. Mas paramos por aí.

Funcionalidades mais elaboradas ou que precisam ser acessadas por pessoas que não fazem parte do “staff” continuam tendo o seu desenvolvimento necessário.

No site Ludeos, que foi desenvolvido em Django, a interface Admin ainda é usada para verificar os pagamentos dos cursos, e na manutenção das lojas e produtos. O fato do Django oferecer essa funcionalidade pra gente fez a diferença entre um projeto “atrasado” e um projeto “no ar”.

Mas o uso da interface Admin é um fator limitante para o nosso uso do sistema. Fica claro que, para que o projeto evolua, será necessário tirar algumas dessas funcionalidades da interface de Admin.

Em resumo: usem a interface Admin, mas saibam que em determinado momento ela pode limitar as suas ações e, nestes casos, Django oferece outras alternativas pra te ajudar a deixar a interface Admin: Generic Views. Falaremos sobre elas em outra oportunidade.

A Triveos é especializada no desenvolvimento de aplicações Web e utiliza Python e Django em grande parte de seus projetos. Tendo como base esse know-how no uso de Python e Django criamos o Curso de Desenvolvimento Web com Python e Django nas modalidades in-company e online.

Copyright © 2010, Triveos Tecnologia Ltda.
Creative Commons License

por Osvaldo Santana Neto em 03 de July de 2010 às 00:57

July 01, 2010

Aprenda Python

Criando dicionários com uma sintaxe mais prática

Em python, um dicionário é o mesmo que um array associativo em PHP. Ou seja, uma lista indexada por chaves (keys) que podem ser strings e apontam para valores. Para criar um dicionário, a sintaxe é: d = {'fruta': 'goiaba', 'dia': 'sabado', 'nome': 'maria'} Um jeito diferente de criar o mesmo dicionário é usando o construtor dict(), assim: d = dict([('fruta', 'goiaba'), ('dia', 'sabado'), ('nome'

por Vinicius Assef (noreply@blogger.com) em 01 de July de 2010 às 03:09

Pegadinha: parâmetro default

Toda linguagem tem suas armadilhas e Python não é uma excessão. A linguagem é prática, clara e objetiva, mas nem tudo é perfeito. A seção 4.22 do General Python FAQ fala sobre esse assunto, mas passa despercebido para iniciantes na linguagem. É o tipo de informação que quem está começando, não se importa muito. Deixa para aprender depois. Daí vem um problema que é relativamente difícil de

por Vinicius Assef (noreply@blogger.com) em 01 de July de 2010 às 03:02

Regexp para validar passagem bíblica

Há alguns dias venho me dedicando na migração de um site de conteúdo bíblico para Django. Uma coisa básica quando trata-se de Bíblia, é lidar com passagens bíblicas. Cada passagem pode envolver um ou mais versos (versículos) ou capítulos em sequência ou não. Seguem alguns exemplos de passagens bíblicas válidas: Genesis 5 Exodo 20:8-11 Mateus 6:5,6 Marcos 5-7 II Reis 2:6 As passagens podem

por Vinicius Assef (noreply@blogger.com) em 01 de July de 2010 às 02:59

Nova formatação de strings

A partir da versão 2.6 o Python traz um recurso diferente para formatar strings. Diz o manual que a partir da versão 3.0 a formatação usando o método % será desencorajado, por isso resolvi incluir esse post. Se você é iniciante em Python, tente começar a mudar logo para o método do str.format(). A mudança é simples. Portanto, vamos aos exemplos: nome = 'Fernando' sobrenome = 'Silva' idade = 9

por Vinicius Assef (noreply@blogger.com) em 01 de July de 2010 às 02:55

[django] Rodar script da linha de comando

Todo site desenvolvido em Django tem uma configuração básica: o mapeamento de URLs para views, no arquivo urls.py. E se eu precisar rodar alguma rotina que manipula o banco de dados via linha de comando do terminal? Esse mapeamento não vai me ajudar em nada, porque a rotina que vai rodar a partir do terminal não é uma view que vai mostrar algo usando um template. Hoje eu me deparei com essa

por Vinicius Assef (noreply@blogger.com) em 01 de July de 2010 às 02:53

filter() ou list comprehension?

Eu postei na lista Python Brasil a seguinte pergunta: Pessoal, bom dia. Eu tenho uma lista retornada pela função re.split(r'(\w+)', s). Para me livrar das ocorrências nulas, estou usando o seguinte comando: partes = [t for t in re.split(r'(\w+)', s) if t] No entanto, consigo o mesmo resultado se eu usar: partes = filter(None, re.split(r'(\w+)', s)) O manual[1] diz que o filter() é

por Vinicius Assef (noreply@blogger.com) em 01 de July de 2010 às 02:50

Atribuir conteúdo default a uma variável

Normalmente, quando queremos checar se uma determinada variável está vazia para atribuir um conteúdo default a ela, fazemos assim: if not minha_var: minha_var = 'default' Existe um atalhozinho legal para isso: minha_var = minha_var or 'default' Aqui entra em ação os operadores lógicos do python, nesse caso, o or. Para saber mais sobre esse assunto e também como funciona o and e o not,

por Vinicius Assef (noreply@blogger.com) em 01 de July de 2010 às 02:46

Várias atribuições na mesma linha

Há alguns dias eu enviei uma pergunta para a lista Python Brasil perguntando sobre estilo de inicialização de variáveis e recebi uma ótima dica. Em Python é possível atribuir conteúdo às variáveis de dois modos: a = b = "" ou a = "" b = "" A primeira forma é um atalho, né? Mais prática e sucinta, mas esconde uma pegadinha. Se eu usar esse atalho com dicionários ou listas, por exemplo, veja o que

por Vinicius Assef (noreply@blogger.com) em 01 de July de 2010 às 02:42

Como gravar campos de largura fixa

Eu gosto das listas Python Brasil e Django Brasil porque nelas o pessoal sempre ajuda os iniciantes, sem preconceito. Lá, todo mundo se lembra que não nasceu sabendo. Esses dias surgiu uma dúvida na lista Django Brasil sobre como formatar um arquivo de saída com campos de largura fixa e, dando continuidade ao objetivo desse blog de fornecer dicas para iniciantes em Python, vou transcrever o que

por Vinicius Assef (noreply@blogger.com) em 01 de July de 2010 às 02:35

June 29, 2010

Gustavo Barbieri

United “sucker” Airlines

Notice: this is a rant posted only to my “life” blog category, if you happen to not like personal stories but got this due some syndication using my global RSS instead of specific, please forgive me and just ignore this post.

Ulisses and I had to travel to a conference in Orlando, FL and we did the stupid mistake of booking the flight with United Airlines. Yes, we already had problems with it in the past and we knew United Breaks Guitars, but nonetheless we insisted to give it another try. It was already strange that our flight to Orlando had to go to Washington DC in the first step, then we would have to go through Chicago during our return… but yeah, it was cheaper and the airlines do these stupid routes to aggregate more people.

Problem#1: So… Sunday, June 20th, we were set to depart at 10pm. Given that my birthday was the day before, I was at my family’s house for a great Brazilian BBQ. However their city is 4 hours away from the airport, you all know the airport checks take some time and they require us to be 3 hours before, so 7 hours earlier I departed. If you happen to like football as I do, and you are Brazilian, you would rather die instead of loosing Brazil versus Ivory Coast in the world cup, but I was forced to.

Arriving at the airport exactly 3 hours earlier, we did the check-in, went through security and waited for hours… to be notified 20 minutes before that our flight was cancelled due no reason. They rumored that the aircraft had mechanical problems and could not fly.

Problem#2: We were told that we should go in the next flight at around 1pm the next day… it was already bad, given that we’d loose the first conference day, but it became worse once other passengers alerted us that UA actually did not had any flights departing at that time! Apparently they were just doing that so they would just have to pay us one hotel night, forcing us to be at the airport in the morning and then wait until 10pm for the actual flight!

We could not afford such delay as the second conference day was the one with the important bits. Thus we made them book us a flight with their partner company “TAM”, departing Monday 21th in the morning. The flight was a direct one and that was awesome, with a new airplane with interactive media displays and so on.

Problem#3: We had to go to Chicago where we had the connection back to São Paulo, it was around 2 hour slack between them and so good balance, not much to wait and enough time to get our luggage transferred. But UA was nice to delay our flight departure by 30 minutes. A bit worried, we were confident it was still enough. However during the flight, the pilot announced “We’ll have to stop in Kansas to refuel”, WTF we thought immediately. Of course this was a stupid excuse for something that they did not tell us. Kansas it was, long delay… but we did manage to get to Chicago 30 minutes before our flight departed.

Obviously, while you can walk from one gate to another in 30 minutes, your luggage cannot go through their unknown process and it did not make into the plane.

Problem#4: We arrived in São Paulo and waited for our baggage… thinking in a logical way, we did know it was not there, but as the government slogan says “we’re brazilian and we’ll never loose hope!” After confirming that it was not there, we went to United Airline help desk. Strange looks, computer queries and questions about our route in USA, they said it was located in Chicago and should be in Brazil in their next flight, which should be this afternoon (June 29th). The whole they happened, but no news from our luggage… called them and they said it is still in Chicago, but at this point: would you believe them?

Problem#5: when entering Brazil you have the usual options “Nothing to declare” or “Goods to declare”. Often then choose some samples from “nothing to declare” to be exhaustively investigated, a quite invasive search I’d say. We did not had anything to declare, but given that our luggages were not there, we had to go be searched just to be able to have our stuff to be allowed through the Customs without us. WTF, what is the logic behind that?! A huge inconvenience.

Problem#6: my luggage was package with all my brand new clothes as we had scheduled some meetings with costumers in the conference. For some stupid mistake, I also dispatched my BlackBerry with my luggage since I did not use it for the whole week. Ulisses also had some nice gifts for his daughter in his bag. Very, very likely we’ll not see such personal items anymore, as they are likely to vanish with our luggage or just handle us opened bags without these items as it already happened to me in the past.

Yeah, United breaks guitars, make you loose your football game, fuck with your business travel, loose your luggage… what a shame, never using United services in future, this time for real. I did learn my lesson.

por Gustavo Sverzut Barbieri em 29 de June de 2010 às 23:11

Eventos da APyB

PythonBrasil[6]

A PythonBrasil[6] acontecerá de 21 a 23 de Outubro de 2010 na UFPR, em Curitiba/PR. Nos encontramos na capital Paranaense!

por dorneles em 29 de June de 2010 às 22:57

FISL 11

A Associação Python Brasil estará presente no FISL 11. Teremos palestras, evento comunitário e as tradicionais palestras relâmpago! Nos encontramos em Porto Alegre!

por dorneles em 29 de June de 2010 às 21:54

June 22, 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 10.4):

deb http://downloads.mongodb.org/distros/ubuntu 10.4 10gen

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

$  sudo apt-key adv --keyserver keyserver.ubuntu.com --recv 7F0CEB10
$  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): Alterada 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.

ATUALIZAÇÃO (22/06/10): Acrescentado o gpg public key.

por Eduardo Willians Bandeira de Melo (noreply@blogger.com) em 22 de June de 2010 às 16:21

June 21, 2010

Gustavo Niemeyer

Mocker 1.0 for Python released!

After a few years in development, version 1.0 of Mocker is now available! Check out the changes since 0.10.1, the supported features, or go straight to the download page.

por Gustavo Niemeyer em 21 de June de 2010 às 00:09

June 19, 2010

Gustavo Niemeyer

Integrating IRC with LDAP and two-way SMSing

A bit of history

I don’t know exactly why, but I’ve always enjoyed IRC bots. Perhaps it’s the fact that it emulates a person in an easy-to-program way, or maybe it’s about having a flexible and shared “command line” tool, or maybe it’s just the fact that it helps people perceive things in an asynchronous way without much effort. Probably a bit of everything, actually.

My bot programming started with pybot many years ago, when I was still working at Conectiva. Besides having many interesting features, this bot eventually got in an abandonware state, since Canonical already had pretty much equivalent features available when I joined, and I had other interests which got in the way. The code was a bit messy as well.. it was a time when I wasn’t very used to testing software properly (a friend has a great excuse for that kind of messy software: “I was young, and needed the money!”).

Then, a couple of years ago, while working in the Landscape project, there was an opportunity of getting some information more visible to the team. Coincidently, it was also a time when I wanted to get some practice with the concepts of Erlang, so I decided to write a bot from scratch with some nice support for plugins, just to get a feeling of how the promised stability of Erlang actually took place for real. This bot is called mup (Mup Pet, more formally), and its code is available publicly through Launchpad.

This was a nice experiment indeed, and I did learn quite a bit about the ins and outs of Erlang with it. Somewhat unexpected, though, was the fact that the bot grew up a few extra features which multiple teams in Canonical started to appreciate. This was of course very nice, but it also made it more obvious that the egocentric reason for having a bot written in Erlang would now hurt, because most of Canonical’s own coding is done in Python, and that’s what internal tools should generally be written in for everyone to contribute and help maintaining the code.

That’s where the desire of migrating mup into a Python-based brain again came from, and having a new feature to write was the perfect motivator for this.

LDAP and two-way SMSing over IRC

Canonical is a very distributed company. Employees are distributed over dozens of countries, literally. Not only that, but most people also work from their homes, rather than in an office. Many different countries also means many different timezones, and working from home with people from different timezones means flexible timing. All of that means communication gets… well.. interesting.

How do we reach someone that should be in an online meeting and is not? Or someone that is traveling to get to a sprint? Or how can someone that has no network connectivity reach an IRC channel to talk to the team? There are probably several answers to this question, but one of them is of course SMS. It’s not exactly cheap if we consider the cost of the data being transfered, but pretty much everyone has a mobile phone which can do SMS, and the model is not that far away from IRC, which is the main communication system used by the company.

So, the itch was itching. Let’s scratch it!

Getting the mobile phone of employees was already a solved problem for mup, because it had a plugin which could interact with the LDAP directory, allowing people to do something like this:

<joe> mup: poke gustavo
<mup> joe: niemeyer is Gustavo Niemeyer <…@canonical.com> <time:…> <mobile:…>

This just had to be migrated from Erlang into a Python-based brain for the reasons stated above. This time, though, there was no reason to write something from scratch. I could even have used pybot itself, but there was also supybot, an IRC bot which started around the same time I wrote the first version of pybot, and unlike the latter, supybot’s author was much more diligent in evolving it. There is quite a comprehensive list of plugins for supybot nowadays, and it includes means for testing plugins and so on. The choice of using it was straighforward, and getting “poke” support ported into a plugin wasn’t hard at all.

So, on to SMSing. Canonical already had a contract with an SMS gateway company which we established to test-drive some ideas on Landscape. With the mobile phone numbers coming out of the LDAP directory in hands and an SMS contract established, all that was needed was a plugin for the bot to talk to the SMS gateway. That “conversation” with the SMS gateway allows not only sending messages, but also receiving SMS messages which were sent to a specific number.

In practice, this means that people which are connected to IRC can very easily deliver an SMS to someone using their nicks. Something like this:

<joe> @sms niemeyer Where are you? We’re waiting!

And this would show up in the mobile screen as:

joe> Where are you? We’re waiting!

In addition to this, people which have no connectivity can also contact individuals and channels on IRC, with mup working as a middle man. The message would show up on IRC in a similar way to:

<mup> [SMS] <niemeyer> Sorry, the flight was delayed. Will be there in 5.

The communication from the bot to the gateway happens via plain HTTPS. The communication back is a bit more complex, though. There is a small proxy service deployed in Google App Engine to receive messages from the SMS gateway. This was done to avoid losing messages when the bot itself is taken down for maintenance. The SMS gateway doesn’t handle this case very well, so it’s better to have something which will be up most of the time buffering messages.

A picture is worth 210 words, so here is a simple diagram explaining how things got linked together:

This is now up for experimentation, and so far it’s working nicely. I’m hoping that in the next few weeks we’ll manage to port the rest of mup into the supybot-based brain.

por Gustavo Niemeyer em 19 de June de 2010 às 21:56

Released editmoin 1.15

Version 1.15 of editmoin is now available.

The following changes were made:

  • Moin used to work with numerical IDs for identification, and editmoin was still based on this model. This release adds support for direct authentication as available in current Moin releases. This was inspired by Reimar Bauer.
  • The new file ~/.moin_users is now parsed to obtain usernames, supporting the feature above. Shortcuts are also supported in this file.
  • Added support for textcha question handling.

por Gustavo Niemeyer em 19 de June de 2010 às 19:15

Christiano Anderson

O Google em linha de comando

Quem gosta de shell já deve ter pensado algo do tipo: e se eu pudesse usar os serviços do Google via linha de comando? Pois é, isso agora é possível. O Google surpreendeu mais uma vez e lançou o GoogleCL,  uma coleção de  ferramentas feitas em Python para administrar via shell alguns serviços como Blogger,  Agenda, Contatos, Documentos, Picasa e Youtube.

Veja o que é possível fazer com essa ferramenta:

  1. Criar um post no Blogger: $ google blogger post –title “Título” “Conteúdo do Post”
  2. Criar um compromisso no calendário: $ google calendar add “Almoço com a família at noon tomorrow” (a data e alguns parâmetros precisam ser em inglês)
  3. Exportar os contatos para um arquivo CSV: $ google contacts list name,email > contatos.csv
  4. Criar um álbum no Picasa e adicionar todas as fotos de um diretório no HD: $ google picasa create –album “Viagem para Manaus” ~/photos/viagem_manaus/*.jpg
  5. Enviar um vídeo do seu HD diretamente para o Youtube: $ google youtube post –category Screencast aprenda_python.avi

Como instalar

Na página http://code.google.com/p/googlecl/ é possível encontrar as versões .tar.gz e .deb (Debian/Ubuntu). É necessário instalar a dependência python-gdata para que a ferramenta funcione. No Ubuntu, um sudo apt-get install python-gdata resolve o problema.

Como funciona

A ferramenta faz o acesso via OAUTH. Na primeira vez que você digitar o comando apropriado, será solicitado um acesso pelo navegador para fazer a autorização. Você deverá copiar e colar aquela URL no navegador, fazer a autorização, depois voltar no shell e dar um enter para continuar. Só precisa fazer isso uma vez por aplicação (Blogger, Calendar, Youtube). Com o acesso feito via OAUTH, não é necessário digitar a senha no terminal, então a senha não ficará gravada em nenhum lugar.

A lista dos comandos e opções para cada serviço pode ser obtida em http://code.google.com/p/googlecl/wiki/ExampleScripts

Gostei muito dessa ferramenta, permite inclusive a criação de diversos scripts para automatizar determinadas tarefas, como adicionar um lembrete na agenda, enviar um lote de fotos para o Picasa ou vídeos para o Youtube com poucas linhas de código. Fica a dica!

por Christiano Anderson em 19 de June de 2010 às 04:00

June 17, 2010

Gustavo Niemeyer

The forgotten art of error checking

I was just rambling randomly yesterday, in the usual microblogging platforms, about how result checking seems to be ignored or done badly. The precise wording was:

It’s really amazing how little attention error handling receives in most software development. Even *tutorials* often ignore it.

It indeed does amaze me. It sometimes feels like we write code for theoretical perfect worlds.. “If the processor executes exactly in this order, and the weather is calm, this program will work.”. There are countless examples of bad assumptions.. someday I will come with some statistics of the form “Every N seconds someone forgets to check the result of write().”.

If you are a teacher, or a developer that enjoys writing snippets of code to teach people, please join me in the quest of building a better future. Do not tell us that you’re “avoiding result checking for terseness”, because that’s exactly what we people will do (terseness is good, right?). On the contrary, take this chance to make us feel bad about avoiding result checking. You might do this by putting a comment like “If you don’t do this, you’re a bad programmer.” right next to the logic which is handling the result, and might take this chance to teach people how proper result handling is done.

Of course, there’s another forgotten art related to result checking. It sits on the other side of the fence. If you are a library author, do think through about how you plan to make us check conditions which happen inside your library, and try to imagine how to make our lives easier. If we suck at handling results when there are obvious ways to handle it, you can imagine what happens when you structure your result logic badly.

Here is a clear example of what not to do, coming straight from Python’s standard library, in the imaplib module:

    def login(self, user, password):
        typ, dat = self._simple_command('LOGIN', user, self._quote(password))
        if typ != 'OK':
            raise self.error(dat[-1])
        self.state = 'AUTH'
        return typ, dat

You see the problem there? How do you handle errors from this library? Should we catch the exception, or should we verify the result code? “Both!” is the right answer, unfortunately, because the author decided to do us a little favor and check the error condition himself in some arbitrary cases and raise the error, while letting it go through and end up in the result code in a selection of other arbitrary cases.

I may provide some additional advice on result handling in the future, but for now I’ll conclude with the following suggestion: please check the results from your actions, and help others to check theirs. That’s a good life-encompassing recommendation, actually.

por Gustavo Niemeyer em 17 de June de 2010 às 15:15

June 10, 2010

Kodumaro

Por que as empresas teimam em contratar programadores mercenários?

Recentemente li The Python Paradox, de Paul Graham, e sua tradução O Paradoxo Python no #!SouNerd.

O texto faz todo sentido: quem aprende a fazer qualquer coisa por gosto tende a fazer melhor do que quem aprende a fazer por dinheiro. É uma verdade.

Assim, quem aprende a programar porque gosta de programar tende a programar melhor do que quem aprende para ganhar dinheiro e a grande maioria de quem aprende a programar Java só o faz por dinheiro (claro que há lá suas exceções), enquanto quem aprende linguagens mais exóticas o faz por prazer.

Então por que as empresas teimam em contratar programadores mercenários?

Pensando sobre isso e observando a comunidade, pensei em uma resposta…

Eu vejo três tipos de programadores, como três vértices de um triângulo cromático, e cada um está em uma região dessa área, mais próximo ou distante de cada vértice.

Esses três tipos são: amador, mercenário e empolgado (por falta de palavra melhor).

Mercenário


O mercenário é aquele que quer dinheiro e lucro é tudo o que o impulsiona. Geralmente não tem escrúpulos e faz tudo o que lhe mandam. Seu mantra é: «Pagando bem, que mal tem?»

Quem é 100% mercenário geralmente acaba largando a profissão por algo que dê mais dinheiro, mas basta estar um pentelésimo mais para o centro do triângulo que permanece na profissão.

Normalmente aprende uma linguagem que dê muitas opções de emprego – e que, por consequência, tenha de competir com muita gente –, como Java, C# ou PHP, e rejeita todas as demais. Quando as trata como inferiores, é apenas para tentar justificar a própria incompetência, resultante da falta de gosto pelo que faz.

Amador


O amador é aquele que gosta de verdade do que está fazendo, ele ama programar, daí amador.

Quem é 100% amador quase sempre se perde aprendendo coisas inúteis e não consegue ganhar dinheiro porque muitas vezes perde o foco do que precisa fazer, distraindo-se com besteiras.

Normalmente aprende linguagens bem diferentes, que poucos sabem, como Lisp, Smalltalk ou Fortran – talvez LOLCODE –, e não é incomum que aprenda uma penca de linguagens, nesse caso, também os hypes, como Python e Ruby.

Empolgado


O empolgado é aquele que vai atrás de algum hype, linguagem da moda. Há uns anos eram de Java, mas os empolgados da atualidade querem Python e/ou Ruby.

Quem é 100% empolgado sabe tudo que acontece na comunidade, mas quase nada de programação. Conhece todas as metodologias em alta, sabe todos os macetes e design patterns de sua linguagem que precisa para impressionar os iniciantes, mas não é lá muito eficiente. É tão preocupado com a auto-imagem e o que acontece na comunidade que se esquece que há todo um background a ser aprendido por trás da Computação.

**


Felizmente (quase) ninguém é 100% alguma coisa.


Depois de toda esta dissertação, por que diabos as empresas mais engessadas preferem os mercenários?

Por causa de seu mantra! Basta pagar o que o mercenário acha muito – o que muitas vezes é quase nada pra empresa – e ele faz qualquer coisa que mandarem, torna-se um cão bem adestrado. Essas empresas não querem eficiência, querem obediência.

O que as empresas não veem é que esses cães não são tão ágeis quanto os gatos que pulam pelos telhados: aqueles que, apesar de em nenhum extremo, se encontram mais próximos do vértice do amador.

Na verdade as metodologias ágeis não são práticas de trabalho, mas técnicas sociais para atrair programadores que, apesar de ainda um pouco mercenários, sejam muito mais amadores – ser um pouco empolgado também ajuda, já que as linguagens hype facilitam pela grande mobilidade da comunidade. As empresas mais espertas e as start-up viram isso e usam as metodologias ágeis para criar equipes enxutas e mais eficientes do que qualquer equipe de mercenários jamais conseguirá ser.

[]’s
Cacilhας, La Batalema

por noreply@blogger.com (Cacilhας, La Batalema) em 10 de June de 2010 às 01:15

June 08, 2010

Pythonologia, o blog da Triveos » python

Django-ZODB 0.2rc1 lançado

Post rápido pra anunciar que hoje eu subi o módulo django-zodb-0.2rc1 no PyPI. Publiquei essa versão para que outros pythonistas que usam Django e/ou ZODB possam colaborar com o projeto.

A ajuda que preciso com maior urgência é para corrigir os meus erros de inglês na documentação (deve ter toneladas deles no README.rst) e completá-la (removendo os XXX). Consertando os bugs que forem aparecendo e finalizando a documentação eu já lanço a versão 0.2final. Modificações que mudem a API só entram nessa versão se forem pra corrigir erros de design.

Novas funcionalidades podem ser incorporadas em um branch separado. O projeto está hospedado no github, portanto, isso é fácil de se fazer. Tem uma mini-lista de coisas que ainda faltam ser feitas no fim do arquivo README.

Layout provisório do site do projeto Django-ZODB

Layout provisório do site do projeto Django-ZODB

Já tenho um template pronto para o site do projeto mas não poderei trabalhar nisso nos próximos dias. Se alguém quiser mexer nisso é só falar comigo.

A Triveos é especializada no desenvolvimento de aplicações Web e utiliza Python e Django em grande parte de seus projetos. Tendo como base esse know-how no uso de Python e Django criamos o Curso de Desenvolvimento Web com Python e Django nas modalidades in-company e online.

Copyright © 2010, Triveos Tecnologia Ltda.
Creative Commons License

por Osvaldo Santana Neto em 08 de June de 2010 às 21:05

June 03, 2010

Flávio Coelho

PyBrain

Just came across this interesting python library for machine learning. People interested in this should also checkout Peach: http://code.google.com/p/peach/acerca de: http://pybrain.org/pages/features (ver no Google Sidewiki)

por Flavio Coelho (noreply@blogger.com) em 03 de June de 2010 às 06:38

May 30, 2010

Eduardo Willians

Conversa Interna

Descortinando uma biblioteca antiga
-- Hmm... Pra que será que serve essa linha?... Vou apagar esse trecho que não serve pra nada...
-- Você tem certeza que vai funcionar se você apagar isso? Talvez seja melhor deixar do jeito que está. Ele sempre funcionou assim.
-- Mas pra que foi mesmo que vim olhar esse modulo?
-- Ah sim, era porque eu queria implementar um nova funcionalidade. Mas talvez eu devesse achar um meio mais fácil de fazer isso sem ter que mexer aqui...

por Eduardo Willians Bandeira de Melo (noreply@blogger.com) em 30 de May de 2010 às 10:54

May 29, 2010

Kodumaro

DISQUS e perda dos comentários

Twitter Gente,

Devido a uma proliferação absurda de spams nos comentários do Kodumaro, implementei o serviço DISQUS para gerência dos mesmos.

Infelizmente, parece que todos os comentários antigos se perderam. =(

Peço desculpas a todos, a implementação foi uma necessidade e a perda dos comentários um efeito colateral indesejado.

[]’s
Cacilhας, La Batalema

por noreply@blogger.com (Cacilhας, La Batalema) em 29 de May de 2010 às 00:40

May 28, 2010

Mosaico Livre » python

MaginBook sem a infra do Lackey

Mudei de idéia em relação a usar a infraestrutura do LackeyCCG.

Optei por implementar um plugin que dado uma lista de siglas de sets de Magic, acesse um site e carregue as informações dos cards, gravando-as num banco de dado SQLite. Foi uma escolha mais divertida.

Outra vez a biblioteca BeautifulSoup foi incrível. Navegar na árvore de tags HTML e extrair os dados é moleza com ela.


por claudiotorcato em 28 de May de 2010 às 22:24

May 26, 2010

Mosaico Livre » python

Glade, Mac OS e MaginBook

Ora, as coisas não poderiam ficar melhores. Depois do trabalho de pesquisa que estava tendo para fazer certas coisas com Gtk, descobri que seria possível utilizar o Glade no Mac OS X. Baixei o binário e problema resolvido.

O trabalho é devagar, pois procuro o melhor jeito para desenvolver o MaginBook. Além de um tutorial ou outro sobre Gtk e Glade, consegui um exemplo inesperado, um organizador de decks e cards feito em Python com Gtk! O criador do Magiclibrary escreveu um comentário num post anterior sobre este assunto. Fui atrás dos códigos-fonte da aplicação para saber como ele resolveu certas coisas. O bacana é que ele também utilizou o Glade como ferramenta para montar a interface gráfica.

Só lembrando a vocês que só vou disponibilizar o código da aplicação quando ela estiver conseguindo baixar a descrição das cartas e suas imagens.

Além do mais, é importante salientar que vou usar a infra-estrutura de plugins do LackeyCCG, onde já se fornece praticamente tudo: informações sobre blocos, edições, descrição das cartas e imagens.


por claudiotorcato em 26 de May de 2010 às 23:43

May 24, 2010

Ricbit

Batman e a escalabilidade

Dia desses eu resolvi colocar os meus gibis em ordem (tarefa bem difícil, dada a quantidade deles). Mas logo no começo eu já apanhei pra conseguir ordenar dois deles. Ambos eram Punisher #1, ambos do Garth Ennis, mas qual veio antes?


Normalmente esse tipo de dúvida eu resolvo consultando o Grand Comics Database, um repositório imenso de informações sobre gibis. Porém, após usar um pouco a busca do site, eu notei que ela, hm, não funciona tão bem.

Por exemplo, um dos meus gibis é o Sergio Aragonés' Groo: Mightier than the Sword. Se você buscar no site por "mightier than sword", ele não acha, porque só faz match exato. Se você buscar por "Groo", também não acha. O nome foi indexado como "Groo:", e sem os dois pontos no final ele não acha. Por fim, se você buscar por "Aragones" ele também não acha, porque você não colocou o acento.

A primeira coisa em que pensei foi "poxa, é simples fazer melhor que isso". Mas falar é fácil né? O jeito é arregaçar as mangas e fazer um search que funcione!

Design

Vamos então aos requisitos: eu quero fazer um buscador que me retorne todas as séries que constem no database do GCD. O buscador precisa ser web-based, escalável e de latência baixa.

Para conseguir latência baixa, o jeito mais fácil é fazer alguma coisa que seja AJAX-like. E pra isso, minha ferramenta predileta é o Google Web Toolkit. Eu até gosto de programar em javascript, acho a linguagem legal, mas o problema é que cada browser implementa javascript de um jeito, e na prática você precisa perder um tempão com as peculiaridades de cada browser.

Com o GWT você escreve a aplicação uma vez só, em Java, e ele então compila seu código, gerando um javascript customizado para cada browser. Quando você faz o request, ele faz o download só do javascript correspondente, assim você não precisa gastar banda baixando código do Firefox se está rodando o Chrome. Daí em em diante é tudo AJAX, ou melhor, AJAJ (por default ele usa JSON ao invés de XML).

Para que a aplicação fosse escalável, eu usei o Google App Engine. Com ele, você pode rodar seu servidor direto na infraestrutura do Google, com todas as vantagens que isso implica. Por exemplo, você não precisa se preocupar em ficar dimensionando quantas máquinas são necessárias, ele faz isso sozinho pra você, adicionando máquinas conforme a carga no servidor começa a subir.

O App Engine ainda tem outra vantagem: ele é gratuito! Quer dizer, é gratuito até um certo limite, mas um buscador de gibis é uma aplicação de nicho, e na prática eu não vou ter tráfego suficiente para precisar passar desses limites. Por exemplo, o limite do database gratuito é 1GB, mais que suficiente pra guardar todos os dados que vão ser buscados.

Implementação

Definida a plataforma, vamos à implementação. O jeito mais fácil de fazer um buscador é usando uma lista invertida. Por exemplo, suponha que o database contém os gibis abaixo:

1 - Green Arrow
2 - Green Lantern
3 - Iron Lantern
4 - Green Lantern: Rebirth

A lista invertida correspondente fica assim:

arrow: 1
green: 1,2,4
iron: 3
lantern: 2,3,4
rebirth: 4

Tendo a lista invertida é fácil fazer a busca: basta procurar na lista invertida cada palavra da minha query, e fazer a intersecção dos conjuntos resultantes. Por exemplo, "Green Lantern" retorna {1,2,4} e {2,3,4}, cuja intersecção é {2,4}, que são os dois gibis que vamos retornar. Se as listas estiverem ordenadas, você pode calcular essa intersecção em O(n), e se não estiverem ordenadas, você ainda pode fazer em O(n) usando um pouco de espaço extra (como?)

Dentro do App Engine, as listas invertidas vão ficar guardadas no Datastore, que é um database escalável construído em cima da BigTable. Vale notar que o Datastore não é um database convencional: ao invés da analogia comum de uma tabela com linhas e colunas, o mais apropriado é pensar nele como se fosse um dicionário de dicionários: cada "linha" agora é a chave do dicionário mais externo, e as "colunas" são as chaves dos dicionários internos. Dessa maneira, não é obrigatório que cada "linha" tenha sempre as mesmas "colunas".

Adicionalmente à lista invertida, nós vamos guardar também uma lista direta. Assim, quando eu descobrir que os gibis a mostrar são o 2 e o 4, eu posso ir na lista direta e pegar mais dados sobre eles, como nome, editora, ano de lançamento, etc.

Depois disso, nós ainda precisamos fazer alguma espécie de ranking pra descobrir em qual ordem vamos mostrar os resultados. Em geral essa é uma das partes mais difíceis de uma search engine, mas eu resolvi simplificar e ordenar por número de edições (então Action Comics, que tem quase 900 edições, vai aparecer antes de Slave Girl Comics, que tem só duas).

Por fim, todo esse trabalho de lista invertida, intersecção, lista direta e ranking pode eventualmente ficar meio pesado, então nós vamos colocar um cache no caminho para guardar todas as queries já feitas, sem precisar repetir trabalho. O App Engine fornece um módulo de Memcache que é ideal para isso.

Preparando os dados

Antes de começar a usar o buscador, precisamos gerar as listas e colocá-las dentro do Datastore. O GCD fornece um arquivão com o dump do MySQL deles (que na verdade é um arquivo texto com 330MB de INSERTs). Com os dados em mãos, eu escrevi um script python que lê esses dados, cria a lista invertida e a lista direta, e faz o bulk upload desses dados para o Datastore.

O único cuidado extra nessa etapa é tomar cuidado com o unicode, já que eu quero que buscas por "mônica" e "monica" retornem o mesmo resultado. Uma maneira seria tirando os acentos no cliente, mas pra que fazer isso online se você pode fazer offline né? Mais fácil, na hora de criar a lista invertida, gerar duas entradas iguais, uma com "mônica" e outra com "monica".

Outra idéia que tive foi retornar as capas dos gibis, e não apenas os nomes deles. Nesse caso o processo foi um pouco mais complicado, porque o GCD não fornece um arquivão com todas as capas, assim como eles fazem com o dump do MySQL. Eles acham que fornecer esse arquivão para download poderia ser uma violação do fair use, então a recomendação é "se você quer as capas, faça um crawling você mesmo".

Bora fazer um crawler então! Usando várias threads em python foi tranquilo, eu baixei os 500MB de capas em poucas horas. Como o Datastore não foi feito para guardar imagens, eu optei por hospedar as capas no meu próprio servidor (www.ricbit.com).

O cliente

Escrever o cliente usando o GWT foi a parte mais difícil. Não que programar em GWT seja difícil, pelo contrário, usando UiBinder é bastante fácil. O problema mesmo é que eu manjo de CSS menos do que gostaria, então demorei um tempão até conseguir o layout desejado. Mas, como esperado, o resultado funciona em tudo quanto é browser, até mesmo no IE!

E para dar um toque especial no layout, eu pedi para a minha esposa fazer umas ilustrações para o logo e para a tela de loading do site, que ficaram bem bacanas (se você precisa de ilustrações para o seu site, fale com a Ila Fox!)

Por fim, eu ainda precisava de um jeito de fazer profiling do site, então fiz com que o servidor me retornasse o tempo gasto em cada etapa do processamento, e usei o Google Chart Tools para apresentar esses dados de uma maneira fácil de interpretar.

Segurança

Você não pode fazer uma aplicação web-based sem pensar na segurança, certo? Mas, felizmente, esse buscador não tem muitos pontos vulneráveis. O único ponto onde o usuário malicioso pode tentar fazer alguma coisa é no campo da query, mas eu não preciso nem sequer sanitizar, porque tudo que a aplicação retorna são os nomes dos gibis que já estão no datastore.

Na verdade, só de rodar a aplicação no App Engine você ainda ganha na faixa um monte de vantagens, entre elas detecção de ataques de DoS. Ele sabe sozinho filtrar ips que estão te bombardeando sem nem precisar configurar nada.

Juntando as peças

No final, o sistema completo ficou assim:



Se você quiser testar a aplicação, basta clicar no screenshot abaixo:



Agora finalmente dá para achar aquele gibi do Groo :)

Profiling

Com o sistema completo e funcionando já dá pra fazer o profiling. Para isso, basta digitar "debug:" antes de uma query qualquer. Por exemplo, se você fizer "debug: Groo" logo após o deploy do servidor, o resultado vai ser esse:


O App Engine faz resource management de maneira bem agressiva, se você não tiver nenhuma query em 10min, ele derruba sua instância. Daí, a primeira query que você fizer tem o overhead de levantar o serviço novamente, que nesse caso foi de quase 5 segundos. Mas se você fizer em seguida a mesma query, ela vai ser bem mais rápida:


Bem melhor né? Alguns poucos milisegundos no memcache, o resto é só o tempo de trafegar o resultado do servidor pro seu cliente. No total, pouco menos de 350ms de roundtrip, o que é bastante rápido.

Mas essa é uma query fácil. Uma das queries mais difíceis é "debug: Batman", porque existem muitos, muitos gibis do Batman. Vejamos:



O tempo é praticamente todo gasto baixando os dados dos gibis da lista direta, quase 3 segundos. Mesmo considerando que é um batch request de 824 gibis, três segundos é meio lento. Mas ao usar o Datastore, o importante é notar que esse tempo é independente da carga. Você até consegue uma solução customizada mais rápida que isso, mas sem tomar muito cuidado, o tempo de cada request vai aumentar se o número de usuários simultâneos crescer. Com o Datastore, o tempo é sempre o mesmo, e você está imune a baleiadas.

Naturalmente, isso só vale para a primeira vez. Se outro usuário buscar por Batman logo em seguida, ele vai pegar o resultado do memcache:


Agora deu só 500ms, e o tempo todo é praticamente só o overhead do download dos 824 gibis.

Outra query curiosa é "debug: Captain America Comics". Existem inúmeros gibis com captain (Captain America, Captain Marvel, etc), inúmeros com america (Captain America, Justice League of America, etc), e um outro sem número de Comics, então o tempo agora não é dominado pela lista direta:


Dessa vez dá pra ver o tempo que ele gasta fazendo a intersecção das listas invertidas (e note que até agora nós nem vimos tempo algum com ranking, é desprezível). O tempo total foi de 800ms, mesmo sem o memcache.

O source

É claro que isso tudo foi uma visão bem high-level do Gibit, tem um monte de detalhes curiosos que eu omiti para não deixar o post muito grande. Se você quiser ver a implementação, o código é open source e está disponível no Google Code:

Source code do Gibit

Se você tiver alguma dúvida específica, é só deixá-la nos comentários que eu tento responder. Enjoy :)

por Ricardo Bittencourt (noreply@blogger.com) em 24 de May de 2010 às 17:57

May 22, 2010

Mosaico Livre » python

Organizador de Decks em Python

Tenho um Nokia N800 que está parado deste que resolvi adotar uma agenda não-eletrônica. O fato do tablet não ter uma bateria de uma boa duração, muitas vezes não tinha a agenda disponível quando realmente precisava.

Bom, desde então fiquei pensando numa maneira de torná-lo útil novamente. Como eu jogo Magic The Gathering, um jogo de cartas colecionáveis, seria interessante ter uma lista de cartas e decks sempre à mão.

As funcionalidades que pretendo implementar para este organizador de decks, que chamarei de Maginbook:

  • Pesquisa de cartas
  • Download de novas cartas
  • Criar e baixar decks da Internet
  • Exportar decks para programas como MWS, LackeyCCG e Apprentice
  • Cotação das cartas

Eu comecei a testar as bibliotecas necessárias para este trabalho. Depois publico o código em algum repositório. Haverá duas versões: uma para Linux/Mac e outro para o Nokia N800 e outros tablets da linha.


por claudiotorcato em 22 de May de 2010 às 19:18