Full Code of mouredev/Hello-Python for AI

main 55e1bb457840 cached
44 files
64.6 KB
19.0k tokens
67 symbols
1 requests
Download .txt
Repository: mouredev/Hello-Python
Branch: main
Commit: 55e1bb457840
Files: 44
Total size: 64.6 KB

Directory structure:
gitextract_uv6mnn0a/

├── .gitignore
├── Backend/
│   ├── FastAPI/
│   │   ├── db/
│   │   │   ├── client.py
│   │   │   ├── models/
│   │   │   │   └── user.py
│   │   │   └── schemas/
│   │   │       └── user.py
│   │   ├── main.py
│   │   ├── requirements.txt
│   │   ├── routers/
│   │   │   ├── basic_auth_users.py
│   │   │   ├── jwt_auth_users.py
│   │   │   ├── products.py
│   │   │   ├── users.py
│   │   │   └── users_db.py
│   │   └── vercel.json
│   └── type_hints.py
├── Basic/
│   ├── 00_helloworld.py
│   ├── 01_variables.py
│   ├── 02_operators.py
│   ├── 03_strings.py
│   ├── 04_lists.py
│   ├── 05_tuples.py
│   ├── 06_sets.py
│   ├── 07_dicts.py
│   ├── 08_conditionals.py
│   ├── 09_loops.py
│   ├── 10_functions.py
│   ├── 11_classes.py
│   ├── 12_exceptions.py
│   ├── 13_modules.py
│   └── my_module.py
├── Intermediate/
│   ├── 00_dates.py
│   ├── 01_list_comprehension.py
│   ├── 02_challenges.py
│   ├── 03_lambdas.py
│   ├── 04_higher_order_functions.py
│   ├── 05_error_types.py
│   ├── 06_file_handling.py
│   ├── 07_regular_expressions.py
│   ├── 08_python_package_manager.py
│   ├── my_file.csv
│   ├── my_file.json
│   ├── my_file.txt
│   └── mypackage/
│       ├── __init__.py
│       └── arithmetics.py
├── LICENSE
└── README.md

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
__pycache__/
*.py[cod]

================================================
FILE: Backend/FastAPI/db/client.py
================================================
# Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=20480)

### MongoDB client ###

# Descarga versión community: https://www.mongodb.com/try/download
# Instalación:https://www.mongodb.com/docs/manual/tutorial
# Módulo conexión MongoDB: pip install pymongo
# Ejecución: sudo mongod --dbpath "/path/a/la/base/de/datos/"
# Conexión: mongodb://localhost

from pymongo import MongoClient

# Descomentar el db_client local o remoto correspondiente

# Base de datos local MongoDB
db_client = MongoClient().local

# Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=25470

# Base de datos remota MongoDB Atlas (https://mongodb.com)
# db_client = MongoClient(
#     "mongodb+srv://<user>:<password>@<url>/?retryWrites=true&w=majority").test

# Despliegue API en la nube:
# Deta (deprecado) - https://www.deta.sh/
# Vercel - https://www.vercel.com
# Instrucciones - https://cleverzone.medium.com/fastapi-deployment-into-vercel-0fa4e6478014
# MUY IMPORTANTE - Al desplegar en producción, preparar el proyecto para trabajar con variables de entorno que hagan referencia a datos sensibles:
# - Nunca subas a un repositorio público el valor de las variables
# - Puedes usar dotenv en Python
# - Añade el valor de las variables desde el proveedor de hosting


================================================
FILE: Backend/FastAPI/db/models/user.py
================================================
# Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=20480

### User model ###

from pydantic import BaseModel
from typing import Optional


class User(BaseModel):
    id: Optional[str] = None
    username: str
    email: str


================================================
FILE: Backend/FastAPI/db/schemas/user.py
================================================
# Clase en vídeo (22/12/2022): https://www.twitch.tv/videos/1686104006

### User schema ###

def user_schema(user) -> dict:
    return {"id": str(user["_id"]),
            "username": user["username"],
            "email": user["email"]}


def users_schema(users) -> list:
    return [user_schema(user) for user in users]


================================================
FILE: Backend/FastAPI/main.py
================================================
# Clase en vídeo: https://youtu.be/_y9qQZXE24A

### Hola Mundo ###

# Documentación oficial: https://fastapi.tiangolo.com/es/

# Instala FastAPI: pip install "fastapi[all]"

from fastapi import FastAPI
from routers import products, users, basic_auth_users, jwt_auth_users, users_db
from fastapi.staticfiles import StaticFiles
import os

app = FastAPI()

# Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=12475
app.include_router(products.router)
app.include_router(users.router)

# Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=14094
app.include_router(basic_auth_users.router)

# Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=17664
app.include_router(jwt_auth_users.router)

# Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=20480
app.include_router(users_db.router)

# Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=13618
app.mount("/static", StaticFiles(directory="static"), name="static")


# Url local: http://127.0.0.1:8000


@app.get("/")
async def root():
    return "Hola FastAPI!"

# Url local: http://127.0.0.1:8000/url


@app.get("/url")
async def url():
    return {"url": "https://mouredev.com/python"}

# Inicia el server: uvicorn main:app --reload
# Detener el server: CTRL+C

# Documentación con Swagger: http://127.0.0.1:8000/docs
# Documentación con Redocly: http://127.0.0.1:8000/redoc


================================================
FILE: Backend/FastAPI/requirements.txt
================================================
fastapi[standard]
python-jose
passlib
bcrypt
pymongo

================================================
FILE: Backend/FastAPI/routers/basic_auth_users.py
================================================
# Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=14094

### Users API con autorización OAuth2 básica ###

from fastapi import APIRouter, Depends, HTTPException, status
from pydantic import BaseModel
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm

router = APIRouter(
    prefix="/basicauth",
    tags=["basicauth"],
    responses={status.HTTP_404_NOT_FOUND: {"message": "No encontrado"}}
)

oauth2 = OAuth2PasswordBearer(tokenUrl="login")


class User(BaseModel):
    username: str
    full_name: str
    email: str
    disabled: bool


class UserDB(User):
    password: str


users_db = {
    "mouredev": {
        "username": "mouredev",
        "full_name": "Brais Moure",
        "email": "braismoure@mouredev.com",
        "disabled": False,
        "password": "123456"
    },
    "mouredev2": {
        "username": "mouredev2",
        "full_name": "Brais Moure 2",
        "email": "braismoure2@mouredev.com",
        "disabled": True,
        "password": "654321"
    }
}


def search_user_db(username: str):
    if username in users_db:
        return UserDB(**users_db[username])


def search_user(username: str):
    if username in users_db:
        return User(**users_db[username])


async def current_user(token: str = Depends(oauth2)):
    user = search_user(token)
    if not user:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Credenciales de autenticación inválidas",
            headers={"WWW-Authenticate": "Bearer"})

    if user.disabled:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Usuario inactivo")

    return user


@router.post("/login")
async def login(form: OAuth2PasswordRequestForm = Depends()):
    user_db = users_db.get(form.username)
    if not user_db:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST, detail="El usuario no es correcto")

    user = search_user_db(form.username)
    if not form.password == user.password:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST, detail="La contraseña no es correcta")

    return {"access_token": user.username, "token_type": "bearer"}


@router.get("/users/me")
async def me(user: User = Depends(current_user)):
    return user


================================================
FILE: Backend/FastAPI/routers/jwt_auth_users.py
================================================
# Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=17664

### Users API con autorización OAuth2 JWT ###

from fastapi import APIRouter, Depends, HTTPException, status
from pydantic import BaseModel
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from jose import jwt, JWTError
from passlib.context import CryptContext
from datetime import datetime, timedelta, timezone

ALGORITHM = "HS256"
ACCESS_TOKEN_DURATION = 1
SECRET = "201d573bd7d1344d3a3bfce1550b69102fd11be3db6d379508b6cccc58ea230b"

router = APIRouter(
    prefix="/jwtauth",
    tags=["jwtauth"],
    responses={status.HTTP_404_NOT_FOUND: {"message": "No encontrado"}}
)

oauth2 = OAuth2PasswordBearer(tokenUrl="login")

crypt = CryptContext(schemes=["bcrypt"])


class User(BaseModel):
    username: str
    full_name: str
    email: str
    disabled: bool


class UserDB(User):
    password: str


users_db = {
    "mouredev": {
        "username": "mouredev",
        "full_name": "Brais Moure",
        "email": "braismoure@mouredev.com",
        "disabled": False,
        "password": "$2a$12$B2Gq.Dps1WYf2t57eiIKjO4DXC3IUMUXISJF62bSRiFfqMdOI2Xa6"
    },
    "mouredev2": {
        "username": "mouredev2",
        "full_name": "Brais Moure 2",
        "email": "braismoure2@mouredev.com",
        "disabled": True,
        "password": "$2a$12$SduE7dE.i3/ygwd0Kol8bOFvEABaoOOlC8JsCSr6wpwB4zl5STU4S"
    }
}


def search_user_db(username: str):
    if username in users_db:
        return UserDB(**users_db[username])


def search_user(username: str):
    if username in users_db:
        return User(**users_db[username])


async def auth_user(token: str = Depends(oauth2)):

    exception = HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="Credenciales de autenticación inválidas",
        headers={"WWW-Authenticate": "Bearer"})

    try:
        username = jwt.decode(token, SECRET, algorithms=[ALGORITHM]).get("sub")
        if username is None:
            raise exception

    except JWTError:
        raise exception

    return search_user(username)


async def current_user(user: User = Depends(auth_user)):
    if user.disabled:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Usuario inactivo")

    return user


@router.post("/login")
async def login(form: OAuth2PasswordRequestForm = Depends()):

    user_db = users_db.get(form.username)
    if not user_db:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST, detail="El usuario no es correcto")

    user = search_user_db(form.username)

    if not crypt.verify(form.password, user.password):
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST, detail="La contraseña no es correcta")

    access_token = {"sub": user.username,
                    "exp": datetime.now(timezone.utc) + timedelta(minutes=ACCESS_TOKEN_DURATION)}

    return {"access_token": jwt.encode(access_token, SECRET, algorithm=ALGORITHM), "token_type": "bearer"}


@router.get("/users/me")
async def me(user: User = Depends(current_user)):
    return user


================================================
FILE: Backend/FastAPI/routers/products.py
================================================
# Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=12475

