{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# El proyecto final\n",
    "\n",
    "Junta todo el libro en un repositorio que puedas enseñar\n",
    "\n",
    "Cuaderno de soluciones del capítulo 32 de **Git desde cero**, de Miss Yera.\n",
    "\n",
    "Corre de arriba abajo. Si lo abres en Google Colab no necesitas instalar nada.\n",
    "\n",
    "Capítulo completo: https://missyera.com/guias/git-desde-cero/proyecto-final/\n",
    "\n",
    "Este es el cuaderno de **soluciones**. Trae el código de cada ejercicio, la\n",
    "explicación de la trampa y la respuesta del quiz. Si vienes del cuaderno de\n",
    "práctica sin haberlo intentado, vuelve 🙂"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Antes de empezar\n",
    "\n",
    "Este capítulo son comandos de terminal, no Python. La celda de abajo baja el\n",
    "ayudante que los ejecuta y que **recuerda en qué carpeta quedaste**, que es lo\n",
    "que hace falta para que un `cd` de una celda siga valiendo en la siguiente.\n",
    "\n",
    "A partir de ahí, cada celda de comandos empieza por `%%consola`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import urllib.request\n",
    "\n",
    "# El ayudante de los cuadernos. Trae la corrección de los ejercicios y, en los\n",
    "# capítulos de consola, la celda mágica que ejecuta los comandos. Se baja en\n",
    "# vez de venir pegado aquí para que siempre sea el último.\n",
    "urllib.request.urlretrieve(\n",
    "    \"https://missyera.com/static/cuadernos/revisa.py\", \"revisa.py\")\n",
    "import revisa\n",
    "revisa.carga({}, lenguaje=\"bash\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Treinta y un capítulos después, toca juntarlo. Y no en un resumen: en un\n",
    "repositorio que puedas mandar por WhatsApp y que hable bien de ti 🏆"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Las siete piezas"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "| Pieza | Capítulo | Qué demuestra |\n",
    "|---|---|---|\n",
    "| README con instrucciones | 18 | Que piensas en quien llega |\n",
    "| `.gitignore` | 9 | Que sabes qué no va |\n",
    "| Licencia | 16 | Que sabes lo que estás publicando |\n",
    "| Commits legibles | 5 | Cómo trabajas |\n",
    "| Una rama fusionada | 10 | Que no trabajas todo en main |\n",
    "| Una versión etiquetada | 24 | Que piensas en quien lo usa |\n",
    "| Revisión automática | 31 | Que compruebas lo que entregas |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Paso 1: la base"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "mkdir ventas-miss-yera\n",
    "cd ventas-miss-yera\n",
    "git init -q\n",
    "printf 'ciudad,monto\\nLima,1200\\nArequipa,890\\nCusco,760\\n' > ventas.csv\n",
    "printf 'API_KEY=no-deberia-estar-aqui\\n' > .env\n",
    "printf '.env\\n__pycache__/\\n' > .gitignore\n",
    "git add ventas.csv .gitignore\n",
    "git commit -q -m \"Primeras ventas por ciudad\"\n",
    "git status --short\n",
    "git ls-files"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Fíjate en que el `.env` existe en la carpeta y no está en la\n",
    "lista. Primera pieza colocada 🚫"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Paso 2: el README y la licencia"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "cat > README.md <<'FIN'\n",
    "# Ventas Miss Yera\n",
    "\n",
    "Calcula el total de ventas por ciudad a partir de un CSV.\n",
    "\n",
    "## Necesitas\n",
    "- Bash\n",
    "\n",
    "## Usar\n",
    "```\n",
    "bash total.sh ventas.csv\n",
    "```\n",
    "\n",
    "Devuelve el monto total de todas las ciudades.\n",
    "FIN\n",
    "printf 'MIT License\\n\\nCopyright (c) 2026 Gera Flores\\n' > LICENSE\n",
    "git add README.md LICENSE\n",
    "git commit -q -m \"Se agregan el README y la licencia MIT\"\n",
    "git ls-files"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Paso 3: el trabajo, en su rama"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "git switch -q -c calcula-el-total\n",
    "cat > total.sh <<'FIN'\n",
    "tail -n +2 \"$1\" | cut -d, -f2 | paste -sd+ | bc\n",
    "FIN\n",
    "git add total.sh\n",
    "git commit -q -m \"Se agrega el calculo del total por ciudad\n",
    "\n",
    "Lee el CSV, se salta la cabecera y suma la segunda columna.\"\n",
    "bash total.sh ventas.csv\n",
    "git log --oneline"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Funciona. Y el commit tiene cuerpo, que es lo que va a leer quien mire tu\n",
    "historia dentro de un año 📖"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Paso 4: fusionar dejando rastro"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "git switch -q main\n",
    "git merge -q --no-ff -m \"Entra el calculo del total por ciudad\" calcula-el-total\n",
    "git branch -d calcula-el-total\n",
    "git log --oneline --topo-order\n",
    "git branch"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "El `--no-ff` deja escrito que hubo una rama, y borrarla después\n",
    "deja la lista limpia. Así se ve un repositorio donde alguien trabajó ordenado 🌿\n",
    "\n",
    "Ese `--topo-order` es el único invitado nuevo de este capítulo, y\n",
    "está por un motivo concreto: sin él, `git log` ordena por la hora de\n",
    "cada commit, y como los tuyos los vas a hacer en otro orden que yo, la lista te\n",
    "saldría distinta a la de aquí. Con él manda la forma de la historia y no el\n",
    "reloj, así que a ti te sale exactamente esto 🕰️"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Paso 5: la revisión automática"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "mkdir -p .github/workflows\n",
    "cat > .github/workflows/revisa.yml <<'FIN'\n",
    "name: Revisa el CSV de ventas\n",
    "\n",
    "on:\n",
    "  push:\n",
    "  pull_request:\n",
    "\n",
    "jobs:\n",
    "  revisar:\n",
    "    runs-on: ubuntu-latest\n",
    "    steps:\n",
    "      - uses: actions/checkout@v4\n",
    "      - run: |\n",
    "          tail -n +2 ventas.csv | cut -d, -f2 | grep -q '^$' && exit 1\n",
    "          echo \"CSV correcto\"\n",
    "FIN\n",
    "git add .github\n",
    "git commit -q -m \"Se revisa el CSV en cada push\"\n",
    "tail -n +2 ventas.csv | cut -d, -f2 | grep -q '^$' && exit 1\n",
    "echo \"la revision pasa\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Paso 6: la primera versión"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "git tag -a v1.0 -m \"Primera version del reporte por ciudad\"\n",
    "git tag\n",
    "git describe --tags\n",
    "git log --oneline --decorate -1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Paso 7: publicarlo"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "cd ..\n",
    "git init -q --bare servidor.git\n",
    "cd ventas-miss-yera\n",
    "git remote add origin ../servidor.git\n",
    "git push -q -u origin main\n",
    "git push -q origin --tags\n",
    "git ls-remote origin"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Con GitHub la única diferencia es la dirección, y ahí lo que sigue es entrar\n",
    "a la web, comprobar que el repositorio esté como quieres y decidir si va público\n",
    "o privado. Todo lo demás ya está hecho 🚀"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## La revisión final"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "echo \"== que se publica ==\" && git ls-files\n",
    "echo \"== historia ==\" && git log --oneline --topo-order\n",
    "echo \"== versiones ==\" && git tag\n",
    "echo \"== nada suelto ==\" && git status --short && echo \"limpio\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Siete archivos, historia legible, una versión marcada y nada pendiente. Eso\n",
    "es un repositorio que se puede enseñar 🎓"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### La trampa\n",
    "\n",
    "Terminas tu proyecto, lo subes a GitHub y lo pones en tu currículum. Nadie lo abre dos veces.\n",
    "\n",
    "```\n",
    "$ git ls-files\n",
    "analisis.py\n",
    "datos.csv\n",
    "notebook.ipynb\n",
    "prueba2.py\n",
    "prueba_final.py\n",
    "prueba_final_v2.py\n",
    "```\n",
    "\n",
    "**Qué está mal**\n",
    "\n",
    "Un repositorio sin README y con tres pruebas finales 😬\n",
    "\n",
    "Quien entra a tu proyecto le da treinta segundos. En esos treinta segundos tiene que entender qué hace, ver que se puede ejecutar y llevarse la impresión de que trabajas ordenado.\n",
    "\n",
    "Los nombres `prueba_final_v2` cuentan justo lo contrario, y son exactamente el problema del capítulo 1 que este libro vino a resolver.\n",
    "\n",
    "Un proyecto de portafolio necesita tres cosas: **README con instrucciones, historia de commits legible y nada de archivos sueltos**. Eso pesa más que el código."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Comprueba que se entendió"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Comprueba que lo tienes\n",
    "\n",
    "Vas a poner un repositorio en tu currículum. ¿Qué mira primero quien lo abra?\n",
    "\n",
    "a) El README y si se entiende qué hace\n",
    "\n",
    "b) La cantidad de commits\n",
    "\n",
    "c) El lenguaje que aparece arriba\n",
    "\n",
    "d) Las estrellas que tenga\n",
    "\n",
    "---\n",
    "\n",
    "**La correcta es la a.**\n",
    "\n",
    "*b)* Un número alto no dice nada por sí solo, y uno bajo tampoco resta.\n",
    "\n",
    "*c)* Da contexto, pero no responde a qué hace el proyecto ni cómo se ejecuta.\n",
    "\n",
    "*d)* Un proyecto de portafolio recién publicado no va a tener ninguna, y no hace falta.\n",
    "\n",
    "Treinta segundos: qué hace, cómo se ejecuta, y que se vea ordenado 🎓"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Ejercicios"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1. Arranca tu repositorio con lo que no va\n",
    "\n",
    "Base del catálogo, con `.gitignore` desde el\n",
    "primer commit."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "cd ..\n",
    "mkdir catalogo-bodegas\n",
    "cd catalogo-bodegas\n",
    "git init -q\n",
    "printf 'bodega,ciudad,monto\\nBodega Inti,Cusco,760\\n' > bodegas.csv\n",
    "printf 'API_KEY=fuera\\n' > .env\n",
    "printf '.env\\n' > .gitignore\n",
    "git add bodegas.csv .gitignore\n",
    "git commit -q -m \"Catalogo inicial de bodegas\"\n",
    "git ls-files\n",
    "git status --short"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    ".gitignore\n",
    "bodegas.csv\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "El `.env` ni aparece. Así se empieza 🚫"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2. Ponle portada y licencia\n",
    "\n",
    "Las dos piezas que se miran primero."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "cat > README.md <<'FIN'\n",
    "# Catalogo de bodegas\n",
    "\n",
    "Lista de bodegas por ciudad con su venta mensual.\n",
    "\n",
    "## Usar\n",
    "```\n",
    "bash total.sh bodegas.csv\n",
    "```\n",
    "FIN\n",
    "printf 'MIT License\\n\\nCopyright (c) 2026 Gera Flores\\n' > LICENSE\n",
    "git add README.md LICENSE\n",
    "git commit -q -m \"Se agregan el README y la licencia MIT\"\n",
    "git ls-files"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    ".gitignore\n",
    "LICENSE\n",
    "README.md\n",
    "bodegas.csv\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Cuatro archivos y el proyecto ya se entiende."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3. Trabaja en una rama\n",
    "\n",
    "El cálculo del total, con su commit bien escrito."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "git switch -q -c calcula-el-total\n",
    "cat > total.sh <<'FIN'\n",
    "tail -n +2 \"$1\" | cut -d, -f3 | paste -sd+ | bc\n",
    "FIN\n",
    "git add total.sh\n",
    "git commit -q -m \"Se agrega el calculo del total por bodega\n",
    "\n",
    "Suma la tercera columna del CSV, saltandose la cabecera.\"\n",
    "bash total.sh bodegas.csv\n",
    "git log --oneline"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "760\n",
    "ac5fc3a Se agrega el calculo del total por bodega\n",
    "1c6ca9e Se agregan el README y la licencia MIT\n",
    "d16ab35 Catalogo inicial de bodegas\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Probado antes de fusionar, que es el orden correcto ✅"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4. Fusiona dejando rastro\n",
    "\n",
    "Con `--no-ff` y limpiando la rama."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "git switch -q main\n",
    "git merge -q --no-ff -m \"Entra el calculo del total\" calcula-el-total\n",
    "git branch -d calcula-el-total\n",
    "git log --oneline --topo-order\n",
    "git branch"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "Deleted branch calcula-el-total (was ac5fc3a).\n",
    "c8f9270 Entra el calculo del total\n",
    "ac5fc3a Se agrega el calculo del total por bodega\n",
    "1c6ca9e Se agregan el README y la licencia MIT\n",
    "d16ab35 Catalogo inicial de bodegas\n",
    "* main\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "La historia cuenta que hubo una rama y la lista queda limpia 🌿"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 5. Marca la versión\n",
    "\n",
    "Una etiqueta anotada para la v1.0."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "git tag -a v1.0 -m \"Primera version del catalogo\"\n",
    "git tag\n",
    "git describe --tags\n",
    "git log --oneline --decorate -1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "v1.0\n",
    "v1.0\n",
    "c8f9270 (HEAD -> main, tag: v1.0) Entra el calculo del total\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Ya se puede decir \"la v1.0\" y que signifique algo 🏷️"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 6. Publícalo con sus etiquetas\n",
    "\n",
    "Recuerda que el push normal no se lleva las etiquetas."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "cd ..\n",
    "git init -q --bare catalogo-servidor.git\n",
    "cd catalogo-bodegas\n",
    "git remote add origin ../catalogo-servidor.git\n",
    "git push -q -u origin main\n",
    "git push -q origin --tags\n",
    "git ls-remote origin"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "c8f9270f3a39746c8bffd44a28cd18bd4f3cbab5\tHEAD\n",
    "c8f9270f3a39746c8bffd44a28cd18bd4f3cbab5\trefs/heads/main\n",
    "6cc816b146b13f45ae2b3a534cb1e1191fa8781a\trefs/tags/v1.0\n",
    "c8f9270f3a39746c8bffd44a28cd18bd4f3cbab5\trefs/tags/v1.0^{}\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "La rama y la etiqueta, las dos allá 🚀"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 7. Haz la revisión final\n",
    "\n",
    "Lo que miro antes de mandarle un repositorio a\n",
    "alguien."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "echo \"== que se publica ==\" && git ls-files\n",
    "echo \"== historia ==\" && git log --oneline --topo-order\n",
    "echo \"== versiones ==\" && git tag\n",
    "echo \"== nada suelto ==\" && git status --short && echo \"limpio\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "== que se publica ==\n",
    ".gitignore\n",
    "LICENSE\n",
    "README.md\n",
    "bodegas.csv\n",
    "total.sh\n",
    "== historia ==\n",
    "c8f9270 Entra el calculo del total\n",
    "ac5fc3a Se agrega el calculo del total por bodega\n",
    "1c6ca9e Se agregan el README y la licencia MIT\n",
    "d16ab35 Catalogo inicial de bodegas\n",
    "== versiones ==\n",
    "v1.0\n",
    "== nada suelto ==\n",
    "limpio\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Si esas cuatro cosas se ven bien, el repositorio está listo para\n",
    "enseñarse 🎓"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 8. Intenta guardar cuando ya no queda nada\n",
    "\n",
    "Con todo commiteado, prueba a hacer otro commit."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "git commit -m \"Un commit mas\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "On branch main\n",
    "Your branch is up to date with 'origin/main'.\n",
    "\n",
    "nothing to commit, working tree clean\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\"nothing to commit, working tree clean\" es la frase que quieres ver al\n",
    "terminar un proyecto: significa que no dejaste nada suelto ✅"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Lo que te llevas"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**README, gitignore, licencia, commits legibles, una rama, una versión\n",
    "y una revisión. Eso es un repositorio que habla bien de ti.**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Git era el requisito. Esto es para lo que lo querías"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Nadie aprende Git por Git. Se aprende porque sin él no puedes trabajar con nadie ni volver atrás cuando algo se rompe, y las dos cosas son la base de construir algo que dure.\n",
    "\n",
    "Con esto ya puedes entrar a [el curso de ingeniería de IA en producción](https://missyera.com/cursos/ingenieria-de-ia/) sin que la herramienta te estorbe, que es justo el motivo por el que este libro existe: ahí vas a trabajar sobre un repositorio de verdad durante cuatro semanas, y quien llega sin saber Git se pasa la primera peleándose con el control de versiones en vez de con el sistema.\n",
    "\n",
    "Y si no vas a ese curso, Git te sirve igual: es la herramienta que te deja volver atrás cuando rompiste algo, y eso vale en cualquier trabajo técnico 🌸"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "Ese era el capítulo 32 de **Git desde cero**. El texto completo, con las salidas de cada bloque, está en https://missyera.com/guias/git-desde-cero/proyecto-final/\n",
    "\n",
    "Que tengas lindo día! 🌸"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python",
   "version": "3.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
