09 junho 2026

Gostei muito do anúncio do Studio MDHR sobre o desenvolvimento de seu próximo projeto, Mighty Cuphead Adventure, para consoles retrô. Para ser mais exato, eles vão lançar um jogo para o SEGA Master System, incluindo um cartucho para rodar diretamente no console.

O último jogo moderno para consoles retrô que joguei foi o incrível Micro Mages. Criado pela Morphcat Games, o título foi lançado para o NES (ou, para os mais chegados, o Nintendinho). Além de bonito, é muito divertido e desafiador, para dizer o mínimo.

Gameplay Micro Mages/NES

Assim como Micro Mages, pretendo jogar esse novo título no meu Android por meio de um emulador. Estou ansioso para experimentar mais um novo jogo para um antigo vídeo game.

22 janeiro 2026

Por que eu deveria colocar CPF nas minhas compras?

Esse é um questionamento comum do brasileiro quando vai às compras. No ato do pagamento, sempre ouvimos:

CPF na nota?

Ao menos aqui, a resposta padrão é sempre:

Não, obrigado!

Mas eis a questão. Isso é realmente útil? Adicionar meu CPF em todas as compras que eu fizer iria me ajudar no quê?

Meu 2026 começou com esses questionamentos. Após um dos eletrodomésticos ter “queimado”, cheguei à conclusão de que, em alguns cenários, é uma burocracia necessária.

Infelizmente, perdi a garantia de um produto, pois eu não tinha mais o cupom fiscal físico, tampouco acesso ao digital, dado que o QR Code de acesso fica no cupom fiscal. Porém, se uma compra é vinculada ao CPF, fica fácil resgatá-la pelo portal estadual da SEFAZ. Porém, não é meu caso, pois o meu automático não na hora do CPF na nota?, me deixou mais distante de uma resolução positiva.

Mas que fique o registro dessa experiência. E, para as próximas compras, talvez valha a pena, não?

02 outubro 2025

Seminário MCTI 2025

Um dos temas do segundo dia do Seminário MCTI (Ministério da Ciência, Tecnologia e Inovação) deste ano de 2025 foi a soberania digital no contexto da Inteligência Artificial. O que mais me chamou a atenção no primeiro bloco foi a iniciativa pública de fomentar o uso de tecnologias livres e abertas para o fortalecimento dessas ferramentas.

Ainda não está formalizado, mas, para o futuro, está previsto um consórcio de universidades com foco em promover o debate, além de produzir e pesquisar tecnologias de IA.

Para mim, porém, o ponto alto do seminário foi a abertura do debate, especialmente quando um funcionário da Magalu, convidado, pontuou que o Brasil não tem demanda para IA. Ele colocou sua experiência internacional em confronto com o que vivencia aqui no país. Mas será mesmo que não temos demandas? Um país em desenvolvimento, com tantos processos e burocracias que poderiam ser melhorados com apoio dessas ferramentas, teria muito a ganhar: fortalecer setores estratégicos, incentivar a inovação e fomentar pesquisa acadêmica.

E, sinceramente, basta pensar nas inúmeras fraudes das quais o Brasil é palco — como os golpes no INSS ou na época do Auxílio Emergencial, quando políticos e pessoas sem necessidade solicitavam o benefício. Situações como essas mostram o quanto tecnologias desse nível poderiam ser úteis. Não para substituir a decisão humana, mas como apoio na tomada de decisão.

26 março 2025

Abrir multiplos arquivos em linhas especificas no VIM

Em algumas situações, gosto de abrir vários arquivos ao mesmo tempo e gostaria de posicioná-los em linhas específicas.

Para abrir um único arquivo em uma determinada linha, utilizo o seguinte comando:

$ vim +{n} main.py

Para abrir múltiplos arquivos em linhas específicas, seguimos a mesma lógica. No entanto, entre o número da linha {n} e o nome do arquivo, também definimos se ele será organizado em um split, vsplit ou tabnew. O comando fica assim:

$ vim +10 main.py +"split +3 lib1.py" +"vsplit +12 lib2.py"

Com certeza, isso é muito mais prático do que abrir arquivo por arquivo e posicioná-los manualmente em suas respectivas linhas.

19 março 2025

Meu relógio de mesa

