Minha foto

Riverfount

Desenvolvedor Python & entusiasta de open source

Posts Recentes

Sua aplicação está buscando os mesmos dados várias vezes

Sua aplicação está buscando os mesmos dados várias vezes

O profiling apontou um endpoint lento. Você abre o relatório do cProfile, ordena por cumtime, e o topo está dominado por chamadas ao banco de dados. Antes de qualquer coisa: se o problema for N+1 queries, cache não é a solução — é um emplastro. N+1 se resolve na query, com joins, selectinload ou subqueries conforme o ORM. Depois disso, índices. Cache entra só se, após a query estar correta e os índices no lugar, a performance ainda não for suficiente. ...

17 de abril de 2026 · 8 min · 1678 words · Riverfount
Hypothesis encontra os bugs que seus testes ignoram

Hypothesis encontra os bugs que seus testes ignoram

A suite de testes está verde. Fixtures bem organizadas, parametrize cobrindo os casos óbvios, mocks isolando as dependências externas. Cobertura em 94%. O PR passa no CI e vai para produção. Três dias depois, um usuário reporta um comportamento estranho. Você reproduz o bug localmente com um input que nunca ocorreu a ninguém testar: uma string vazia em que se esperava pelo menos um caractere, um número negativo em que a função assumia valores positivos, uma lista com um único elemento no qual a lógica de comparação silenciosamente quebra. O teste que teria pego isso seria trivial de escrever — se alguém tivesse pensado em escrever. ...

14 de abril de 2026 · 8 min · 1637 words · Riverfount
dataclass, NamedTuple, attrs ou pydantic: qual usar de verdade?

dataclass, NamedTuple, attrs ou pydantic: qual usar de verdade?

Existe um ponto no crescimento de qualquer projeto Python em que os dicionários começam a doer. Não de vez — vai acontecendo aos poucos. Você passa um dict para uma função, a função passa para outra, e em algum momento ninguém mais sabe ao certo quais chaves estão garantidas, qual é o tipo de cada valor, ou o que acontece se uma chave estiver faltando. 1 2 3 4 def calcular_desconto(pedido: dict) -> float: # pedido tem "valor"? "valor_bruto"? "subtotal"? # "cliente" é um dict também? tem "nivel"? return pedido["valor"] * _fator(pedido["cliente"]["nivel"]) Funciona. Ninguém vai questionar em code review. O problema aparece três meses depois, quando alguém passa um pedido sem a chave "nivel" — ou quando você tenta debugar e o repr do dicionário tem quarenta chaves misturadas. ...

10 de abril de 2026 · 9 min · 1731 words · Riverfount
O .env que você não deveria ter commitado

O .env que você não deveria ter commitado

Existe uma busca no GitHub que retorna milhares de resultados úteis para um atacante: filename:.env DB_PASSWORD. Repositórios públicos com arquivos .env commitados por acidente, contendo senhas de banco, chaves de API, segredos JWT — tudo em texto claro, indexado, pesquisável. Não é incompetência. É o resultado natural de uma prática que parece razoável: colocar credenciais num arquivo, adicionar esse arquivo ao .gitignore, e confiar que o .gitignore vai proteger. Funciona até o dia que não funciona — um git add . no momento errado, um novo membro do time que clona o repo e cria o .env a partir do .env.example sem perceber que o exemplo já tem valores reais, ou um editor que cria arquivos temporários fora do padrão ignorado. ...

6 de abril de 2026 · 12 min · 2546 words · Riverfount
JWT: três erros que todo mundo comete na primeira implementação

JWT: três erros que todo mundo comete na primeira implementação

Você abre o README do PyJWT, copia o exemplo de dez linhas, gera um token, valida do outro lado — e funciona. O token tem o user_id, expira em uma hora, a assinatura bate. O que pode estar errado? Bastante coisa. JWT é um dos padrões mais mal implementados em aplicações web, não porque seja complicado, mas porque os exemplos básicos funcionam mesmo com configurações que criam vulnerabilidades sérias. O código roda, os testes passam, e os problemas aparecem meses depois — ou não aparecem, porque ninguém tentou explorar. ...

26 de março de 2026 · 9 min · 1773 words · Riverfount
Ver todos os posts →