Planeta PythonBrasil

December 08, 2019

Vinta Software

PyGotham 2019: Talking Python in NY!

We are arriving in New York! Part of our team is on their way to PyGotham 2019, the biggest event of the Python community in New York. The experience last year was amazing, so we decided to come back. We are also sponsoring it this year, so if you are going to the event make sure to stop by our booth, we are bringing lots of cool swags and some Br

08 de December de 2019 às 02:00

DjangoCon US 2019: Python & Django in San Diego!

We are back to San Diego!! Our team will be joining DjangoCon US's conference, one of the biggest Django events in the world. For this year, we'll be giving two talks: Pull Requests: Merging good practices into your project and Building effective Django queries with expressions Here is the slide from the talk we gave during the conference: Pull Re

08 de December de 2019 às 02:00

December 01, 2019

Gabbleblotchits

Interoperability #rust2020

In January I wrote a post for the Rust 2019 call for blogs. The 2020 call is aiming for an RFC and roadmap earlier this time, so here is my 2020 post =]

Last call review: what happened?

An attribute proc-macro like #[wasm_bindgen] but for FFI

This sort of happened... because WebAssembly is growing =]

I was very excited when Interface Types showed up in August, and while it is still very experimental it is moving fast and bringing saner paths for interoperability than raw C FFIs. David Beazley even point this at the end of his PyCon India keynote, talking about how easy is to get information out of a WebAssembly module compared to what had to be done for SWIG.

This doesn't solve the problem where strict C compatibility is required, or for platforms where a WebAssembly runtime is not available, but I think it is a great solution for scientific software (or, at least, for my use cases =]).

"More -sys and Rust-like crates for interoperability with the larger ecosystems" and "More (bioinformatics) tools using Rust!"

I did some of those this year (bbhash-sys and mqf), and also found some great crates to use in my projects. Rust is picking up steam in bioinformatics, being used as the primary choice for high quality software (like varlociraptor, or the many coming from 10X Genomics) but it is still somewhat hard to find more details (I mostly find it on Twitter, and sometime Google Scholar alerts). It would be great to start bringing this info together, which leads to...

"A place to find other scientists?"

Hey, this one happened! Luca Palmieri started a conversation on reddit and the #science-and-ai Discord channel on the Rust community server was born! I think it works pretty well, and Luca also has being doing a great job running workshops and guiding the conversation around rust-ml.

Rust 2021: Interoperability

Rust is amazing because it is very good at bringing many concepts and ideas that seem contradictory at first, but can really shine when synthesized. But can we share this combined wisdom and also improve the situation in other places too? Despite the "Rewrite it in Rust" meme, increased interoperability is something that is already driving a lot of the best aspects of Rust:

  • Interoperability with other languages: as I said before, with WebAssembly (and Rust being having the best toolchain for it) there is a clear route to achieve this, but it will not replace all the software that already exist and can benefit from FFI and C compatibility. Bringing together developers from the many language specific binding generators (helix, neon, rustler, PyO3...) and figuring out what's missing from them (or what is the common parts that can be shared) also seems productive.

  • Interoperability with new and unexplored domains. I think Rust benefits enormously from not focusing only in one domain, and choosing to prioritize CLI, WebAssembly, Networking and Embedded is a good subset to start tackling problems, but how to guide other domains to also use Rust and come up with new contributors and expose missing pieces of the larger picture?

Another point extremely close to interoperability is training. A great way to interoperate with other languages and domains is having good documentation and material from transitioning into Rust without having to figure everything at once. Rust documentation is already amazing, especially considering the many books published by each working group. But... there is a gap on the transitions, both from understanding the basics of the language and using it, to the progression from beginner to intermediate and expert.

I see good resources for JavaScript and Python developers, but we are still covering a pretty small niche: programmers curious enough to go learn another language, or looking for solutions for problems in their current language.

Can we bring more people into Rust? RustBridge is obviously the reference here, but there is space for much, much more. Using Rust in The Carpentries lessons? Creating RustOpenSci, mirroring the communities of practice of rOpenSci and pyOpenSci?

Comments?

por luizirber em 01 de December de 2019 às 15:00

November 11, 2019

Thiago Avelino

Diferença entre amadores e profissionais

Porque algumas pessoas parecem ser extremamente bem sucedidas e fazer muito, enquanto a grande maioria de nós luta para pisar na água? A resposta é complicada e provavelmente composta por diversas respostas. O aspecto principal é a forma de pensar e planejamento. Mas qual é a diferença? Na verdade, há diversas diferenças: Amadores param quando chega a seu objetivo, profissionais entendem que a realização inicial é apenas o começo; Amadores têm um objetivo, profissionais têm um processo; Amadores pensam que são bons em tudo, profissionais entendem seus círculos de competência; Amadores ver feedback e concelho como criticas, profissionais sabem que têm pontos fracos e procuram críticas construtivas; Amadores valorizam o desempenho isolado, pense sobre o receptor que pega a bola uma vez em um lance difícil.

11 de November de 2019 às 16:00

November 08, 2019

Thiago Avelino

Chegar ao estado de Flow, para alcançar metas

Compreendendo a Psicologia do Flow Você já se sentiu completamente imerso em uma atividade? Se sim, você pode ter experimentado um estado mental que os psicólogos chama de flow, mas o que é isso? Vamos fazer uma analogia para tentar explicar: imagine que você está fazendo uma corrida Sua atenção está focada nos movimentos do seu corpo, na força dos seus músculos, sua respiração e sensação da rua aos seus pés.

08 de November de 2019 às 21:00

October 01, 2019

PythonClub

Criando dicts a partir de outros dicts

Neste tutorial, será abordado o processo de criação de um dict ou dicionário, a partir de um ou mais dicts em Python.

Como já é de costume da linguagem, isso pode ser feito de várias maneiras diferentes.

Abordagem inicial

Pra começar, vamos supor que temos os seguintes dicionários:

dict_1 = {
    'a': 1,
    'b': 2,
}

dict_2 = {
    'b': 3,
    'c': 4,
}

Como exemplo, vamos criar um novo dicionário chamado new_dict com os valores de dict_1 e dict_2 logo acima. Uma abordagem bem conhecida é utilizar o método update.

new_dict = {}

new_dcit.update(dict_1)
new_dcit.update(dict_2)

Assim, temos que new_dict será:

>> print(new_dict)
{
    'a': 1,
    'b': 3,
    'c': 4,
}

Este método funciona bem, porém temos de chamar o método update para cada dict que desejamos mesclar em new_dict. Não seria interessante se fosse possível passar todos os dicts necessários já na inicialização de new_dict?

Novidades do Python 3

O Python 3 introduziu uma maneira bem interessante de se fazer isso, utilizando os operadores **.

new_dict = {
    **dict_1,
    **dict_2,
}

Assim, de maneira semelhante ao exemplo anterior, temos que new_dict será :

>> print(new_dict['a'])
1
>> print(new_dict['b'])
3
>> print(new_dict['c'])
4

Cópia real de dicts

Ao utilizamos o procedimento de inicialização acima, devemos tomar conseiderar alguns fatores. Apenas os valores do primeiro nível serão realmente duplicados no novo dicionário. Como exemplo, vamos alterar uma chave presente em ambos os dicts e verificar se as mesmas possuem o mesmo valor:

>> dict_1['a'] = 10
>> new_dict['a'] = 11
>> print(dict_1['a'])
10
>> print(new_dict['a'])
11

Porém isso muda quando um dos valores de dict_1 for uma list, outro dict ou algum objeto complexo. Por exemplo:

dict_3 = {
    'a': 1,
    'b': 2,
    'c': {
        'd': 5,
    }
}

e agora, vamos criar um novo dict a partir desse:

new_dict = {
    **dict_3,
}

Como no exemplo anterior, podemos imaginar que foi realizado uma cópia de todos os elementos de dict_3, porém isso não é totalmente verdade. O que realmente aconteceu é que foi feita uma cópia superficial dos valores de dict_3, ou seja, apenas os valores de primeiro nível foram duplicados. Observe o que acontece quando alteramos o valor do dict presente na chave c.

>> new_dict['c']['d'] = 11
>> print(new_dict['c']['d'])
11
>> print(dict_3['c']['d'])
11 
# valor anterior era 5

No caso da chave c, ela contem uma referência para outra estrutura de dados (um dict, no caso). Quando alteramos algum valor de dict_3['c'], isso reflete em todos os dict que foram inicializados com dict_3. Em outras palavras, deve-se ter cuidado ao inicializar um dict a partir de outros dicts quando os mesmos possuírem valores complexos, como list, dict ou outros objetos (os atributos deste objeto não serão duplicados).

De modo a contornar este inconveniente, podemos utilizar o método deepcopy da lib nativa copy. Agora, ao inicializarmos new_dict:

import copy

dict_3 = {
    'a': 1,
    'b': 2,
    'c': {
        'd': 5,
    }
}

new_dict = copy.deepcopy(dict_3)

O método deepcopy realiza uma cópia recursiva de cada elemento de dict_3, resolvendo nosso problema. Veja mais um exemplo:

>> new_dict['c']['d'] = 11
>> print(new_dict['c']['d'])
11
>> print(dict_3['c']['d'])
5 
# valor não foi alterado

Conclusão

Este artigo tenta demonstrar de maneira simples a criação de dicts, utilizando os diversos recursos que a linguagem oferece bem como os prós e contras de cada abordagem.

Referências

Para mais detalhes e outros exemplos, deem uma olhada neste post do forum da Python Brasil aqui.

É isso pessoal. Obrigado por ler!

por Michell Stuttgart em 01 de October de 2019 às 16:00

September 23, 2019

Vinta Software

DjangoCon US 2019: Python & Django in San Diego!

We are back to San Diego!! Our team will be joining DjangoCon US's conference, one of the biggest Django events in the world. For this year, we'll be giving two talks: Pull Requests: Merging good practices into your project and Building effective Django queries with expressions. Here are the slides from the talks we gave during the conference: Pu

23 de September de 2019 às 20:00

September 16, 2019

Filipe Saraiva

Grupo de Estudos do Laboratório Amazônico de Estudos Sociotécnicos – UFPA

Eu e o prof. Leonardo Cruz da Faculdade de Ciências Sociais estamos juntos trabalhando no desenvolvimento do Laboratório Amazônico de Estudos Sociotécnicos da UFPA.

Nossa proposta é realizar leituras e debates críticos sobre o tema da sociologia da tecnologia, produzir pesquisas teóricas e empíricas na região amazônica sobre as relações entre tecnologia e sociedade, e trabalhar com tecnologias livres em comunidades próximas a Belém.

No momento estamos com um grupo de estudos montado com cronograma de textos e filmes para trabalharmos e debatermos criticamente. Esse grupo será o embrião para a orientação de alunos de graduação e pós em temas como impacto da inteligência artificial, computação e guerra, cibernética, vigilantismo, capitalismo de plataforma, fake news, pirataria, software livre, e outros.

Aos interessados, nosso cronograma de estudos está disponível nesse link.

E para quem usa Telegram, pode acessar o grupo de discussão aqui.

Quaisquer dúvidas, só entrar em contato!

por Filipe Saraiva em 16 de September de 2019 às 13:24

September 10, 2019

Humberto Rocha

Desbravando o pygame 5 - Movimento e Colisão

O movimento é uma característica que está presente na maioria dos jogos. Ao saltar entre plataformas, atirar contra a horda de inimigos, pilotar uma nave espacial e correr pelas estradas estamos exercendo movimento, interagindo com o ambiente do jogo, aplicando ações e causando reações. Neste capítulo iremos conhecer os conceitos básicos de movimentação de objetos na tela e sua interação com outros elementos através da detecção de colisão. Movimento Se você vem acompanhando esta série de postagens, teve um breve exemplo de movimentação na postagem sobre game loop, onde uma bola que se movimentava quicando pela tela foi implementada.

