Para instalar o Poetry, você pode seguir as instruções presentes na documentação oficial do Poetry para o seu sistema operacional. Alternativamente, se você optou por usar o pipx, pode instalar o Poetry com o seguinte comando:
$ Execução no terminal!
pipxinstallpoetry
@@ -2613,7 +2613,7 @@
Introdução ao Pytest: Tes
Caso não tenha muita experiência com Pytest
Temos uma live de Python explicando os conceitos básicos da biblioteca
A parte importante dessa Mensagem está na tabela gerada pelo coverage. Que diz que temos 5 linhas de código (Stmts) no arquivo fast_zero/app.py e nenhuma delas está coberta pelos nossos testes. Como podemos ver na coluna Miss.
Por não encontrar nenhum teste, o pytest retornou um "erro". Isso significa que nossa tarefa post_test não foi executada. Podemos executá-la manualmente:
@@ -2730,7 +2730,7 @@
Estrutura de um teste
Caso fazer testes ainda seja complicado para você
Temos uma live de python focada em ensinar os primeiros passos no mundo dos testes.
Neste caso, criaremos uma fixture que retorna nosso client. Para fazer isso, precisamos criar o arquivo tests/conftest.py. O arquivo conftest.py é um arquivo especial reconhecido pelo pytest que permite definir fixtures que podem ser reutilizadas em diferentes módulos de teste em um projeto. É uma forma de centralizar recursos comuns de teste.
Além disso, expor credenciais de banco de dados e outras informações sensíveis no código-fonte é uma prática de segurança ruim. Se esse código fosse comprometido, essas informações poderiam ser usadas para acessar e manipular seus recursos.
Por isso, usaremos o pydantic-settings para gerenciar nossas configurações de ambiente. A biblioteca permite que você defina configurações em arquivos separados ou variáveis de ambiente e acesse-as de uma maneira estruturada e segura em seu código.
@@ -2344,7 +2344,7 @@
Executando o teste
TOTAL 54 2 96%
Neste caso, podemos ver que todos os nossos testes passaram com sucesso. Isso significa que nossa funcionalidade de criação de usuário está funcionando corretamente e que nosso modelo de usuário está sendo corretamente persistido no banco de dados.
-
Embora tudo esteja se encaixando bem, esse teste não é muito legal, pois não faz a validação do objeto como um todo. Conseguimos garantir que toda a estrutura do bando de dados funciona, porém, não conseguimos garantir ainda que todos os valores estão corretos.
+
Embora tudo esteja se encaixando bem, esse teste não é muito legal, pois não faz a validação do objeto como um todo. Conseguimos garantir que toda a estrutura do banco de dados funciona, porém, não conseguimos garantir ainda que todos os valores estão corretos.
Eventos do ORM
Embora nossos testes tenham sido executados corretamente, temos um problema se quisermos validar o objeto como um todo, por existirem alguns campos da tabela que fogem do mecanismo da criação do objeto (init=False).
Um desses casos é o campo created_at. Quando configuramos o modelo, deixamos que o banco de dados defina seu horário e data atual para preencher esse campo. Será que existe uma forma de alterar esse comportamento durante os testes? Pra podermos validar quando o objeto foi criado? A resposta é sim.
@@ -2357,7 +2357,7 @@
Eventos do ORM
end
Isso nos permite modificar os dados antes ou depois de determinadas operações serem executadas pelo SQLAlchemy.
Por exemplo, nosso modelo de User não permite que sejam enviados os campos id e created_at no momento em que a instância de User é criada. Por conta da restrição init=False no mapped_column.
-
Escrever testes com essa restrição pode nos trazer algumas dificuldades no momento das validações (asserts). Então vamos programar um evento para acontecer antes que o dado seja inserido no banco de dados.
+
Ao escrever testes, essa restrição pode nos trazer algumas dificuldades no momento das validações (asserts). Então vamos programar um evento para acontecer antes que o dado seja inserido no banco de dados.
flowchart TD
commit --> Z["Inserir registro no banco (operação)"]
subgraph Z["Inserir registro no banco (operação)"]
@@ -2416,7 +2416,7 @@
Evento para manipular o tempo
O decorador @contextmanager cria um gerenciador de contexto para que a função _mock_db_time seja usada com um bloco with. Caso você não tenha experiência com gerenciadores de contexto, você pode assistir a essa Live.
Todos os parâmetros após * devem ser chamados de forma nomeada, para ficarem explícitos na função. Ou seja mock_db_time(model=User). Os parâmetros não podem ser chamados de forma posicional _mock_db_time(User), isso acarretará em um erro.
Função para alterar alterar o método created_at do objeto de target.
-
event.listen adiciona um evento relação a um model que será passado a função. Esse evento é o before_insert, ele executará uma função (hook) antes de inserir o registro no banco de dados. O hook é a função fake_time_handler.
+
event.listen adiciona um evento relação a um model que será passado a função. Esse evento é o before_insert, ele executará uma função (hook) antes de inserir o registro no banco de dados. O hook é a função fake_time_hook.
Retorna o datetime na abertura do gerenciamento de contexto.
Após o final do gerenciamento de contexto o hook dos eventos é removido.
@@ -2485,7 +2485,7 @@
Adicionando o evento ao teste
O teste permanece praticamente igual, com a diferença de que todas as operações envolvendo a criação de User no banco de dados acontecem no escopo de mock_db_time.
Isso faz com que durante o commit, quando os objetos são persistidos da sessão para o banco de dados, o evento de before_insert seja executado para cada objeto do modelo passado em mock_db_time(model=*MODEL*).
-
Por conta do campo created_at agora ser determinístico podemos fazer uma comparação completa dos campos.
+
Por conta do campo created_at agora ser determinístico podemos fazer uma comparação completa dos campos.
Para simplificar a comparação de todos os campos, como nossos objetos de modelo são dataclasses, a função dataclass.asdict(), converte uma dataclass para um dicionário:
Agora, começaremos instalando o Alembic, que é uma ferramenta de migração de banco de dados para SQLAlchemy. Usaremos o Poetry para adicionar o Alembic ao nosso projeto:
$ Execução no terminal!
poetryaddalembic
@@ -2559,7 +2559,7 @@
Instalando o Alembic
├── test_app.py
└── test_db.py
-
No arquivo alembic.ini: ficam as configurações gerais das nossas migrações. Na pasta migrations foram criados um arquivo chamado env.py, esse arquivo é responsável por como as migrações serão feitas, e o arquivo script.py.mako é um template para as novas migrações.
+
No arquivo alembic.ini: ficam as configurações gerais das nossas migrações. Na pasta migrations foram criados dois arquivos, um chamado env.py que é responsável por como as migrações serão feitas, e o outro chamado script.py.mako que é um template para as novas migrações.
Criando uma migração automática
Com o Alembic devidamente instalado e iniciado, agora é o momento de gerar nossa primeira migração. Mas, antes disso, precisamos garantir que o Alembic consiga acessar nossas configurações e modelos corretamente. Para isso, faremos algumas alterações no arquivo migrations/env.py.
Neste arquivo, precisamos:
@@ -2921,7 +2921,7 @@
Conclusão
- 13 de novembro de 2024
+ 16 de novembro de 2024
@@ -2936,7 +2936,7 @@
Uma peça chave do SQLAlchemy é o conceito de uma "sessão". Se você é novo no mundo dos bancos de dados, pode pensar na sessão como um carrinho de compras virtual: conforme você navega pelo site (ou, neste caso, conforme seu código executa), você pode adicionar ou remover itens desse carrinho. No entanto, nenhuma alteração é realmente feita até que você decida finalizar a compra. No contexto do SQLAlchemy, "finalizar a compra" é equivalente a fazer o commit das suas alterações.
A sessão no SQLAlchemy é tão poderosa que, na verdade, incorpora três padrões de arquitetura importantes.
Ao longo da evolução de um projeto, é natural que sua estrutura inicial necessite de ajustes para manter a legibilidade, a facilidade de manutenção e a organização do código. Nesta aula, faremos exatamente isso em nosso projeto FastAPI: refatoraremos partes dele para melhorar sua estrutura e, em seguida, ampliar a cobertura de nossos testes para garantir que todos os cenários possíveis sejam tratados corretamente. Vamos começar!
Após a implementação do nosso gerenciador de tarefas na aula anterior, temos uma primeira versão estável da nossa aplicação. Nesta aula, além de aprendermos a "dockerizar" nossa aplicação FastAPI, também abordaremos a migração do banco de dados SQLite para o PostgreSQL.
Na aula anterior, preparamos nossa aplicação para execução em containers Docker, um passo fundamental para replicar o ambiente de produção. Agora, vamos garantir que nossa aplicação mantenha sua integridade a cada mudança, implementando Integração Contínua.
Agora que temos uma API criada com integração ao banco de dados e testes sendo executados via integração contínua. Chegou a tão esperada hora de colocar nossa aplicação em produção para que todas as pessoas possam acessá-la. Colocaremos nossa aplicação em produção usando um serviço de PaaS, chamado Fly.io.
Estamos chegando ao final de nossa jornada juntos neste curso. Durante esse tempo, tivemos a oportunidade de explorar uma série de conceitos e tecnologias essenciais para o desenvolvimento de aplicações web modernas e escaláveis. É importante lembrar que o que vimos aqui é apenas a ponta do iceberg. Ainda há muitos aspectos e detalhes que não pudemos cobrir neste curso, como tratamento de logs, observabilidade, segurança avançada, otimizações de desempenho, entre outros. Encorajo a todos que continuem explorando e aprendendo.
A nossa intenção neste curso é facilitar o aprendizado no desenvolvimento de APIs usando o FastAPI. Vamos explorar como integrar bancos de dados, criar testes e um sistema básico de autenticação com JWT. Tudo isso para oferecer uma boa base para quem quer trabalhar com desenvolvimento web com Python. A ideia desse curso é apresentar os conceitos de forma prática, construindo um projeto do zero e indo até a sua fase de produção.
@@ -1872,10 +1872,10 @@
Pré-requisitos
Caso esteja iniciando seus estudos em Python!
Caso você ainda não se sinta uma pessoa preparada, ou caiu aqui sem saber exatamente o que esperar. Temos um pequeno curso introdutório. Destinado aos primeiros passos com python.