Estava sentindo falta de um relógio na mesa de trabalho. Alguns fins de semana atrás, codei uma pequena aplicação que transforma o descanso de tela do Android em um relógio.

Em teoria, funciona em qualquer dispositivo Android. O código-fonte está aqui e usei o DreamService para fazer isso acontecer.

12 agosto 2024

Links interessantes #1

Uma coletania de links que achei durante minhas "navegadas" na internet e que para mim são interessantes. Sem qualquer compromisso com algum tema em especial, a ideia é manter um registro de bons conteúdos em um espaço único. E essa é um texto com forte inspiração no Manual do Usuário.

  • Elvis Chidera é um jovem nigeriano que começou a programar desenvolvendo J2ME com um J2ME (Nokia 2690) e hoje trabalha como programador em uma startup do MIT; entrepreneurship.mit.edu

  • Brasiliana Museus é uma plataforma que conecta todos (ou os que aderem ao programa) os museus do Brasil e suas informações, permitindo que o usuário cruze informações de peças de diferentes Museus em um único lugar; Brasiliana Museus

  • 7 hábitos para um edição de texto efetiva (Vim: Seven habits of effective text editing), por Bram Mooler, publicado em 2000 mas continua tão válido e útil até os dias de hoje; www.moolenaar.net/habits.html

  • Engenharia de software é Engenharia? Texto escrito por Hillel Wayne em seu blog

  • Produção científica no Brasil vem caindo desde 2022; Nexo Jornal

  • Go (Lang) é meu martelo e tudo é um prego; Um breve relato do programador Markus, sobre sua escolha singular de ferramentas de trabalho, vale a leitura do texto

08 agosto 2024

Lançador (launcher) de TUI para GNU Screen

 Se tem uma coisa que eu gosto é conforto. Determinadas tarefas repetitivas, costumo pensar como de alguma forma posso automatiza-las. E uma dessas tarefas para mim tem sido abrir programas TUI no GNU Screen. O CTRL-A + c seguido do comando ou CTRL-A + : seguido de screen <camando> uma hora cansa, então com o fzf fiz um pequeno atalho de tecla (CTRL-A+ Espaço) e ele abre um lançador similar ao rofi, mas de binários.

No .screenrc adicionei:

bind ' ' screen 'compgen -c | grep -iP "^[a-z].*" | grep -v fzf | fzf

12 julho 2024

Resolvendo problema de timezone com Python (ZoneInfoNotFoundError) no Termux

Tenho experimentado usar o Termux para escrever e executar alguns pequenos programas no meu Android. Algumas provas de conceito, ideias ou teste rápidos. Porém recentemente após instalar e tentar rodar um projeto que implementa o i18n recebi a seguinte mensagem de erro no traceback do Python:

File "/data/data/com.termux/files/usr/lib/python3.11/zoneinfo/_common.py", line 24, in load_tzdata raise ZoneInfoNotFoundError(f"No time zone found with key {key}") zoneinfo._common.ZoneInfoNotFoundError: 'No time zone found with key America/Sao_Paulo'
 

A falha ocorreu pelo fato de não existir esse timezone America/São Paulo no sistema. Para resolver isso de forma pontual, encontrei um pacote Python tzdata que serve justamente como fallback para sistemas que não contém os dados dos timezones.

pip install tzdata

09 julho 2024

Homelab com um ARM

Recentemente tenho me aventurado em manter ativo um servidor local em casa. Minha ideia principal é manter alguns softwares de backup que sincronize principalmente meus documentos e fotos. Além de servir como um pequeno servidor de serviços locais como Git, Backup e Mídia, por exemplo.

Essa ideia surgiu pela necessidade de automatizar com mais autonomia algumas tarefas de backup, mas além disso, também pelo fato de eu ter um pequeno dispositivo ARM disponivel em casa e que provavelmente não teria mais utilidade. Muito conhecido como TV Box, esses mini computadores em sua grande maioria são equipados com processador ARM, geralmente da Amlogic ou da Rockchip com alguma versão do Android instalado. O meu é da Rockchip, sendo mais especifico é um RK3318 e nele veio o Android 9 que posteriormente foi substituido pelo GNU/Linux Debian (Armbian).


Configuração da máquina