10 de September de 2019 às 03:00

August 28, 2019

Humberto Rocha

Publicando meu primeiro Jogo

Jogos sempre me conectam com tecnologia desde o início. Eu e meu pai montamos nosso primeiro computador (um Pentium 286) e a primeira coisa que eu me lembro de fazer, foi jogar os jogos de DOS como Prince of Persia e Lunar Lander. Eu aprendi vários comandos de CLI só para poder jogar os meus jogos favoritos. A paixão por jogar e fazer jogos sempre me acompanhou como um hobby.

28 de August de 2019 às 03:00

August 19, 2019

Vinta Software

PyBay 2019: Talking about Python in SF

We are back to San Francisco! Our team will be joining PyBay's conference, one of the biggest Python events in the Bay Area. For this year, we'll be giving the talk: Building effective Django queries with expressions. PyBay has been a fantastic place to meet new people, connect with new ideas, and integrate this thriving community. Here is the sl

19 de August de 2019 às 21:59

[pt-BR] PythonBrasil[14] talks

Slides from talks given during the PythonBrasil[14] event will be posted here. This post and the slides are written in Brazilian Portuguese. Como Programar seu Processo de Software Palestrante: Robertson Novelino Link dos Slides: Como Programar seu Processo de Software Todos usamos um método para programar, uma forma que nós gostamos de fazer as

19 de August de 2019 às 21:59

Understanding Time Series Forecasting with Python

Vinta is a software studio whose focus is to produce high quality software and give clients great consulting advices to make their businesses grow. However, even though our main focus is web development, we also do our share of machine learning over here. This article is the first of a few designed to show everything (or almost everything) you need

19 de August de 2019 às 21:59

Dealing with resource-consuming tasks on Celery

In this post, we will talk about how you can optimize your Celery tasks and avoid certain kind of problems related to resource-consuming tasks. If you are new to Celery or want to know more about it before reading this, you might wanna check first this post with an overview about Celery and this one with some more advanced tips and tricks. When w

19 de August de 2019 às 21:59

Celery in the wild: tips and tricks to run async tasks in the real world

