1. Instalando Python 3 na Dreamhost

    Quase um ano depois de instalar manualmente o python 2.7 e django na dreamhost, senti que era hora de tentar fazer o mesmo para o python 3.4.

    Hoje, o python padrão das instancias compartilhadas da Dreamhost já é o 2.7, tornando o post anterior desnecessário, mas já é hora de fazer o máximo de uso possível do python 3.

    Usei como base meu post anterior e este aqui Deploying Django with virtualenv on Dreamhost, que é bem direto e mais simples do que o que eu havia feito no passado, e pude seguir praticamente linha a linha para conseguir rodar uma aplicação com python 3 na dreamhost.

    Primeiro, é necessário fazer download e extrair o código fonte do python:

    1
    2
    3
    wget http://python.org/ftp/python/3.4.3/Python-3.4.3.tar.xz
    tar xvfJ Python-3.4.3.tar.xz 
    cd Python-3.4.3
    

    Depois disso, compilar e instalar o python (essa etapa vai demorar bastante, uma opção é fazer tudo dentro de uma screen):

    1
    2
    3
    ./configure --prefix=$HOME/python34
    make
    make install
    

    Depois de um bom tempo, as últimas linhas da instalação são especialmente interessantes:

    1
    2
    3
    4
    5
    6
    Collecting setuptools
    Collecting pip
    Installing collected packages: pip, setuptools
    
    
    Successfully installed pip-6.0.8 setuptools-12.0.5
    

    Ou seja, já temos o pip a nossa disposição, podemos checar que estamos usando a versão instalada no home do usuário.

    1
    2
    3
    4
    5
    6
    $ which python3
    /home/foo/python34/bin/python3
    $ which pip3
    /home/foo/python34/bin/pip3
    $ which pyvenv-3.4
    /home/foo/python34/bin/pyvenv-3.4
    

    Nesse ponto chegamos no momento mais específico da Dreamhost, que é o uso do passenger para aplicações python.

    Ele utiliza um arquivo passenger_wsgi.py na raiz do domínio que é usado para definir o python que será usado pela aplicação e outras informações, ele depende de uma variável “application” que é a aplicação wsgi que irá rodar.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    import sys, os
    import logging
    cwd = os.getcwd()
    sys.path.append(cwd)
    
    INTERP = os.path.expanduser("~/venv/bin/python")
    
    if sys.executable != INTERP: os.execl(INTERP, INTERP, *sys.argv)
    
    sys.path.insert(0,'$HOME/my_project/my_project')
    sys.path.insert(0,'$HOME/venv/bin')
    sys.path.insert(0,'$HOME/venv/lib/python3.4/site-packages/django')
    sys.path.insert(0,'$HOME/venv/lib/python3.4/site-packages')
    
    os.environ['DJANGO_SETTINGS_MODULE'] = "my_project.settings"
    from django.core.wsgi import get_wsgi_application
    application = get_wsgi_application()
    

    E pronto, bem mais simples que o caso do python 2.7 e pronto para trabalhar numa versão mais “evoluída” do python, mesmo que a hospedagem em si ainda não esteja.


  2. Um Djangonauta no Flask

    Quando saí do desenvolvimento com PHP fui diretamente para o Django, o ORM e admin foram suficientes para que convencer de que seria o framework ideal para mim, e venho usando ele em diversos projetos desde então.

    Porém me deparei com uma demanda de “criar uma página de contatos que envia um email”, e só, cheguei a começar a fazer o setup do projeto com o Django, mas a cada momento parecia mais que estava usando um canhão para matar uma formiga.

    Então resolvi fazer o projeto em Flask, havia feito apenas o tutorial alguns anos atrás mas parecia ser a opção correta para um projeto pequeno, um microframework para uma pequena demanda.

    Uma hora depois, 2 arquivos python (routes.py e forms.py), um template e alguns statics o problema estava resolvido.

    Além do flask, precisei instalar mais dois pacotes, Flask-Mail, Flask-WTF, o que foi bem tranquilo, já que ambos os pacotes tem uma boa documentação e são simples de usar, de certo modo, mais simples que o do Django.

    Um lado negativo que vejo é que para conseguir desenvolver essa pequena aplicação tive que manter 3 documentações diferentes abertas, e tive alguns problemas pra me acostumar com isso e as diferenças de como integrar as coisas, mas nada que um pouco de pratica não resolveria.


  3. Vantagens ao usar o runserver_plus

    O runserver_plus é um utilitário que pode te dar um pouco mais de produtividade quando desenvolvendo usando Django, faz parte do pacote django-extensions que tem vários outros comandos úteis para o desenvolvimento (como o shell_plus) e faz uso do Werkzeug, é simples instalá-lo via pip.

    1
    2
    pip install django-extensions
    pip install Werkzeug
    

    E adicioná-lo nas INSTALLED_APPS do django:

    1
    2
    3
    INSTALLED_APPS += (
            'django_extensions',
    ) 
    

    A partir daías telas d erro do Django ficaram assim:

    Traceback do runserver_plus

    A mais útil é um terminal python direto no traceback na tela, onde é possível fazer o debug do que causou a Exception, inspecionar as variáveis e o ambiente naquele momento e encontrar o problema.

    Terminal integrado

    Outra opção é ver o código fonte do arquivo onde aconteceu a Exception, talvez seu arquivo de view já esteja aberto no editor, mas como é possível visualizar isso do traceback inteiro, você pode ter mais informações do fonte do próprio Django

    Código Fonte

    E também é possível ver os comandos SQL gerados durante uma requisição passando o parametro “--print-sql” para o runserver_plus, que pode ser muito útil para visualizar o que o ORM do django está gerando, e encontrar locais onde o acesso ao banco pode estar gerando problemas.

    Código Fonte

    Essas são algumas vantagens que que o runserver_plus pode oferecer, são pequenos ganhos que ajudam na produtividade com Django.


  4. Problemas com pip freeze > requirements.txt

    Em muitos tutoriais é comum encontrar o comando pip freeze > requirements.txt como exemplo de como guardar os requisitos de um projeto.

    usar o requirements é uma boa prática e deve ser sempre seguida, porém o problema é quando ela é mal executada, podendo gerar mais problemas do que ajudar dependendo da situação.

    Por exemplo, tenho um projeto que usa o Markdoc para gerar uma wiki simples a partir de arquivos markdown, e tinha feito, a um bom tempo, o arquivo de requirements usando o pip freeze… gerando um arquivo assim:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    CherryPy==3.2.2
    Jinja2==2.6
    Markdoc==0.6.6
    Markdown==2.2.1
    PyYAML==3.10
    Pygments==1.5
    WebOb==1.2.3
    argparse==1.2.1
    wsgiref==0.1.2
    

    Onde todas as dependências do Markdoc foram parar no requirements, no momento tudo pareceu estar bem, porém, 2 anos depois, tentando regerar o virtualenv, me deparo com o erro a seguir:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    $ pip install -r requirements.txt
    Downloading/unpacking CherryPy==3.2.2 (from -r requirements.txt (line 1))
      Could not find a version that satisfies the requirement CherryPy==3.2.2 (from
      -r requirements.txt (line 1)) (from versions: 3.2.6, 3.4.0, 2.1.1, 2.2.0beta,
      3.2.3, 3.2.4, 3.2.4, 3.2.5, 3.2.5, 3.2.6, 3.2.6, 3.3.0, 3.3.0, 3.4.0, 3.4.0,
      3.5.0, 3.5.0, 3.6.0, 3.6.0)
        Some externally hosted files were ignored (use --allow-external to allow).
        Cleaning up...
        No distributions matching the version for CherryPy==3.2.2 (from -r
        requirements.txt (line 1))
        Storing debug log for failure in ~/.pip/pip.log
    

    Ou seja, a versão do CherryPy na época da criação do projeto não está mais disponível no PyPI, porém não é do CherryPy que eu preciso, e sim do Markdoc, então, ignorei o requirements e instalei o Markdoc diretamente.

    1
    $ pip install Markdoc
    

    E a instalação ocorreu normalmente, olhando o pip freeze, é possível notar que várias dependências do Markdoc foram atualizadas, mas o Markdoc em si continua na mesma versão:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    CherryPy==3.6.0
    Jinja2==2.7.3
    Markdoc==0.6.6
    Markdown==2.5.1
    MarkupSafe==0.23
    PyYAML==3.11
    Pygments==2.0.1
    WebOb==1.4
    argparse==1.2.1
    wsgiref==0.1.2
    

    Então, atualizei o requirements para ter apenas o Markdoc, o que vai evitar qualquer problema desse tipo no futuro.

    Como o projeto é muito simples foi fácil encontrar o problema e corrigir, mas se houvessem várias dependências ou dependências compartilhadas poderia ter sido bem mais complicado de se resolver.


  5. Instalando Python e Django na Dreamhost

    Os shared-hosts já foram a melhor opção de hospedagem barata e funcional que se tinha, porém a cada dia opções de VPS e de IaaS mais baratas aparecem, e os shared-hosts e suas limitações são deixados para trás.

    Um dos pontos negativos é a versão do python disponível, atualmente a dreamhost oferece a versão 2.6.6, o que obviamente não é o ideal, a última versão de cada ciclo (2.7 e 3.3) seria a melhor escolha.

    No meu caso, instalei a versão 2.7 que é a que estou usando em um projeto, aqui o passo a passo do que fiz, que poderia facilmente ser transformado em um bash script como já foi feito em alguns lugares, mas como eu só precisava do python, virtualenv e virtualenvwrapper, resolvi fazer manualmente.

    Para instalar o python:

    1
    2
    3
    4
    5
    wget http://www.python.org/ftp/python/2.7.8/Python-2.7.8.tgz --no-check-certificate
    tar xzvf Python-2.7.8.tgz
    cd Python-2.7.8
    ./configure --enable-shared --prefix=$HOME/opt/python-2.7.8
    make && make install
    

    O mais importante ali é a definição de um “prefix” no .configure, que permite instalar o python em uma pasta dentro do home do usuário.

    Depois, o virtualenv:

    1
    2
    3
    4
    5
    6
    7
    8
    mkdir opt/python-2.7.8/local
    wget https://pypi.python.org/packages/source/v/virtualenv/virtualenv-1.9.1.tar.gz --no-check-certificate
    tar -xzf virtualenv-1.9.1.tar.gz
    cd virtualenv-1.9.1
    python virtualenv.py /home/user/opt/python-2.7.8/local/
    easy_install virtualenv
    source ~/opt/python-2.7.8/local/bin/activate
    easy_install virtualenv
    

    E finalmente o virtualenvwrapper:

    1
    2
    3
    4
    5
    6
    wget http://www.doughellmann.com/downloads/virtualenvwrapper-2.6.1.tar.gz --no-check-certificate
    tar -xzf virtualenvwrapper-2.6.1.tar.gz
    cd virtualenvwrapper-2.6.1
    python setup.py install
    cp virtualenvwrapper.sh ~/opt/python-2.7.8/
    mdkir ~/.virtualenvs
    

    Para que tudo isso funcione, é necessário complementar e adicionar algumas variáveis de ambiente e ativar o virtualenvwrapper, isso pode ser feito a partir do .profile ou do .bashrc

    .profile

    1
    2
    3
    4
    5
    export PATH=$HOME/opt/python-2.7.8/local/bin:$HOME/opt/python-2.7.8/bin:$PATH
    export PYTHONPATH=$HOME/opt/python-2.7.8/local/lib/python2.7/site-packages:$PYTHONPATH
    export LD_LIBRARY_PATH=$HOME/opt/python-2.7.8/lib/
    export WORKON_HOME=$HOME/.virtualenvs
    source $HOME/opt/python-2.7.8/virtualenvwrapper.sh
    

    Agora considerando um projeto usando Django, a dreamhost usa o passenger para executar aplicações em python, e um arquivo passenger_wsgi.py é necessário na raiz da pasta para a qual o domínio está apontando para fazer o passenger encontrar a aplicação.

    Essa deve ser provavelmente a parte mais complicada do processo, porque existe pouca ou nenhuma documentação de como é o modo correto de criar este arquivo.

    Os pontos importantes dele são:

    • Definir na variável INTERP o caminho para o executável do python a ser usável, de preferência sendo o do virtualenv criado para o projeto

    • Adicionar no path todos os caminhos pertinentes ao projeto, através do sys.path.insert, que atualiza o path adicionando novos valores no começo do mesmo.

    • Adicionar qualquer variável de ambiente necessária para o sistema no ambiente através do os.environ, no caso, estou setando o arquivo settings a ser usado pelo projeto.

    • A criação da variável “application” que vai ser usada pelo passenger para rodar a aplicação.

    passenger_wsgi.py

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    import sys, os
    
    # Switch to the virtualenv if we're not already there
    INTERP = os.path.expanduser("~/.virtualenvs/python/bin/python")
    if sys.executable != INTERP: os.execl(INTERP, INTERP, *sys.argv)
    
    PROJECT_ROOT = '/home/user/example'
    
    sys.path.insert(0, PROJECT_ROOT + '/example/')
    sys.path.insert(0, '/home/user/.virtualenvs/example/lib/python2.7/site-packages')
    os.environ['DJANGO_SETTINGS_MODULE'] = "example.settings.dreamhost"
    import django.core.handlers.wsgi
    application = django.core.handlers.wsgi.WSGIHandler()
    

    E por último, na dreamhost a pasta “public” deve ser usada para servir os arquivos estáticos da aplicação, nesse caso, é necessário definir o STATIC_ROOT e MEDIA_ROOT em pastas dentro do public, e os STATIC_URL e MEDIA_URL considerando o caminho a partir da public.

    settings/dreamhost.py

    1
    2
    3
    4
    5
    6
    7
    STATIC_ROOT = os.path.join(HOME_DIR, 'example.daniloshiga.com', 'public', 'static')
    
    STATIC_URL = '/static/'
    
    MEDIA_ROOT = os.path.join(HOME_DIR, 'example.daniloshiga.com', 'public', 'media')
    
    MEDIA_URL = '/media/'
    

    Do modo que está acima, essas pastas vão ficar em /home/user/example/example.daniloshiga.com/public/static e /public/media, mas a URL delas é apenas /static e /media.

    Depois disso, para reiniciar o passenger toda vez que houver uma novidade no projeto, é necessário alterar a data de modificação de um arquivo restart.txt dentro da pasta tmp/ do domínio, por exemplo, através do comando:

    1
    touch ~/example.daniloshiga.com/tmp/restart.txt
    

    Se isso não for suficiente, ainda é possível matar os processor do python que estiverem rodando, usando o comando pkil python.

    E é isso, foi um processo um pouco trabalhoso, mas tem a vantagem de dar mais liberdade em um ambiente limitado, o que permite aproveitar algumas vantagens de uma hospedagem como a dreamhost


  6. Microdata para receitas

    O Blogger dá uma força e por padrão já adiciona os metadados de BlogPost, mas dependendo do tipo de postagem é possível adicionar ainda mais marcações, como no caso de uma receita de Bolo de Coca-Cola, mesmo a marcação de Recipe, sendo bem completa, não é necessário ter todos os dados para usar a marcação, no caso, usei apenas a do nome (que é obrigatória), imagem (para todas as fotos), ingredients e recipeInstruction.

    Para testar os metadados a melhor ferramenta ainda é o Google Structured Data Testing Tool, foi onde, por exemplo, percebi que havia esquecido de colocar o atributo name.

    Atualmente o uso dessas estruturas pode parecer ser útil apenas para fazer SEO, mas quanto maior for seu uso no momento de criar conteúdo, mais útil ela será na hora de fazer a analise dos dados.


  7. Introdução aos Testes no Django

    Estou iniciando no processo de gerar testes para meu código no django, vou ir colocando as minhas impressões sobre o assunto.

    Em primeiro lugar, pelo menos na versão 1.5, é de senso comum que o código de testes apresentado para o Django está longe do ideal, o que vejo é que a maioria dos projetos não faz uso do “tests.py” padrão gerado no comando “createapp”, logo existem muitas versões diferentes de estruturas e testrunners na internet.

    Decidi me basear no que pode ser encontrado no Two Scoops of Django.

    Um detalhe importante é verificar qual versão do Django está sendo usada, porque da 1.5 para a 1.6 houve uma troca no “test runner” para usar um que encontra com mais facilidade os testes dentro dos módulos.

    Nesse caso, é interessante criar um settings/test.py específico para testes. De modo que seja usado um banco de dados sqlite na memória, que torna o processo bem mais rápido. o settings pra versão 1.5 e 1.6 podem ser encontrados no github do projeto base do Two Scoops of Django.

    A partir daí, é apenas começar a escrever os testes :), o que preciso começar a fazer e aprender conforme faço.


  8. Consistência não é crítica

    Vendo um dos vídeos do Google I/O 2013 sobre design, além de vários conceitos comuns que permitem usar o modo como as pessoas percebem o mundo para melhorar o design, um trecho do final me chamou a atenção, aonde o palestrante diz que:

    Consistência não é crítica”, e é o tipo de coisa na qual as pessoas se concentram, acreditando que manter a consistência entre diversas partes do sistema ou entre mudanças realizadas em novas versões seja o mais importante para evitar dúvidas no usuário final, quando na realidade não é assim, mais importante que consistência é ter inovação e aprendizado, mostrando para as pessoas o que mudou, ensinando através de exemplos simples de modo que cada um possa extrapolar os usos das novas funcionalidades.

    Consistency is not critical

    Esse trecho acontece bem no final da palestra, aos 35 minutos, tudo o que vem antes é muito interessante, mas essa parte é a principal do meu ponto de vista, já que é muito comum ver casos onde não há inovação por medo que a falta de consistência vá afastar os usuários, acredito fortemente que, se a mudança for positiva, e bem definida para o usuário, as chances de que ele aprenda rapidamente a lidar com o que mudou e fique feliz com essa inconsistência são muito grandes.


  9. Pelican

    É isso aí, wordpress é legal, tem um painel administrativo e tudo mais, mas está na hora de ser um dos caras legais, resolvi trocar o wordpress por um gerador de sites estático, e entre vários, escolhi o Pelican.

    Pra mim, a grande vantagem é o tempo de carregamento, sem a necessidade de processamento e acesso ao banco, o blog ficou bem mais rápido.

    A grande maioria dos meus posts aqui acabaram sendo sobre o próprio blog, técnicas mirabolantes para manter o wordpress atualizado e plugins bizarros para conseguir postar usando o vim (bizarro mas legal).

    Queria um tema simples, o mais minimalista possível, principalmente porque não sou muito bom na parte de design. Então montei o layout usando o Toast, um framework CSS bem simples, que o próprio autor considera como apenas framework para facilitar a criação de wireframes, mas que eu gostei muito da simplicidade, sem a necessidade de colocar algo enorme como um bootstrap (o código do Toast tem apenas algumas regras bem simples.).

    Para atingir essa simplicidade o mesmo não funciona no IE7, mas tudo bem, não espero que ninguém acessando isso daqui esteja usando ele.

    Considerei em colocar os comentários do Google Plus, gosto do modo como eles se misturam com as postagens na rede social (de forma muito melhor do que a do facebook, por exemplo), mas por padrão o widget do Google não é responsivo, além de ser necessário ter conta para comentar.

    E como o Pelican já tinha tudo pronto para uso do Disqus, resolvi utilizá-lo, tinha trauma do mesmo pela lentidão que apresentava anos atrás, mas isso parece ter se resolvido.

    Outra coisa que aproveitei para fazer foi adicionar as tags semânticas do schema.org, agora os posts tem definido corretamente autor, conteúdo e data de postagem, o que já é um bom começo e que o Google já entende do que se trata na hora de indexar.

    Então é isso, não cheguei a fazer uma comparação muito exata, mas tenho certeza que o blog está por volta de 3 vezes mais rápido para carregar, e aguentando uma quantidade muito maior de visitas sem problemas, agora é fazer mais postagens, se possível sem ser apenas sobre o próprio blog.


  10. Wordpress e temas padrão

    A versão 3.8 do  wordpress está realmente diferente, o admin está com um visual novo, e o tema padrão apresenta novo segue a mesma linha flat que tem feito muito sucesso.

    Gostei tanto do tema padrão que resolvi usá-lo para esse blog, só com algumas pequenas mudanças, talvez eu “fuce” mais no decorrer do tempo, mas está bem aceitável. O suficiente para que eu cancelasse os planos de fazer algo baseado no temas roots.

    No caso, as alterações que fiz no CSS foram as seguintes:

    1
    2
    3
    4
    5
    6
    7
    8
    .entry-title {
    text-transform: none;
    }
    
    .site-content .entry-header,.site-content .entry-content,.site-content .entry-summary,.site-content .entry-meta,.page-content {
    margin: 0 auto;
    max-width: 674px;
    }
    

    O primeiro para remover o estilo que deixa o título dos posts todo em maiúsculo, e o segundo para aumentar um pouco a largura do espaço de postagem.

Página 1 / 3 »