Tenho em mãos um ARM Rockchip RK3318 Quad-Core (1,8GHz) com 4GB de RAM e 64GB de memória interna (flash) e um HD adicional de 1TB. O sistema é um Debian 12 para processadores ARM (ou para ser mais exato, o Armbian).


Esses computadores são conhecidos por serem simples e sucintos em recursos de hardware. Todos os componentes são soldados na placa, impedindo a troca ou expansão, como por exemplo a memória interna ou a memória RAM. Mas nada que seja um impedimento para esse primeiro experimento com servidores caseiros.

Primeiro serviço

A principal função atualmente do meu servidor é manter meus backups em funcionamento.

Gosto de manter meus documentos e fotos sempre disponível e seguro, afim de evitar alguma catastrofe¹ nas nuvens.

Eu costumava armazenar meus documentos em alguns HD’s e fazia todo o processo de baixar e organizar de forma manual. Porém comecei a experimentar uma ferramenta mais eficiente que minha força de vontade de fazer manualmente, talvez o RCLONE seja um baixador melhor.

Atualmente tenho um script shell similar a isso:

rclone sync --interactive /mnt/homecloud/photos remote:album/newAlbum

Que executo (por enquanto) manualmente dentro de uma sessão do GNU Screen.

Considerações finais

Meu plano é fazer melhorias pequenas e continuas no meu servidor. Inicialmente minha principal necessidade era manter meus backups seguros e locais, porém existem outras possibilidades de uso além disso.

Algumas ideias que achei intessantes para meu dia a dia, seriam ter um servidor de mídia (DLNA) e um servidor de arquivos disponível na REDE com Samba, além de um DNS local nomeando os endereços de IP para nomes humanamente memorisaveis (homelab.local?).

Hoje todo o processo é bem manual e sem qualquer ferramenta de monitoração, apenas o bom e velho SSH e o HTOP.

02 agosto 2023

RetroCON 2023

Neste domingo (30), tive o prazer de estar presente no primeiro evento de retro games de São Paulo, a RetroCON. Foi uma experiência incrível. A quantidade de GAMES disponíveis para jogar era imensa; ficaria até difícil listar todos aqui. Talvez eu nem tenha conseguido ver todos. Dos que joguei e me lembro, destacam-se: Atari 2600, Mega Drive, Super Nintendo, Xbox 360, Arcade (ou fliperama) e Playstation 4. É curioso mencionar o Playstation 4, mas ele estava lá para rodar o Top Racer, um jogo moderno com visual e mecânica retrô que lembra muito o Out Run do Mega Drive.

Não houve apenas vídeo games para jogar. Havia diversos estandes para comprar camisetas, pôsteres, jogos, apresentações de games retrô e também uma exposição mostrando a história e as gerações dos games ao longo do tempo.

De lá, trouxe um pôster do SONIC 3. A escolha foi realmente difícil, dada a variedade de opções, tamanhos e alguns até com molduras!

Além de decorar meu escritório com um pôster de um dos meus jogos favoritos, ele também servirá como uma boa lembrança desse evento.

Fiz alguns poucos registros fotográficos desse dia épico:





Jogos novos para games antigos;



Encerramento do evento com palavras finais dos organizadores



04 abril 2023

Orçamentos rápidos com "DIN"

Já me peguei em várias momentos tendo que fazer uma lista de “compras” ou de divisão de despesas em um bloco de notas. Sempre é eficiente e prático, basta abrir um arquivo texto e começar a digitar a despesa em si e seu valor e ao fim o sub-total e total para manter a organização e posteriormente se necessário compartilhar entre os envolvidos. Isso nunca foi o problema, porém com maior frequência essa pode ser uma atividade um tanto quanto trabalhosa, descrever, calcular em aplicativos distintos e ainda organizar essas anotações.


A fim agilizar um pouco mais minha atividade, criei um pequeno aplicativo web (webapp) para realizar essa função, o DIN. Um WebApp que me permite inserir entradas e saídas e ao fim der o resultado final e com a descrição de cada item independente da sua razão. Além de simples é bem intuitivo pois contém uma interface simples e objetivo, contando apenas com 2 campos ao fim da tela para inserção dos dados.