### Products API ###

from fastapi import APIRouter

router = APIRouter(
    prefix="/products",
    tags=["products"],
    responses={404: {"message": "No encontrado"}}
)

products_list = ["Producto 1", "Producto 2", "Producto 3", "Producto 4", "Producto 5"]


@router.get("/")
async def products():
    return products_list


@router.get("/{id}")
async def products(id: int):
    return products_list[id]


================================================
FILE: Backend/FastAPI/routers/users.py
================================================
# Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=5382

### Users API ###

from fastapi import APIRouter, HTTPException
from pydantic import BaseModel

# Inicia el server: uvicorn users:app --reload

router = APIRouter()


class User(BaseModel):
    id: int
    name: str
    surname: str
    url: str
    age: int


users_list = [User(id=1, name="Brais", surname="Moure", url="https://moure.dev", age=35),
              User(id=2, name="Moure", surname="Dev",
                   url="https://mouredev.com", age=35),
              User(id=3, name="Brais", surname="Dahlberg", url="https://haakon.com", age=33)]


@router.get("/usersjson")
async def usersjson():  # Creamos un JSON a mano
    return [{"name": "Brais", "surname": "Moure", "url": "https://moure.dev", "age": 35},
            {"name": "Moure", "surname": "Dev",
                "url": "https://mouredev.com", "age": 35},
            {"name": "Haakon", "surname": "Dahlberg", "url": "https://haakon.com", "age": 33}]


@router.get("/users")
async def users():
    return users_list


@router.get("/user/{id}")  # Path
async def user(id: int):
    return search_user(id)


@router.get("/user/")  # Query
async def user(id: int):
    return search_user(id)


# Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=8529


@router.post("/user/", response_model=User, status_code=201)
async def user(user: User):
    if type(search_user(user.id)) == User:
        raise HTTPException(status_code=404, detail="El usuario ya existe")

    users_list.append(user)
    return user


@router.put("/user/")
async def user(user: User):

    found = False

    for index, saved_user in enumerate(users_list):
        if saved_user.id == user.id:
            users_list[index] = user
            found = True

    if not found:
        return {"error": "No se ha actualizado el usuario"}

    return user


@router.delete("/user/{id}")
async def user(id: int):

    found = False

    for index, saved_user in enumerate(users_list):
        if saved_user.id == id:
            del users_list[index]
            found = True

    if not found:
        return {"error": "No se ha eliminado el usuario"}


def search_user(id: int):
    users = filter(lambda user: user.id == id, users_list)
    try:
        return list(users)[0]
    except:
        return {"error": "No se ha encontrado el usuario"}


================================================
FILE: Backend/FastAPI/routers/users_db.py
================================================
# Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=20480

### Users DB API ###

from fastapi import APIRouter, HTTPException, status
from db.models.user import User
from db.schemas.user import user_schema, users_schema
from db.client import db_client
from bson import ObjectId

router = APIRouter(
    prefix="/userdb",
    tags=["userdb"],
    responses={status.HTTP_404_NOT_FOUND: {"message": "No encontrado"}})


@router.get("/", response_model=list[User])
async def users():
    return users_schema(db_client.users.find())


@router.get("/{id}")  # Path
async def user(id: str):
    return search_user("_id", ObjectId(id))


@router.get("/")  # Query
async def user(id: str):
    return search_user("_id", ObjectId(id))


@router.post("/", response_model=User, status_code=status.HTTP_201_CREATED)
async def user(user: User):
    if type(search_user("email", user.email)) == User:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND, detail="El usuario ya existe")

    user_dict = dict(user)
    del user_dict["id"]

    id = db_client.users.insert_one(user_dict).inserted_id

    new_user = user_schema(db_client.users.find_one({"_id": id}))

    return User(**new_user)


@router.put("/", response_model=User)
async def user(user: User):

    user_dict = dict(user)
    del user_dict["id"]

    try:
        db_client.users.find_one_and_replace(
            {"_id": ObjectId(user.id)}, user_dict)
    except:
        return {"error": "No se ha actualizado el usuario"}

    return search_user("_id", ObjectId(user.id))


@router.delete("/{id}", status_code=status.HTTP_204_NO_CONTENT)
async def user(id: str):

    found = db_client.users.find_one_and_delete({"_id": ObjectId(id)})

    if not found:
        return {"error": "No se ha eliminado el usuario"}

# Helper


def search_user(field: str, key):

    try:
        user = db_client.users.find_one({field: key})
        return User(**user_schema(user))
    except:
        return {"error": "No se ha encontrado el usuario"}


================================================
FILE: Backend/FastAPI/vercel.json
================================================
{
    "builds": [
        {
            "src": "main.py",
            "use": "@vercel/python"
        }
    ],
    "routes": [
        {
            "src": "/(.*)",
            "dest": "main.py"
        }
    ]
}

================================================
FILE: Backend/type_hints.py
================================================
# Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=1810

### Type Hints ###

my_string_variable = "My String variable"
print(my_string_variable)
print(type(my_string_variable))

my_string_variable = 5
print(my_string_variable)
print(type(my_string_variable))

my_typed_variable: str = "My typed String variable"
print(my_typed_variable)
print(type(my_typed_variable))

my_typed_variable = 5
print(my_typed_variable)
print(type(my_typed_variable))


================================================
FILE: Basic/00_helloworld.py
================================================
# Clase en vídeo: https://youtu.be/Kp4Mvapo5kc

### Hola Mundo ###

# Nuestro hola mundo en Python
print("Hola Python")
print('Hola Python')

# Esto es un comentario

"""
Este es un
comentario
en varias líneas
"""

'''
Este también es un
comentario
en varias líneas
'''

# Cómo consultar el tipo de dato
print(type("Soy un dato str"))  # Tipo 'str'
print(type(5))  # Tipo 'int'
print(type(1.5))  # Tipo 'float'
print(type(3 + 1j))  # Tipo 'complex'
print(type(True))  # Tipo 'bool'
print(type(print("Mi cadena de texto")))  # Tipo 'NoneType'


================================================
FILE: Basic/01_variables.py
================================================
# Clase en vídeo: https://youtu.be/Kp4Mvapo5kc?t=2938

### Variables ###

my_string_variable = "My String variable"
print(my_string_variable)

my_int_variable = 5
print(my_int_variable)

my_int_to_str_variable = str(my_int_variable)
print(my_int_to_str_variable)
print(type(my_int_to_str_variable))

my_bool_variable = False
print(my_bool_variable)

# Concatenación de variables en un print
print(my_string_variable, my_int_to_str_variable, my_bool_variable)
print("Este es el valor de:", my_bool_variable)

# Algunas funciones del sistema
print(len(my_string_variable))

# Variables en una sola línea. ¡Cuidado con abusar de esta sintaxis!
name, surname, alias, age = "Brais", "Moure", 'MoureDev', 35
print("Me llamo:", name, surname, ". Mi edad es:",
      age, ". Y mi alias es:", alias)

# Inputs
name = input('¿Cuál es tu nombre? ')
age = input('¿Cuántos años tienes? ')
print(name)
print(age)

# Cambiamos su tipo
name = 35
age = "Brais"
print(name)
print(age)

# ¿Forzamos el tipo?
address: str = "Mi dirección"
address = True
address = 5
address = 1.2
print(type(address))


================================================
FILE: Basic/02_operators.py
================================================
# Clase en vídeo: https://youtu.be/Kp4Mvapo5kc?t=5665

### Operadores Aritméticos ###