This post is aimed at people with some experience writing async taks, if you are starting on Celery you might want to read this other post I wrote before starting on this one. The thing about async tasks is that the hard part is not how to run them [although it can be fairly complicated to understand the architecture and set up things when you

19 de August de 2019 às 21:59

[pt-BR] PythonBrasil[13] Talks

Vinhemos para a Python Brasil novamente. Dessa vez aprovamos 6 palestras. Indo desde Python para uso científico até técnicas para salvar grandes projetos.

19 de August de 2019 às 21:59

Vinta's Talks Around the Globe: DjangoConUS, PyBay2017 and DjangoConAU

Slides from talks given during the DjangoConUS, PyBay2017 and DjangoConAU events will be posted here

19 de August de 2019 às 21:59

Advanced Django querying: sorting events by date

Imagine the situation where our application has events (scheduled tasks, appointments, python conferences across the world) happening in different moments of time. Almost anything with a date attached to it. We want to display them in a simple list to the user. Given we are in February 2017 (the date this post was written), what would be the best w

19 de August de 2019 às 21:59

Contributing to Django Framework is easier than you think

For those who are starting to code and wish to make open source, sometimes it is hard to start. The idea of contributing with that fancy and wonderful lib that you love can sound a little bit scary. Lucky for us many of those libs have room for whoever is willing to start. They also give us the support that we need. Pretty sweet, right? Do you know

19 de August de 2019 às 21:59

Don't forget the stamps: testing email content in Django

When developing a web app how often do you check the emails you send are all working properly? Not as often as your web pages, right? That's ok, don't feel guilty, emails are hard to test and they are often someone's else responsibility to write and take care. This doesn't mean we should give up on them. There are some things we can do to prevent e

19 de August de 2019 às 21:59

How I test my DRF serializers

In this blog post, I will show the whats and whys on testing Django REST Framework serializers. First, some context. Here is the model setup we are going to use for this example: from django.db import models class Bike(models.Model): COLOR_OPTIONS = (('yellow', 'Yellow'), ('red', 'Red'), ('black', 'B

19 de August de 2019 às 21:59

Python API clients with Tapioca

In this post I'll present to you Tapioca, a Python library to create powerful API clients with very few lines of code. If you don't want to read through the reasons why I've built it, you may just jump straight to the Tapioca Wrapper section. Why do we need a better way to build API clients Integrating with external services is painful. Here at Vin

19 de August de 2019 às 21:59

Happython 2019!

Happy PyHolidays and Happy New Year! We are approaching the end of the year 2018! And as it turns out this was an incredible year for Python! Even though Guido stepped out of his role as BDFL (this alone is worth a couple of blogposts so this one will not extend the discussion), there are a lot of happy recollections from this year. In 2017 StackO

19 de August de 2019 às 21:59

PyGotham 2018 Talks

Critical Incidents: a guide for developers Presenter: Lais Varejão Slides: http://bit.ly/critical-incidents-guide Pluggable Libs Through Design Patterns Presenter: Filipe Ximenes Video: https://www.youtube.com/watch?v=PfgEU3W0kyU Slides: http://bit.ly/pluggable-libs Examples: https://github.com/filipeximenes/talk-design-patterns 1 + 1 = 1 or Re

19 de August de 2019 às 21:59

Taming Irreversibility with Feature Flags (in Python)

Feature Flags are a very simple technique to make features of your application quickly toggleable. The way it works is, everytime we change some behavior in our software, a logical branch is created and this new behavior is only accessible if some specific configuration variable is set or, in certain cases, if the application context respects some

19 de August de 2019 às 21:59

Django REST Framework Read & Write Serializers

Django REST Framework (DRF) is a terrific tool for creating very flexible REST APIs. It has a lot of built-in features like pagination, search, filters, throttling, and many other things developers usually don't like to worry about. And it also lets you easily customize everything so you can make your API work the way you want. There are many gen

19 de August de 2019 às 21:59

Celery: an overview of the architecture and how it works

Asynchronous task queues are tools to allow pieces of a software program to run in a separate machine/process. It is often used in web architectures as way to delegate long lasting tasks while quickly answering requests. The delegated task can trigger an action such as sending an email to the user or simply update data internally in the system whe

19 de August de 2019 às 21:59

Multitenancy: juggling customer data in Django

Suppose you want to build a new SaaS (Software as a Service) application. Suppose your application will store sensitive data from your customers. What is the best way to guarantee the isolation of the data and make sure information from one client does not leak to the other? The answer to that is: it depends. It depends on the number of customers y

19 de August de 2019 às 21:59

PyCon US 2017: the biggest Python Event in the World

Pycon 2017 happened in Oregon, Portland! If you wanted to discuss anything about Python, that was the place to be. It was the biggest Python event of the world, it lasted from May 17th to May 25th. I got to see talks from some important names on it, like Lisa Guo and Katy Huff, both of them are using Python to make great things! Lisa is using on In

19 de August de 2019 às 21:59

[pt-BR] Python Nordeste 2017 Talks

Slides from talks given during the Python Nordeste 2017 event will be posted here. This post and the slides are written in Brazilian Portuguese. 5 meses de Python: o que aprendi Palestrante: @rsarai Link dos slides: 5 meses de Python: o que aprendi Trabalhar como desenvolvedor de software pode ser um pouco frustrante, as vezes por estar preso a

19 de August de 2019 às 21:59

[Talk] All Things Python meetup in Sunnyvale

I'll be talking at the All Things Python meetup! It will happen on June 6 in Sunnyvale, California. I'll be talking about good practices designing async tasks and some advanced Celery features.This will be a first version of the talk I'm preparing for DjangoCon US in August. For signing up or more information, this is the link to the event. Looki

19 de August de 2019 às 21:59

Metaprogramming and Django - Using Decorators

While programming is about, in some way, doing code to transform data, metaprogramming can be seen as the task of doing code to change code. This category is often used to help programmers to enhance the readability and maintainability of the code, help with separation of concerns and respect one of the most important principles of software develop

19 de August de 2019 às 21:59

Vinta's Review of PythonBrasil[12]

PythonBrasil[12] happened in Florianópolis - SC and lasted for 6 days. We saw some amazing Keynotes from some awesome speakers, such as @SagnewShreds, @hannelita, @NaomiCeder, @freakboy3742, @seocam we got to have a lot of community time getting to know new people from all around Brazil and still got to present 4 talks(Hooray!!). On the following

19 de August de 2019 às 21:59

[pt-BR] PythonBrasil[12] Talks

Slides from talks given during the PythonBrasil[12] event will be posted here. This post and the slides are in written in Brazilian Portuguese. O que é esse tal de REST? Palestrante: @xima Link dos slides: O que é esse tal de REST? REST é a bola vez quando falamos sobre API. As maioria dos serviços que encontramos na web fornece interfaces dest

19 de August de 2019 às 21:59

Database concurrency in Django the right way

When developing applications which have real-time requirements or other specific needs for running asynchronous tasks outside the web application, it is common to adopt a task queue such as Celery. This allows, for example, for the server to handle a request, start an asynchronous task responsible of doing some heavyweight processing, and return an answer while the task is still running. Here, we are considering a similar scenario: a request is made, and the server has to do some processing on the request. Ideally, we want to separate the high time-demanding parts from the view processing flow, so we run those parts in a separate task. Now, let's suppose we have to do some database operations both in the view and the task when the request happens. If not done carefully, those operations can be a source for issues that can be hard to track.

19 de August de 2019 às 21:59

August 08, 2019

Humberto Rocha

Libs Fantásticas: pipx

Estou começando esta série para dar dicas sobre bibliotecas que podem ser muito úteis no seu dia a dia, e também para apresentar bibliotecas interessantes nas quais que você deveria ficar de olho. Uma das habilidades de um bom Programador é ter a ferramenta certa para realizar seu trabalho, e nada mais apropriado que começar esta série com uma ferramenta que instala outras ferramentas! Quantas vezes você já teve que instalar algum programa Python em uma virtualenv que você acabou de criar?

08 de August de 2019 às 03:00

July 12, 2019

Humberto Rocha

TLDR: Gerando Secret Key para o Django

Levante a mão quem nunca versionou a SECRET_KEY do Django no início de um projeto e precisou gerar uma nova na hora de subir pra produção. Este TLDR é um lembrete rápido de como você pode regerar uma secret key localmente, sem recorrer a sites na internet para gera-la para você. Como o Django gera a secret key no início de um projeto, já existe esta função implementada em seu código e você pode acessá-la desta forma:

12 de July de 2019 às 00:00

July 07, 2019

Thiago Avelino

Trocando forma de pensar (mudando mindset) de empresário para 'empregado'

Se ainda não me conhece empreendi desde 2011 até junho/2019 (durante esse tempo comentei algumas vezes que nunca mais iria empreender) e resolvi voltar para o mercado de trabalho e não é por motivos que quebrei financeiramente, indo na contramão do hype de startups. Acredito que surgiu diversas perguntas em sua cabeça ao ler o texto acima, acredite que na minha cabeça foram longos meses (quase 1 ano) refletindo sobre o assunto, colocando no papel os prós e contras, imaginando como seria, como me portaria em algumas situações até que por fim resolvi experimentar um ambiente novo, “desconhecido” e acredito que seja desafiador (pelo menos para mim).

07 de July de 2019 às 00:00

June 25, 2019

PythonClub

Tutorial Django 2.2

Este tutorial é baseado no Intro to Django que fica na parte de baixo da página start do Django project.

Até a data deste post o Django está na versão 2.2.2, e requer Python 3.

O que você precisa?

Python 3.6 ou superior, pip e virtualenv.

Considere que você tenha instalado Python 3.6 ou superior, pip e virtualenv.

Criando o ambiente

Crie uma pasta com o nome django2-pythonclub

$ mkdir django2-pythonclub
$ cd django2-pythonclub

A partir de agora vamos considerar esta como a nossa pasta principal.

Considerando que você está usando Python 3, digite

python3 -m venv .venv

Lembre-se de colocar esta pasta no seu .gitignore, caso esteja usando.

echo .venv >> .gitignore

Depois ative o ambiente digitando

source .venv/bin/activate

Lembre-se, sempre quando você for mexer no projeto, tenha certeza de ter ativado o virtualenv, executando o comando source .venv/bin/activate. Você deve repetir esse comando toda a vez que você abrir um novo terminal.

Instalando Django 2.2.2

Basta digitar

pip install django==2.2.2

Dica: se você digitar pip freeze você verá a versão dos programas instalados.

É recomendável que você atualize a versão do pip

pip install -U pip

Se der erro então faça:

python -m pip install --upgrade pip

Instalando mais dependências

Eu gosto de usar o django-extensions e o django-widget-tweaks, então digite

pip install django-extensions django-widget-tweaks python-decouple

Importante: você precisa criar um arquivo requirements.txt para instalações futuras do projeto em outro lugar.

pip freeze > requirements.txt

Este é o resultado do meu até o dia deste post:

(.venv):$ cat requirements.txt 

django-extensions==2.1.6
django-widget-tweaks==1.4.3
python-decouple==3.1
pytz==2018.9
six==1.12.0

Escondendo a SECRET_KEY e trabalhando com variáveis de ambiente

É muito importante que você não deixe sua SECRET_KEY exposta. Então remova-o imediatamente do seu settings.py ANTES mesmo do primeiro commit. Espero que você esteja usando Git.

Vamos usar o python-decouple escrito por Henrique Bastos para gerenciar nossas variáveis de ambiente. Repare que já instalamos ele logo acima.

Em seguida você vai precisar criar um arquivo .env, para isso rode o comando a seguir, ele vai criar uma pasta contrib e dentro dele colocar um arquivo env_gen.py

if [ ! -d contrib ]; then mkdir contrib; fi; git clone https://gist.github.com/22626de522f5c045bc63acdb8fe67b24.git contrib/
rm -rf contrib/.git/  # remova a pasta .git que está dentro de contrib.

Em seguida rode

python contrib/env_gen.py

que ele vai criar o arquivo .env.

Supondo que você está versionando seu código com Git, é importante que você escreva isso dentro do seu arquivo .gitignore, faça direto pelo terminal

echo .env >> .gitignore
echo .venv >> .gitignore
echo '*.sqlite3' >> .gitignore

Pronto, agora você pode dar o primeiro commit.

Criando o projeto e a App

Para criar o projeto digite

$ django-admin startproject myproject .

repare no ponto no final do comando, isto permite que o arquivo manage.py fique nesta mesma pasta django2-pythonclub .

Agora vamos criar a app bands, mas vamos deixar esta app dentro da pasta myproject. Então entre na pasta

$ cd myproject

e digite

$ python ../manage.py startapp bands

A intenção é que os arquivos tenham a seguinte hierarquia nas pastas:

.
├── manage.py
├── myproject
│   ├── bands
│   │   ├── admin.py
│   │   ├── apps.py
│   │   ├── models.py
│   │   ├── tests.py
│   │   └── views.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── requirements.txt

Agora permaneça sempre na pasta django2-pythonclub

cd ..

e digite

$ python manage.py migrate

para criar a primeira migração (isto cria o banco de dados SQLite), e depois rode a aplicação com

$ python manage.py runserver

e veja que a aplicação já está funcionando. Veja o endereço da url aqui

Django version 2.2.2, using settings 'myproject.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

Editando settings.py

Em INSTALLED_APPS acrescente as linhas abaixo.

INSTALLED_APPS = (
    ...
    'widget_tweaks',
    'django_extensions',
    'myproject.bands',
)

E mude também o idioma.

LANGUAGE_CODE = 'pt-br'

E caso você queira o mesmo horário de Brasília-BR

TIME_ZONE = 'America/Sao_Paulo'

Já que falamos do python-decouple, precisamos de mais alguns ajustes

from decouple import config, Csv

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = config('SECRET_KEY')

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = config('DEBUG', default=False, cast=bool)

ALLOWED_HOSTS = config('ALLOWED_HOSTS', default=[], cast=Csv())

Veja que é importante manter sua SECRET_KEY bem guardada (em outro lugar).

Então crie um arquivo .env e guarde sua SECRET_KEY dentro dele, exemplo:

SECRET_KEY=your_secret_key
DEBUG=True
ALLOWED_HOSTS=127.0.0.1,.localhost

Editando models.py

from django.db import models
from django.urls import reverse_lazy


class Band(models.Model):

    """A model of a rock band."""
    name = models.CharField(max_length=200)
    can_rock = models.BooleanField(default=True)

    class Meta:
        ordering = ('name',)
        verbose_name = 'band'
        verbose_name_plural = 'bands'

    def __str__(self):
        return self.name

    def get_absolute_url(self):
        # retorna a url no formato /bands/1/
        return reverse_lazy('band_detail', kwargs={'pk': self.pk})

    def get_members_count(self):
        # count members by band
        # conta os membros por banda
        return self.band.count()


class Member(models.Model):

    """A model of a rock band member."""
    name = models.CharField("Member's name", max_length=200)
    instrument = models.CharField(choices=(
        ('g', "Guitar"),
        ('b', "Bass"),
        ('d', "Drums"),
        ('v', "Vocal"),
        ('p', "Piano"),
    ),
        max_length=1
    )

    band = models.ForeignKey("Band", related_name='band', on_delete=models.CASCADE)

    class Meta:
        ordering = ('name',)
        verbose_name = 'member'
        verbose_name_plural = 'members'

    def __str__(self):
        return self.name

Tem algumas coisas que eu não estou explicando aqui para o tutorial ficar curto, mas uma coisa importante é que, como nós editamos o models.py vamos precisar criar um arquivo de migração do novo modelo. Para isso digite

python manage.py makemigrations
python manage.py migrate

O primeiro comando cria o arquivo de migração e o segundo o executa, criando as tabelas no banco de dados.

Editando urls.py

from django.urls import include, path
from myproject.bands import views as v
from django.contrib import admin

app_name = 'bands'

urlpatterns = [
    path('', v.home, name='home'),
    # path('bands/', v.band_list, name='bands'),
    # path('bands/<int:pk>/', v.band_detail, name='band_detail'),
    # path('bandform/', v.BandCreate.as_view(), name='band_form'),
    # path('memberform/', v.MemberCreate.as_view(), name='member_form'),
    # path('contact/', v.band_contact, name='contact'),
    # path('protected/', v.protected_view, name='protected'),
    # path('accounts/login/', v.message),
    path('admin/', admin.site.urls),
]

Obs: deixei as demais urls comentada porque precisa da função em views.py para que cada url funcione. Descomente cada url somente depois que você tiver definido a função em classe em views.py a seguir.

Editando views.py

from django.shortcuts import render
from django.http import HttpResponse
from django.contrib.auth.decorators import login_required
from django.views.generic import CreateView
from django.urls import reverse_lazy
from .models import Band, Member
# from .forms import BandContactForm, BandForm, MemberForm

Obs: Deixei a última linha comentada porque ainda não chegamos em forms.

A função a seguir retorna um HttpResponse, ou seja, uma mensagem simples no navegador.

def home(request):
    return HttpResponse('Welcome to the site!')

A próxima função (use uma ou outra) renderiza um template, uma página html no navegador.

def home(request):
    return render(request, 'home.html')

A função band_list retorna todas as bandas.

Para fazer a busca por nome de banda usamos o comando search = request.GET.get('search_box'), onde search_box é o nome do campo no template band_list.html.

E os nomes são retornados a partir do comando bands = bands.filter(name__icontains=search). Onde icontains procura um texto que contém a palavra, ou seja, você pode digitar o nome incompleto (ignora maiúsculo ou minúsculo).

def band_list(request):
    """ A view of all bands. """
    bands = Band.objects.all()
    search = request.GET.get('search_box')
    if search:
        bands = bands.filter(name__icontains=search)
    return render(request, 'bands/band_list.html', {'bands': bands})

Em urls.py pode descomentar a linha a seguir:

path('bands/', v.band_list, name='bands'),

A função band_contact mostra como tratar um formulário na view. Esta função requer BandContactForm, explicado em forms.py.

def band_contact(request):
    """ A example of form """
    if request.method == 'POST':
        form = BandContactForm(request.POST)
    else:
        form = BandContactForm()
    return render(request, 'bands/band_contact.html', {'form': form})

Em urls.py pode descomentar a linha a seguir:

path('contact/', v.band_contact, name='contact'),

A função band_detail retorna todos os membros de cada banda, usando o pk da banda junto com o comando filter em members.

def band_detail(request, pk):
    """ A view of all members by bands. """
    band = Band.objects.get(pk=pk)
    members = Member.objects.all().filter(band=band)
    context = {'members': members, 'band': band}
    return render(request, 'bands/band_detail.html', context)

Em urls.py pode descomentar a linha a seguir:

path('bands/<int:pk>/', v.band_detail, name='band_detail'),

BandCreate e MemberCreate usam o Class Based View para tratar formulário de uma forma mais simplificada usando a classe CreateView. O reverse_lazy serve para tratar a url de retorno de página.

As classes a seguir requerem BandForm e MemberForm, explicado em forms.py.

class BandCreate(CreateView):
    model = Band
    form_class = BandForm
    template_name = 'bands/band_form.html'
    success_url = reverse_lazy('bands')


class MemberCreate(CreateView):
    model = Member
    form_class = MemberForm
    template_name = 'bands/member_form.html'
    success_url = reverse_lazy('bands')

Em urls.py pode descomentar a linha a seguir:

path('bandform/', v.BandCreate.as_view(), name='band_form'),
path('memberform/', v.MemberCreate.as_view(), name='member_form'),

A próxima função requer que você entre numa página somente quando estiver logado.

[@login_required](https://docs.djangoproject.com/en/2.2/topics/auth/default/#the-login-required-decorator) é um decorator.

login_url='/accounts/login/' é página de erro, ou seja, quando o usuário não conseguiu logar.

E render(request, 'bands/protected.html',... é página de sucesso.

@login_required(login_url='/accounts/login/')
def protected_view(request):
    """ A view that can only be accessed by logged-in users """
    return render(request, 'bands/protected.html', {'current_user': request.user})

HttpResponse retorna uma mensagem simples no navegador sem a necessidade de um template.

def message(request):
    """ Message if is not authenticated. Simple view! """
    return HttpResponse('Access denied!')

Em urls.py pode descomentar a linha a seguir:

path('protected/', v.protected_view, name='protected'),
path('accounts/login/', v.message),

Comandos básicos do manage.py

Para criar novas migrações com base nas alterações feitas nos seus modelos

$ python manage.py makemigrations bands

Obs: talvez dê erro porque está faltando coisas de forms.py, explicado mais abaixo.

Para aplicar as migrações

$ python manage.py migrate

Para criar um usuário e senha para o admin

$ python manage.py createsuperuser

Para rodar a aplicação localmente

$ python manage.py runserver

Após criar um super usuário você pode entrar em localhost:8000/admin

Obs: Se você entrar agora em localhost:8000 vai faltar o template home.html. Explicado mais abaixo.

shell_plus

É o interpretador interativo do python rodando via terminal direto na aplicação do django.

Com o comando a seguir abrimos o shell do Django.

$ python manage.py shell

Mas se você está usando o django-extensions (mostrei como configurá-lo no settings.py), então basta digitar

$ python manage.py shell_plus

Veja a seguir como inserir dados direto pelo shell.

>>> from myproject.bands.models import Band, Member
>>> # Com django-extensions não precisa fazer o import
>>> # criando o objeto e salvando
>>> band = Band.objects.create(name='Metallica')
>>> band.name
>>> band.can_rock
>>> band.id
>>> # criando uma instancia da banda a partir do id
>>> b = Band.objects.get(id=band.id)
>>> # criando uma instancia do Membro e associando o id da banda a ela
>>> m = Member(name='James Hetfield', instrument='b', band=b)
>>> m.name
>>> # retornando o instrumento
>>> m.instrument
>>> m.get_instrument_display()
>>> m.band
>>> # salvando
>>> m.save()
>>> # listando todas as bandas
>>> Band.objects.all()
>>> # listando todos os membros
>>> Member.objects.all()
>>> # criando mais uma banda
>>> band = Band.objects.create(name='The Beatles')
>>> band = Band.objects.get(name='The Beatles')
>>> band.id
>>> b = Band.objects.get(id=band.id)
>>> # criando mais um membro
>>> m = Member(name='John Lennon', instrument='v', band=b)
>>> m.save()
>>> # listando tudo novamente
>>> Band.objects.all()
>>> Member.objects.all()
>>> exit()

Criando os templates

Você pode criar os templates com os comandos a seguir...

$ mkdir -p myproject/bands/templates/bands
$ touch myproject/bands/templates/{menu,base,home}.html
$ touch myproject/bands/templates/bands/{band_list,band_detail,band_form,band_contact,member_form,protected}.html

... ou pegar os templates já prontos direto do Github.

mkdir -p myproject/bands/templates/bands
wget https://raw.githubusercontent.com/rg3915/django2-pythonclub/master/myproject/bands/templates/base.html -P myproject/bands/templates/
wget https://raw.githubusercontent.com/rg3915/django2-pythonclub/master/myproject/bands/templates/home.html -P myproject/bands/templates/
wget https://raw.githubusercontent.com/rg3915/django2-pythonclub/master/myproject/bands/templates/menu.html -P myproject/bands/templates/
wget https://raw.githubusercontent.com/rg3915/django2-pythonclub/master/myproject/bands/templates/bands/band_contact.html -P myproject/bands/templates/bands/
wget https://raw.githubusercontent.com/rg3915/django2-pythonclub/master/myproject/bands/templates/bands/band_detail.html -P myproject/bands/templates/bands/
wget https://raw.githubusercontent.com/rg3915/django2-pythonclub/master/myproject/bands/templates/bands/band_form.html -P myproject/bands/templates/bands/
wget https://raw.githubusercontent.com/rg3915/django2-pythonclub/master/myproject/bands/templates/bands/band_list.html -P myproject/bands/templates/bands/
wget https://raw.githubusercontent.com/rg3915/django2-pythonclub/master/myproject/bands/templates/bands/member_form.html -P myproject/bands/templates/bands/
wget https://raw.githubusercontent.com/rg3915/django2-pythonclub/master/myproject/bands/templates/bands/protected.html -P myproject/bands/templates/bands/

forms.py

$ touch myproject/bands/forms.py

Edite o forms.py.

from django import forms
from .models import Band, Member


class BandContactForm(forms.Form):
    subject = forms.CharField(max_length=100)
    message = forms.CharField(widget=forms.Textarea)
    sender = forms.EmailField()
    cc_myself = forms.BooleanField(required=False)


class BandForm(forms.ModelForm):

    class Meta:
        model = Band
        fields = '__all__'


class MemberForm(forms.ModelForm):

    class Meta:
        model = Member
        fields = '__all__'

Lembra que eu deixei o código comentado em views.py?

Descomente ele por favor

from .forms import BandContactForm, BandForm, MemberForm

admin.py

Criamos uma customização para o admin onde em members aparece um filtro por bandas.

from django.contrib import admin
from .models import Band, Member


class MemberAdmin(admin.ModelAdmin):
    """Customize the look of the auto-generated admin for the Member model."""
    list_display = ('name', 'instrument')
    list_filter = ('band',)


admin.site.register(Band)  # Use the default options
admin.site.register(Member, MemberAdmin)  # Use the customized options

Carregando dados de um CSV

Vamos baixar alguns arquivos para criar os dados no banco a partir de um CSV.

wget https://raw.githubusercontent.com/rg3915/django2-pythonclub/master/create_data.py
mkdir fix
wget https://raw.githubusercontent.com/rg3915/django2-pythonclub/master/fix/bands.csv -P fix/
wget https://raw.githubusercontent.com/rg3915/django2-pythonclub/master/fix/members.csv -P fix/

Estando na pasta principal, rode o comando

python create_data.py

que ele vai carregar alguns dados pra você.

Veja o código de create_data.py.

Veja o código completo em https://github.com/rg3915/django2-pythonclub

git clone https://github.com/rg3915/django2-pythonclub.git

por Regis da Silva em 25 de June de 2019 às 01:00

April 15, 2019

Thiago Avelino

Formando desenvolvedores de alta performance

Estou a mais de 1 ano treinando para meu primeiro triathlon (IRONMAN 70.3) e nos últimos 7 meses treinando com time de alta performance que faz triathlon profissionalmente a muitos anos. O ano de 2018 foi um ano de muito aprendizado em uma área que nunca imaginei que entraria, para contextualizar segue o conteúdo abaixo: 1. Pivotei minha carreira profissional para área de #esporte 2. Estou escrevendo o meu primeiro #livro, minha saída de 180kg a treinar para meu primeiro #ironman (#Triathlon)

15 de April de 2019 às 00:00

April 12, 2019

Bruno Cezar Rocha

from dynaconf import settings

Often when starting a new Python project we need to spend some time thinking about how to manage the settings, decide on which module the configuration manager will be written, decide which name to give to this module, create a class or function to store the configuration keys, create the conditions for multiple environments and still need to worry about where these keys will be stored and in which file format?

No more! now you have Dynaconf!

Spend your precious time developing your application, run pip install dynaconf and let Dynaconf take care of your settings.

Quick start.

from dynaconf import settings

And that's it!

That is the only line of code you need, no complicated boilerplate, no hadouken-ifs, no need to maintain config classes.

You must be wondering - "What magic is this? Where does the setting values come from?"

Well, there is no magic, and the values can come from wherever you want, by default and following the recommendations of the 12 factor apps Dynaconf has preference for environment variables.

# optionally you can save it in .env file
export DYNACONF_DEBUG=true
export DYNACONF_NAME=Bruno
# app.py
from dynaconf import settings
if settings.DEBUG is True:
    print(settings.NAME)
$ python3 app.py
Bruno

And the environment variables for Dynaconf are typed using the toml format sotrue has been evaluated to boolean True and this makes it possible to export lists, dictionaries, floats, booleans, and so on.

Read more about envvars

More than environment variables

Well, that's cool, but your project will not have settings coming from just the environment variables, I'm sure you want to have a settings file where you can set default values.

Dynaconf can read multiple file formats, out of the box it supports .py, .toml, .ini and .json. If PyYAML is installed then it will also support .yaml and you don't have to take care of finding and opening the files. The preferred format is .toml because it is currently the best configuration format, widely addopted, and you can use whatever file format you want.

# settings.toml
[default]
name = "Bruno"

[development]
debug = true

[production]
debug = false
# app.py
from dynaconf import settings
if settings.DEBUG is True:
    print(settings.NAME)
$ python3 app.py
Bruno

And as you can see now using settings. file we can have separate [environments] by default dynaconf will always work on [development] which means only [default] and [development] variables will be loaded. At any time you can do export ENV_FOR_DYNACONF=production and then it starts using the values from [production] environment.

If you don't want to have that separation by environment, you can simply put everything under [default] section.

Read more about environments and settings file

Some values are secrets

A good practice is to not store your secrets like passwords and tokens directly on settings files, because you can make a mistake and commit that to a public git repository, so there are some alternatives to store secrets

Environment Variables

Not recommended

There are some people who disagrees and it is really a point of security failure. However, if you are sure that your machine is protected, you can leave the secrets in the variables, at your own risk, Dynaconf can read it normally.

Secret files

This is a simple level of security for keeping secrets, and it is specially useful to keep development secrets. That token you use to access the development API etc.

It is very simple, together with your normal settings.toml you put a new file called .secrets.toml and store your sensitive data there. Dynaconf will read it after the read of the settings.toml

Wait.. how does it solve my security problem?

Well it does not (yet) but it make your life easier in 2 ways.

  1. Put .secrets.* in your ~/.gitignore so you will never commit the mistake of sending that data to a public git repository.
  2. Dynaconf can output debug information when DEBUG_LEVEL_FOR_DYNACON=DEBUG is exported, all loaded values are printed but if the values comes from a .secrets.* file, then only the key is printed and the value is masked. It is useful to use on public CI.
  3. You can setup a step on your Ansible deployment playbook that will safely copy or generate the secrets file to store there on your production environment.

You can also tell Dynaconf to load that file from somewhere else export SECRETS_FOR_DYNACONF=/path/to/secrets/location/.secrets.yaml (very useful for CI like Jenkins)

Vault Project from Hashicorp

Recommended!

Now we are really talking about true security

Using Vault is the better way to protect your secrets dynaconf has built-in support:

export VAULT_ENABLED_FOR_DYNACONF=true
export VAULT_URL_FOR_DYNACONF=https://..../
export OTHER_VAULT_CONFIGS

And then if have for example the TOKEN stores on your vault server you can simply do:

from dynaconf import settings
perform_your_authentication(settings.TOKEN)

Vault has lots of features like leases and sealed vaults.

Read More

Are you using Django or Flask?

Dynaconf provides extensions for those 2 frameworks, with 2 lines of code you enable it and then your framework will start reading settings from Dynaconf.

Django

# settings.py
import dynaconf  # noqa
settings = dynaconf.DjangoDynaconf(__name__, **options)

Now you if you do export DJANGO_FOO=BAR you can access inside your app via django.conf.settings.FOO

read more

Flask

# app.py
from dynaconf import FlaskDynaconf
FlaskDynaconf(app, **options)

Now you if you do export FLASK_FOO=BAR you can access inside your app via app.config['FOO']

read more

What if you are using a different settings file format? a different framework and a different external storage?

You can extend Dynaconf adding new loaders!

Dynaconf already provides loaders for:

  • .py
  • .json
  • .yaml
  • .toml
  • .ini
  • Redis Server
  • Vault Server
  • .env files
  • Environment variables

But if this is not a fit for your project you can still create your own loader

Conclusion

Dynaconf is the only thing you need to manage your settings!

  • Well tested
  • Trusted by companies like Red Hat, Seek, Catho and others
  • Well tested both on Linux and Windows environment
  • Strict separation of settings from code (following 12-factor applications Guide).
  • Define comprehensive default values.
  • Store parameters in multiple file formats (.toml, .json, .yaml, .ini and .py).
  • Sensitive secrets like tokens and passwords can be stored in safe places like .secrets file or vault server.
  • Parameters can optionally be stored in external services like Redis server.
  • Simple feature flag system.
  • Layered [environment] system.
  • Environment variables can be used to override parameters.
  • Support for .env files to automate the export of environment variables.
  • Correct data types (even for environment variables).
  • Have only one canonical settings module to rule all your instances.
  • Drop in extension for Flask app.config object.
  • Drop in extension for Django conf.settings object.
  • Powerful $ dynaconf CLI to help you manage your settings via console.
  • Customizable Validation System to ensure correct config parameters.
  • Allow the change of dynamic parameters on the fly without the need to redeploy your application.

Read the docs

Settings are simple but Dynaconf provides even more features like Feature Flags, Settings Context Managers, Plugin Settings etc..

Documentation: http://dynaconf.readthedocs.io/

Dynaconf is waiting for your feedback and Contribution

:)

from dynaconf import settings
settings.THANKS_FOR_READING

por Bruno Rocha em 12 de April de 2019 às 14:38

March 20, 2019

Osvaldo Santana Neto

How to create a variable in Python

Hello there, in this post we are going to learning about creating a variable in Python. The process is very simple like creating a variable in other languages but if you are new to programming don’t worry I’ll explain each step in details. What is Python variable: A Python variable is used to store some information/value that we can use in our program. It can be anything; a number, string, function, or a variable itself. Well, this is how a Python variable look like: website = "Pythonologia" Let me explain... Read More

por Deepak Jangra em 20 de March de 2019 às 03:14

March 10, 2019

Osvaldo Santana Neto

How to install LEMP stack on Digital Ocean

Hello and welcome everybody. I’m Deepak and today we are going to looking at How to install LEMP stack on Digital Ocean. Before installing LEMP stack on Digital Ocean you must have an Digital Ocean account. For creating the Digital Ocean account. Visit this link and sign up there by using this link you will get $100 free credit for 2 months that means you can use a live hosting for free for 2 months. Disclaimer: The link mentioned above is an affiliate link. It will help Pythonologia to continue... Read More

por Deepak Jangra em 10 de March de 2019 às 22:59

January 10, 2019

Rodrigo Delduca

Empreendendo sem dinheiro

Criei uma espécie de desafio mental, esse desafio consiste em resolver problemas já enfrentados ou de outras origens de forma criativa, em pouco tempo e se possível evolvendo pouco ou nenhum custo!

E o desafio da semana foi criar um daqueles projetos de “media indoor”.

Então pensei: “já sei vou usar grpc, s3 rsync, elastic transcoder, fastly, frontend do admin em react e é claro kubernetes!”

Já no cliente, que é responsável por tocar os vídeos…: “vou escrever em Qt, criar a interface em QML, usar boost.asio para o meu downloader e criar uma distribuição de Linux embarcado usando o yocto !“.

“The best code is no code at all.”

Painel administrativo

As pessoas, e desse ramo principalmente, estão acostumadas a usar planilhas para as mais variadas tarefas, então por que não usar uma planilha como “admin”?

Google Sheets

Envio, armazenamento, transcodificação e distribuição de vídeos

Ao invés de desenvolver um complexo sistema de gerenciamento de arquivos de vídeo, com transcodificação usando as ferramentas que citei acima, usando lambda e outras coisas, vamos usar o YouTube.

Quê?

É isso mesmo, no nosso protótipo vamos usar o YouTube, pois não tem nenhum custo e já faz a conversão e distribuição do vídeo nos mais variados formatos e tamanhos.

Atenção: De acordo com os termos de uso do YouTube não é permitido reproduzir o conteúdo da plataforma fora do player do youtube, o que estou demonstrando é apenas para fins educacionais.

O nosso work é playá

Nada mais do que um pequeno script em bash será necessário para executar as tarefas de baixar a playlist, os vídeos, a remoção de vídeos não mais usados entre outras coisas.

Já o player propriamente dito é o omxplayer, que é capaz de decodificar vídeos usando aceleração por hardware; omxplayer foi escrito especialmente para a GPU do Raspberry Pi e faz uso da API OpenMAX, é extremamente eficiente.

O trecho abaixo é de um apps script que transforma a primeira coluna da planilha num array de objetos e serializa a reposta num JSON.

function doGet(request) {
  var app = SpreadsheetApp;
  var worksheet = app.getActiveSpreadsheet();
  var sheet = worksheet.getSheetByName(request.parameters.sheet);
  if (sheet) {
    var range = sheet.getDataRange();
    var values = range.getValues();
    var headers = values.shift();
    var playlist = values.map(function (el) { return { url: el[0] }; });
    return ContentService.createTextOutput(JSON.stringify({ playlist: playlist }))
      .setMimeType(ContentService.MimeType.JSON);
  }
}

É possível publicar o script acima num endereço público e de acesso anônimo, de modo que seja possível baixar o JSON até mesmo pelo cURL, e é com essa reposta que iremos usar para saber quais arquivos baixar e gerar a playlist:

$ curl -sL "https://script.google.com/macros/s/${...}/exec?sheet=Sheet1" | jq
{
  "result": [
    {
      "url": "https://www.youtube.com/watch?v=..."
    },
    ...
  ]
}

Com uma simples entrada no cron é possível criar um agendamento para baixar a playlist de tempos em tempos:

*/30 * * * * user curl -sL "https://script.google.com/macros/s/${...}/exec?sheet=Sheet1" > playlists/1.json

A função download usa a ferramenta jq para gerar uma lista de urls a serem baixadas pelo youtube-dl que por sua vez executa um pequeno script (--exec) para adicionar o arquivo recém baixado para a playlist, tomando cuidado para não duplicar:

download() {
  cat playlists/*.json | jq '.[].url' \
    | xargs youtube-dl --exec "grep -sqxF '{}' $playlist || echo '{}' >> $playlist"
}

Alguns parâmetros do youtube-dl foram omitidos pois foram movidos para o arquivo de configuração global.

Com o entr é possível monitorar se algum arquivo foi modificado ou mesmo adicionado novos arquivos no diretório; se isso acontecer, a função download será chamada:

watch() {
  while :; do
    ls -d playlists/*.json | entr -d "$0" download
  done
}

De tempos em tempos é necessário remover os arquivos antigos e downloads incompletos; a função recycle remove todos os arquivos do tipo vídeo modificados pela última vez há mais de 7 dias e que não estão sendo usados:

A razão de ser alguns dias depois e não imediatamente é de ser maleável caso tenha sido algum equívoco.

recycle() {
  declare -a args=(
    -mtime +7
    -type f
  )

  while read -r uri; do
    args+=(-not -name "$uri")
  done <<< "$(cat $playlist)"

  find "$PWD" "${args[@]}" -exec bash -c "file -b --mime-type {} | grep -q ^video/" \; -delete
}

Todas essas funções podem ser chamadas inúmeras vezes sem efeitos indesejados.

Tocar a playlist é a parte mais fácil:

play() {
  setterm -cursor off

  export DISPLAY=":0.0"

  while :; do
    while read -r uri; do
      omxplayer --refresh --no-osd --no-keys "$uri"
      xrefresh -display :0
    done <<< "$(cat $playlist)"
  done
}

Graças ao omxplayer o consumo de CPU fica bem baixo, mesmo em 1080@60fps, algo em torno de ~0.5% num Raspberry 3.

O próximo passo é contabilizar algumas estatísticas, como o número de vezes que um vídeo foi tocado, se teve alguma interrupção por falta de energia ou por problemas técnicos, etc.

Para isso uma boa pedida é o papertrail, com essa ferramenta é possível centralizar todos os logs da máquina, exportar para o BigQuery e executar as consultas na mesma planilha que ficam os vídeos.

Ops… Acho que minha febre por cloud computing voltou :-)

Criei uma espécie de desafio mental, esse desafio consiste em resolver problemas já enfrentados ou de outras origens de forma criativa, em pouco tempo e se possível evolvendo pouco ou nenhum custo!

por Rodrigo Delduca (rodrigodelduca@gmail.com) em 10 de January de 2019 às 00:00

January 05, 2019

Gabbleblotchits

Scientific Rust #rust2019

The Rust community requested feedback last year for where the language should go in 2018, and now they are running it again for 2019. Last year I was too new in Rust to organize a blog post, but after an year using it I feel more comfortable writing this!

(Check my previous post about replacing the C++ core in sourmash with Rust for more details on how I spend my year in Rust).

What counts as "scientific Rust"?

Anything that involves doing science using computers counts as scientific programming. It includes from embedded software running on satellites to climate models running in supercomputers, from shell scripts running tools in a pipeline to data analysis using notebooks.

It also makes the discussion harder, because it's too general! But it is very important to keep in mind, because scientists are not your regular user: they are highly qualified in their field of expertise, and they are also pushing the boundaries of what we know (and this might need flexibility in their tools).

In this post I will be focusing more in two areas: array computing (what most people consider 'scientific programming' to be) and "data structures".

Array computing

This one is booming in the last couple of years due to industry interest in data sciences and deep learning (where they will talk about tensors instead of arrays), and has its roots in models running in supercomputers (a field where Fortran is still king!). Data tends to be quite regular (representable with matrices) and amenable to parallel processing.

A good example is the SciPy stack in Python, built on top of NumPy and SciPy. The adoption of the SciPy stack (both in academia and industry) is staggering, and many alternative implementations try to provide a NumPy-like API to try to capture its mindshare.

This is the compute-intensive side science (be it CPU or GPU/TPU), and also the kind of data that pushed CPU evolution and is still very important in defining policy in scientific computing funding (see countries competing for the largest supercomputers and measuring performance in floating point operations per second).

Data structures for efficient data representation

For data that is not so regular the situation is a bit different. I'll use bioinformatics as an example: the data we get out of nucleotide sequencers is usually represented by long strings (of ACGT), and algorithms will do a lot of string processing (be it building string-overlap graphs for assembly, or searching for substrings in large collections). This is only one example: there are many analyses that will work with other types of data, and most of them don't have a universal data representation as in the array computing case.

This is the memory-intensive science, and it's hard to measure performance in floating point operations because... most of the time you're not even using floating point numbers. It also suffers from limited data locality (which is almost a prerequisite for compute-intensive performance).

High performance core, interactive API

There is something common in both cases: while performance-intensive code is implemented in C/C++/Fortran, users usually interact with the API from other languages (especially Python or R) because it's faster to iterate and explore the data, and many of the tools already available in these languages are very helpful for these tasks (think Jupyter/pandas or RStudio/tidyverse). These languages are used to define the computation, but it is a lower-level core library that drives it (NumPy or Tensorflow follow this idea, for example).

How to make Rust better for science?

The biggest barrier to learning Rust is the ownership model, and while we can agree it is an important feature it is also quite daunting for newcomers, especially if they don't have previous programming experience and exposure to what bugs are being prevented. I don't see it being the first language we teach to scientists any time soon, because the majority of scientists are not system programmers, and have very different expectations for a programming language. That doesn't mean that they can't benefit from Rust!

Rust is already great for building the performance-intensive parts, and thanks to Cargo it is also a better alternative for sharing this code around, since they tend to get 'stuck' inside Python or R packages. And the 'easy' approach of vendoring C/C++ instead of having packages make it hard to keep track of changes and doesn't encourage reusable code.

And, of course, if this code is Rust instead of C/C++ it also means that Rust users can use them directly, without depending on the other languages. Seems like a good way to bootstrap a scientific community in Rust =]

What I would like to see in 2019?

An attribute proc-macro like #[wasm_bindgen] but for FFI

While FFI is an integral part of Rust goals (interoperability with C/C++), I have serious envy of the structure and tooling developed for WebAssembly! (Even more now that it works in stable too)

We already have #[no_mangle] and pub extern "C", but they are quite low-level. I would love to see something closer to what wasm-bindgen does, and define some traits (like IntoWasmAbi) to make it easier to pass more complex data types through the FFI.

I know it's not that simple, and there are different design restrictions than WebAssembly to take into account... The point here is not having the perfect solution for all use cases, but something that serves as an entry point and helps to deal with the complexity while you're still figuring out all the quirks and traps of FFI. You can still fallback and have more control using the lower-level options when the need rises.

More -sys and Rust-like crates for interoperability with the larger ecosystems

There are new projects bringing more interoperability to dataframes and tensors. While this ship has already sailed and they are implemented in C/C++, it would be great to be a first-class citizen, and not reinvent the wheel. (Note: the arrow project already have pretty good Rust support!)

In my own corner (bioinformatics), the Rust-bio community is doing a great job of wrapping useful libraries in C/C++ and exposing them to Rust (and also a shout-out to 10X Genomics for doing this work for other tools while also contributing to Rust-bio!).

More (bioinformatics) tools using Rust!

We already have great examples like finch and yacrd, since Rust is great for single binary distribution of programs. And with bioinformatics focusing so much in independent tools chained together in workflows, I think we can start convincing people to try it out =]

A place to find other scientists?

Another idea is to draw inspiration from rOpenSci and have a Rust equivalent, where people can get feedback about their projects and how to better integrate it with other crates. This is quite close to the working group idea, but I think it would serve more as a gateway to other groups, more focused on developing entry-level docs and bringing more scientists to the community.

Final words

In the end, I feel like this post ended up turning into my 'wishful TODO list' for 2019, but I would love to find more people sharing these goals (or willing to take any of this and just run with it, I do have a PhD to finish! =P)

Comments?

por luizirber em 05 de January de 2019 às 19:00

Filipe Saraiva

LaKademy 2018

Em outubro de 2018, Florianópolis foi sede da sexta edição do LaKademy, o sprint latinoamericano do KDE. Esse momento é uma oportunidade para termos em um mesmo lugar vários desenvolvedores do KDE – tanto veteranos quanto novatos – de diferentes projetos para melhorarem os respectivos softwares em que trabalham e também planejar as ações de promoção da comunidade para o subcontinente.

Na parte técnica, eu trabalhei com Cantor, Sprat, e nos sites do KDE Brasil e LaKademy.

Para o Cantor, eu pesquisei algumas novas maneiras de implementar os backends, em especial quanto a utilização de websockets. Essa é uma ideia antiga que tenta encontrar uma abordagem a ser recomendada para implementação desses backends de forma que possam ser utilizados para qualquer linguagem de programação e funcionem em qualquer plataforma. Entretanto, como nas tentativas anteriores, ainda tenho dúvidas se essa é uma maneira interessante e se os objetivos podem ser atingidos por ela. Enfim, é algo que precisa de mais pesquisa.

Sprat é um editor de texto direcionado para a escrita de artigos científicos. O software implementa a metodologia Amadeus para escrita de artigos, e é mais como uma coleção de sentenças comuns que podem ser utilizadas in seções específicas do artigo. Sprat é meu projeto-pet, e espero lançar esse ano além de transformá-lo em um projeto do KDE.

O site do KDE Brasil uma uma antiga versão do Drupal. Eu e Fred pesquisamos alguns plugins para importar o conteúdo desse site para o WordPress, e atualmente estamos estudando como realizar essa tarefa.

Por último, portei o site do LaKademy para Jekyll. Isso é algo que ainda precisa de algum trabalho, e espero lançá-lo o quanto antes.

Na parte social, discutimos algumas atividades para o KDE nesse ano, como voltar a participar do FISL e Latinoware, tentar comparecer a outros eventos na América Latina (DebConf e Cubaconf, estamos olhando pra vocês), organizar o “Café com Qt” (nosso evento distribuído sobre Qt e KDE), feedbacks sobre o gerenciamento do nosso grupo do KDE Brasil no Telegram, nossos novos materiais promocionais para serem produzidos e distribuídos nos eventos daqui, e mais.

Ainda nesse aspecto, também ajudei os novatos no trabalho de revisão de código do KDE e tirando dúvidas sobre Qt.

LaKademy é uma grande oportunidade para encontrar outros desenvolvedores do KDE e trabalharmos juntos para aumentar nossa comunidade. Nos últimos anos, o KDE assumiu um papel de importância na comunidade brasileira, e estamos planejando expandi-la para diferentes países. Esperamos organizar o próximo LaKademy em algum outro país fora do Brasil, e trabalharemos forte para expandir a comunidade no subcontinente.

Foto em grupo do LaKademy 2018

Nos vemos no LaKademy 2019!

por Filipe Saraiva em 05 de January de 2019 às 17:43

January 02, 2019

Blog do PauloHRPinheiro

Feature toggles com django-waffle

Feature toggles: ativando e desativando comportamentos em um sistema sem alterar o código, usando django-waffle.

02 de January de 2019 às 00:00

December 27, 2018

Rodrigo Delduca

Blobs, blurbs, bubbles…

TL;DR Usar o SQLite ao invés do sistema de arquivos para armazenar em forma de blob os assets do jogo pode ser uma ótima ideia.

Dia desses estava lendo SQLite As An Application File Format o que me fez lembrar de quando eu lia muito a respeito de desenvolvimento de jogos, até cheguei a desenvolver um framework chamado Wintermoon, no meu framework eu usei o PhysicsFS foi quando descobri o MPQ e fiquei encantado.

Mo’PaQ

O MPQ é (ou era) amplamente utilizado em praticamente todos os jogos da Blizzard, desde o Diablo (1997) até o StarCraft 2 (2010). Inclusive o StarCraft 2 recebe atualizações até hoje, e quase que mensalmente desde seu lançamento! Digo isto para dar um contexto de onde quero chegar.

O MPQ leva o nome de seu criador, e surgiu devido há alguns requerimentos da época, como segurança, acesso rápido, compressão, expansibilidade e multi-linguagem.

Atualmente alguns requerimentos mencionados não fazem muito sentido, porém estamos falando de uma época onde o principal sistema de arquivos onde esses títulos rodavam era o FAT32.

PhysicsFS

Sempre gostei da ideia de empacotar os assets do jogo num único arquivo comprimido. O PhysicsFS permite “montar” diretórios e arquivos comprimidos como se fossem um único diretório, com todos os arquivos estruturados dentro dos seus respectivos diretórios; algo semelhante ao que o UnionFS, OverlayFS e similares fazem.

Outra vantagem é a segurança, pois o processo fica restrito à aquele(s) diretório(s) previamente especificado(s).

Usar o physfs com a SDL é bem simples, veja como é o processo de montar um arquivo comprimido e carregar uma imagem:

int main(int argc, char *argv[]) {
  PHYSFS_init(argv[0]);

  SDL_Init(SDL_INIT_VIDEO);

  // monta o arquivo `assets.7z` como se fosse um diretório.
  PHYSFS_mount("assets.7z", "/", 0);

  SDL_Window * window = SDL_CreateWindow(
    NULL, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_OPENGL | SDL_WINDOW_ALLOW_HIGHDPI);

  SDL_Renderer * renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);

  // carrega o arquivo `texture001.tga` que está dentro de `assets.7z`.
  SDL_RWops * rwops = PHYSFSRWOPS_openRead("texture001.tga");

  // carrega a textura.
  SDL_Surface * surface = IMG_Load_RW(rwops, 1);
  SDL_Texture * texture = SDL_CreateTextureFromSurface(renderer, surface);
  SDL_FreeSurface(surface);

  SDL_bool running = SDL_TRUE;
  while(running) {
    SDL_Event event;
    while (SDL_PollEvent(&event)) {
      if (event.type == SDL_QUIT) {
        running = SDL_FALSE;
      }
    }

    // desenha a textura na janela.
    SDL_RenderCopy(renderer, texture, NULL, NULL);
    SDL_RenderPresent(renderer);
    SDL_Delay(1000 / 60);
  }

  SDL_DestroyWindow(window);
  SDL_Quit();
  return 0;
}

Legal né?

Little Bobby Tables

O SQLite é provavelmente um dos componentes de software mais utilizados no mundo, está presente em todo o lugar; se estiver lendo esse texto num Android deve ter pelo menos umas 3 cópias dele na suas mãos! SQLite é como um fopen(3) com esteroides.

Lendo o texto que menciono no inicio do texto, penso “E se eu usar SQLite no lugar do PhysicsFS?”

DBA wanna be…

Embora o SQLite possua uma forma prática de ser fazer o que farei a seguir, o SQLite Archive Files, irei apresentar o passo a passo.

Primeiro vamos criar uma tabela com dois campos, um deles para indentificação e o outro com o conteúdo binario em si.

O SQLite (e a grande maioria dos bancos de dados) não suportam armazenar dados binários, para isso existe um tipo de dados especial chamado BLOB (Binary Large OBject).

sqlite3 assets.db "CREATE TABLE IF NOT EXISTS assets (key TEXT PRIMARY KEY, blob BLOB);"

E é isso. O campo key é uma chave primaria e portanto tem um índice próprio, como sei?

$ sqlite3 assets.db
SQLite version 3.24.0 2018-06-04 14:10:15
Enter ".help" for usage hints.
sqlite> .schema assets
CREATE TABLE assets (key TEXT PRIMARY KEY, blob BLOB);
sqlite> .indexes assets
sqlite_autoindex_assets_1

O próximo passo é inserir o arquivo da textura texture001.tga que será usada:

sqlite3 assets.db "INSERT INTO assets(key, blob) VALUES ('texture001', readfile('texture001.tga'));"

O SQLite tem uma função readfile que carrega o arquivo diretamente.

É possível verificar o tamanho do blob com a função length:

$ sqlite3 assets.db
SQLite version 3.24.0 2018-06-04 14:10:15
Enter ".help" for usage hints.
sqlite> select key, length(blob) from assets;
texture001|3686418

Que é exatamente o mesmo do arquivo original:

$ stat -f%z texture001.tga
3686418

Adaptando o exemplo acima para a API em C do SQLite temos:

sqlite3 * db;
// abre o arquivo do banco de dados do sqlite.
sqlite3_open("assets.db", &db);
// ...

// preparamos a query.
const char * sql = "SELECT blob FROM assets WHERE key = ?";
sqlite3_stmt * stmt;
sqlite3_prepare_v2(db, sql, -1, &stmt, 0);

// "atrela" o valor `texture001` no primeiro parâmetro do sql, o `?`.
sqlite3_bind_text(stmt, 1, "texture001", -1, SQLITE_STATIC);

// executa a query "SELECT blob FROM assets WHERE key = 'texture001'".
sqlite3_step(stmt);

// criamos um `SDL_RWops` com os bytes do blob.
int bytes = sqlite3_column_bytes(stmt, 0);
const void * buffer = sqlite3_column_blob(stmt, 0);
SDL_RWops * rwops = SDL_RWFromConstMem(buffer, (sizeof(unsigned char) * bytes));

// finaliza (responsável por liberar a memória retornada por sqlite3_column_blob e outros recursos.)
sqlite3_reset(stmt);

// (como anteriormente) carrega a textura.
SDL_Surface * surface = IMG_Load_RW(rwops, 1);
SDL_Texture * texture = SDL_CreateTextureFromSurface(renderer, surface);
SDL_FreeSurface(surface);

Benchmarks, é disso que o povo gosta!

Usando a função SDL_GetPerformanceFrequency para mensurar o trecho responsável apenas por carregar a textura obtive os seguintes resultados:

$ file texture001.tga
texture001.tga: Targa image data - RGB 1280 x 960 x 24
$ ls -lh texture001.tga | awk '{print $5}'
3.5M
PhysicsFS (gzip compressed)
for i in {1..10}; do ./physfs; done
42.060247
40.972251
38.589466
40.684438
43.327696
38.578994
...
SQLite
for i in {1..10}; do ./sqlite; done
27.433850
30.553595
27.706754
27.282197
27.561867
27.853982
...
IMG_Load("texture001.tga") (A.K.A. diretamente)
for i in {1..10}; do ./a.out; done
22.792655
23.667172
22.286974
23.551452
22.094010
23.657177
...

Acredito que se utilizado compressão no SQLite o uso de disco seria reduzido e como consequência resultados ainda melhores.

Patches everywhere!

metalhead with lots of patches

Uma das principais características do software é que ele não funciona e precisa constantemente ser remendado, e nos jogos não é diferente.

O MPQ tem um mecanismo de patches, como na época a maioria dos jogos eram distribuídas em mídias somente leitura, como o CD-ROM, era preciso uma outra abordagem, já que não era possível reescrever o .mpq original, portanto era criado uma espécie de corrente, então após o jogo carregar, as alterações eram aplicadas em cima, na mesma sequencia de que foram publicadas.

A ideia por trás de usar o SQLite no lugar do PhysicsFS é de aproveitar algumas características de um banco de dados, que é de… criar, atualizar, modificar e deletar de forma atômica!

O arquivo de update do jogo poderia ser um conjunto de instruções SQL.

Vamos desconsiderar o binário do jogo por hora, e vamos supor que uma nova textura foi adicionada no banco de dados do desenvolvedor, e por algum motivo desconhecido ele é preguiçoso e usou a ferramenta sqldiff para gerar o patch e não schema migration.

sqlite3 assets.db "INSERT INTO assets(key, blob) VALUES ('texture002', readfile('texture002.jpg'));"

Estou usando texturas como exemplo pois geralmente é o tipo de arquivo que ocupa mais espaço em disco dos jogos. O exemplo vale para qualquer tipo de arquivo… seja textos, scripts, shaders, etc.

$ sqldiff old.db assets.db > patch01.sql
$ # checando o conteúdo da atualização.
$ head -c 100 up.sql
INSERT INTO assets(rowid,"key", blob) VALUES(2,'texture002',x'ffd8ffe000104a46494600010100000100010%
$ ls -lh patch01.sql | awk '{print $5}'
663K
$ tar -cvzf patch01.tgz patch01.sql
$ ls -lh patch01.tgz | awk '{print $5}'
363K

Como se trata de um arquivo .jpeg representado em hexadecimal dentro de um .sql os ganhos com compressão são pequenos.

Agora basta a nossa ferramenta responsável por atualizar o jogo aplicar os patches na mesma sequencia que foram gerados.

Essa é uma forma bem simples e descomplicada de atualizar o jogo e é algo bem resolvido no mundo dos banco de dados há décadas.

É possível criar updates ainda menores, o Google Chrome tem um projeto chamado courgette que usa a ferramenta bsdiff combinada com um outro algoritmo descrito no link, podemos usar o bsdiff para gerar o patch do asset a ser atualizado e no cliente usar o bspatch para aplicar a modificação.

Além de todas essas vantagens, o uso do SQLite ainda possibilita o data-driven programming.

Winterphobos

Pretendo utilizar o SQLite como descrito num novo projeto chamado Winterphobos, um motor de jogos minimalista, e uma das premissas é ser totalmente “scriptável” em lua com entity–component–system .

vault boy

TL;DR Usar o SQLite ao invés do sistema de arquivos para armazenar em forma de blob os assets do jogo pode ser uma ótima ideia.

por Rodrigo Delduca (rodrigodelduca@gmail.com) em 27 de December de 2018 às 00:00

November 29, 2018

PythonClub

Algoritmos de Ordenação

Fala pessoal, tudo bom?

Nos vídeos abaixo, vamos aprender como implementar alguns dos algoritmos de ordenação usando Python.

Bubble Sort

Como o algoritmo funciona: Como implementar o algoritmo usando Python: https://www.youtube.com/watch?v=Doy64STkwlI.

Como implementar o algoritmo usando Python: https://www.youtube.com/watch?v=B0DFF0fE4rk.

Código do algoritmo

def sort(array):

    for final in range(len(array), 0, -1):
        exchanging = False

        for current in range(0, final - 1):
            if array[current] > array[current + 1]:
                array[current + 1], array[current] = array[current], array[current + 1]
                exchanging = True

        if not exchanging:
            break

Selection Sort

Como o algoritmo funciona: Como implementar o algoritmo usando Python: https://www.youtube.com/watch?v=vHxtP9BC-AA.

Como implementar o algoritmo usando Python: https://www.youtube.com/watch?v=0ORfCwwhF_I.

Código do algoritmo

def sort(array):
    for index in range(0, len(array)):
        min_index = index

        for right in range(index + 1, len(array)):
            if array[right] < array[min_index]:
                min_index = right

        array[index], array[min_index] = array[min_index], array[index]

Insertion Sort

Como o algoritmo funciona: Como implementar o algoritmo usando Python: https://www.youtube.com/watch?v=O_E-Lj5HuRU.

Como implementar o algoritmo usando Python: https://www.youtube.com/watch?v=Sy_Z1pqMgko.

Código do algoritmo

def sort(array):
    for p in range(0, len(array)):
        current_element = array[p]

        while p > 0 and array[p - 1] > current_element:
            array[p] = array[p - 1]
            p -= 1

        array[p] = current_element

Merge Sort

Como o algoritmo funciona: Como implementar o algoritmo usando Python: https://www.youtube.com/watch?v=Lnww0ibU0XM.

Como implementar o algoritmo usando Python - Parte I: https://www.youtube.com/watch?v=cXJHETlYyVk.

Código do algoritmo

def sort(array):
    sort_half(array, 0, len(array) - 1)


def sort_half(array, start, end):
    if start >= end:
        return

    middle = (start + end) // 2

    sort_half(array, start, middle)
    sort_half(array, middle + 1, end)

    merge(array, start, end)


def merge(array, start, end):
    array[start: end + 1] = sorted(array[start: end + 1])

por Lucas Magnum em 29 de November de 2018 às 15:10

November 22, 2018

Blog do PauloHRPinheiro

Teste de carga e desempenho

Testando a capacidade e desempenho de uma API com o framework Locust, em Python

22 de November de 2018 às 00:00

October 21, 2018

Thiago Avelino

A arte de reescrever software

Lidar com software legado hoje em dia é mais comum do que podemos imaginar, costumo dizer que muitos softwares nascem legado, como assim? Para mim software que não tem teste automatizado é legado, não tem como garantir funcionamento de absolutamente nada dentro dele e muitos comportamentos (recursos ou bugs) só irá aparecer com usuários usando constantemente. Após alinhamento do que é software legado é comum a empresa (principalmente as com cultura de startup) e desenvolvedores ter que trocar peças do software em pleno o voo, não temos como pousar o avião para fazer manutenção e depois decolar novamente quando a empresa está com clientes usando o software em produção.

21 de October de 2018 às 00:00

October 06, 2018

PythonClub

Trabalhando com operadores ternários

Quando estamos escrevendo um código qualquer, possivelmente a expressão que mais utilizamos é o if. Para qualquer tarefas que buscamos automatizar ou problemas que buscamos resolver, sempre acabamos caindo em lógicas como "Se isso acontecer, então faça aquilo, senão faça aquele outro...".

Quando estamos falando de ações a serem executadas, pessoalmente gosto da forma com que o código fica organizado em python quando usamos este tipo de condições, por exemplo:

if vencer_o_thanos:
    restaurar_a_paz()

else:
    foo()

Graças a indentação e ao espaçamento, vemos onde onde começa e/ou termina o bloco executado caso a varável vencer_o_thanos seja True. Quanto mais if's você aninhar, mais bonito seu código fica e em momento algum o mesmo se torna mais confuso (ao menos, não deveria se tornar). Entretanto, sempre fico extremamente incomodado quando tenho de escrever um bloco apenas marcar uma variável, como por exemplo:

if vencer_o_thanos:
    paz = True

else:
    paz = False

Por isso, para trabalhar com variáveis que possuem um valor condicional, gosto sempre de trabalhar com expressões condicionais, ou como costumam ser chamadas, operadores ternários.

Operadores ternários são todos os operadores que podem receber três operandos. Como as expressões condicionais costumam ser os operadores ternários mais populares nas linguagens em que aparecem, acabamos por associar estes nomes e considerar que são a mesma coisa. Cuidado ao tirar este tipo de conclusão, mesmo que toda vogal esteja no alfabeto, o alfabeto não é composto apenas por vogais.

A estrutura de uma expressão condicional é algo bem simples, veja só:

paz = True if vencer_o_thanos else False
tipo_de_x = "Par" if x % 2 == 0 else "impar"

Resumidamente, teremos um valor seguido de uma condição e por fim seu valor caso a condição seja falsa. Pessoalmente acredito que apesar de um pouco diferente, essa forma de escrita para casos como o exemplificado acima é muito mais clara, mais explicita.

Se você fizer uma tradução literal das booleanas utilizadas no primeiro exemplo, lerá algo como paz é verdadeira caso vencer_o_thanos, caso contrário é Falsa. já o segundo exemplo fica mais claro ainda, pois lemos algo como tipo_de_x é par caso o resto da divisão de x por 2 seja 0, se não, tipo_de_x é impar..

Interpretar código dessa forma pode ser estranho para um programador. Interpretar uma abertura de chave ou uma indentação já é algo mas natural. Todavia, para aqueles que estão começando, o raciocínio ocorre de forma muito mais parecida com a descrita acima. Espero que tenham gostado do texto e que esse conhecimento lhes seja útil.

por Vitor Hugo de Oliveira Vargas em 06 de October de 2018 às 12:21

October 01, 2018

Bruno Cezar Rocha

Hacktoberfest 2018

Hacktoberfest 2018

Hacktoberfest is an amazing campaign by Digital Ocean and Github, you contribute with at least 5 open source Pull Requests and then you get a T-shirt and some stickers.

Maintainers are encouraged to label and organize the issues to be worked on.

Register at: https://hacktoberfest.digitalocean.com/

I will list here some of my Projects and the issues I am expecting to get some contributions.

Dynaconf

Dynaconf is a library for settings management in any kind of Python project.

Skills needed: CI, Python, decorators, Python Module Initialization, Data Structures and Python data Model

Issues: https://github.com/rochacbruno/dynaconf/issues

Highlights:

Flasgger

Flasgger is the project powering the http://httpbin.org website, it allows you to document your Flask API and serves Swagger UI.

Skills needed: API REST, Flask, OPenAPISpec, Decorators, Python data model.

Issues: https://github.com/rochacbruno/flasgger/issues
HIghlights:

Flask Google Maps

Easy way to add maps to Flask views.

Skills needed: Flask, Google APIs

Issues: https://github.com/rochacbruno/Flask-GoogleMaps

Flask Simple Login

Easy way to protect your Flask views with login.

Skills needed: Python, Flask, environment variables, templating, CSS, HTML, Bootstrap.

Issues: https://github.com/rochacbruno/flask_simplelogin/issues

Highlights:

Quokka CMS

Quokka is a Content Management Framework, which is in process of rewriting, the idea is having a core written in Flask, use Pelican themes and allow generation of static websites.

Skills needed: Flask, Python, Templating, MongoDB

Issues: https://github.com/rochacbruno/quokka

All the issues are good, as it is a re-writing from scratch project.

Py2rs

This is a Guide for Pythonistas who are learning Rust language

Issues: https://github.com/rochacbruno/py2rs/issues

The project really needs more examples to be written and also more comparison and fixes. Any kind of contributions are welcome.

Talkshow

This is a call 4 papers system (used as didatic example only)

Skills needed: Flask, Templating, mongoDB

Issues: https://github.com/rochacbruno/talkshow/issues

por Bruno Rocha em 01 de October de 2018 às 18:20

September 25, 2018

Thiago Avelino

Keeping open source projects - awesome-go

Beginning of any project (especially when we are talking about open source) is extremely entertaining for developer, over the years the fun passes and it is the responsibility to keep your “son” following the path of it. How did the starting awesome-go? All projects I started are out of necessity, the awesome-go was no different. After knowing the awesome-python and seeing other “awesomes” projects I searched for the awesome-go and did not get results.

25 de September de 2018 às 00:00

September 24, 2018

Gabbleblotchits

What open science is about

Today I got a pleasant surprise: Olga Botvinnik posted on Twitter about a poster she is presenting at the Beyond the Cell Atlas conference and she name-dropped a bunch of people that helped her. The cool thing? They are all open source developers, and Olga interacted thru GitHub to ask for features, report bugs and even submit pull requests.

That's what open science is about: collaboration, good practices, and in the end coming up with something that is larger than each individual piece. Now sourmash is better, bamnostic is better, reflow is better. I would like to see this becoming more and more common =]

Comments?

por luizirber em 24 de September de 2018 às 20:00

September 22, 2018

Filipe Saraiva

Akademy 2018

Procure seu colaborador favorito do KDE na Foto em grupo oficial do Akademy 2018

Estive em Viena para participar do Akademy 2018, o encontro anual do KDE. Este foi o meu quarto Akademy, sendo antecedido por Berlin’2012 (na verdade, Desktop Summit ), Brno’2014, e Berlin’2016 (junto com a QtCon). Interessante, vou ao Akademy a cada 2 anos – pretendo melhorar isso já no próximo. 🙂

Após uma viagem muito longa, pude finalmente encontrar “cabeças de engrenagem” de todas as partes do mundo, incluindo o próprio Brasil. Vi velhos e novos amigos trabalhando juntos para melhorar a experiência de utilizar um computador com software livre, cada qual contribuindo com pequenas (e alguns, realmente gigantes) partes para tornar isso realidade. Sempre que encontro esse pessoal me sinto reenergizado para seguir com esse trabalho.

Das palestras, gostei muito da feita por Volker sobre o KDE Itinerary, uma nova aplicação para gerenciar passbooks relacionados com viagens. Penso que um software para gerenciar todos os tipos de arquivos passbook (como entradas para shows, cinemas, e mais) como este seria uma interessante adição para a família de softwares do KDE, e um passo anterior à ideia perseguida pelo KDE Itinerary. De qualquer forma, estou na expectativa por novidades deste software.

A palestra sobre criação de transições utilizando o Kdenlive me fez pensar em quão interessante seria um plugin para executar scripts bash (ou python, talvez) de forma a automatizar vários passos realizados por editores nesse software. Inclusive, talves utilizando a KDE Store para compartilhar esses scripts… enfim, muitas ideias.

Conheci Camilo durante o evento. A palestra dele sobre o vvave me deu esperanças por uma nova e interessante aplicação de player multimídia, como uma vez tivemos no passado (saudades Amarok).

A última palestra que chamou minha atenção foi de Nate sobre algumas ideias para melhorar nosso ecossistema. Nate está fazendo um trabalho fabuloso sobre usabilidade, “polindo” nossos software de diversas formas. Recomendo o blog dele para quem quiser ficar acompanhar também. Apesar de eu concordar em geral com boa parte das ideias – por exemplo, é urgente a necessidade de melhorarmos nossa suíte de aplicações pessoais -, eu tive alguns desacordos em outras, em especial a ideia de que os desenvolvedores do KDE se dediquem a contribuir também para o LibreOffice. LibreOffice tem um código fonte completamente diferente, que utiliza tecnologias e práticas nada relacionadas com o que vemos no KDE, e há várias (e para muitos de nós, desconhecidas) influências das diferentes organizações que gerem a The Document Foundation, entidade responsável por desenvolver o LibreOffice. E por fim, nós ainda temos a suíte de escritório Calligra – a idea me soou como “vamos acabar com o Calligra”. De qualquer forma, isso foi apenas um desacordo com uma das sugestões, nada demais.

Após as seções de palestras o Akademy teve batantes sessões de BoF, que são mini-reuniões direcionadas sobre tópicos específicos. Pude participar de algumas, como a sobre o KDE e Qt (é sempre bom manter os olhos sobre esse tópico), KDE Phabricator (Phabricator é um conjunto muito bom de ferramentas para gerenciamento de projetos/repositórios/e afins, mas sofre por conta dos competidores (Gitlab) serem muito mais conhecidos e também por não ter das melhores usabilidades), e MyCroft (gosto da ideia de integração entre o MyCroft e o Plasma, especialmente para casos de uso especĩficos como auxiliar pessoas com deficiência – estou pensando nisso já há alguns meses).

Este ano, Aracele, Sandro e eu realizamos um BoF chamado “KDE in Americas”. A ideia foi apresentar algumas das nossas conquistas para o KDE na América Latina e discutir com o pessoal das demais américas sobre um evento “continental”, trazendo de volta o antigo CampKDE em uma nova edição junto com o LaKademy (o nome secreto é LaKamp :D). Esta ideia ainda precisa de alguma maturação para seguir em frente, mas estamos trabalhando.

Este ano eu tentei realizar o BoF sobre KDE na ciência e Cantor, mas infelizmente eu não tive o feedback necessário sobre potenciais participantes. Vamos ver se no futuro poderemos ter alguns deles acontecendo.

Akademy é um evento fantástico onde você encontra colaboradores do KDE de diferentes frentes e culturas, pode discutir com eles, pegar opiniões sobre projetos atuais e mesmo iniciar novos. Gostaria de agradecer ao KDE e.V. pelo patrocínio que me permitiu ir ao evento e espero ver todos vocês e mais alguns no próximo ano (vou tentar inserir um distúrbio naquela distribuição da minha sequência bianual de participações) no Akademy ou, em algumas semanas, no LaKademy!

Brasileiros no Akademy 2018: KDHelio, Caio, Sandro, Filipe (eu), Tomaz (abaixo), Eliakin, Aracele, e Lays

por Filipe Saraiva em 22 de September de 2018 às 21:13

September 13, 2018

Gabbleblotchits

New crate: nthash

A quick announcement: I wrote a Rust implementation of ntHash and published it in crates.io. It implements an Iterator to take advantage of the rolling properties of ntHash which make it so useful in bioinformatics (where we work a lot with sliding windows over sequences).

It's a pretty small crate, and probably was a better project to learn Rust than doing a sourmash implementation because it doesn't involve gnarly FFI issues. I also put some docs, benchmarks using criterion, and even an oracle property-based test with quickcheck.

More info in the docs, and if you want an optimization versioning bug discussion be sure to check the ntHash bug? repo, which has a (slow) Python implementation and a pretty nice analysis notebook.

Comments?

por luizirber em 13 de September de 2018 às 20:00

August 27, 2018

Gabbleblotchits

Oxidizing sourmash: WebAssembly

sourmash calculates MinHash signatures for genomic datasets, meaning we are reducing the data (via subsampling) to a small representative subset (a signature) capable of answering one question: how similar is this dataset to another one? The key here is that a dataset with 10-100 GB will be reduced to something in the megabytes range, and two approaches for doing that are:

  • The user install our software in their computer. This is not so bad anymore (yay bioconda!), but still requires knowledge about command line interfaces and how to install all this stuff. The user data never leaves their computer, and they can share the signatures later if they want to.
  • Provide a web service to calculate signatures. In this case no software need to be installed, but it's up to someone (me?) to maintain a server running with an API and frontend to interact with the users. On top of requiring more maintenance, another drawback is that the user need to send me the data, which is very inefficient network-wise and lead to questions about what I can do with their raw data (and I'm not into surveillance capitalism, TYVM).

But... what if there is a third way?

What if we could keep the frontend code from the web service (very user-friendly) but do all the calculations client-side (and avoid the network bottleneck)? The main hurdle here is that our software is implemented in Python (and C++), which are not supported in browsers. My first solution was to write the core features of sourmash in JavaScript, but that quickly started hitting annoying things like JavaScript not supporting 64-bit integers. There is also the issue of having another codebase to maintain and keep in sync with the original sourmash, which would be a relevant burden for us. I gave a lab meeting about this approach, using a drag-and-drop UI as proof of concept. It did work but it was finicky (dealing with the 64-bit integer hashes is not fun). The good thing is that at least I had a working UI for further testing1

In "Oxidizing sourmash: Python and FFI" I described my road to learn Rust, but something that I omitted was that around the same time the WebAssembly support in Rust started to look better and better and was a huge influence in my decision to learn Rust. Reimplementing the sourmash C++ extension in Rust and use the same codebase in the browser sounded very attractive, and now that it was working I started looking into how to use the WebAssembly target in Rust.

WebAssembly?

From the official site,

WebAssembly (abbreviated Wasm) is a binary
instruction format for a stack-based
virtual machine. Wasm is designed as a
portable target for compilation of high-level
languages like C/C++/Rust, enabling deployment
on the web for client and server applications.

You can write WebAssembly by hand, but the goal is to have it as lower level target for other languages. For me the obvious benefit is being able to use something that is not JavaScript in the browser, even though the goal is not to replace JS completely but complement it in a big pain point: performance. This also frees JavaScript from being the target language for other toolchains, allowing it to grow into other important areas (like language ergonomics).

Rust is not the only language targeting WebAssembly: Go 1.11 includes experimental support for WebAssembly, and there are even projects bringing the scientific Python to the web using WebAssembly.

But does it work?

With the Rust implementation in place and with all tests working on sourmash, I added the finishing touches using wasm-bindgen and built an NPM package using wasm-pack: sourmash is a Rust codebase compiled to WebAssembly and ready to use in JavaScript projects.

(Many thanks to Madicken Munk, who also presented during SciPy about how they used Rust and WebAssembly to do interactive visualization in Jupyter and helped with a good example on how to do this properly =] )

Since I already had the working UI from the previous PoC, I refactored the code to use the new WebAssembly module and voilà! It works!2. 3 But that was the demo from a year ago with updated code and I got a bit better with frontend development since then, so here is the new demo:

sourmash + Wasm

Drag & drop a FASTA or FASTQ file here to calculate the sourmash signature.

For the source code for this demo, check the sourmash-wasm directory.

Next steps

The proof of concept works, but it is pretty useless right now. I'm thinking about building it as a Web Component and making it really easy to add to any webpage4.

Another interesting feature would be supporting more input formats (the GMOD project implemented a lot of those!), but more features are probably better after something simple but functional is released =P

Next time!

Where we will go next? Maybe explore some decentralized web technologies like IPFS and dat, hmm? =]

Comments?

Updates

  • 2018-08-30: Added a demo in the blog post.

Footnotes

  1. even if horrible, I need to get some design classes =P

  2. the first version of this demo only worked in Chrome because they implemented the BigInt proposal, which is not in the official language yet. The funny thing is that BigInt would have made the JS implementation of sourmash viable, and I probably wouldn't have written the Rust implementation =P. Turns out that I didn't need the BigInt support if I didn't expose any 64-bit integers to JS, and that is what I'm doing now.

  3. Along the way I ended up writing a new FASTQ parser... because it wouldn't be bioinformatics if it didn't otherwise, right? =P

  4. or maybe a React component? I really would like to have something that works independent of framework, but not sure what is the best option in this case...

por luizirber em 27 de August de 2018 às 18:30