É necessário ainda aprimoramentos, inclusive visuais, mas a função principal que é a de listar os recursos, seja de entrada e saída, está sendo feito que era meu objetivo. Para um futuro, talvez algumas melhorias funcionais como editar um registro já inserido ou poder remover um registro e também um uma melhoria visual no campo referente ao preço para diminuir a fricção na hora de inserir valores monetários que exigem a inserção de ponto atualmente.

08 março 2023

Limitando uso de recursos de máquina pelo Docker no WSL2 (VMMEM)

 Trabalhar com containers no Windows tornou-se fácil depois do WSL2. Com ele é possível ter uma experiência de usabilidade próxima ao GNU/Linux, porém existe um problema crônico em toda solução Windows que é o excesso de uso de memória RAM, causando lentidão e travamentos no sistema, afetando outros serviços e recursos. No Docker for Windows não é diferente, após fazer a instalação e integração com WSL2, é necessário deixar explicito o limite de uso de recursos, seja CPU ou RAM.

Como limitar?

No meu caso, estava com um sério problema de excesso de uso de memória RAM. Minha máquina é bem limitada, porém o Docker com o WSL utilizava em médio 70 à 90% da memória (de 4GB). Meu objetivo era limitar a 1GB de uso, apenas da memória RAM. Para isso é necessário criar um arquivo .wslconfig no "HOME" do Windows (%UserProfile%/.wslconfig, o mesmo que C:\Users\<meu usuario>\.wslconfig).

Abra o explorador de arquivos (win + E) e na barra de endereços digite:




Após aberto o editor com o arquivo, basta limitar o número da memória RAM a ser utilizada:

[wsl2]
memory=1GB
debugConsole=true

Além de notar o desempenho melhor para confirmar a configuração, é possível visualizar no Gerenciador de Tarefas o processo VMMen com consumo abaixo dos 1GB:



Referências:

06 janeiro 2023

Manipulando caminhos (path) e arquivos no Python moderno

Uma atividade comum no desenvolvimento de software com Python é a manipulação de arquivos e caminhos do sistema operacional. Seja para leitura de um arquivo ou a escrita do mesmo em qualquer que seja o caminho destino. Isso não é complicado no Python com a ajuda da biblioteca os e a instrução open, por exemplo. Porém podemos acabar tendo que descrever em mais linhas que o necessário em versões mais modernas do Python ou utilizando bibliotecas "pobre" de recursos para este fim. Tomemos como exemplo um trecho de código comum em muitos programas escritos em Python (2 ou 3). O objetivo deste pequeno trecho de código é ler o arquivo de configuração do git, se existir, caso contrário não retorna nada:

import os

git_config = os.path.join(os.path.expanduser('~'), '.gitconfig')

if os.path.exists(git_config):
    with open(git_config, 'r') as raw_file:
        print(raw_file.read())

É um código funcional e cumpre seu objetivo. Mas existem formas "melhores" de descrever essa mesma atividade, em menos linhas, sem truques de abertura ou fechamento de arquivos e com recursos nativos da linguagem.

A partir da versão >= 3.4, Python introduziu o módulo pathlib. Com o principal e único objetivo de fazer manipulações de caminhos e arquivos de forma genérica e compatível com diferentes sistemas operacionais. Além de não retornar uma simples string, como é o caso do módulo os.path. o pathlib retorna um objeto Path (se for Unix PosixPath se for Windows WindowsPath). Além permitir uma sintaxe mais expressiva em relação aos caminhos, já que permite o uso de / (barras) como separador o módulo conta com recursos para leitura e escrita sem a necessidade do statement open.

import pathlib

git_config = pathlib.Path.home() / '.gitconfig'

if git_config.exists():
    print(git_config.read_text())

É possível também fazer a escrita de forma mais simples e sem a necessidade do uso do gerenciador de contexto ou fechamento de arquivos de forma explicita:

import pathlib

my_file = pathlib.Path('/tmp') / 'my_file.txt'
content = 'content file with pathlib module'

my_file.write_text(content)

18 novembro 2022

Integridade de dados e race condition com sinais (signals) no Django

Para quem já trabalhou com Django, sabe dos ótimos recursos disponíveis dentro do framework, além do ilustríssimo e ótimo ORM, uma estrutura de rotas, comunidade enorme e uma vasta experiência para fornecer ferramentas de qualidade para resolução de problemas no desenvolvimento de aplicações web. Mas além desses recursos ele conta também com um o sinais ou signals um disparador de eventos que acontece antes ou depois que uma ação é feita.

