diff --git a/slides/brutos/aula_01.md b/slides/brutos/aula_01.md index d65b7ea6..fde2023f 100644 --- a/slides/brutos/aula_01.md +++ b/slides/brutos/aula_01.md @@ -59,13 +59,13 @@ Ferramentas incríveis que tornam o gerenciamento mais simples: --- -# Python 3.12 +# Python 3.13 Se você precisar (re)construir o ambiente usado nesse curso, é **extremamente recomendado** que você use o [pyenv](https://github.com/pyenv/pyenv). ```bash pyenv update -pyenv install 3.12:latest +pyenv install 3.13:latest ``` > Momento de uma pausa dramática! @@ -146,14 +146,14 @@ isso vai nos gerar essa estrutura: Para que a versão que instalamos com pyenv seja usada em nosso projeto criado com poetry, devemos dizer ao pyenv qual versão do python será usada nesse diretório: ```shell title="$ Execução no terminal!" -pyenv local 3.12.6 # Essa era a maior versão do 3.12 quando escrevi +pyenv local 3.13.0 # Essa era a maior versão do 3.13 quando escrevi ``` Em conjunto com essa instrução, devemos dizer ao poetry que usaremos essa versão em nosso projeto. Para isso vamos alterar o arquivo de configuração do projeto o `pyproject.toml` na raiz do projeto: ```toml title="pyproject.toml" linenums="9" [tool.poetry.dependencies] -python = "3.12.*" # .* quer dizer qualquer versão da 3.12 +python = "3.13.*" # .* quer dizer qualquer versão da 3.12 ``` --- diff --git a/slides/brutos/aula_10.md b/slides/brutos/aula_10.md index 84d3b332..ee878b8b 100644 --- a/slides/brutos/aula_10.md +++ b/slides/brutos/aula_10.md @@ -274,7 +274,7 @@ Agora a session faz tudo que precisa fazer, mas sem a responsabilidade do inicia ## Criando a imagem do nosso projeto ```docker -FROM python:3.12-slim +FROM python:3.13-slim ENV POETRY_VIRTUALENVS_CREATE=false WORKDIR app/ diff --git a/slides/brutos/aula_11.md b/slides/brutos/aula_11.md index 65abc2c3..b2673918 100644 --- a/slides/brutos/aula_11.md +++ b/slides/brutos/aula_11.md @@ -49,7 +49,7 @@ flowchart RL Ubuntu -- Execute os --> Passos Ubuntu --> Z[Configure as variáveis de ambiente] subgraph Passos - A[Instale a versão 3.12 do Python] --> B[Copie os arquivos do repositório para o ambiente] + A[Instale a versão 3.13 do Python] --> B[Copie os arquivos do repositório para o ambiente] B --> C[Instale o Poetry] C --> D[Instale as dependência do projeto com Poetry] D --> E[Poetry execute os testes do projeto] @@ -72,7 +72,7 @@ jobs: - name: Instalar o python uses: actions/setup-python@v5 with: - python-version: '3.12' + python-version: '3.13' ``` --- @@ -116,7 +116,7 @@ flowchart LR - name: Instalar o python uses: actions/setup-python@v5 with: - python-version: '3.12' + python-version: '3.13' - name: Instalar o poetry run: pipx install poetry @@ -165,7 +165,7 @@ jobs: - name: Instalar o python uses: actions/setup-python@v5 with: - python-version: '3.12' + python-version: '3.13' # continua com os passos anteriormente definidos ``` diff --git a/slides/html/aula_01.html b/slides/html/aula_01.html index 4a2ea79a..b5fb8164 100644 --- a/slides/html/aula_01.html +++ b/slides/html/aula_01.html @@ -30,17 +30,17 @@ /* Code blok */div#\:\$p>svg>foreignObject>section .hljs-bullet{color:var(--text)}div#\:\$p>svg>foreignObject>section .hljs-comment{color:var(--muted)}div#\:\$p>svg>foreignObject>section .hljs-attr{color:var(--foam)}div#\:\$p>svg>foreignObject>section .hljs-punctuation{color:var(--subtle)}div#\:\$p>svg>foreignObject>section .hljs-string{color:var(--gold)}div#\:\$p>svg>foreignObject>section .hljs-title{color:var(--foam)}div#\:\$p>svg>foreignObject>section .hljs-keyword{color:var(--pine)}div#\:\$p>svg>foreignObject>section .hljs-variable{color:var(--text)}div#\:\$p>svg>foreignObject>section .hljs-literal{color:var(--rose)}div#\:\$p>svg>foreignObject>section .hljs-type{color:var(--love)}div#\:\$p>svg>foreignObject>section .hljs-number{color:var(--gold)}div#\:\$p>svg>foreignObject>section .hljs-built_in{color:var(--love)}div#\:\$p>svg>foreignObject>section .hljs-params{color:var(--iris)}div#\:\$p>svg>foreignObject>section .hljs-symbol{color:var(--foam)}div#\:\$p>svg>foreignObject>section .hljs-meta{color:var(--subtle)}div#\:\$p>svg>foreignObject>section .hljs-subst{color:var(--subtle)}div#\:\$p>svg>foreignObject>section blockquote{font-size:20px}div#\:\$p>svg>foreignObject>section blockquote p{font-size:20px}div#\:\$p>svg>foreignObject>section blockquote p a{font-size:30px}div#\:\$p>svg>foreignObject>section div.mermaid{text-align:center}div#\:\$p>svg>foreignObject>section img[alt~=center]{display:block;margin:0 auto}div#\:\$p>svg>foreignObject>section .columns{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:calc(var(--marpit-root-font-size, 1rem) * 1)}div#\:\$p>svg>foreignObject>section .mermaid{font-size:10px}div#\:\$p>svg>foreignObject>section section.mermaid{--marpit-root-font-size:10px} -/* @theme iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf */div#\:\$p>svg>foreignObject>section .columns{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:calc(var(--marpit-root-font-size, 1rem) * 1)}div#\:\$p>svg>foreignObject>section[data-marpit-scope-c0maS96S] blockquote{margin-top:60px;font-size:20px}div#\:\$p>svg>foreignObject>section[data-marpit-scope-ZBUepyLo] blockquote{margin-top:60px;font-size:20px}div#\:\$p>svg>foreignObject>section[data-marpit-scope-q1dFRKTN] blockquote{font-size:20px}div#\:\$p>svg>foreignObject>section[data-marpit-scope-X4zpLPoT] blockquote{margin-top:30px;font-size:20px}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]{columns:initial!important;display:block!important;padding:0!important}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]:after,div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]:before,div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=content]:after,div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=content]:before{display:none!important}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]>div[data-marpit-advanced-background-container]{all:initial;display:flex;flex-direction:row;height:100%;overflow:hidden;width:100%}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]>div[data-marpit-advanced-background-container][data-marpit-advanced-background-direction=vertical]{flex-direction:column}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background][data-marpit-advanced-background-split]>div[data-marpit-advanced-background-container]{width:var(--marpit-advanced-background-split,50%)}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background][data-marpit-advanced-background-split=right]>div[data-marpit-advanced-background-container]{margin-left:calc(100% - var(--marpit-advanced-background-split, 50%))}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]>div[data-marpit-advanced-background-container]>figure{all:initial;background-position:center;background-repeat:no-repeat;background-size:cover;flex:auto;margin:0}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]>div[data-marpit-advanced-background-container]>figure>figcaption{position:absolute;border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;white-space:nowrap;width:1px}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=content],div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=pseudo]{background:transparent!important}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=pseudo],div#\:\$p>svg[data-marpit-svg]>foreignObject[data-marpit-advanced-background=pseudo]{pointer-events:none!important}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background-split]{width:100%;height:100%}
+;--theme:k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79;">