# Operaciones con enteros
print(3 + 4)
print(3 - 4)
print(3 * 4)
print(3 / 4)
print(10 % 3)
print(10 // 3)
print(2 ** 3)
print(2 ** 3 + 3 - 7 / 1 // 4)

# Operaciones con cadenas de texto
print("Hola " + "Python " + "¿Qué tal?")
print("Hola " + str(5))

# Operaciones mixtas
print("Hola " * 5)
print("Hola " * (2 ** 3))

my_float = 2.5 * 2
print("Hola " * int(my_float))

### Operadores Comparativos ###

# Operaciones con enteros
print(3 > 4)
print(3 < 4)
print(3 >= 4)
print(4 <= 4)
print(3 == 4)
print(3 != 4)

# Operaciones con cadenas de texto
print("Hola" > "Python")
print("Hola" < "Python")
print("aaaa" >= "abaa")  # Ordenación alfabética por ASCII
print(len("aaaa") >= len("abaa"))  # Cuenta caracteres
print("Hola" <= "Python")
print("Hola" == "Hola")
print("Hola" != "Python")

### Operadores Lógicos ###

# Basada en el Álgebra de Boole https://es.wikipedia.org/wiki/%C3%81lgebra_de_Boole
print(3 > 4 and "Hola" > "Python")
print(3 > 4 or "Hola" > "Python")
print(3 < 4 and "Hola" < "Python")
print(3 < 4 or "Hola" > "Python")
print(3 < 4 or ("Hola" > "Python" and 4 == 4))
print(not (3 > 4))


================================================
FILE: Basic/03_strings.py
================================================
# Clase en vídeo: https://youtu.be/Kp4Mvapo5kc?t=8643

### Strings ###

my_string = "Mi String"
my_other_string = 'Mi otro String'

print(len(my_string))
print(len(my_other_string))
print(my_string + " " + my_other_string)

my_new_line_string = "Este es un String\ncon salto de línea"
print(my_new_line_string)

my_tab_string = "\tEste es un String con tabulación"
print(my_tab_string)

my_scape_string = "\\tEste es un String \\n escapado"
print(my_scape_string)

# Formateo

name, surname, age = "Brais", "Moure", 35
print("Mi nombre es {} {} y mi edad es {}".format(name, surname, age))
print("Mi nombre es %s %s y mi edad es %d" % (name, surname, age))
print("Mi nombre es " + name + " " + surname + " y mi edad es " + str(age))
print(f"Mi nombre es {name} {surname} y mi edad es {age}")

# Desempaqueado de caracteres

language = "python"
a, b, c, d, e, f = language
print(a)
print(e)

# División

language_slice = language[1:3]
print(language_slice)

language_slice = language[1:]
print(language_slice)

language_slice = language[-2]
print(language_slice)

language_slice = language[0:6:2]
print(language_slice)

# Reverse

reversed_language = language[::-1]
print(reversed_language)

# Funciones del lenguaje

print(language.capitalize())
print(language.upper())
print(language.count("t"))
print(language.isnumeric())
print("1".isnumeric())
print(language.lower())
print(language.lower().isupper())
print(language.startswith("Py"))
print("Py" == "py")  # No es lo mismo


================================================
FILE: Basic/04_lists.py
================================================
# Clase en vídeo: https://youtu.be/Kp4Mvapo5kc?t=10872

### Lists ###

# Definición

my_list = list()
my_other_list = []

print(len(my_list))

my_list = [35, 24, 62, 52, 30, 30, 17]

print(my_list)
print(len(my_list))

my_other_list = [35, 1.77, "Brais", "Moure"]

print(type(my_list))
print(type(my_other_list))

# Acceso a elementos y búsqueda

print(my_other_list[0])
print(my_other_list[1])
print(my_other_list[-1])
print(my_other_list[-4])
print(my_list.count(30))
# print(my_other_list[4]) IndexError
# print(my_other_list[-5]) IndexError

print(my_other_list.index("Brais"))

age, height, name, surname = my_other_list
print(name)

name, height, age, surname = my_other_list[2], my_other_list[1], my_other_list[0], my_other_list[3]
print(age)

# Concatenación

print(my_list + my_other_list)
#print(my_list - my_other_list)

# Creación, inserción, actualización y eliminación

my_other_list.append("MoureDev")
print(my_other_list)

my_other_list.insert(1, "Rojo")
print(my_other_list)

my_other_list[1] = "Azul"
print(my_other_list)

my_other_list.remove("Azul")
print(my_other_list)

my_list.remove(30)
print(my_list)

print(my_list.pop())
print(my_list)

my_pop_element = my_list.pop(2)
print(my_pop_element)
print(my_list)

del my_list[2]
print(my_list)

# Operaciones con listas

my_new_list = my_list.copy()

my_list.clear()
print(my_list)
print(my_new_list)

my_new_list.reverse()
print(my_new_list)

my_new_list.sort()
print(my_new_list)

# Sublistas

print(my_new_list[1:3])

# Cambio de tipo

my_list = "Hola Python"
print(my_list)
print(type(my_list))


================================================
FILE: Basic/05_tuples.py
================================================
# Clase en vídeo: https://youtu.be/Kp4Mvapo5kc?t=14711

### Tuples ###

# Definición

my_tuple = tuple()
my_other_tuple = ()

my_tuple = (35, 1.77, "Brais", "Moure", "Brais")
my_other_tuple = (35, 60, 30)

print(my_tuple)
print(type(my_tuple))

# Acceso a elementos y búsqueda

print(my_tuple[0])
print(my_tuple[-1])
# print(my_tuple[4]) IndexError
# print(my_tuple[-6]) IndexError

print(my_tuple.count("Brais"))
print(my_tuple.index("Moure"))
print(my_tuple.index("Brais"))

# my_tuple[1] = 1.80 'tuple' object does not support item assignment

# Concatenación

my_sum_tuple = my_tuple + my_other_tuple
print(my_sum_tuple)

# Subtuplas

print(my_sum_tuple[3:6])

# Tupla mutable con conversión a lista

my_tuple = list(my_tuple)
print(type(my_tuple))

my_tuple[4] = "MoureDev"
my_tuple.insert(1, "Azul")
my_tuple = tuple(my_tuple)
print(my_tuple)
print(type(my_tuple))

# Eliminación

# del my_tuple[2] TypeError: 'tuple' object doesn't support item deletion

del my_tuple
# print(my_tuple) NameError: name 'my_tuple' is not defined


================================================
FILE: Basic/06_sets.py
================================================
# Clase en vídeo: https://youtu.be/Kp4Mvapo5kc?t=16335

### Sets ###

# Definición

my_set = set()
my_other_set = {}

print(type(my_set))
print(type(my_other_set))  # Inicialmente es un diccionario

my_other_set = {"Brais", "Moure", 35}
print(type(my_other_set))

print(len(my_other_set))

# Inserción

my_other_set.add("MoureDev")

print(my_other_set)  # Un set no es una estructura ordenada

my_other_set.add("MoureDev")  # Un set no admite repetidos

print(my_other_set)

# Búsqueda

print("Moure" in my_other_set)
print("Mouri" in my_other_set)

# Eliminación

my_other_set.remove("Moure")
print(my_other_set)

my_other_set.clear()
print(len(my_other_set))

del my_other_set
# print(my_other_set) NameError: name 'my_other_set' is not defined

# Transformación

my_set = {"Brais", "Moure", 35}
my_list = list(my_set)
print(my_list)
print(my_list[0])

my_other_set = {"Kotlin", "Swift", "Python"}

# Otras operaciones

my_new_set = my_set.union(my_other_set)
print(my_new_set.union(my_new_set).union(my_set).union({"JavaScript", "C#"}))
print(my_new_set.difference(my_set))


================================================
FILE: Basic/07_dicts.py
================================================
# Clase en vídeo: https://youtu.be/Kp4Mvapo5kc

### Dictionaries ###

# Definición

my_dict = dict()
my_other_dict = {}

print(type(my_dict))
print(type(my_other_dict))

my_other_dict = {"Nombre": "Brais",
                 "Apellido": "Moure", "Edad": 35, 1: "Python"}

my_dict = {
    "Nombre": "Brais",
    "Apellido": "Moure",
    "Edad": 35,
    "Lenguajes": {"Python", "Swift", "Kotlin"},
    1: 1.77
}

print(my_other_dict)
print(my_dict)

print(len(my_other_dict))
print(len(my_dict))

# Búsqueda

print(my_dict[1])
print(my_dict["Nombre"])

print("Moure" in my_dict)
print("Apellido" in my_dict)

# Inserción

my_dict["Calle"] = "Calle MoureDev"
print(my_dict)

# Actualización

my_dict["Nombre"] = "Pedro"
print(my_dict["Nombre"])

# Eliminación

del my_dict["Calle"]
print(my_dict)

# Otras operaciones

print(my_dict.items())
print(my_dict.keys())
print(my_dict.values())

my_list = ["Nombre", 1, "Piso"]

my_new_dict = dict.fromkeys((my_list))
print(my_new_dict)
my_new_dict = dict.fromkeys(("Nombre", 1, "Piso"))
print((my_new_dict))
my_new_dict = dict.fromkeys(my_dict)
print((my_new_dict))
my_new_dict = dict.fromkeys(my_dict, "MoureDev")
print((my_new_dict))

my_values = my_new_dict.values()
print(type(my_values))

print(my_new_dict.values())
print(list(dict.fromkeys(list(my_new_dict.values())).keys()))
print(tuple(my_new_dict))
print(set(my_new_dict))


================================================
FILE: Basic/08_conditionals.py
================================================
# Clase en vídeo: https://youtu.be/Kp4Mvapo5kc?t=21442

### Conditionals ###

# if

my_condition = False

if my_condition:  # Es lo mismo que if my_condition == True:
    print("Se ejecuta la condición del if")

my_condition = 5 * 5

if my_condition == 10:
    print("Se ejecuta la condición del segundo if")

# if, elif, else

if my_condition > 10 and my_condition < 20:
    print("Es mayor que 10 y menor que 20")
elif my_condition == 25:
    print("Es igual a 25")
else:
    print("Es menor o igual que 10 o mayor o igual que 20 o distinto de 25")

print("La ejecución continúa")

# Condicional con ispección de valor

my_string = ""

if not my_string:
    print("Mi cadena de texto es vacía")

if my_string == "Mi cadena de textoooooo":
    print("Estas cadenas de texto coinciden")


================================================
FILE: Basic/09_loops.py
================================================
# Clase en vídeo: https://youtu.be/Kp4Mvapo5kc?t=23822

### Loops ###

# While

my_condition = 0

while my_condition < 10:
    print(my_condition)
    my_condition += 2
else:  # Es opcional
    print("Mi condición es mayor o igual que 10")

print("La ejecución continúa")

while my_condition < 20:
    my_condition += 1
    if my_condition == 15:
        print("Se detiene la ejecución")
        break
    print(my_condition)

print("La ejecución continúa")

# For

my_list = [35, 24, 62, 52, 30, 30, 17]

for element in my_list:
    print(element)

my_tuple = (35, 1.77, "Brais", "Moure", "Brais")

for element in my_tuple:
    print(element)

my_set = {"Brais", "Moure", 35}

for element in my_set:
    print(element)

my_dict = {"Nombre": "Brais", "Apellido": "Moure", "Edad": 35, 1: "Python"}

for element in my_dict:
    print(element)
    if element == "Edad":
        break
else:
    print("El bucle for para el diccionario ha finalizado")

print("La ejecución continúa")

for element in my_dict:
    print(element)
    if element == "Edad":
        continue
    print("Se ejecuta")
else:
    print("El bluce for para diccionario ha finalizado")


================================================
FILE: Basic/10_functions.py
================================================
# Clase en vídeo: https://youtu.be/Kp4Mvapo5kc?t=26619

### Functions ###

# Definición

def my_function():
    print("Esto es una función")


my_function()
my_function()
my_function()

# Función con parámetros de entrada/argumentos


def sum_two_values(first_value: int, second_value):
    print(first_value + second_value)


sum_two_values(5, 7)
sum_two_values(54754, 71231)
sum_two_values("5", "7")
sum_two_values(1.4, 5.2)

# Función con parámetros de entrada/argumentos y retorno


def sum_two_values_with_return(first_value, second_value):
    my_sum = first_value + second_value
    return my_sum


my_result = sum_two_values(1.4, 5.2)
print(my_result)

my_result = sum_two_values_with_return(10, 5)
print(my_result)

# Función con parámetros de entrada/argumentos por clave


def print_name(name, surname):
    print(f"{name} {surname}")


print_name(surname="Moure", name="Brais")

# Función con parámetros de entrada/argumentos por defecto


def print_name_with_default(name, surname, alias="Sin alias"):
    print(f"{name} {surname} {alias}")


print_name_with_default("Brais", "Moure")
print_name_with_default("Brais", "Moure", "MoureDev")

# Función con parámetros de entrada/argumentos arbitrarios


def print_upper_texts(*texts):
    print(type(texts))
    for text in texts:
        print(text.upper())


print_upper_texts("Hola", "Python", "MoureDev")
print_upper_texts("Hola")


================================================
FILE: Basic/11_classes.py
================================================
# Clase en vídeo: https://youtu.be/Kp4Mvapo5kc?t=29327

### Classes ###

# Definición

class MyEmptyPerson:
    pass  # Para poder dejar la clase vacía


print(MyEmptyPerson)
print(MyEmptyPerson())

# Clase con constructor, funciones y propiedades privadas y públicas


class Person:
    def __init__(self, name, surname, alias="Sin alias"):
        self.full_name = f"{name} {surname} ({alias})"  # Propiedad pública
        self.__name = name  # Propiedad privada

    def get_name(self):
        return self.__name

    def walk(self):
        print(f"{self.full_name} está caminando")


my_person = Person("Brais", "Moure")
print(my_person.full_name)
print(my_person.get_name())
my_person.walk()

my_other_person = Person("Brais", "Moure", "MoureDev")
print(my_other_person.full_name)
my_other_person.walk()
my_other_person.full_name = "Héctor de León (El loco de los perros)"
print(my_other_person.full_name)

my_other_person.full_name = 666
print(my_other_person.full_name)


================================================
FILE: Basic/12_exceptions.py
================================================
# Clase en vídeo: https://youtu.be/Kp4Mvapo5kc?t=32030

### Exception Handling ###

numberOne = 5
numberTwo = 1
numberTwo = "1"

# Excepción base: try except

try:
    print(numberOne + numberTwo)
    print("No se ha producido un error")
except:
    # Se ejecuta si se produce una excepción
    print("Se ha producido un error")

# Flujo completo de una excepción: try except else finally

try:
    print(numberOne + numberTwo)
    print("No se ha producido un error")
except:
    print("Se ha producido un error")
else:  # Opcional
    # Se ejecuta si no se produce una excepción
    print("La ejecución continúa correctamente")
finally:  # Opcional
    # Se ejecuta siempre
    print("La ejecución continúa")

# Excepciones por tipo

try:
    print(numberOne + numberTwo)
    print("No se ha producido un error")
except ValueError:
    print("Se ha producido un ValueError")
except TypeError:
    print("Se ha producido un TypeError")

# Captura de la información de la excepción

try:
    print(numberOne + numberTwo)
    print("No se ha producido un error")
except ValueError as error:
    print(error)
except Exception as my_random_error_name:
    print(my_random_error_name)


================================================
FILE: Basic/13_modules.py
================================================
# Clase en vídeo: https://youtu.be/Kp4Mvapo5kc?t=34583

### Modules ###

from math import pi as PI_VALUE
import math
from my_module import sumValue, printValue
import my_module

my_module.sumValue(5, 3, 1)
my_module.printValue("Hola Python!")


sumValue(5, 3, 1)
printValue("Hola python")


print(math.pi)
print(math.pow(2, 8))


print(PI_VALUE)


================================================
FILE: Basic/my_module.py
================================================
# Clase en vídeo: https://youtu.be/Kp4Mvapo5kc?t=34583

### Módulo para pruebas ###

def sumValue(numberOne, numberTwo, numberThree):
    print(numberOne + numberTwo + numberThree)


def printValue(value):
    print(value)


================================================
FILE: Intermediate/00_dates.py
================================================
# Clase en vídeo: https://youtu.be/TbcEqkabAWU

### Dates ###

# Date time

from datetime import timedelta
from datetime import date
from datetime import time
from datetime import datetime

now = datetime.now()


def print_date(date):
    print(date.year)
    print(date.month)
    print(date.day)
    print(date.hour)
    print(date.minute)
    print(date.second)
    print(date.timestamp())


print_date(now)

year_2023 = datetime(2023, 1, 1)

print_date(year_2023)

# Time


current_time = time(21, 6, 0)

print(current_time.hour)
print(current_time.minute)
print(current_time.second)

# Date


current_date = date.today()

print(current_date.year)
print(current_date.month)
print(current_date.day)

current_date = date(2022, 10, 6)

print(current_date.year)
print(current_date.month)
print(current_date.day)

current_date = date(current_date.year,
                    current_date.month + 1, current_date.day)

print(current_date.month)

# Operaciones con fechas

diff = year_2023 - now
print(diff)

diff = year_2023.date() - current_date
print(diff)

# Timedelta


start_timedelta = timedelta(200, 100, 100, weeks=10)
end_timedelta = timedelta(300, 100, 100, weeks=13)

print(end_timedelta - start_timedelta)
print(end_timedelta + start_timedelta)


================================================
FILE: Intermediate/01_list_comprehension.py
================================================
# Clase en vídeo: https://youtu.be/TbcEqkabAWU?t=3239

### List Comprehension ###

my_original_list = [0, 1, 2, 3, 4, 5, 6, 7]
print(my_original_list)

my_range = range(8)
print(list(my_range))

# Definición

my_list = [i + 1 for i in range(8)]
print(my_list)

my_list = [i * 2 for i in range(8)]
print(my_list)

my_list = [i * i for i in range(8)]
print(my_list)


def sum_five(number):
    return number + 5


my_list = [sum_five(i) for i in range(8)]
print(my_list)


================================================
FILE: Intermediate/02_challenges.py
================================================
# Clase en vídeo: https://youtu.be/TbcEqkabAWU?t=4142

### Challenges ###

"""
EL FAMOSO "FIZZ BUZZ”:
Escribe un programa que muestre por consola (con un print) los
números de 1 a 100 (ambos incluidos y con un salto de línea entre
cada impresión), sustituyendo los siguientes:
- Múltiplos de 3 por la palabra "fizz".
- Múltiplos de 5 por la palabra "buzz".
- Múltiplos de 3 y de 5 a la vez por la palabra "fizzbuzz".
"""


def fizzbuzz():
    for index in range(1, 101):
        if index % 3 == 0 and index % 5 == 0:
            print("fizzbuzz")
        elif index % 3 == 0:
            print("fizz")
        elif index % 5 == 0:
            print("buzz")
        else:
            print(index)


fizzbuzz()

"""
¿ES UN ANAGRAMA?
Escribe una función que reciba dos palabras (String) y retorne
verdadero o falso (Bool) según sean o no anagramas.
- Un Anagrama consiste en formar una palabra reordenando TODAS
  las letras de otra palabra inicial.
- NO hace falta comprobar que ambas palabras existan.
- Dos palabras exactamente iguales no son anagrama.
"""


def is_anagram(word_one, word_two):
    if word_one.lower() == word_two.lower():
        return False
    return sorted(word_one.lower()) == sorted(word_two.lower())


print(is_anagram("Amor", "Roma"))

"""
LA SUCESIÓN DE FIBONACCI
Escribe un programa que imprima los 50 primeros números de la sucesión
de Fibonacci empezando en 0.
- La serie Fibonacci se compone por una sucesión de números en
  la que el siguiente siempre es la suma de los dos anteriores.
  0, 1, 1, 2, 3, 5, 8, 13...
"""


def fibonacci():

    prev = 0
    next = 1

    for index in range(0, 50):
        print(prev)
        fib = prev + next
        prev = next
        next = fib


fibonacci()

"""
¿ES UN NÚMERO PRIMO?
Escribe un programa que se encargue de comprobar si un número es o no primo.
Hecho esto, imprime los números primos entre 1 y 100.
"""


def is_prime():

    for number in range(1, 101):

        if number >= 2:

            is_divisible = False

            for index in range(2, number):
                if number % index == 0:
                    is_divisible = True
                    break

            if not is_divisible:
                print(number)


is_prime()

"""
INVIRTIENDO CADENAS
Crea un programa que invierta el orden de una cadena de texto
sin usar funciones propias del lenguaje que lo hagan de forma automática.
- Si le pasamos "Hola mundo" nos retornaría "odnum aloH"
"""


def reverse(text):
    text_len = len(text)
    reversed_text = ""
    for index in range(0, text_len):
        reversed_text += text[text_len - index - 1]
    return reversed_text


print(reverse("Hola mundo"))


================================================
FILE: Intermediate/03_lambdas.py
================================================
# Clase en vídeo: https://youtu.be/TbcEqkabAWU?t=9145

### Lambdas ###

sum_two_values = lambda first_value, second_value: first_value + second_value
print(sum_two_values(2, 4))

multiply_values = lambda first_value, second_value: first_value * second_value - 3
print(multiply_values(2, 4))

def sum_three_values(value):
    return lambda first_value, second_value: first_value + second_value + value

print(sum_three_values(5)(2, 4))

================================================
FILE: Intermediate/04_higher_order_functions.py
================================================
# Clase en vídeo: https://youtu.be/TbcEqkabAWU?t=10172

### Higher Order Functions ###

from functools import reduce


def sum_one(value):
    return value + 1


def sum_five(value):
    return value + 5


def sum_two_values_and_add_value(first_value, second_value, f_sum):
    return f_sum(first_value + second_value)


print(sum_two_values_and_add_value(5, 2, sum_one))
print(sum_two_values_and_add_value(5, 2, sum_five))

### Closures ###


def sum_ten(original_value):
    def add(value):
        return value + 10 + original_value
    return add


add_closure = sum_ten(1)
print(add_closure(5))
print((sum_ten(5))(1))

### Built-in Higher Order Functions ###

numbers = [2, 5, 10, 21, 3, 30]

# Map


def multiply_two(number):
    return number * 2


print(list(map(multiply_two, numbers)))
print(list(map(lambda number: number * 2, numbers)))

# Filter


def filter_greater_than_ten(number):
    if number > 10:
        return True
    return False


print(list(filter(filter_greater_than_ten, numbers)))
print(list(filter(lambda number: number > 10, numbers)))

# Reduce


def sum_two_values(first_value, second_value):
    return first_value + second_value


print(reduce(sum_two_values, numbers))


================================================
FILE: Intermediate/05_error_types.py
================================================
# Clase en vídeo: https://youtu.be/TbcEqkabAWU?t=12721

### Error Types ###

# SyntaxError
# print "¡Hola comunidad!" # Descomentar para Error
from math import pi
import math
print("¡Hola comunidad!")

# NameError
language = "Spanish"  # Comentar para Error
print(language)

# IndexError
my_list = ["Python", "Swift", "Kotlin", "Dart", "JavaScript"]
print(my_list[0])
print(my_list[4])
print(my_list[-1])
# print(my_list[5]) # Descomentar para Error

# ModuleNotFoundError
# import maths # Descomentar para Error

# AttributeError
# print(math.PI) # Descomentar para Error
print(math.pi)

# KeyError
my_dict = {"Nombre": "Brais", "Apellido": "Moure", "Edad": 35, 1: "Python"}
print(my_dict["Edad"])
# print(my_dict["Apelido"]) # Descomentar para Error
print(my_dict["Apellido"])

# TypeError
# print(my_list["0"]) # Descomentar para Error
print(my_list[0])
print(my_list[False])

# ImportError
# from math import PI # Descomentar para Error
print(pi)

# ValueError
# my_int = int("10 Años") # Descomentar para Error
my_int = int("10")
print(type(my_int))

# ZeroDivisionError
# print(4/0) # Descomentar para Error
print(4/2)


================================================
FILE: Intermediate/06_file_handling.py
================================================
# Clase en vídeo: https://youtu.be/TbcEqkabAWU?t=15524

### File Handling ###

import xml
import csv
import json
import os

# .txt file

# Leer, escribir y sobrescribir si ya existe
txt_file = open("my_file.txt", "w+")

txt_file.write(
    "Mi nombre es Brais\nMi apellido es Moure\n35 años\nY mi lenguaje preferido es Python")

# Posiciona el cursor al inicio del fichero
txt_file.seek(0)

# Lee e imprime todo el contenido del fichero
print(txt_file.read())

# Lee e imprime 10 caracteres desde el inicio del fichero
txt_file.seek(0)
print(txt_file.read(10))

# Lee e imprime el resto de la línea actual desde la posición 11
print(txt_file.readline())

# Lee e imprime la siguiente línea
print(txt_file.readline())

# Lee e imprime las líneas restantes del fichero
for line in txt_file.readlines():
    print(line)

# Escribe una nueva línea en el fichero
txt_file.write("\nAunque también me gusta Kotlin")

# Posiciona el cursor al inicio del fichero, lee e imprime todo su contenido
txt_file.seek(0)
print(txt_file.read())

# Cierra el fichero
txt_file.close()

# Agrega una nueva línea en el fichero
with open("my_file.txt", "a") as my_other_file:
    my_other_file.write("\nY Swift")

# os.remove("Intermediate/my_file.txt")

# .json file

json_file = open("Intermediate/my_file.json", "w+")

json_test = {
    "name": "Brais",
    "surname": "Moure",
    "age": 35,
    "languages": ["Python", "Swift", "Kotlin"],
    "website": "https://moure.dev"}

json.dump(json_test, json_file, indent=2)

json_file.close()

with open("Intermediate/my_file.json") as my_other_file:
    for line in my_other_file.readlines():
        print(line)

json_dict = json.load(open("Intermediate/my_file.json"))
print(json_dict)
print(type(json_dict))
print(json_dict["name"])

# .csv file


csv_file = open("Intermediate/my_file.csv", "w+")

csv_writer = csv.writer(csv_file)
csv_writer.writerow(["name", "surname", "age", "language", "website"])
csv_writer.writerow(["Brais", "Moure", 35, "Python", "https://moure.dev"])
csv_writer.writerow(["Roswell", "", 2, "COBOL", ""])

csv_file.close()

with open("Intermediate/my_file.csv") as my_other_file:
    for line in my_other_file.readlines():
        print(line)

# .xlsx file
# import xlrd # Debe instalarse el módulo

# .xml file

# ¿Te atreves a practicar cómo trabajar con este tipo de ficheros?


================================================
FILE: Intermediate/07_regular_expressions.py
================================================
# Clase en vídeo: https://youtu.be/TbcEqkabAWU?t=19762

### Regular Expressions ###

import re

# match

my_string = "Esta es la lección número 7: Lección llamada Expresiones Regulares"
my_other_string = "Esta no es la lección número 6: Manejo de ficheros"

match = re.match("Esta es la lección", my_string, re.I)
print(match)
start, end = match.span()
print(my_string[start:end])

match = re.match("Esta no es la lección", my_other_string)
# if not(match == None): # Otra forma de comprobar el None
# if match != None: # Otra forma de comprobar el None
if match is not None:
    print(match)
    start, end = match.span()
    print(my_other_string[start:end])

print(re.match("Expresiones Regulares", my_string))

# search

search = re.search("lección", my_string, re.I)
print(search)
start, end = search.span()
print(my_string[start:end])

# findall

findall = re.findall("lección", my_string, re.I)
print(findall)

# split

print(re.split(":", my_string))

# sub

print(re.sub("[l|L]ección", "LECCIÓN", my_string))
print(re.sub("Expresiones Regulares", "RegEx", my_string))

### Regular Expressions Patterns ###

# Para aprender y validar expresiones regulares: https://regex101.com

pattern = r"[lL]ección"
print(re.findall(pattern, my_string))

pattern = r"[lL]ección|Expresiones"
print(re.findall(pattern, my_string))

pattern = r"[0-9]"
print(re.findall(pattern, my_string))
print(re.search(pattern, my_string))

pattern = r"\d"
print(re.findall(pattern, my_string))

pattern = r"\D"
print(re.findall(pattern, my_string))

pattern = r"[l].*"
print(re.findall(pattern, my_string))

email = "mouredev@mouredev.com"
pattern = r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z-.]+$"
print(re.match(pattern, email))
print(re.search(pattern, email))
print(re.findall(pattern, email))

email = "mouredev@mouredev.com.mx"
print(re.findall(pattern, email))


================================================
FILE: Intermediate/08_python_package_manager.py
================================================
# Clase en vídeo: https://youtu.be/TbcEqkabAWU?t=24010

### Python Package Manager ###

# PIP https://pypi.org

# pip install pip
# pip --version

# pip install numpy
import pandas
from mypackage import arithmetics
import requests
import numpy

print(numpy.version.version)

numpy_array = numpy.array([35, 24, 62, 52, 30, 30, 17])
print(type(numpy_array))

print(numpy_array * 2)

# pip install pandas

# pip list
# pip uninstall pandas
# pip show numpy

# pip install requests

response = requests.get("https://pokeapi.co/api/v2/pokemon?limit=151")
print(response)
print(response.status_code)
print(response.json())

# Arithmetics Package


print(arithmetics.sum_two_values(1, 4))


================================================
FILE: Intermediate/my_file.csv
================================================
name,surname,age,language,website
Brais,Moure,35,Python,https://moure.dev
Roswell,,2,COBOL,


================================================
FILE: Intermediate/my_file.json
================================================
{
  "name": "Brais",
  "surname": "Moure",
  "age": 35,
  "languages": [
    "Python",
    "Swift",
    "Kotlin"
  ],
  "website": "https://moure.dev"
}

================================================
FILE: Intermediate/my_file.txt
================================================
Mi nombre es Brais
Mi apellido es Moure
35 años
Y mi lenguaje preferido es Python
Aunque también me gusta Kotlin
Y Swift

================================================
FILE: Intermediate/mypackage/__init__.py
================================================


================================================
FILE: Intermediate/mypackage/arithmetics.py
================================================
# Clase en vídeo: https://youtu.be/TbcEqkabAWU?t=24010

### Arithmetics ###

def sum_two_values(first_value, second_value):
    return first_value + second_value


================================================
FILE: LICENSE
================================================
                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "[]"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright [yyyy] [name of copyright owner]

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.


================================================
FILE: README.md
================================================
# Hello Python

[![Python](https://img.shields.io/badge/Python-3.10+-yellow?style=for-the-badge&logo=python&logoColor=white&labelColor=101010)](https://python.org)
[![FastAPI](https://img.shields.io/badge/FastAPI-0.88.0+-00a393?style=for-the-badge&logo=fastapi&logoColor=white&labelColor=101010)](https://fastapi.tiangolo.com)
[![MongoDB](https://img.shields.io/badge/MongoDB-6.0+-00684A?style=for-the-badge&logo=mongodb&logoColor=white&labelColor=101010)](https://www.mongodb.com)
[![ChatGPT](https://img.shields.io/badge/ChatGPT-GPT--4-7CF178?style=for-the-badge&logo=openai&logoColor=white&labelColor=101010)](https://platform.openai.com)
[![Reflex](https://img.shields.io/badge/Reflex-0.4.6+-5646ED?style=for-the-badge&logo=reflex&logoColor=white&labelColor=101010)](https://reflex.dev)

## Curso para aprender el lenguaje de programación Python desde cero y para principiantes

![](./Images/header.jpg)

### Proyecto realizado durante emisiones en directo desde [Twitch](https://twitch.tv/mouredev)

> ##### Si consideras útil el curso, apóyalo haciendo "★ Star" en el repositorio. ¡Gracias!

## Clases en vídeo

### Curso de fundamentos desde cero

Curso que agrupa todas las clases en directo que hacen referencia a los fundamentos de Python.

> Código: Directorio "Basic" en el proyecto

<a href="https://youtu.be/Kp4Mvapo5kc"><img src="http://i3.ytimg.com/vi/Kp4Mvapo5kc/maxresdefault.jpg" style="height: 50%; width:50%;"/></a>

- [Introducción](https://youtu.be/Kp4Mvapo5kc)
- [Contexto](https://youtu.be/Kp4Mvapo5kc?t=244)
- [Lección 1 - Configuración](https://youtu.be/Kp4Mvapo5kc?t=850)
- [Lección 2 - Hola Mundo](https://youtu.be/Kp4Mvapo5kc?t=1518)
- [Lección 3 - Variables](https://youtu.be/Kp4Mvapo5kc?t=2938)
- [Lección 4 - Operadores](https://youtu.be/Kp4Mvapo5kc?t=5665)
- [Lección 5 - Strings](https://youtu.be/Kp4Mvapo5kc?t=8643)
- [Lección 6 - Listas](https://youtu.be/Kp4Mvapo5kc?t=10872)
- [Lección 7 - Tuplas](https://youtu.be/Kp4Mvapo5kc?t=14711)
- [Lección 8 - Sets](https://youtu.be/Kp4Mvapo5kc?t=16335)
- [Lección 9 - Diccionarios](https://youtu.be/Kp4Mvapo5kc?t=18506)
- [Lección 10 - Condicionales](https://youtu.be/Kp4Mvapo5kc?t=21442)
- [Lección 11 - Bucles/Loops/Ciclos](https://youtu.be/Kp4Mvapo5kc?t=23822)
- [Lección 12 - Funciones](https://youtu.be/Kp4Mvapo5kc?t=26619)
- [Lección 13 - Clases](https://youtu.be/Kp4Mvapo5kc?t=29327)
- [Lección 14 - Excepciones](https://youtu.be/Kp4Mvapo5kc?t=32030)
- [Lección 15 - Módulos](https://youtu.be/Kp4Mvapo5kc?t=34583)
- [Próximos pasos](https://youtu.be/Kp4Mvapo5kc?t=36390)

### Curso intermedio de fundamentos desde cero

Curso en el que continuamos aprendiendo Python desde sus bases, siguiendo la ruta de aprendizaje desde la última lección del curso de inicial.

> Código: Directorio "Intermediate" en el proyecto

<a href="https://youtu.be/TbcEqkabAWU"><img src="http://i3.ytimg.com/vi/TbcEqkabAWU/maxresdefault.jpg" style="height: 50%; width:50%;"/></a>

- [Introducción](https://youtu.be/TbcEqkabAWU)
- [Lección 1 - Dates](https://youtu.be/TbcEqkabAWU?t=202)
- [Lección 2 - List Comprehension](https://youtu.be/TbcEqkabAWU?t=3239)
- [Lección 3 - Resolución de retos de programación](https://youtu.be/TbcEqkabAWU?t=4142)
- [Lección 4 - Lambdas](https://youtu.be/TbcEqkabAWU?t=9145)
- [Lección 5 - Funciones de orden superior](https://youtu.be/TbcEqkabAWU?t=10172)
- [Lección 6 - Tipos de error](https://youtu.be/TbcEqkabAWU?t=12721)
- [Lección 7 - Manejo de ficheros](https://youtu.be/TbcEqkabAWU?t=15524)
- [Lección 8 - Expresiones regulares](https://youtu.be/TbcEqkabAWU?t=19762)
- [Lección 9 - Manejo de paquetes](https://youtu.be/TbcEqkabAWU?t=24010)
- [Próximos pasos](https://youtu.be/TbcEqkabAWU?t=26228)

### Backend desde cero

Curso en el que aprenderemos a utilizar Python para backend e implementaremos un API REST con autenticación, base de datos y desplegaremos el proyecto en un servidor real.

> Código: Directorio "Backend" en el proyecto

<a href="https://youtu.be/_y9qQZXE24A"><img src="http://i3.ytimg.com/vi/_y9qQZXE24A/maxresdefault.jpg" style="height: 50%; width:50%;"/></a>

- [Introducción](https://youtu.be/_y9qQZXE24A)
- [Lección 01 - ¿Qué es un backend?](https://youtu.be/_y9qQZXE24A?t=125)
- [Lección 02 - API y FastAPI](https://youtu.be/_y9qQZXE24A?t=834)
- [Lección 03 - Type Hints](https://youtu.be/_y9qQZXE24A?t=1810)
- [Lección 04 - Configuración FastAPI](https://youtu.be/_y9qQZXE24A?t=2629)
- [Lección 05 - Hola mundo](https://youtu.be/_y9qQZXE24A?t=3504)
- [Lección 06 - Operación GET](https://youtu.be/_y9qQZXE24A?t=5382)
- [Lección 07 - Peticiones HTTP](https://youtu.be/_y9qQZXE24A?t=5925)
- [Lección 08 - Creación API](https://youtu.be/_y9qQZXE24A?t=6099)
- [Lección 09 - Path y Query](https://youtu.be/_y9qQZXE24A?t=7510)
- [Lección 10 - Operaciones POST, PUT y DELETE](https://youtu.be/_y9qQZXE24A?t=8529)
- [Lección 11 - HTTP status codes](https://youtu.be/_y9qQZXE24A?t=11072)
- [Lección 12 - Routers](https://youtu.be/_y9qQZXE24A?t=12475)
- [Lección 13 - Recursos estáticos](https://youtu.be/_y9qQZXE24A?t=13618)
- [Lección 14 - Autorización OAuth2](https://youtu.be/_y9qQZXE24A?t=14094)
- [Lección 15 - OAuth2 JWT](https://youtu.be/_y9qQZXE24A?t=17664)
- [Lección 16 - MongoDB](https://youtu.be/_y9qQZXE24A?t=20480)
- [Lección 17 - MongoDB Atlas](https://youtu.be/_y9qQZXE24A?t=25470)
- [Lección 18 - Despliegue en Deta \*](https://youtu.be/_y9qQZXE24A?t=27335)
- [Próximos pasos](https://youtu.be/_y9qQZXE24A?t=28484)

**\*ACTUALIZACIÓN Sobre la lección 18:** Deta, el servicio utilizado para el despliegue durante el curso, ya no existe. Te recomiendo revisar la documentación oficial de FastAPI sobre [despliegue](https://fastapi.tiangolo.com/deployment/). Puedes utilizar alguno de los [proveedores gratuitos](https://fastapi.tiangolo.com/deployment/cloud/) recomendados. En mi caso, te dejo el [fichero de configuración](./Backend/FastAPI/vercel.json) y el de [dependencias](./Backend/FastAPI/requirements.txt) para hacerlo desde [Vercel](https://vercel.com/) (al crear el proyecto en la plataforma selecciona que el directorio "Backend/FastAPI" es el root).

### Frontend desde cero

Cursos en los que aprenderemos a utilizar Python para desarrollo web con dos proyectos reales desplegados en producción. Tutoriales en vídeo paso a paso con 9 horas de contenido.

<a href="https://github.com/mouredev/python-web"><img src="http://i3.ytimg.com/vi/n2YrGsXJC6Y/maxresdefault.jpg" style="height: 50%; width:50%;"/></a>

<a href="https://github.com/mouredev/python-web"><img src="http://i3.ytimg.com/vi/bNy8OZJfA6I/maxresdefault.jpg" style="height: 50%; width:50%;"/></a>

[![Curso Python Web](https://img.shields.io/github/stars/mouredev/python-web?label=Curso%20Python%20web&style=social)](https://github.com/mouredev/python-web)

<a href="https://github.com/mouredev/adeviento-web"><img src="http://i3.ytimg.com/vi/h8Tn0ITRoQs/maxresdefault.jpg" style="height: 50%; width:50%;"/></a>

[![Curso Python Web](https://img.shields.io/github/stars/mouredev/adeviento-web?label=Tutorial%20Python%20web%20extra&style=social)](https://github.com/mouredev/adeviento-web)

### Aprende a integrar ChatGPT en tu proyecto desde cero

<a href="https://youtu.be/b8COygWdvmw"><img src="http://i3.ytimg.com/vi/b8COygWdvmw/maxresdefault.jpg" style="height: 50%; width:50%;"/></a>

Clase de una hora de duración donde aprenderás a interactuar con ChatGPT desde tu aplicación, mantener conversaciones y establecer el contexto de la IA para potenciar tu proyecto.

Con todo el código publicado [aquí](https://gist.github.com/mouredev/58abfbcef017efaf3852e8821564c011).

### Traductor de Voz con IA

<a href="https://youtu.be/oxLvf2nDCvQ"><img src="http://i3.ytimg.com/vi/oxLvf2nDCvQ/maxresdefault.jpg" style="height: 50%; width:50%;"/></a>

Aprende a desarrollar un traductor de voz a varios idiomas utilizando con IA. Creando su Web y todo en 100 líneas.

Con todo el código publicado [aquí](https://gist.github.com/mouredev/0ea42112751f0187d90d5403d1f333e2).

### Introducción al Testing

Taller de introducción a testing con Python creado junto a [Carlos Blé](https://www.carlosble.com) y [Miguel A. Gómez](https://softwarecrafters.io), expertos en la materia.

<a href="https://youtu.be/344uwF1z2Gg"><img src="http://i3.ytimg.com/vi/344uwF1z2Gg/maxresdefault.jpg" style="height: 50%; width:50%;"/></a>

### Extra: 15 curiosidades sobre Python

Y para finalizar... ¿Quieres saber aun más sobre él? Aquí tienes 15 curiosidades que quizás no conozcas sobre el lenguaje.

<a href="https://youtu.be/q2lCm2KAz3w"><img src="http://i3.ytimg.com/vi/q2lCm2KAz3w/maxresdefault.jpg" style="height: 50%; width:50%;"/></a>

## Información importante y preguntas frecuentes

Actualmente el curso está en pausa. Se han finalizados los bloques básico, intermedio y backend, y ese era el objetivo inicial del proyecto.
No descarto añadir nuevas lecciones a futuro, pero creo que por el momento puede servir de base a cualquier persona que quiera empezar a aprender este lenguaje.

- Recuerda que he creado en el [Discord](https://discord.gg/mouredev) un canal "🐍python" para que puedas comentar lo que quieras.
- En el momento que el curso continúe, actualizaré el repositorio y avisaré en redes.

¡Muchísimas gracias por todo el apoyo mostrado!

## Enlaces de interés

- [Web oficial de Python](https://www.python.org/)
- [Tutorial oficial de Python en Español](https://docs.python.org/es/3/tutorial/index.html)
- [Repo 30 días de Python](https://github.com/Asabeneh/30-Days-Of-Python)
- [Juego Codédex para aprender Python](https://www.codedex.io/)
- [Visual Studio Code](https://code.visualstudio.com/): El editor que estoy usando
- [FastAPI](https://fastapi.tiangolo.com/es/): El framework para crear nuestra API Backend
- [MongoDB](https://www.mongodb.com/): La base de datos que utiliza nuestro backend
- [Vercel](https://vercel.com/): Para desplegar nuestra API en la nube

## Únete al campus de programación de la comunidad

![https://mouredev.pro](./Images/pro.jpg)

#### Te presento [mouredev pro](https://mouredev.pro), mi proyecto más importante para ayudarte a estudiar programación y desarrollo de software de manera diferente.

> **¿Buscas un extra?** Aquí encontrarás este y otros cursos editados por lecciones individuales, para avanzar a tu ritmo y guardar el progreso. También dispondrás de ejercicios y correcciones, test para validar tus conocimientos, examen y certificado público de finalización, soporte, foro de estudiantes, reunionnes grupales, cursos exclusivos y mucho más.
>
> Entra en **[mouredev.pro](https://mouredev.pro)** y utiliza el cupón **"PYTHON"** con un 10% de descuento en tu primera suscripción.

## ![https://mouredev.com](https://raw.githubusercontent.com/mouredev/mouredev/master/mouredev_emote.png) Hola, mi nombre es Brais Moure.

### Freelance full-stack iOS & Android engineer

[![YouTube Channel Subscribers](https://img.shields.io/youtube/channel/subscribers/UCxPD7bsocoAMq8Dj18kmGyQ?style=social)](https://youtube.com/mouredevapps?sub_confirmation=1)
[![Twitch Status](https://img.shields.io/twitch/status/mouredev?style=social)](https://twitch.com/mouredev)
[![Discord](https://img.shields.io/discord/729672926432985098?style=social&label=Discord&logo=discord)](https://mouredev.com/discord)
[![Twitter Follow](https://img.shields.io/twitter/follow/mouredev?style=social)](https://twitter.com/mouredev)
![GitHub Followers](https://img.shields.io/github/followers/mouredev?style=social)
![GitHub Followers](https://img.shields.io/github/stars/mouredev?style=social)

Soy ingeniero de software desde 2010. Desde 2018 combino mi trabajo desarrollando Apps con la creación de contenido formativo sobre programación y tecnología en diferentes redes sociales como **[@mouredev](https://moure.dev)**.

Si quieres unirte a nuestra comunidad de desarrollo, aprender programación, mejorar tus habilidades y ayudar a la continuidad del proyecto, puedes encontrarnos en:

[![Twitch](https://img.shields.io/badge/Twitch-Programación_en_directo-9146FF?style=for-the-badge&logo=twitch&logoColor=white&labelColor=101010)](https://twitch.tv/mouredev)
[![Discord](https://img.shields.io/badge/Discord-Servidor_de_la_comunidad-5865F2?style=for-the-badge&logo=discord&logoColor=white&labelColor=101010)](https://mouredev.com/discord) [![Pro](https://img.shields.io/badge/Cursos-mouredev.pro-FF5500?style=for-the-badge&logo=gnometerminal&logoColor=white&labelColor=101010)](https://moure.dev)
[![Link](https://img.shields.io/badge/Links_de_interés-moure.dev-14a1f0?style=for-the-badge&logo=Linktree&logoColor=white&labelColor=101010)](https://moure.dev) [![Web](https://img.shields.io/badge/GitHub-MoureDev-087ec4?style=for-the-badge&logo=github&logoColor=white&labelColor=101010)](https://github.com/mouredev)
Download .txt
gitextract_uv6mnn0a/

├── .gitignore
├── Backend/
│   ├── FastAPI/
│   │   ├── db/
│   │   │   ├── client.py
│   │   │   ├── models/
│   │   │   │   └── user.py
│   │   │   └── schemas/
│   │   │       └── user.py
│   │   ├── main.py
│   │   ├── requirements.txt
│   │   ├── routers/
│   │   │   ├── basic_auth_users.py
│   │   │   ├── jwt_auth_users.py
│   │   │   ├── products.py
│   │   │   ├── users.py
│   │   │   └── users_db.py
│   │   └── vercel.json
│   └── type_hints.py
├── Basic/
│   ├── 00_helloworld.py
│   ├── 01_variables.py
│   ├── 02_operators.py
│   ├── 03_strings.py
│   ├── 04_lists.py
│   ├── 05_tuples.py
│   ├── 06_sets.py
│   ├── 07_dicts.py
│   ├── 08_conditionals.py
│   ├── 09_loops.py
│   ├── 10_functions.py
│   ├── 11_classes.py
│   ├── 12_exceptions.py
│   ├── 13_modules.py
│   └── my_module.py
├── Intermediate/
│   ├── 00_dates.py
│   ├── 01_list_comprehension.py
│   ├── 02_challenges.py
│   ├── 03_lambdas.py
│   ├── 04_higher_order_functions.py
│   ├── 05_error_types.py
│   ├── 06_file_handling.py
│   ├── 07_regular_expressions.py
│   ├── 08_python_package_manager.py
│   ├── my_file.csv
│   ├── my_file.json
│   ├── my_file.txt
│   └── mypackage/
│       ├── __init__.py
│       └── arithmetics.py
├── LICENSE
└── README.md
Download .txt
SYMBOL INDEX (67 symbols across 17 files)

FILE: Backend/FastAPI/db/models/user.py
  class User (line 9) | class User(BaseModel):

FILE: Backend/FastAPI/db/schemas/user.py
  function user_schema (line 5) | def user_schema(user) -> dict:
  function users_schema (line 11) | def users_schema(users) -> list:

FILE: Backend/FastAPI/main.py
  function root (line 37) | async def root():
  function url (line 44) | async def url():

FILE: Backend/FastAPI/routers/basic_auth_users.py
  class User (line 18) | class User(BaseModel):
  class UserDB (line 25) | class UserDB(User):
  function search_user_db (line 47) | def search_user_db(username: str):
  function search_user (line 52) | def search_user(username: str):
  function current_user (line 57) | async def current_user(token: str = Depends(oauth2)):
  function login (line 74) | async def login(form: OAuth2PasswordRequestForm = Depends()):
  function me (line 89) | async def me(user: User = Depends(current_user)):

FILE: Backend/FastAPI/routers/jwt_auth_users.py
  class User (line 27) | class User(BaseModel):
  class UserDB (line 34) | class UserDB(User):
  function search_user_db (line 56) | def search_user_db(username: str):
  function search_user (line 61) | def search_user(username: str):
  function auth_user (line 66) | async def auth_user(token: str = Depends(oauth2)):
  function current_user (line 84) | async def current_user(user: User = Depends(auth_user)):
  function login (line 94) | async def login(form: OAuth2PasswordRequestForm = Depends()):
  function me (line 114) | async def me(user: User = Depends(current_user)):

FILE: Backend/FastAPI/routers/products.py
  function products (line 17) | async def products():
  function products (line 22) | async def products(id: int):

FILE: Backend/FastAPI/routers/users.py
  class User (line 13) | class User(BaseModel):
  function usersjson (line 28) | async def usersjson():  # Creamos un JSON a mano
  function users (line 36) | async def users():
  function user (line 41) | async def user(id: int):
  function user (line 46) | async def user(id: int):
  function user (line 54) | async def user(user: User):
  function user (line 63) | async def user(user: User):
  function user (line 79) | async def user(id: int):
  function search_user (line 92) | def search_user(id: int):

FILE: Backend/FastAPI/routers/users_db.py
  function users (line 18) | async def users():
  function user (line 23) | async def user(id: str):
  function user (line 28) | async def user(id: str):
  function user (line 33) | async def user(user: User):
  function user (line 49) | async def user(user: User):
  function user (line 64) | async def user(id: str):
  function search_user (line 74) | def search_user(field: str, key):

FILE: Basic/10_functions.py
  function my_function (line 7) | def my_function():
  function sum_two_values (line 18) | def sum_two_values(first_value: int, second_value):
  function sum_two_values_with_return (line 30) | def sum_two_values_with_return(first_value, second_value):
  function print_name (line 44) | def print_name(name, surname):
  function print_name_with_default (line 53) | def print_name_with_default(name, surname, alias="Sin alias"):
  function print_upper_texts (line 63) | def print_upper_texts(*texts):

FILE: Basic/11_classes.py
  class MyEmptyPerson (line 7) | class MyEmptyPerson:
  class Person (line 17) | class Person:
    method __init__ (line 18) | def __init__(self, name, surname, alias="Sin alias"):
    method get_name (line 22) | def get_name(self):
    method walk (line 25) | def walk(self):

FILE: Basic/my_module.py
  function sumValue (line 5) | def sumValue(numberOne, numberTwo, numberThree):
  function printValue (line 9) | def printValue(value):

FILE: Intermediate/00_dates.py
  function print_date (line 15) | def print_date(date):

FILE: Intermediate/01_list_comprehension.py
  function sum_five (line 23) | def sum_five(number):

FILE: Intermediate/02_challenges.py
  function fizzbuzz (line 16) | def fizzbuzz():
  function is_anagram (line 41) | def is_anagram(word_one, word_two):
  function fibonacci (line 59) | def fibonacci():
  function is_prime (line 80) | def is_prime():
  function reverse (line 107) | def reverse(text):

FILE: Intermediate/03_lambdas.py
  function sum_three_values (line 11) | def sum_three_values(value):

FILE: Intermediate/04_higher_order_functions.py
  function sum_one (line 8) | def sum_one(value):
  function sum_five (line 12) | def sum_five(value):
  function sum_two_values_and_add_value (line 16) | def sum_two_values_and_add_value(first_value, second_value, f_sum):
  function sum_ten (line 26) | def sum_ten(original_value):
  function multiply_two (line 43) | def multiply_two(number):
  function filter_greater_than_ten (line 53) | def filter_greater_than_ten(number):
  function sum_two_values (line 65) | def sum_two_values(first_value, second_value):

FILE: Intermediate/mypackage/arithmetics.py
  function sum_two_values (line 5) | def sum_two_values(first_value, second_value):
Condensed preview — 44 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (72K chars).
[
  {
    "path": ".gitignore",
    "chars": 22,
    "preview": "__pycache__/\n*.py[cod]"
  },
  {
    "path": "Backend/FastAPI/db/client.py",
    "chars": 1238,
    "preview": "# Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=20480)\n\n### MongoDB client ###\n\n# Descarga versión community: https://w"
  },
  {
    "path": "Backend/FastAPI/db/models/user.py",
    "chars": 222,
    "preview": "# Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=20480\n\n### User model ###\n\nfrom pydantic import BaseModel\nfrom typing i"
  },
  {
    "path": "Backend/FastAPI/db/schemas/user.py",
    "chars": 322,
    "preview": "# Clase en vídeo (22/12/2022): https://www.twitch.tv/videos/1686104006\n\n### User schema ###\n\ndef user_schema(user) -> di"
  },
  {
    "path": "Backend/FastAPI/main.py",
    "chars": 1306,
    "preview": "# Clase en vídeo: https://youtu.be/_y9qQZXE24A\n\n### Hola Mundo ###\n\n# Documentación oficial: https://fastapi.tiangolo.co"
  },
  {
    "path": "Backend/FastAPI/requirements.txt",
    "chars": 52,
    "preview": "fastapi[standard]\npython-jose\npasslib\nbcrypt\npymongo"
  },
  {
    "path": "Backend/FastAPI/routers/basic_auth_users.py",
    "chars": 2321,
    "preview": "# Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=14094\n\n### Users API con autorización OAuth2 básica ###\n\nfrom fastapi i"
  },
  {
    "path": "Backend/FastAPI/routers/jwt_auth_users.py",
    "chars": 3131,
    "preview": "# Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=17664\n\n### Users API con autorización OAuth2 JWT ###\n\nfrom fastapi impo"
  },
  {
    "path": "Backend/FastAPI/routers/products.py",
    "chars": 463,
    "preview": "# Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=12475\n\n### Products API ###\n\nfrom fastapi import APIRouter\n\nrouter = AP"
  },
  {
    "path": "Backend/FastAPI/routers/users.py",
    "chars": 2340,
    "preview": "# Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=5382\n\n### Users API ###\n\nfrom fastapi import APIRouter, HTTPException\nf"
  },
  {
    "path": "Backend/FastAPI/routers/users_db.py",
    "chars": 2013,
    "preview": "# Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=20480\n\n### Users DB API ###\n\nfrom fastapi import APIRouter, HTTPExcepti"
  },
  {
    "path": "Backend/FastAPI/vercel.json",
    "chars": 212,
    "preview": "{\n    \"builds\": [\n        {\n            \"src\": \"main.py\",\n            \"use\": \"@vercel/python\"\n        }\n    ],\n    \"rout"
  },
  {
    "path": "Backend/type_hints.py",
    "chars": 445,
    "preview": "# Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=1810\n\n### Type Hints ###\n\nmy_string_variable = \"My String variable\"\npri"
  },
  {
    "path": "Basic/00_helloworld.py",
    "chars": 542,
    "preview": "# Clase en vídeo: https://youtu.be/Kp4Mvapo5kc\n\n### Hola Mundo ###\n\n# Nuestro hola mundo en Python\nprint(\"Hola Python\")\n"
  },
  {
    "path": "Basic/01_variables.py",
    "chars": 1081,
    "preview": "# Clase en vídeo: https://youtu.be/Kp4Mvapo5kc?t=2938\n\n### Variables ###\n\nmy_string_variable = \"My String variable\"\nprin"
  },
  {
    "path": "Basic/02_operators.py",
    "chars": 1193,
    "preview": "# Clase en vídeo: https://youtu.be/Kp4Mvapo5kc?t=5665\n\n### Operadores Aritméticos ###\n\n# Operaciones con enteros\nprint(3"
  },
  {
    "path": "Basic/03_strings.py",
    "chars": 1477,
    "preview": "# Clase en vídeo: https://youtu.be/Kp4Mvapo5kc?t=8643\n\n### Strings ###\n\nmy_string = \"Mi String\"\nmy_other_string = 'Mi ot"
  },
  {
    "path": "Basic/04_lists.py",
    "chars": 1569,
    "preview": "# Clase en vídeo: https://youtu.be/Kp4Mvapo5kc?t=10872\n\n### Lists ###\n\n# Definición\n\nmy_list = list()\nmy_other_list = []"
  },
  {
    "path": "Basic/05_tuples.py",
    "chars": 1035,
    "preview": "# Clase en vídeo: https://youtu.be/Kp4Mvapo5kc?t=14711\n\n### Tuples ###\n\n# Definición\n\nmy_tuple = tuple()\nmy_other_tuple "
  },
  {
    "path": "Basic/06_sets.py",
    "chars": 1077,
    "preview": "# Clase en vídeo: https://youtu.be/Kp4Mvapo5kc?t=16335\n\n### Sets ###\n\n# Definición\n\nmy_set = set()\nmy_other_set = {}\n\npr"
  },
  {
    "path": "Basic/07_dicts.py",
    "chars": 1373,
    "preview": "# Clase en vídeo: https://youtu.be/Kp4Mvapo5kc\n\n### Dictionaries ###\n\n# Definición\n\nmy_dict = dict()\nmy_other_dict = {}\n"
  },
  {
    "path": "Basic/08_conditionals.py",
    "chars": 787,
    "preview": "# Clase en vídeo: https://youtu.be/Kp4Mvapo5kc?t=21442\n\n### Conditionals ###\n\n# if\n\nmy_condition = False\n\nif my_conditio"
  },
  {
    "path": "Basic/09_loops.py",
    "chars": 1153,
    "preview": "# Clase en vídeo: https://youtu.be/Kp4Mvapo5kc?t=23822\n\n### Loops ###\n\n# While\n\nmy_condition = 0\n\nwhile my_condition < 1"
  },
  {
    "path": "Basic/10_functions.py",
    "chars": 1395,
    "preview": "# Clase en vídeo: https://youtu.be/Kp4Mvapo5kc?t=26619\n\n### Functions ###\n\n# Definición\n\ndef my_function():\n    print(\"E"
  },
  {
    "path": "Basic/11_classes.py",
    "chars": 980,
    "preview": "# Clase en vídeo: https://youtu.be/Kp4Mvapo5kc?t=29327\n\n### Classes ###\n\n# Definición\n\nclass MyEmptyPerson:\n    pass  # "
  },
  {
    "path": "Basic/12_exceptions.py",
    "chars": 1181,
    "preview": "# Clase en vídeo: https://youtu.be/Kp4Mvapo5kc?t=32030\n\n### Exception Handling ###\n\nnumberOne = 5\nnumberTwo = 1\nnumberTw"
  },
  {
    "path": "Basic/13_modules.py",
    "chars": 346,
    "preview": "# Clase en vídeo: https://youtu.be/Kp4Mvapo5kc?t=34583\n\n### Modules ###\n\nfrom math import pi as PI_VALUE\nimport math\nfro"
  },
  {
    "path": "Basic/my_module.py",
    "chars": 223,
    "preview": "# Clase en vídeo: https://youtu.be/Kp4Mvapo5kc?t=34583\n\n### Módulo para pruebas ###\n\ndef sumValue(numberOne, numberTwo, "
  },
  {
    "path": "Intermediate/00_dates.py",
    "chars": 1253,
    "preview": "# Clase en vídeo: https://youtu.be/TbcEqkabAWU\n\n### Dates ###\n\n# Date time\n\nfrom datetime import timedelta\nfrom datetime"
  },
  {
    "path": "Intermediate/01_list_comprehension.py",
    "chars": 469,
    "preview": "# Clase en vídeo: https://youtu.be/TbcEqkabAWU?t=3239\n\n### List Comprehension ###\n\nmy_original_list = [0, 1, 2, 3, 4, 5,"
  },
  {
    "path": "Intermediate/02_challenges.py",
    "chars": 2663,
    "preview": "# Clase en vídeo: https://youtu.be/TbcEqkabAWU?t=4142\n\n### Challenges ###\n\n\"\"\"\nEL FAMOSO \"FIZZ BUZZ”:\nEscribe un program"
  },
  {
    "path": "Intermediate/03_lambdas.py",
    "chars": 434,
    "preview": "# Clase en vídeo: https://youtu.be/TbcEqkabAWU?t=9145\n\n### Lambdas ###\n\nsum_two_values = lambda first_value, second_valu"
  },
  {
    "path": "Intermediate/04_higher_order_functions.py",
    "chars": 1206,
    "preview": "# Clase en vídeo: https://youtu.be/TbcEqkabAWU?t=10172\n\n### Higher Order Functions ###\n\nfrom functools import reduce\n\n\nd"
  },
  {
    "path": "Intermediate/05_error_types.py",
    "chars": 1125,
    "preview": "# Clase en vídeo: https://youtu.be/TbcEqkabAWU?t=12721\n\n### Error Types ###\n\n# SyntaxError\n# print \"¡Hola comunidad!\" # "
  },
  {
    "path": "Intermediate/06_file_handling.py",
    "chars": 2337,
    "preview": "# Clase en vídeo: https://youtu.be/TbcEqkabAWU?t=15524\n\n### File Handling ###\n\nimport xml\nimport csv\nimport json\nimport "
  },
  {
    "path": "Intermediate/07_regular_expressions.py",
    "chars": 1848,
    "preview": "# Clase en vídeo: https://youtu.be/TbcEqkabAWU?t=19762\n\n### Regular Expressions ###\n\nimport re\n\n# match\n\nmy_string = \"Es"
  },
  {
    "path": "Intermediate/08_python_package_manager.py",
    "chars": 682,
    "preview": "# Clase en vídeo: https://youtu.be/TbcEqkabAWU?t=24010\n\n### Python Package Manager ###\n\n# PIP https://pypi.org\n\n# pip in"
  },
  {
    "path": "Intermediate/my_file.csv",
    "chars": 95,
    "preview": "name,surname,age,language,website\r\nBrais,Moure,35,Python,https://moure.dev\r\nRoswell,,2,COBOL,\r\n"
  },
  {
    "path": "Intermediate/my_file.json",
    "chars": 152,
    "preview": "{\n  \"name\": \"Brais\",\n  \"surname\": \"Moure\",\n  \"age\": 35,\n  \"languages\": [\n    \"Python\",\n    \"Swift\",\n    \"Kotlin\"\n  ],\n  "
  },
  {
    "path": "Intermediate/my_file.txt",
    "chars": 120,
    "preview": "Mi nombre es Brais\nMi apellido es Moure\n35 años\nY mi lenguaje preferido es Python\nAunque también me gusta Kotlin\nY Swift"
  },
  {
    "path": "Intermediate/mypackage/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "Intermediate/mypackage/arithmetics.py",
    "chars": 162,
    "preview": "# Clase en vídeo: https://youtu.be/TbcEqkabAWU?t=24010\n\n### Arithmetics ###\n\ndef sum_two_values(first_value, second_valu"
  },
  {
    "path": "LICENSE",
    "chars": 11357,
    "preview": "                                 Apache License\n                           Version 2.0, January 2004\n                   "
  },
  {
    "path": "README.md",
    "chars": 12749,
    "preview": "# Hello Python\n\n[![Python](https://img.shields.io/badge/Python-3.10+-yellow?style=for-the-badge&logo=python&logoColor=wh"
  }
]

About this extraction

This page contains the full source code of the mouredev/Hello-Python GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 44 files (64.6 KB), approximately 19.0k tokens, and a symbol index with 67 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!