Uma das formas mais comuns de usar sinais no Django é quando precisamos executar uma determinada tarefa depois de salvar as informações no banco de dados, claro, partindo de um modelo (model) qualquer. O código seria assim:

from django.db.models.signals import pre_save
from django.core.mail import send_mail
from django.dispatch import receiver

from bank.models import Account

@receiver(post_save, sender=Account)
def send_mail(sender, instance, **kwargs):
    if instance.balance < 0:
        send_mail(
            subject="Saldo baixo!",
            message="Você entrou no cheque especial",
            from_email="admin@domain.tld",
            recipient_list=["user@domain.tld"]
        )

Essa seria uma possível implementação, porém falha, dado que parte da instrução da função send_email depende dos dados do modelo, como é visto logo abaixo da definição dela. O problema é que logo após o sinal ser acionado, o banco de dados ainda está processando o salvamento das informações, por tanto pode ser que no momento da consulta do instance.balance o valor seja o anterior e não 0, como seria esperado, isso é conhecido também como race condition.

A resolução do problema é simples e utilizando os próprios recursos do Django. Dado que as duas atividades estão perdendo a comunicação ao longo de suas execuções e uma depende da outra. É necessário esperar uma ser concluída para em seguida acionar a outra. Para isso é necessário garantir que os dados foram salvos para na sequência fazer o disparo da tarefa (send_mail). Para isso podemos usar o modulo de transaction e a função on_commit que é a responsável por garatir que o sinal será chamado ao fim da "transação" de dados no banco (ou seja depois que ele salvar os dados).

O uso do on_commit para essa finalidade teria uma implementação assim:

[...]

from django.db import transaction

def do_mail(instance):
    if instance.balance < 0:
        send_mail(
        subject="Saldo baixo!",
        message="Você entrou no cheque especial",
        from_email="admin@domain.tld",
        recipient_list=["user@domain.tld"]
    )

@receiver(post_save, sender=Account)
def send_mail(sender, instance, **kwargs):
    transaction.on_commit(lambda: do_email(instance))

Os sinais do Django é uma ferramenta muito útil em muitos casos, mesmo tendo possibilidade de adicionar ferramentas externas para atividades de baixa escala o uso desse recurso se faz necessário, porém é importante entender alguns detalhes para extrair o máximo possível de funcionalidade durante o desenvolvimento de aplicações web.

01 maio 2022

Armadilhas das variáveis de ambiente em testes unitários Python

Atualmente com o grande uso de computação em nuvem, também, é comum nós desenvolvedores criamos ferramentas que precisam de um certo dinamismo em alguns pontos do software, como por exemplo, chaves de acesso, informações do “host” do banco de dados e exposição de porta. Para ter essa fácil troca de valores o caminho mais fácil é usar variáveis de ambiente. Porém em um cenário de testes com Python e UnitTest (pacote encontrado na biblioteca padrão), alguns problemas podem aparecer se não utilizada os recursos corretos para se compor os testes.

Tomemos como exemplo o seguinte código para teste:

import os
from urllib.parse import urlparse
from unittest import TestCase


def resolver_service():
    url = os.getenv('SERVICE_URL', 'https://duck.com/')
    service = urlparse(url)
    return service.scheme, service.netloc


class Test(TestCase):
    def test_service_default(self):
        protocol, name = resolver_service()

        self.assertEqual(protocol, 'https')
        self.assertEqual(name, 'duck.com')

Ao ser executado, ele retorna os valores (padrões) esperado. Porém precisamos alterar esses mesmo valores para validar seu real funcionamento. Uma das formas de inserir valores de variávies de ambiente no Python é injetando diretamento no os.environ com o nome da variável. Extendendo o exemplo com mais 2 unidades de teste.

class Test(TestCase):
    def test_service_default(self):
        protocol, name = resolver_service()

        self.assertEqual(protocol, 'https')
        self.assertEqual(name, 'duck.com')

    def test_service_ftp(self):
        os.environ['SERVICE_URL'] = 'ftp://example.tld'
        protocol, name = resolver_service()

        self.assertEqual(protocol, 'ftp')
        self.assertEqual(name, 'example.tld')

    def test_service_https(self):
        protocol, name = resolver_service()

        self.assertEqual(protocol, 'https')
        self.assertEqual(name, 'duck.com')