01 - Configurando o Ambiente de Desenvolvimento

https://fastapidozero.dunossauro.com/01/

@@ -51,12 +51,12 @@

01 - Configurando o Amb grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -" data-theme="iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf" lang="en-US" style="--style:.columns { +" data-theme="k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79" lang="en-US" style="--style:.columns { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -;--theme:iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf;"> +;--theme:k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79;">

Objetivos dessa aula:

  • Introdução ao ambiente de desenvolvimento @@ -74,12 +74,12 @@

    Objetivos dessa aula:

    grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -" data-theme="iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf" lang="en-US" style="--style:.columns { +" data-theme="k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79" lang="en-US" style="--style:.columns { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -;--theme:iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf;"> +;--theme:k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79;">

    O ambiente de desenvolvimento

    1. Um editor de texto a sua escolha (Eu vou usar o GNU/Emacs)
    2. @@ -100,12 +100,12 @@

      O ambiente de desenvolvimento

      grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -" data-theme="iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf" lang="en-US" style="--style:.columns { +" data-theme="k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79" lang="en-US" style="--style:.columns { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -;--theme:iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf;"> +;--theme:k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79;">

      Caso seja preciso

      Materiais de qualidades e de pessoas incrível que fazem material aberto como eu:

        @@ -119,12 +119,12 @@

        Caso seja preciso

        grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -" data-theme="iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf" lang="en-US" style="--style:.columns { +" data-theme="k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79" lang="en-US" style="--style:.columns { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -;--theme:iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf;"> +;--theme:k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79;">

        Coisas opcionais que podem ajudar

        Ferramentas incríveis que tornam o gerenciamento mais simples:

          @@ -141,16 +141,16 @@

          Coisas opcionais que podem ajudar

          -

          Python 3.12

          +;--theme:k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79;"> +

          Python 3.13

          Se você precisar (re)construir o ambiente usado nesse curso, é extremamente recomendado que você use o pyenv.

          pyenv update
          -pyenv install 3.12:latest
          +pyenv install 3.13:latest
           

          Momento de uma pausa dramática!

          @@ -161,12 +161,12 @@

          Python 3.12

          grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -" data-theme="iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf" lang="en-US" style="--style:.columns { +" data-theme="k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79" lang="en-US" style="--style:.columns { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -;--theme:iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf;"> +;--theme:k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79;">

          Pyenv

          Pyenv é uma aplicação externa ao python que permite a instalação de diferentes versões do python no sistema e as isola.

          Na computação, chamamos esse conceito de shim. Uma camada, onde toda vez que o python for chamado, ele redirecionará a chamada do python ao pyenv. Uma espécie de "proxy".

          @@ -183,12 +183,12 @@

          Pyenv

          grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -" data-theme="iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf" lang="en-US" style="--style:.columns { +" data-theme="k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79" lang="en-US" style="--style:.columns { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -;--theme:iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf;"> +;--theme:k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79;">

          Instalação do pyenv

          É o famoso depende... Qual SO? Qual versão? Qual arquitetura?

            @@ -210,12 +210,12 @@

            Instalação do pyenv

            grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -" data-theme="iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf" lang="en-US" style="--style:.columns { +" data-theme="k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79" lang="en-US" style="--style:.columns { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -;--theme:iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf;"> +;--theme:k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79;">

            Poetry

            Para instalar o poetry você pode fazer a instalação recomendada pelo site ou de forma mais simplificada via pipx

            pip install pipx
            @@ -227,12 +227,12 @@ 

            Poetry

            grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -" data-theme="iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf" lang="en-US" style="--style:.columns { +" data-theme="k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79" lang="en-US" style="--style:.columns { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -;--theme:iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf;"> +;--theme:k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79;">

            Instalação das ferramentas externas

            Isso pode te ajudar a ter menos dificuldade, caso trave em algum lugar

            @@ -244,12 +244,12 @@

            Instalação das ferramen grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -" data-theme="iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf" lang="en-US" style="--style:.columns { +" data-theme="k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79" lang="en-US" style="--style:.columns { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -;--theme:iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf;"> +;--theme:k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79;">

            Estrutura base do projeto

            Vamos criar nossa estrutura com base na estrutura simples que o Poetry cria para nós.

            poetry new fast_zero
            @@ -270,19 +270,19 @@ 

            Estrutura base do projeto

            grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -" data-theme="iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf" lang="en-US" style="--style:.columns { +" data-theme="k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79" lang="en-US" style="--style:.columns { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -;--theme:iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf;"> +;--theme:k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79;">

            Contornando possíveis erros

            Para que a versão que instalamos com pyenv seja usada em nosso projeto criado com poetry, devemos dizer ao pyenv qual versão do python será usada nesse diretório:

            -
            pyenv local 3.12.6  # Essa era a maior versão do 3.12 quando escrevi
            +
            pyenv local 3.13.0  # Essa era a maior versão do 3.13 quando escrevi
             

            Em conjunto com essa instrução, devemos dizer ao poetry que usaremos essa versão em nosso projeto. Para isso vamos alterar o arquivo de configuração do projeto o pyproject.toml na raiz do projeto:

            [tool.poetry.dependencies]
            -python = "3.12.*"  # .* quer dizer qualquer versão da 3.12
            +python = "3.13.*"  # .* quer dizer qualquer versão da 3.12
             
Contornando possíveis erros grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -" data-theme="iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf" lang="en-US" style="--style:.columns { +" data-theme="k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79" lang="en-US" style="--style:.columns { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -;--theme:iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf;"> +;--theme:k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79;">

Criando o ambiente virtual

poetry install
 
@@ -305,12 +305,12 @@

Criando o ambiente virtual

grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -" data-theme="iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf" lang="en-US" style="--style:.columns { +" data-theme="k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79" lang="en-US" style="--style:.columns { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -;--theme:iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf;"> +;--theme:k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79;">

Eu sei, você quer FastAPI, veio por isso

Para instalar o fastapi

poetry add fastapi[standard]
@@ -321,12 +321,12 @@ 

Eu sei, você quer FastAPI, grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -" data-theme="iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf" lang="en-US" style="--style:.columns { +" data-theme="k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79" lang="en-US" style="--style:.columns { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -;--theme:iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf;"> +;--theme:k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79;">

Nosso olá mundo [0]

Um código python simples!

# fastzero/app.py
@@ -342,12 +342,12 @@ 

Nosso olá mundo [0]

grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -" data-theme="iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf" lang="en-US" style="--style:.columns { +" data-theme="k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79" lang="en-US" style="--style:.columns { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -;--theme:iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf;"> +;--theme:k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79;">

Nosso olá mundo [1]

from fastapi import FastAPI
 
@@ -363,12 +363,12 @@ 

Nosso olá mundo [1]

grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -" data-theme="iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf" lang="en-US" style="--style:.columns { +" data-theme="k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79" lang="en-US" style="--style:.columns { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -;--theme:iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf;"> +;--theme:k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79;">

Executando esse código

Executando esse código grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -" data-theme="iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf" lang="en-US" style="--style:.columns { +" data-theme="k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79" lang="en-US" style="--style:.columns { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -;--theme:iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf;"> +;--theme:k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79;">

Para que a execução ocorra, precisamos de um servidor

Isso inicia o servidor de desenvolvimento do FastAPI:

fastapi dev fast_zero/app.py
@@ -392,12 +392,12 @@ 

Para que grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -" data-theme="iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf" lang="en-US" style="--style:.columns { +" data-theme="k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79" lang="en-US" style="--style:.columns { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -;--theme:iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf;"> +;--theme:k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79;">

O "teste"

Se acessarmos http://localhost:8000 podemos ver nossa aplicação

@@ -406,12 +406,12 @@

O "teste"

grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -" data-theme="iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf" lang="en-US" style="--style:.columns { +" data-theme="k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79" lang="en-US" style="--style:.columns { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -;--theme:iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf;"> +;--theme:k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79;">

O swagger

Se acessarmos http://localhost:8000/docs podemos ver os endpoinds da nossa aplicação e testar os requests

O redoc

@@ -422,12 +422,12 @@

O redoc

grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -" data-theme="iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf" lang="en-US" style="--style:.columns { +" data-theme="k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79" lang="en-US" style="--style:.columns { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -;--theme:iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf;"> +;--theme:k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79;">

O ambiente de desenvolvimento

O ambiente de desenvolvimento grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -" data-theme="iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf" lang="en-US" style="--style:.columns { +" data-theme="k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79" lang="en-US" style="--style:.columns { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -;--theme:iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf;"> +;--theme:k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79;">

Para nosso ambiente vamos usar algumas ferramentas diferentes

Ferramentas de desenvolvimento são bastante pessoais. Selecionei 3 que representam bem o que esperamos de um ambiente de desenvolvimento:

    @@ -454,12 +454,12 @@

    Para noss grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -" data-theme="iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf" lang="en-US" style="--style:.columns { +" data-theme="k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79" lang="en-US" style="--style:.columns { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -;--theme:iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf;"> +;--theme:k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79;">

    Ruff

    O Ruff é uma ferramenta moderna em python, compatível com os projetos de análise estática escritos e mantidos originalmente pela comunidade no projeto PYCQA e tem duas funções principais:

      @@ -475,12 +475,12 @@

      Ruff

      grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -" data-theme="iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf" lang="en-US" style="--style:.columns { +" data-theme="k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79" lang="en-US" style="--style:.columns { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -;--theme:iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf;"> +;--theme:k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79;">

      Configurando o ruff

      Para configurar o ruff montamos a configuração em 3 tabelas distintas no arquivo pyproject.toml. Uma para as configurações globais, uma para o linter e uma para o formatador.

      A global:

      @@ -494,12 +494,12 @@

      Configurando o ruff

      grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -" data-theme="iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf" lang="en-US" style="--style:.columns { +" data-theme="k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79" lang="en-US" style="--style:.columns { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -;--theme:iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf;"> +;--theme:k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79;">

      O linter do ruff

      Durante a análise estática do código, queremos buscar por coisas específicas. No Ruff, precisamos dizer exatamente o que ele deve analisar.

        @@ -511,17 +511,17 @@

        O linter do ruff

      • PT (flake8-pytest): boas práticas do Pytest
-
+;--theme:k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79;">

Configuração no pyproject.toml

[tool.ruff.lint]
 preview = true
@@ -532,17 +532,17 @@ 

Configuração no pyproject.tom

Para mais informações sobre a configuração e sobre os códigos do ruff e dos projetos do PyCQA, você pode checar a documentação do ruff ou as documentações originais dos projetos PyQCA.

-
+;--theme:k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79;">

Formatador do ruff

A formatação do Ruff praticamente não precisa ser alterada. Pois ele vai seguir as boas práticas e usar a configuração global de 79 caracteres por linha. A única alteração que farei é o uso de aspas simples ' no lugar de aspas duplas ":

[tool.ruff.format]
@@ -559,12 +559,12 @@ 

Formatador do ruff

grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -" data-theme="iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf" lang="en-US" style="--style:.columns { +" data-theme="k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79" lang="en-US" style="--style:.columns { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -;--theme:iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf;"> +;--theme:k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79;">

Usando o ruff

O ruff é feito para ser usado no terminal, alguns comandos são bem interessantes. Como:

    @@ -577,12 +577,12 @@

    Usando o ruff

    grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -" data-theme="iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf" lang="en-US" style="--style:.columns { +" data-theme="k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79" lang="en-US" style="--style:.columns { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -;--theme:iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf;"> +;--theme:k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79;">

    Pytest

    O Pytest é uma framework de testes, que usaremos para escrever e executar nossos testes. O configuraremos para reconhecer o caminho base para execução dos testes na raiz do projeto .:

    poetry add --group dev pytest pytest-cov
    @@ -594,12 +594,12 @@ 

    Pytest

    grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -" data-theme="iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf" lang="en-US" style="--style:.columns { +" data-theme="k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79" lang="en-US" style="--style:.columns { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -;--theme:iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf;"> +;--theme:k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79;">

    Configuração do pytest

    O configuraremos para reconhecer o caminho base para execução dos testes na raiz do projeto .:

    [tool.pytest.ini_options]
    @@ -613,29 +613,29 @@ 

    Configuração do pytest

    grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -" data-theme="iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf" lang="en-US" style="--style:.columns { +" data-theme="k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79" lang="en-US" style="--style:.columns { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -;--theme:iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf;"> +;--theme:k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79;">

    Com isso podemos ver o que está ou não testado

    pytest --cov=fast_zero -vv
     coverage html
     

    Queremos ver a cobertura do código e os erros de forma verbosa

-
+;--theme:k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79;">

Taskipy

Bom, esses comandos são bem difíceis de lembrar e mais chatos ainda de digitar.

ruff check . && ruff format .       # Para checar e formatar
@@ -656,12 +656,12 @@ 

Taskipy

grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -" data-theme="iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf" lang="en-US" style="--style:.columns { +" data-theme="k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79" lang="en-US" style="--style:.columns { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -;--theme:iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf;"> +;--theme:k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79;">

Instalação e Configuração do taskpy

Instalação:

poetry add --group dev taskipy
@@ -673,17 +673,17 @@ 

Instalação e post_test = 'coverage html'

-
+;--theme:k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79;">

Juntando comandos com taskipy

Alguns comandos fazem mais sentido quando compostos. Queremos fazer mais, com menos comandos:

[tool.taskipy.tasks]
@@ -699,12 +699,12 @@ 

Juntando comandos com taskipy

grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -" data-theme="iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf" lang="en-US" style="--style:.columns { +" data-theme="k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79" lang="en-US" style="--style:.columns { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -;--theme:iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf;"> +;--theme:k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79;">

Cadeia de comandos com taskipy

Em outros momentos, queremos fazer uma coisa, só se a primeira der certo, para isso podemos fazer:

pre_test = 'task lint'
@@ -718,12 +718,12 @@ 

Cadeia de comandos com taskipy

grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -" data-theme="iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf" lang="en-US" style="--style:.columns { +" data-theme="k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79" lang="en-US" style="--style:.columns { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -;--theme:iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf;"> +;--theme:k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79;">

Testando o nosso hello world

Dentro da pasta test vamos criar um arquivo chamado test_app.py

from fastapi.testclient import TestClient
@@ -737,12 +737,12 @@ 

Testando o nosso hello world

grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -" data-theme="iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf" lang="en-US" style="--style:.columns { +" data-theme="k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79" lang="en-US" style="--style:.columns { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -;--theme:iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf;"> +;--theme:k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79;">

Testando de fato

from http import HTTPStatus
 from fastapi.testclient import TestClient
@@ -763,12 +763,12 @@ 

Testando de fato

grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -" data-theme="iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf" lang="en-US" style="--style:.columns { +" data-theme="k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79" lang="en-US" style="--style:.columns { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -;--theme:iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf;"> +;--theme:k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79;">

A estrutura de um teste

A estrutura de um teste, costuma contar com 3 ou 4 fases importantes.

    @@ -783,12 +783,12 @@

    A estrutura de um teste

    grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -" data-theme="iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf" lang="en-US" style="--style:.columns { +" data-theme="k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79" lang="en-US" style="--style:.columns { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -;--theme:iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf;"> +;--theme:k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79;">

    Commit

    ignr -p python > .gitignore
     git init .
    @@ -800,12 +800,12 @@ 

    Commit

    grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -" data-theme="iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf" lang="en-US" style="--style:.columns { +" data-theme="k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79" lang="en-US" style="--style:.columns { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } -;--theme:iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf;"> +;--theme:k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79;">

    Exercício

    Crie um repositório para acompanhar o curso e suba em alguma plataforma, como Github, gitlab, codeberg, etc. E compartilhe o link no repositório do curso para podermos aprender juntos.

    diff --git a/slides/html/aula_10.html b/slides/html/aula_10.html index 2f811e1f..d41b7f4b 100644 --- a/slides/html/aula_10.html +++ b/slides/html/aula_10.html @@ -30,13 +30,13 @@ /* Code blok */div#\:\$p>svg>foreignObject>section .hljs-bullet{color:var(--text)}div#\:\$p>svg>foreignObject>section .hljs-comment{color:var(--muted)}div#\:\$p>svg>foreignObject>section .hljs-attr{color:var(--foam)}div#\:\$p>svg>foreignObject>section .hljs-punctuation{color:var(--subtle)}div#\:\$p>svg>foreignObject>section .hljs-string{color:var(--gold)}div#\:\$p>svg>foreignObject>section .hljs-title{color:var(--foam)}div#\:\$p>svg>foreignObject>section .hljs-keyword{color:var(--pine)}div#\:\$p>svg>foreignObject>section .hljs-variable{color:var(--text)}div#\:\$p>svg>foreignObject>section .hljs-literal{color:var(--rose)}div#\:\$p>svg>foreignObject>section .hljs-type{color:var(--love)}div#\:\$p>svg>foreignObject>section .hljs-number{color:var(--gold)}div#\:\$p>svg>foreignObject>section .hljs-built_in{color:var(--love)}div#\:\$p>svg>foreignObject>section .hljs-params{color:var(--iris)}div#\:\$p>svg>foreignObject>section .hljs-symbol{color:var(--foam)}div#\:\$p>svg>foreignObject>section .hljs-meta{color:var(--subtle)}div#\:\$p>svg>foreignObject>section .hljs-subst{color:var(--subtle)}div#\:\$p>svg>foreignObject>section blockquote{font-size:20px}div#\:\$p>svg>foreignObject>section blockquote p{font-size:20px}div#\:\$p>svg>foreignObject>section blockquote p a{font-size:30px}div#\:\$p>svg>foreignObject>section div.mermaid{text-align:center}div#\:\$p>svg>foreignObject>section img[alt~=center]{display:block;margin:0 auto}div#\:\$p>svg>foreignObject>section .columns{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:calc(var(--marpit-root-font-size, 1rem) * 1)}div#\:\$p>svg>foreignObject>section .mermaid{font-size:10px}div#\:\$p>svg>foreignObject>section section.mermaid{--marpit-root-font-size:10px} -/* @theme iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf */div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]{columns:initial!important;display:block!important;padding:0!important}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]:after,div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]:before,div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=content]:after,div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=content]:before{display:none!important}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]>div[data-marpit-advanced-background-container]{all:initial;display:flex;flex-direction:row;height:100%;overflow:hidden;width:100%}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]>div[data-marpit-advanced-background-container][data-marpit-advanced-background-direction=vertical]{flex-direction:column}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background][data-marpit-advanced-background-split]>div[data-marpit-advanced-background-container]{width:var(--marpit-advanced-background-split,50%)}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background][data-marpit-advanced-background-split=right]>div[data-marpit-advanced-background-container]{margin-left:calc(100% - var(--marpit-advanced-background-split, 50%))}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]>div[data-marpit-advanced-background-container]>figure{all:initial;background-position:center;background-repeat:no-repeat;background-size:cover;flex:auto;margin:0}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]>div[data-marpit-advanced-background-container]>figure>figcaption{position:absolute;border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;white-space:nowrap;width:1px}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=content],div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=pseudo]{background:transparent!important}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=pseudo],div#\:\$p>svg[data-marpit-svg]>foreignObject[data-marpit-advanced-background=pseudo]{pointer-events:none!important}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background-split]{width:100%;height:100%}
    +/* @theme k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79 */div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]{columns:initial!important;display:block!important;padding:0!important}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]:after,div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]:before,div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=content]:after,div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=content]:before{display:none!important}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]>div[data-marpit-advanced-background-container]{all:initial;display:flex;flex-direction:row;height:100%;overflow:hidden;width:100%}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]>div[data-marpit-advanced-background-container][data-marpit-advanced-background-direction=vertical]{flex-direction:column}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background][data-marpit-advanced-background-split]>div[data-marpit-advanced-background-container]{width:var(--marpit-advanced-background-split,50%)}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background][data-marpit-advanced-background-split=right]>div[data-marpit-advanced-background-container]{margin-left:calc(100% - var(--marpit-advanced-background-split, 50%))}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]>div[data-marpit-advanced-background-container]>figure{all:initial;background-position:center;background-repeat:no-repeat;background-size:cover;flex:auto;margin:0}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]>div[data-marpit-advanced-background-container]>figure>figcaption{position:absolute;border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;white-space:nowrap;width:1px}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=content],div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=pseudo]{background:transparent!important}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=pseudo],div#\:\$p>svg[data-marpit-svg]>foreignObject[data-marpit-advanced-background=pseudo]{pointer-events:none!important}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background-split]{width:100%;height:100%}

    Dockerizando a nossa aplicação e introduzindo o PostgreSQL

    https://fastapidozero.dunossauro.com/10/

    -
    +

    Objetivos dessa aula

    • Entender como criar uma imagem Docker para a nossa aplicação
    • @@ -46,13 +46,13 @@

      Objetivos dessa aula

    • Entender os benefícios e motivos da mudança para o PostgreSQL
    -
    +

    Parte 1

    Docker e Postgres

    -
    +

    Docker

    Docker é uma ferramenta para criar containers.

    Containers são formas de isolar as dependências. Da mesma forma que fazemos com o ambiente virtual. Que isolam as dependências do python.

    @@ -61,7 +61,7 @@

    Docker

    Cruso gratuito sobre docker da linuxtips

    -
    +

    PostgreSQL

    Um Banco de Dados Relacional de código aberto.

      @@ -70,13 +70,13 @@

      PostgreSQL

    • Funcionalidades avançadas: PostgreSQL vem com várias extensões e funcionalidades que o SQLite pode não oferecer.
    -
    +

    Nota importante

    Embora para o escopo da nossa aplicação e os objetivos de aprendizado o SQLite pudesse ser suficiente, é sempre bom nos prepararmos para cenários de produção real. A adoção de PostgreSQL nos dá uma prévia das práticas do mundo real e garante que nossa aplicação possa escalar sem grandes modificações de infraestrutura.

    -
    +

    Executando o postgres com docker

    docker run \
         --name app_database \
    @@ -88,7 +88,7 @@ 

    Executando o postgres com docker

    Essa instrução vai iniciar um container do postgres no nosso pc e disponibilizando ele na porta 5432.

    -
    +

    Conectando nossa aplicação ao postgres

    Precisamos instalar o driver para o postgres na nossa aplicação:

    poetry add "psycopg[binary]"
    @@ -98,12 +98,12 @@ 

    Conectando nossa aplic DATABASE_URL="postgresql+psycopg://app_user:app_password@127.0.0.1:5432/app_db"

    -
    +

    Subindo a aplicação

    task run
     
    -
    +

    Erro na migração

    Ao fazer uma chamada que depende do banco de dados, vamos obter um:

    Internal Server Error

    @@ -113,7 +113,7 @@

    Erro na migração

    A tabela users não existe na nossa aplicação.

    -
    +

    Executando as migrações no novo banco

    alembic upgrade head
     INFO  [alembic.runtime.migration] Context impl PostgresqlImpl.
    @@ -123,7 +123,7 @@ 

    Executando as migraçõ

    Com isso, tudo deve funcionar como esperado!

    -
    +

    Os testes envolvendo o postgres

    Se executarmos os testes, eles vão continuar passando, pois os dados estão fixos na fixture:

    @pytest.fixture
    @@ -136,7 +136,7 @@ 

    Os testes envolvendo o postgres

    # ...
    -
    +

    Usando as variáveis de ambiente no teste

    from fast_zero.settings import Settings
     # ...
    @@ -148,7 +148,7 @@ 

    Usando as variáveis de a

    Porém, agora temos um novo problema :)

    -
    +

    O container do banco de dados precisa estar rodando

    E           sqlalchemy.exc.OperationalError: (psycopg.OperationalError) connection failed:
     E    connection to server at "127.0.0.1", port 5432 failed: Connection refused
    @@ -158,14 +158,14 @@ 

    O container do banc OperationalError

    -
    +

    Testando com Docker

    Existe uma biblioteca python que gerencia as dependências de containers externos para que a aplicação seja executada. O TestContainers

    Para instalar:

    poetry add --group dev testcontainers
     
    -
    +

    Alterando a fixture para usar o TestContainer

    from testcontainers.postgres import PostgresContainer 
     # ...
    @@ -183,7 +183,7 @@ 

    Alterando a fixture para

    Assim os testes podem iniciar um container novo a cada vez que a fixture for chamada

    -
    +

    O escopo da fixture

    sequenceDiagram @@ -193,7 +193,7 @@

    O escopo da fixture

    PytestRunner-->>Fixture: Executa a fixture depois do yield
    -
    +

    Diferentes escopos

    • function: executada em todas as funções de teste;
    • @@ -204,7 +204,7 @@

      Diferentes escopos

    Para resolver o problema com a lentidão dos testes, iremos criar uma fixture para iniciar o container do banco de dados com o escopo session.

    -
    +

    Criando uma nova fixture

    Para criar um única imagem docker, podemos iniciar ela de forma isolada na aplicação

    @pytest.fixture(scope='session')
    @@ -217,7 +217,7 @@ 

    Criando uma nova fixture

    yield _engine
    -
    +

    Alterando a fixture de session

    @pytest.fixture
     def session(engine):
    @@ -231,15 +231,15 @@ 

    Alterando a fixture de session

    Agora a session faz tudo que precisa fazer, mas sem a responsabilidade do iniciar a conexão

    -
    +

    Parte 2

    Criando a imagem do nosso projeto

    -
    +

    Criando a imagem do nosso projeto

    -
    FROM python:3.12-slim
    +
    FROM python:3.13-slim
     ENV POETRY_VIRTUALENVS_CREATE=false
     
     WORKDIR app/
    @@ -254,7 +254,7 @@ 

    Criando a imagem do nosso projeto

    CMD poetry run uvicorn --host 0.0.0.0 fast_zero.app:app
    -
    +

    Rodando o código

    # Criar a imagem
     docker build -t "fast_zero" .
    @@ -265,18 +265,18 @@ 

    Rodando o código

    Podemos acessar para ver nossa aplicação http://127.0.0.1:8000/docs

    -
    +

    Parte 3

    Docker compose

    -
    +

    Docker compose

    A ideia do docker compose é criar um único arquivo yaml que reúna todos os containers necessários para executar a aplicação.

    Dessa forma podemos gerenciar todos os os containers com um único comando o docker compose.

    -
    +

    O banco de dados

    services:
       fastzero_database:
    @@ -294,7 +294,7 @@ 

    O banco de dados

    pgdata:
    -
    +

    A aplicação

      fastzero_app:
         image: fastzero_app
    @@ -307,16 +307,16 @@ 

    A aplicação

    DATABASE_URL: postgresql+psycopg://app_user:app_password@fastzero_database:5432/app_db
    -
    +

    Rodando tudo

    docker compose up
     
    -
    +

    Funciona?

    Não ... migrações ...

    -
    +

    Entrypoint

    A ideia do entrypoint é alterar o comando CMD para executar um script bash.

    #!/bin/sh
    @@ -329,7 +329,7 @@ 

    Entrypoint

    Assim que o container for inciado, ele executará esse script.

    -
    +

    Entrypoint no compose

      fastzero_app:
         image: fastzero_app
    @@ -337,12 +337,12 @@ 

    Entrypoint no compose

    build: .
    -
    +

    Refazendo o container

    docker-compose up --build
     
    -
    +

    Não esqueça de responder ao quiz

    Quiz

    diff --git a/slides/html/aula_11.html b/slides/html/aula_11.html index ff81f127..aa8e2561 100644 --- a/slides/html/aula_11.html +++ b/slides/html/aula_11.html @@ -30,13 +30,13 @@ /* Code blok */div#\:\$p>svg>foreignObject>section .hljs-bullet{color:var(--text)}div#\:\$p>svg>foreignObject>section .hljs-comment{color:var(--muted)}div#\:\$p>svg>foreignObject>section .hljs-attr{color:var(--foam)}div#\:\$p>svg>foreignObject>section .hljs-punctuation{color:var(--subtle)}div#\:\$p>svg>foreignObject>section .hljs-string{color:var(--gold)}div#\:\$p>svg>foreignObject>section .hljs-title{color:var(--foam)}div#\:\$p>svg>foreignObject>section .hljs-keyword{color:var(--pine)}div#\:\$p>svg>foreignObject>section .hljs-variable{color:var(--text)}div#\:\$p>svg>foreignObject>section .hljs-literal{color:var(--rose)}div#\:\$p>svg>foreignObject>section .hljs-type{color:var(--love)}div#\:\$p>svg>foreignObject>section .hljs-number{color:var(--gold)}div#\:\$p>svg>foreignObject>section .hljs-built_in{color:var(--love)}div#\:\$p>svg>foreignObject>section .hljs-params{color:var(--iris)}div#\:\$p>svg>foreignObject>section .hljs-symbol{color:var(--foam)}div#\:\$p>svg>foreignObject>section .hljs-meta{color:var(--subtle)}div#\:\$p>svg>foreignObject>section .hljs-subst{color:var(--subtle)}div#\:\$p>svg>foreignObject>section blockquote{font-size:20px}div#\:\$p>svg>foreignObject>section blockquote p{font-size:20px}div#\:\$p>svg>foreignObject>section blockquote p a{font-size:30px}div#\:\$p>svg>foreignObject>section div.mermaid{text-align:center}div#\:\$p>svg>foreignObject>section img[alt~=center]{display:block;margin:0 auto}div#\:\$p>svg>foreignObject>section .columns{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:calc(var(--marpit-root-font-size, 1rem) * 1)}div#\:\$p>svg>foreignObject>section .mermaid{font-size:10px}div#\:\$p>svg>foreignObject>section section.mermaid{--marpit-root-font-size:10px} -/* @theme iyyh2866o7dw2fbrrlm9ub03n0zaylvan8iszae7enf */div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]{columns:initial!important;display:block!important;padding:0!important}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]:after,div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]:before,div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=content]:after,div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=content]:before{display:none!important}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]>div[data-marpit-advanced-background-container]{all:initial;display:flex;flex-direction:row;height:100%;overflow:hidden;width:100%}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]>div[data-marpit-advanced-background-container][data-marpit-advanced-background-direction=vertical]{flex-direction:column}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background][data-marpit-advanced-background-split]>div[data-marpit-advanced-background-container]{width:var(--marpit-advanced-background-split,50%)}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background][data-marpit-advanced-background-split=right]>div[data-marpit-advanced-background-container]{margin-left:calc(100% - var(--marpit-advanced-background-split, 50%))}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]>div[data-marpit-advanced-background-container]>figure{all:initial;background-position:center;background-repeat:no-repeat;background-size:cover;flex:auto;margin:0}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]>div[data-marpit-advanced-background-container]>figure>figcaption{position:absolute;border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;white-space:nowrap;width:1px}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=content],div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=pseudo]{background:transparent!important}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=pseudo],div#\:\$p>svg[data-marpit-svg]>foreignObject[data-marpit-advanced-background=pseudo]{pointer-events:none!important}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background-split]{width:100%;height:100%}
    +/* @theme k4k1jvqw2uhobima29g6lp5dg66ahxp93t26vp83qc79 */div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]{columns:initial!important;display:block!important;padding:0!important}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]:after,div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]:before,div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=content]:after,div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=content]:before{display:none!important}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]>div[data-marpit-advanced-background-container]{all:initial;display:flex;flex-direction:row;height:100%;overflow:hidden;width:100%}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]>div[data-marpit-advanced-background-container][data-marpit-advanced-background-direction=vertical]{flex-direction:column}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background][data-marpit-advanced-background-split]>div[data-marpit-advanced-background-container]{width:var(--marpit-advanced-background-split,50%)}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background][data-marpit-advanced-background-split=right]>div[data-marpit-advanced-background-container]{margin-left:calc(100% - var(--marpit-advanced-background-split, 50%))}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]>div[data-marpit-advanced-background-container]>figure{all:initial;background-position:center;background-repeat:no-repeat;background-size:cover;flex:auto;margin:0}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]>div[data-marpit-advanced-background-container]>figure>figcaption{position:absolute;border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;white-space:nowrap;width:1px}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=content],div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=pseudo]{background:transparent!important}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=pseudo],div#\:\$p>svg[data-marpit-svg]>foreignObject[data-marpit-advanced-background=pseudo]{pointer-events:none!important}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background-split]{width:100%;height:100%}

    Automatizando os testes com Integração Contínua (CI)

    https://fastapidozero.dunossauro.com/11/

    -
    +

    Objetivos da aula

    • Compreender a prática de Integração Contínua (CI)
    • @@ -44,7 +44,7 @@

      Objetivos da aula

    • Configurar um pipeline de CI para nossa aplicação que execute testes
    -
    +

    Integração contínua (CI)

    Integração Contínua (CI) é uma prática de desenvolvimento que envolve a integração regular do código-fonte ao repositório principal, acompanhada de testes automatizados para garantir a qualidade.

    @@ -59,11 +59,11 @@

    Integração contínua (CI)

    não --> id1["Envia uma notificação"]
    -
    +

    Github Actions

    Entre as ferramentas disponíveis para CI, o GitHub Actions é um serviço do GitHub que automatiza workflows dentro do seu repositório. Você pode configurar o GitHub Actions para executar ações específicas — como testes automatizados — cada vez que um novo código é commitado no repositório.

    -
    +

    Nosso workflow

    flowchart RL @@ -71,14 +71,14 @@

    Nosso workflow

    Ubuntu -- Execute os --> Passos Ubuntu --> Z[Configure as variáveis de ambiente] subgraph Passos - A[Instale a versão 3.12 do Python] --> B[Copie os arquivos do repositório para o ambiente] + A[Instale a versão 3.13 do Python] --> B[Copie os arquivos do repositório para o ambiente] B --> C[Instale o Poetry] C --> D[Instale as dependência do projeto com Poetry] D --> E[Poetry execute os testes do projeto] end
    -
    +

    Iniciando nosso flow

    name: Pipeline
     on: [push, pull_request]
    @@ -91,10 +91,10 @@ 

    Iniciando nosso flow

    - name: Instalar o python uses: actions/setup-python@v5 with: - python-version: '3.12' + python-version: '3.13'
    -
    +

    Executando o CI

    Pra ver o CI rodando, precisamos fazer commit no repositório:

    git add .
    @@ -105,7 +105,7 @@ 

    Executando o CI

    Vamos ver o que acontece repositório

    -
    +

    Passos do CI

    Para executar nossos testes no workflow, precisamos seguir alguns passos essenciais:

      @@ -121,13 +121,13 @@

      Passos do CI

      Deps --> Testes["4: Executar os testes via Poetry"]
    -
    +

    Codando esse fluxo

        steps:
           - name: Instalar o python
             uses: actions/setup-python@v5
             with:
    -          python-version: '3.12'
    +          python-version: '3.13'
     
           - name: Instalar o poetry
             run: pipx install poetry
    @@ -139,7 +139,7 @@ 

    Codando esse fluxo

    run: poetry run task test
    -
    +

    Vamos ver o que deu

    git add .
     git commit -m "Adicionando passos para executar os testes no CI"
    @@ -149,12 +149,12 @@ 

    Vamos ver o que deu

    Repositório

    -
    +

    ERRO!

    Poetry could not find a pyproject.toml file in <path> or its parents
     
    -
    +

    Precisamos copiar os arquivos para o CI

    jobs:
       test:
    @@ -167,12 +167,12 @@ 

    Precisamos copiar os arquivos p - name: Instalar o python uses: actions/setup-python@v5 with: - python-version: '3.12' + python-version: '3.13' # continua com os passos anteriormente definidos

    -
    +

    Vamos pra mais um erro!

    git add .
     git commit -m "Adicionando o checkout ao pipeline"
    @@ -182,7 +182,7 @@ 

    Vamos pra mais um erro!

    Repositório

    -
    +

    Variáveis de ambiente no CI

    USEM O GH, dito isso...

    gh secret set -f .env
    @@ -191,7 +191,7 @@ 

    Variáveis de ambiente no CI

    Caso contrário

    -
    +

    Dando acesso o CI

    jobs:
       test:
    @@ -204,14 +204,14 @@ 

    Dando acesso o CI

    ACCESS_TOKEN_EXPIRE_MINUTES: ${{ secrets.ACCESS_TOKEN_EXPIRE_MINUTES }}
    -
    +

    Outro commit ...

    git add .
     git commit -m "Adicionando as variáveis de ambiente para o CI"
     git push
     
    -
    +

    Quiz

    Não esqueça de responder o quiz!

    diff --git a/slides/pdf/aula_01.pdf b/slides/pdf/aula_01.pdf index 2f153304..338a8960 100644 Binary files a/slides/pdf/aula_01.pdf and b/slides/pdf/aula_01.pdf differ diff --git a/slides/pdf/aula_10.pdf b/slides/pdf/aula_10.pdf index c7cef4e6..5dd3cb14 100644 Binary files a/slides/pdf/aula_10.pdf and b/slides/pdf/aula_10.pdf differ diff --git a/slides/pdf/aula_11.pdf b/slides/pdf/aula_11.pdf index b332c899..0fec4b5f 100644 Binary files a/slides/pdf/aula_11.pdf and b/slides/pdf/aula_11.pdf differ