Ao executar temos um erro no último teste:

..F
======================================================================
FAIL: test_service_https (__main__.Test)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/tmp/example_erro_testing.py", line 29, in test_service_https
    self.assertEqual(protocol, 'https')
AssertionError: 'ftp' != 'https'
- ftp
+ https

----------------------------------------------------------------------
Ran 3 tests in 0.001s

FAILED (failures=1)

O último teste está falhando, pois está carregando o valor do teste anterior. O esperado era pegar o valor padrão que seria https. Ou seja, o Python não limpa os valores por padrão para a próxima execução. Mas ele tem ferramentas adequadas para esse tipo de trabalho, que seriam os mocks. No caso iremos usar o patch para ser mais exato, patch.dict que após a execução dos testes, restaura os valores padrões do dicionário que é a estrutura que estamos manipulando no Python para ter os valores da variável de ambiente.

class Test(TestCase):
    def test_service_default(self):
        protocol, name = resolver_service()

        self.assertEqual(protocol, 'https')
        self.assertEqual(name, 'duck.com')

    @patch.dict('os.environ', {'SERVICE_URL': 'ftp://example.tld'})
    def test_service_ftp(self):
        protocol, name = resolver_service()

        self.assertEqual(protocol, 'ftp')
        self.assertEqual(name, 'example.tld')

    def test_service_https(self):
        protocol, name = resolver_service()

        self.assertEqual(protocol, 'https')
        self.assertEqual(name, 'duck.com')

Com isso já teremos nossos testes funcionando e escrito da forma correta quando se quer manipular valores de variáveis de ambiente.

09 abril 2022

Reconhecimento facial no laptop para o bem ou para o mal

Com o passar do tempo, tenho me adequado ao modo de vida “preguiçoso” - ou moderno. Acredito que por passar muitas vezes executando as mesmas tarefas que muitas vezes, são tediosas e suscetíveis a erros, chega um momento que a cabeça pede ajuda. Uma dessas tarefas é a questão das senhas. Digitar senhas é um fardo quando se precisa digitar dezenas e dezenas de vezes. Com mais e mais vazamento de dados, a responsabilidade de se manter se seguro aumenta, o que aumenta também o trabalho de manter sua vida digital minimamente segura (se é que é possível), porém se você não está disposto a gastar alguns “milhares” de dólares com licenças de sistemas operacionais fechados e confiar sua segurança (ou seus dados) a outro, o trabalho precisa ser feito na mão. Porém, graças a grande e boa comunidade do Software Livre, o trabalho é feito uma única vez para todo o sempre e com atualização e colabaração de muitos desenvolvedores em volta do mundo.

Uma das tecnologias já em uso pela indústria é o reconhecimento facial, tecnologia essa que tem muitas ressalvas no âmbito comercial[1] e muitas vezes até no pessoal[2]. Porém não deixa de ser uma tecnologia interessante para o grande público, quando pensamos em melhorar nosso dia a dia, como por exemplo, nunca mais digitar senhas ao ligar o computador ou executar uma tarefa com nível de permissão mais alto que exige senhas.

Pois bem, se você usa smartphone (o que é provável), deve saber da existência desse recurso de autenticação fácil em aparelhos Android ou iOS. Assim como nesses sistemas no Linux também existe uma maneira de “habilitar” essa funcionalidade de autenticação. Por meio do Howdy[3], um módulo PAM escrito atualmente em Python[4] é possível ter essa funcionalidade em questão de minutos. O único requisito é ter um computador com webcam.

Com a autenticação facial funcionando, não é mais preciso digitar senhas tanto nas tarefas de linha de comando quanto nas interfaces gráficas. Como é um módulo PAM, é possível destravar quase tudo com o reconhecimento facial, com exceção do molho de chaves “Keyring”. E também é possível especificar aplicações ou comandos disponíveis para requisitar o reconhecimento facial.

As coisas parecem bem mais fluidas, não é necessário digitar dezenas de vezes a senha pois esbarrou numa tecla errada, ou ficar “dançando” os dedos na impressão digital. Claro que não se resume apenas a simplicidade, pois toda facilidade nem sempre vem sem algum peso. Existem algumas ressalvas de segurança em relação a esse tipo de sistema de autenticação, por exemplo, ter apenas esse método de autenticação, ou até mesmo sobre burlar o sistema de autenticação com uma foto de alta qualidade. O próprio Howdy nos permiti 3 níveis de autenticação segura, uma com reconhecimento rápido, outra intermediário e uma terceira que leva muita mais tempo para reconhecer, porém é mais seguro pois evita fraudes com fotos de nossos rostos, por exemplo.

Notas e Referências 

24 março 2021

Se "achando" em um projeto (git) desconhecido

Uma das atividades comuns de um programador é dar suporte e manutenção para softwares já em funcionamento, muitas vezes em ambientes e tecnologias das quais não se tem domínio. Mas graças ao controle de versão que é quase que onipresente em projetos profissionais, podemos usar ele para nos encontrar no projeto.

Boa parte do trabalho é feita com o git log¹.

Procurando mensagens referentes a uma determinada palavra:

git log -g --grep "lambda function"

Uma busca na historia do repositorio com determinado termo dentro do codigo:

git log -p -S "lambda_function"

Para abranger todos os *branch* nessa busca, além do HEAD (atual), adicione o parâmetro --all:

git log -p --all -S "lambda_function"

Além desses meio se ambientar, também existe o git grep², que funciona de forma similar ao grep³.

Referências 

02 março 2021

Não tem pra onde fugir...

Nas ruas as câmeras te filmam e alimentam um grade banco de dados para identificação.

Na redes sociais seu perfil é traçado, desde a busca, digitação até as "emoção".

Em casa os celulares e TVs te ouvem e aprendem quem é você, seu perfil, sua voz e até seus costumes.

Nem você sabe quem é você.

Mas alguém sabe.

Não tem pra onde fugir, você é um pequeno número no banco de dados de "alguém"... na inteligência artificial de alguém.

22 maio 2020

Reescrevendo mensagens de "commits" no GIT

O git é uma excelente ferramenta no desenvolvimento de projetos, além de manter o registro de mudanças, ele permite também a mudança de coisas já feitas, os commits já feitos. Pode ter situações que se faz necessária a mudança, seja por WIP's ou TODO esquecidos em alguma mensagem de commit ou dentro de arquivos.

Existe duas formas de alterar commits, o --amend da qual vamos tratar primeiro, é mais objetivo ele altera o último commit feito no branch atual. Exemplo de um --amend:

About to make the tackle, Yale Alumni Gam

Outra forma de fazer essas alterações é com o rebase, ele permiti fazer alterações em commits mais antigos, não só isso, mas em "lotes", sendo possível alterar mais de 1 commit no mesmo fluxo. Usando o parâmetro -i, ele entra em modo iterativo e permite o uso de prefixos já pré definidos, como pick, edit, rename, para dizer o que fazer com o commit. Em um exemplo, vou editar 2 commits de um repositório (GNU Stow ), em um deles vou adicionar uma mudança nos arquivos e acrescentar mais informações na mensagem commit (com --amend, enquanto estou fazendo o rebase) e o outro vou apenas alterar a mensagem de commit. Para essas duas mudanças vou usar edit (que atualiza o commit para permitir acrescentar também uma mudança de arquivo, além de permitir alterar a mensagem de commit) e o reword (que atualiza apenas a mensagem).

About to make the tackle, Yale Alumni Gam

Porém fazer essas mudanças tem um custo, por exemplo o de na hora de mandar as alterações para o repositório o git não deixar sem que você deixe explicito isso ao enviar, com o parâmetro --force (ex.: git push --force). Ele faz isso, pois as árvores entre seu repositório local e o remoto estão diferentes¹ no que se refere aos commits passados.

13 agosto 2019

Não seja autodestrutivo!

Não seja autodestrutiv

Não seja autodestruti

Não seja autodestrut

Não seja autodestru

Não seja autodestr

Não seja autodest

Não seja autodes

Não seja autode

Não seja autod

Não seja auto

Não seja aut

Não seja au

Não seja a

Não seja

Não sej

Não se

Não s

Não

N

Fim de semana!