diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 00000000..0a63314d Binary files /dev/null and b/.DS_Store differ diff --git a/.gitignore b/.gitignore index d6831164..44f5e3e5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ *.pyc .env -models/ \ No newline at end of file +models/ +mlops/ +*.pyc # Python virtual environment files \ No newline at end of file diff --git a/src/api/Dockerfile.api b/Dockerfile.api similarity index 66% rename from src/api/Dockerfile.api rename to Dockerfile.api index bf23533c..c663d1dd 100644 --- a/src/api/Dockerfile.api +++ b/Dockerfile.api @@ -1,7 +1,6 @@ -# This Dockerfile is meant to be run from the root of the repo +# Base Python image (Python 3.9.6) +FROM python:3.12.4 -# Base Python image (Python 3.12) -FROM python:3.12-slim # Set the working directory in the container WORKDIR /app @@ -9,7 +8,8 @@ WORKDIR /app # Copy the current folder (on the host machine) that contains the whole app project into the container /app folder COPY . /app -RUN pip install . +# install the required packages +RUN pip install --no-cache-dir -r requirements.txt # Expose the port on which FastAPI will run EXPOSE 8000 @@ -18,4 +18,4 @@ EXPOSE 8000 ENV DSBA_MODELS_ROOT_PATH=/app/models # Define the default command run when starting the container: Run the FastAPI app using Uvicorn -CMD ["uvicorn", "src.api.api:app", "--host", "0.0.0.0", "--port", "8000"] +CMD ["uvicorn", "api:app", "--host", "0.0.0.0", "--port", "8000"] diff --git a/Project_Report.pdf b/Project_Report.pdf new file mode 100644 index 00000000..3ba883cc Binary files /dev/null and b/Project_Report.pdf differ diff --git a/README.md b/README.md index eec68152..64fb7740 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,9 @@ # DSBA Platform -A toy MLOps Platform for educational purposes +A toy MLOps Project ## Project Structure -This project has a fairly standard structure (but it is still adapted to be simplified compared to a slightly more typical structure): - a `pyproject.toml` file contains the project metadata, including the dependencies. It is common to see a "setup.py" file in Python projects but we use this more modern approach to define the project metadata. - The `src` folder contains the code code (dsba) as well as the code for the CLI, the API, the web app, the notebooks, as well as the Dockerfiles. @@ -98,9 +97,52 @@ For windows, something of the sort may work: set DSBA_MODELS_ROOT_PATH="C:\path\to\your\models" ``` -## CLI -List models registered on your system: + + + +# MLOps student project +This project aimed to create an interface for a bank employees that allows them to choose a prediction model, a customer dataset, and then provide a result on whether customers will churn or not. + +To do this, we based our work on a machine learning project on bank churners that one of us had previously created. This project used the dataset of a kaggle challenge available at : https://www.kaggle.com/datasets/thedevastator/predicting-credit-card-customer-attrition-with-m + + +## Important Folders and Files + +### Data + +```bash +data/ +``` + +This contains: +- the original `BankChurners.csv` file of the Kaggle challenge used for the original ML project +- the `X_test.csv` and the `y_test.csv` files created after the preprocessing of the original dataset, this files are the ones used for the rest of the MLOps project + + +### Models + +```bash +models/ +``` + +This contains the different models trained and available to predict results. The 4 models are : +- `lgbm_model.pkl` +- `rf_model.pkl` +- `svm_model.pkl` +- `xgb_model.pkl` + + +### Src + +```bash +src/ +``` +This is the main source directory where the code resides. + +#### CLI + +Not used in the MLOps project, normally it's used to list models registered on your system: ```bash src/cli/dsba_cli list @@ -112,17 +154,82 @@ Use a model to predict on a file: src/cli/dsba_cli predict --input /path/to/your/data/file.csv --output /path/to/your/output/file.csv --model-id your_model_id ``` -### Notebook +### API +An API is provided, it allows to interact with models. You can start the API by running: +```bash +uvicorn api:app --reload +``` + +Dockerized API +To run the API in a Docker container, follow these steps: +1. Build the Docker image: +```bash +docker build -f Dockerfile.api -t fastapi . +``` +2. Run the Docker container: +```bash +docker run -d -p 8000:80 fastapi +``` +The API will be available at http://127.0.0.1:8000/ + +Note: Ensure Docker is installed on your machine. +3. Tag the image +```bash +docker tag fastapi stanchiangtw/fastapi +``` + +Note: Ensure Docker Desktop is logged in by using +```bash +docker login +``` + +4. Push the tag image to Docker Hub +```bash +docker push stanchiangtw/fastapi:latest +``` + + +AWS ECS & EC2 +We successfully implemented the deployment and scaling of Docker containers on AWS ECS. The process involved the following steps: +- Creating an ECS cluster +- Defining a Task Definition +- Configuring a Security Group +- Setting up a service +- Accessing the running service + +The API was successfully running at http://13.37.241.233:8000/. + +However, the service quickly exceeded the free tier quota, resulting in costs ($12.46). Before stopping the service, we took a screenshot to document the progress made. +![](https://drive.google.com/uc?export=view&id=1YI7dOU-cK-AJIUZxjXoJGsSZiGhT2f55) + + +### Templates +The `templates/` directory contains HTML templates used for rendering web views in our application. The main file `dashboard.html` serves as the user interface for our ML model evaluation dashboard. +![](./static/dashboard.gif) + + +### static +The `static/` directory stores static resources like generated plots (.png files). The image is served directly to the client browser and don't change during runtime. The visualization image created during model evaluation is stored here, allowing it to be displayed in the dashboard. + + +### Dockerfile +The .api file includes all the necessary instructions, organized in a way that ensures Docker executes them correctly. + +### Requirements +The .txt file contains all the necessary Python packages required to process the data, train the model, and run the API. + + +#### DSBA +This contains the core functionality of the MLOps project, including model handling, data preprocessing, and utilities for training and predicting. -... -### API -... +#### Notebooks +This contains: +- `model_training_example.ipynb` the original example of Notebook of the MLOps platform project +- `Bank_MLOps.ipynb` the notebook of an ML project from which we used it for our MLOps project. The original code from the ML project has not been modified; it may contain some elements from LLM. To use the notebook, navigate to the `notebooks/` folder and open the file. You can use the provided utilities to train models, preprocess data, and evaluate performance. -### Dockerized API -... -### REMARKS -remove extra preprocessing files \ No newline at end of file +## REMARKS +No remarks diff --git a/api.py b/api.py new file mode 100644 index 00000000..df3a2556 --- /dev/null +++ b/api.py @@ -0,0 +1,182 @@ +from fastapi import FastAPI, UploadFile, File +import pandas as pd +import joblib +import pickle +from src.dsba.data_ingestion.data_ingestion import load_csv +from src.dsba.preprocessing_a import preprocess_data +from src.dsba.model_evaluation import evaluate_models +import io +from pathlib import Path +from typing import Optional +import sys +from fastapi.responses import HTMLResponse +from fastapi.staticfiles import StaticFiles +from fastapi import Request +import matplotlib.pyplot as plt +from fastapi.templating import Jinja2Templates +import numpy +sys.modules['numpy._core'] = numpy.core + + + + + +df = load_csv("data/BankChurners.csv") +X_train, X_test, y_train, y_test = preprocess_data("data/BankChurners.csv") + +lgbm_model = joblib.load('models/lgbm_model.pkl') +rf_model = joblib.load('models/rf_model.pkl') +xgb_model = joblib.load('models/xgb_model.pkl') +svm_model = joblib.load('models/svm_model.pkl') + +models = { + "LGBM": lgbm_model, + "RandomForest": rf_model, + "XGBoost": xgb_model, + "SVM": svm_model +} + +results, model_comparison = evaluate_models(models, X_train, y_train, X_test, y_test) + +png_path = "static/model_comparison.png" +model_comparison.savefig(png_path) + + + +data_info = df.iloc[:5].to_html(classes='table table-striped table-bordered', index=False) +columns_df = pd.DataFrame({'Column Name': df.columns.tolist()}) +columns_info = columns_df.to_html(classes='table table-striped table-bordered', index=False) +model_info = {"Show the model info": {}} +for model_name, model in models.items(): + model_info["Show the model info"][model_name] = model.__class__.__name__ + +results_dict = results.to_dict(orient="records") +metrics_summary = {} + +for record in results_dict: + model_name = record["Model"] + dataset_type = record["Dataset"] + + if model_name not in metrics_summary: + metrics_summary[model_name] = {} + + metrics_summary[model_name][dataset_type] = { + "accuracy": record["accuracy"], + "precision": record["precision"], + "recall": record["recall"], + "f1_score": record["f1_score"] + } + +app = FastAPI() + +template = Jinja2Templates(directory="templates") +app.mount("/static", StaticFiles(directory="static"), name="static") + +async def tmp_save_file(upload_file: UploadFile) -> Path: + try: + temp_dir = Path("temp_uploads") + temp_dir.mkdir(exist_ok=True) + + # Generate Temporary file path + file_path = temp_dir / f"{upload_file.filename}" + + # Read the contents + contents = await upload_file.read() + + # Write the temporary file + with open(file_path, "wb") as f: + f.write(contents) + + return file_path + + except Exception as e: + raise ValueError(f"Error when saving the file: {str(e)}") + + +@app.get("/") +async def read_root(request: Request): + return template.TemplateResponse("dashboard.html", { + "request": request, + "data_info": data_info, + "columns_info": columns_info, + "model_info": model_info, + "metrics_summary": metrics_summary, + "plot_image_path": "static/model_comparison.png" + + }) + +@app.post("/upload-and-evaluate/") +async def upload_and_evaluate(request: Request, file: Optional[UploadFile] = None): + try: + + if file is None: + return template.TemplateResponse("dashboard.html", { + "request": request, + "data_info": data_info, + "columns_info": columns_info, + "model_info": model_info, + "metrics_summary": metrics_summary, + "plot_image_path": "static/model_comparison.png" + + }) + + + # Need HTML to design the layout to upload the file + temp_file_path = await tmp_save_file(file) + + df_upload = pd.read_csv(temp_file_path) + + X_train_upload, X_test_upload, y_train_upload, y_test_upload = preprocess_data(temp_file_path) + + + results_upload, model_comparison_upload = evaluate_models(models, X_train_upload, X_test_upload, y_train_upload, y_test_upload ) + + png_path_upload = "static/model_comparison_upload.png" + model_comparison_upload.savefig(png_path_upload) + + # Need HTML to show the plot for model_comparison_upload + + data_upload = df_upload.iloc[:5].to_html(classes='table table-striped table-bordered', index=False)# Over 5 records, the layout will be messy + + + columns_upload_df = pd.DataFrame({'Column Name': df_upload.columns.tolist()}) + columns_info_upload = columns_upload_df.to_html(classes='table table-striped table-bordered', index=False) + + model_info_upload = {"Show the model info": {}} + for model_name, model in models.items(): + model_info_upload["Show the model info"][model_name] = model.__class__.__name__ + + results_dict_upload = results_upload.to_dict(orient="records") + metrics_summary_upload = {} + + + for record in results_dict_upload: + model_name = record["Model"] + dataset_type = record["Dataset"] + + if model_name not in metrics_summary_upload: + metrics_summary_upload[model_name] = {} + + metrics_summary_upload[model_name][dataset_type] = { + "accuracy": record["accuracy"], + "precision": record["precision"], + "recall": record["recall"], + "f1_score": record["f1_score"] + } + + return template.TemplateResponse("dashboard.html", { + "request": request, + "data_info": data_upload, + "columns_info": columns_info_upload, + "model_info": model_info_upload, + "metrics_summary": metrics_summary_upload, + "plot_image_path": "static/model_comparison_upload.png" + + }) + + except ValueError as e: + return {"error": str(e)} + + except Exception as e: + return {"error": f"Unexpected Error: {str(e)}"} + diff --git a/poetry.lock b/poetry.lock index 24819abf..1efcc35a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -535,6 +535,24 @@ files = [ {file = "iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7"}, ] +[[package]] +name = "jinja2" +version = "3.1.6" +description = "A very fast and expressive template engine." +optional = false +python-versions = ">=3.7" +groups = ["main"] +files = [ + {file = "jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67"}, + {file = "jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d"}, +] + +[package.dependencies] +MarkupSafe = ">=2.0" + +[package.extras] +i18n = ["Babel (>=2.7)"] + [[package]] name = "joblib" version = "1.4.2" @@ -637,6 +655,77 @@ files = [ {file = "kiwisolver-1.4.8.tar.gz", hash = "sha256:23d5f023bdc8c7e54eb65f03ca5d5bb25b601eac4d7f1a042888a1f45237987e"}, ] +[[package]] +name = "markupsafe" +version = "3.0.2" +description = "Safely add untrusted strings to HTML/XML markup." +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-win32.whl", hash = "sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-win32.whl", hash = "sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-win32.whl", hash = "sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a"}, + {file = "markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0"}, +] + [[package]] name = "matplotlib" version = "3.10.1" @@ -1234,6 +1323,18 @@ files = [ [package.dependencies] six = ">=1.5" +[[package]] +name = "python-multipart" +version = "0.0.20" +description = "A streaming multipart parser for Python" +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "python_multipart-0.0.20-py3-none-any.whl", hash = "sha256:8a62d3a8335e06589fe01f2a3e178cdcc632f3fbe0d492ad9ee0ec35aab1f104"}, + {file = "python_multipart-0.0.20.tar.gz", hash = "sha256:8dd0cab45b8e23064ae09147625994d090fa46f5b0d1e13af944c331a7fa9d13"}, +] + [[package]] name = "pytz" version = "2025.2" @@ -1765,4 +1866,4 @@ dev = ["mypy", "pytest", "ruff"] [metadata] lock-version = "2.1" python-versions = ">=3.10" -content-hash = "b75ca6c82233281f9ff2c9d56a07b3409ca30f03f9d0d633bace6c0df94b1910" +content-hash = "a59a1bb687e83fa0e4f37a52641e9c6695d2054f9f6f38305567d01babe2b1ac" diff --git a/pyproject.toml b/pyproject.toml index e8dbac9e..29c3e237 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,6 +21,8 @@ dependencies = [ "uvicorn>=0.34.0", "xgboost>=2.1.3", "imbalanced-learn (>=0.13.0,<0.14.0)", + "jinja2 (>=3.1.6,<4.0.0)", + "python-multipart (>=0.0.20,<0.0.21)", ] diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 00000000..53279d34 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,17 @@ +imbalanced-learn==0.12.3 +matplotlib==3.10.1 +scikit-learn==1.6.1 +seaborn==0.13.2 +numpy==2.2.4 +xgboost==3.0.0 +lightgbm==4.6.0 + +fastapi==0.110.1 +pandas==2.2.3 +joblib==1.4.2 +requests==2.32.3 +uvicorn==0.17.6 + +python-multipart==0.0.5 +pydantic==2.5.3 +jinja2==3.1.3 diff --git a/src/api/api.py b/src/api/api.py deleted file mode 100644 index 485d2549..00000000 --- a/src/api/api.py +++ /dev/null @@ -1,45 +0,0 @@ -import json -import logging -from fastapi import FastAPI, HTTPException -from dsba.model_registry import list_models_ids, load_model, load_model_metadata -from dsba.model_prediction import classify_record - - -logging.basicConfig( - level=logging.INFO, - format="%(asctime)s [%(levelname)s] %(message)s", - datefmt="%H:%M:%S,", -) - -app = FastAPI() - - -# using FastAPI with defaults is very convenient -# we just add this "decorator" with the "route" we want. -# If I deploy this app on "https//mywebsite.com", this function can be called by visiting "https//mywebsite.com/models/" -@app.get("/models/") -async def list_models(): - return list_models_ids() - - -@app.api_route("/predict/", methods=["GET", "POST"]) -async def predict(query: str, model_id: str): - """ - Predict the target column of a record using a model. - The query should be a json string representing a record. - """ - # This function is a bit naive and focuses on the logic. - # To make it more production-ready you would want to validate the input, manage authentication, - # process the various possible errors and raise an appropriate HTTP exception, etc. - try: - record = json.loads(query) - model = load_model(model_id) - metadata = load_model_metadata(model_id) - prediction = classify_record(model, record, metadata.target_column) - return {"prediction": prediction} - except Exception as e: - # We do want users to be able to see the exception message in the response - # FastAPI will by default block the Exception and send a 500 status code - # (In the HTTP protocol, a 500 status code just means "Internal Server Error" aka "Something went wrong but we're not going to tell you what") - # So we raise an HTTPException that contains the same details as the original Exception and FastAPI will send to the client. - raise HTTPException(status_code=500, detail=str(e)) diff --git a/src/dsba/dashboard.html b/src/dsba/dashboard.html deleted file mode 100644 index 7a66f137..00000000 --- a/src/dsba/dashboard.html +++ /dev/null @@ -1,113 +0,0 @@ - - - - - - ML Model Evaluation Dashboard - - - - -
-

ML Model Evaluation Dashboard

- -
-
Data Preview
-
-
    - {% for row in data_info["Show the first 5 records of the dataset"] %} -
  • {{ row }}
  • - {% endfor %} -
-
-
- -
-
Model Information
- - -
-
- -
-
Metrics Summary
- - {% for model, metrics in metrics_summary.items() %} -

{{ model }}

- - - - - - - - {% for dataset_type, metric in metrics.items() %} - - - - - - - - {% endfor %} - {% endfor %} -
DatasetAccuracyPrecisionRecallF1 Score
{{ dataset_type }}{{ metric.accuracy }}{{ metric.precision }}{{ metric.recall }}{{ metric.f1_score }}
-
- -

📈 Model Comparison Plot

- Model Comparison - -
- - \ No newline at end of file diff --git a/src/dsba/data_ingestion/files.py b/src/dsba/data_ingestion/files.py index 2ffde2ad..4b5ca8cd 100644 --- a/src/dsba/data_ingestion/files.py +++ b/src/dsba/data_ingestion/files.py @@ -1,11 +1,11 @@ from io import StringIO from pathlib import Path -from typing import Any +from typing import Union, Optional import requests import pandas as pd -def load_csv_from_path(filepath: str | Path) -> pd.DataFrame: +def load_csv_from_path(filepath: Union[str, Path]) -> pd.DataFrame: """ Loads a CSV file on the local filesystem into a pandas DataFrame Since it loads it all in memory, it is only suitable for datasets small enough to fit in memory @@ -19,5 +19,5 @@ def load_csv_from_url(url: str) -> pd.DataFrame: return pd.read_csv(StringIO(response.text)) -def write_csv_to_path(df: pd.DataFrame, filepath: str | Path) -> None: +def write_csv_to_path(df: pd.DataFrame, filepath: Union[str, Path]) -> None: df.to_csv(filepath, index=False) diff --git a/src/dsba/model_evaluation.py b/src/dsba/model_evaluation.py index 4b275f7d..03134468 100644 --- a/src/dsba/model_evaluation.py +++ b/src/dsba/model_evaluation.py @@ -8,10 +8,14 @@ f1_score, precision_score, recall_score, + make_scorer ) import matplotlib.pyplot as plt import seaborn as sns -from dsba.preprocessing import preprocess_dataframe, split_features_and_target +from statistics import mean +import logging +from typing import Any +from sklearn.model_selection import cross_val_score @dataclass @@ -20,60 +24,118 @@ class ClassifierEvaluationResult: precision: float recall: float f1_score: float - confusion_matrix: list[list[int]] + confusion_matrix: Any = None - -def evaluate_classifier( - classifier: ClassifierMixin, target_column: str, df: pd.DataFrame +def get_cross_val_score( + fitted_model: ClassifierMixin, X: pd.DataFrame, y: pd.Series, num_cv: int = 5 ) -> ClassifierEvaluationResult: - df = preprocess_dataframe(df) - X, y_actual = split_features_and_target(df, target_column) - y_predicted = classifier.predict(X) + + f1_scorer=make_scorer(f1_score,average='weighted', zero_division=0) #average='weighted' ensures that the F1-score is computed for each class separately and then weighted by the number of true instances for each class + f1=cross_val_score(fitted_model, X, y, cv=num_cv, scoring=f1_scorer) + + #PRECISION (proportion of correctly predicted positive observations out of all predicted positives) + precision_scorer=make_scorer(precision_score,average='weighted', zero_division=0) + precision=cross_val_score(fitted_model, X , y ,cv=num_cv,scoring=precision_scorer) + + #RECALL (proportion of correctly predicted positive observations out of all actual positives) + recall_scorer=make_scorer(recall_score,average='weighted', zero_division=0) + recall=cross_val_score(fitted_model, X , y ,cv=num_cv,scoring=recall_scorer) - accuracy = accuracy_score(y_actual, y_predicted) - precision = precision_score( - y_actual, y_predicted, average="weighted", zero_division=0 + #ACCURACY (proportion of correctly classified observations out of the total number of observations) + accuracy= cross_val_score(fitted_model, X , y ,cv=num_cv, scoring='accuracy') + + return ClassifierEvaluationResult( + accuracy= mean(accuracy), + precision= mean(precision), + recall= mean(recall), + f1_score= mean(f1) ) - recall = recall_score(y_actual, y_predicted, average="weighted", zero_division=0) - f1 = f1_score(y_actual, y_predicted, average="weighted", zero_division=0) - conf_matrix = confusion_matrix(y_actual, y_predicted) +def get_test_score(predictions, y_test) -> ClassifierEvaluationResult: + accuracy = accuracy_score(y_test, predictions) + precision = precision_score(y_test, predictions, average="weighted", zero_division=0) + recall = recall_score(y_test, predictions, average="weighted", zero_division=0) + f1 = f1_score(y_test, predictions, average="weighted", zero_division=0) return ClassifierEvaluationResult( - accuracy=accuracy, - precision=precision, - recall=recall, - f1_score=f1, - confusion_matrix=conf_matrix, + accuracy = accuracy, + precision = precision, + recall = recall, + f1_score = f1, ) +def add_to_results(df, model_name, cv_metrics, test_metrics): + logging.info(f"Storing results for {model_name}") + + # Convert to dictionary if not already a dictionary + cv_dict = cv_metrics.__dict__ if hasattr(cv_metrics, '__dict__') else cv_metrics + test_dict = test_metrics.__dict__ if hasattr(test_metrics, '__dict__') else test_metrics + + new_rows = pd.DataFrame([ + {"Dataset": "Cross-Validation", "Model": model_name, **cv_dict}, + {"Dataset": "Test Set", "Model": model_name, **test_dict} + ]) + + return pd.concat([df, new_rows], ignore_index=True) + +def plot_model_comparison(results_df: pd.DataFrame, y_axis_start: float = 0.4): + # Set style for Seaborn plots + logging.info("Generating model comparison plots..") + sns.set_style("whitegrid") + + # Plot Accuracy, Precision, Recall, F1-Score, and FOR for each model + metrics_plot = ["accuracy", "precision", "recall", "f1_score"] + metrics_titles = ["Accuracy", "Precision", "Recall", "F1 Score"] + + # Set up the figure for subplots + fig, axes = plt.subplots(2, 2, figsize=(16, 10)) + axes = axes.flatten() + + for i, (metric, metric_title) in enumerate(zip(metrics_plot, metrics_titles)): + sns.barplot( + data=results_df, + x="Model", + y=metric, + hue="Dataset", + ax=axes[i], + palette="muted" + ) + axes[i].set_title(f"Model Comparison: {metric}") + axes[i].set_ylabel(metric) + axes[i].set_xlabel("Model") + axes[i].legend(title="Dataset", loc="lower right") + + axes[i].set_ylim(y_axis_start, axes[i].get_ylim()[1]) #here to adjust vertical axis : 0; 0,4 or other value + + # Adjust spacing between plots + plt.tight_layout() + + return fig -# Display functions : +def evaluate_models(models, X_train, y_train, X_test, y_test): -def visualize_classification_evaluation(result: ClassifierEvaluationResult): - confusion_maxtrix_fig = plot_confusion_matrix(result) - plt.show(confusion_maxtrix_fig) - evaluation_metrics_fig = plot_classification_metrics(result) - plt.show(evaluation_metrics_fig) + results_df = pd.DataFrame(columns=["Dataset", "Model", "accuracy", "precision", "recall", "f1_score"]) + for model_name, model in models.items(): + cv_metrics = get_cross_val_score(model, X_train, y_train) + y_pred_test = model.predict(X_test) + test_metrics = get_test_score(y_test, y_pred_test) + results_df = add_to_results(results_df, model_name, cv_metrics, test_metrics) -def plot_confusion_matrix(result: ClassifierEvaluationResult) -> plt.Figure: - confusion_matrix_df = pd.DataFrame(result.confusion_matrix) - fig, ax = plt.subplots(figsize=(6, 6)) - sns.heatmap(confusion_matrix_df, annot=True, fmt="d", cmap="Blues", ax=ax) - ax.set_title("Confusion Matrix") - ax.set_xlabel("Predicted") - ax.set_ylabel("Actual") - return fig + results_df = results_df.sort_values(by=["Dataset"], ignore_index=True) + + + + + return results_df, plot_model_comparison(results_df) + + +#models = { +# "SVM": best_model_svm, +# "Random Forest": best_model_rfc, +# "XGBoost": best_model_xgb, +# "LGBM": best_model_lgbm +#} +#results_df = evaluate_models(models, X_train, y_train, X_test, y_test) -def plot_classification_metrics(result: ClassifierEvaluationResult) -> plt.Figure: - metrics = ["accuracy", "precision", "recall", "f1_score"] - scores = [result.accuracy, result.precision, result.recall, result.f1_score] - metric_data = pd.DataFrame({"Metric": metrics, "Score": scores}) - fig, ax = plt.subplots(figsize=(6, 6)) - sns.barplot(data=metric_data, x="Metric", y="Score", ax=ax) - ax.set_ylim(0, 1) - ax.set_title("Classification Metrics") - ax.set_ylabel("Score") - return fig diff --git a/src/dsba/model_prediction.py b/src/dsba/model_prediction.py index 12d1b507..ec19505f 100644 --- a/src/dsba/model_prediction.py +++ b/src/dsba/model_prediction.py @@ -1,36 +1,9 @@ import logging import pandas as pd from sklearn.base import ClassifierMixin -from dsba.preprocessing import preprocess_dataframe -def classify_dataframe( - model: ClassifierMixin, df: pd.DataFrame, target_column: str -) -> pd.DataFrame: - _check_target_column(df, target_column) - df = preprocess_dataframe(df) - y_predicted = model.predict(df) - df[target_column] = y_predicted - return df - - -def classify_record( - model: ClassifierMixin, record: dict, target_column: str -) -> int | float | str: - df = pd.DataFrame([record]) - _check_target_column(df, target_column) - df = classify_dataframe(model, df, target_column) - return df.iloc[0][target_column] - - -def _check_target_column(df: pd.DataFrame, target_column: str) -> None: - """ - As a convenience, we allow the user to pass a dataframe that already has the target column in the input - but this is quite suspicious, so we warn the user. - then we need to drop the target column before we can continue to have the right shape for the prediction - """ - if target_column in df.columns: - logging.warning( - f"Target column {target_column} already exists in the DataFrame." - ) - df.drop(columns=[target_column], inplace=True) +def predict( + model: ClassifierMixin, X_test: pd.DataFrame +) -> np.ndarray: + return model.predict(X_test) diff --git a/src/dsba/preprocessing.py b/src/dsba/preprocessing.py deleted file mode 100644 index f8affcb0..00000000 --- a/src/dsba/preprocessing.py +++ /dev/null @@ -1,36 +0,0 @@ -from pandas import DataFrame, Series -from sklearn.model_selection import train_test_split -from sklearn.preprocessing import LabelEncoder - -# from sklearn.model_selection import train_test_split - - -def split_features_and_target( - df: DataFrame, target_column: str -) -> tuple[DataFrame, Series]: - """ - Splits a DataFrame into features and target, which is a common format used by machine learning libraries such as scikit-learn. - """ - if target_column not in df.columns: - raise ValueError(f"Target column '{target_column}' not found in the DataFrame.") - X = df.drop(columns=[target_column]) - y = df[target_column] - return X, y - - -def split_dataframe( - df: DataFrame, test_size: float = 0.2 -) -> tuple[DataFrame, DataFrame]: - return train_test_split(df, test_size=test_size, random_state=42) - - -def preprocess_dataframe(df): - """ - Preprocess DataFrame by encoding categorical columns. - ML algorithms typically can't only handle numbers, so there may be quite a lot of feature engineering and preprocessing with other types of data. - Here, we take a very simplistic approach of applying the same treatment to all non-numeric columns. - """ - for column in df.select_dtypes(include=["object"]): - le = LabelEncoder() - df[column] = le.fit_transform(df[column].astype(str)) - return df diff --git a/src/dsba/preprocessing2.py b/src/dsba/preprocessing2.py deleted file mode 100644 index 033b305b..00000000 --- a/src/dsba/preprocessing2.py +++ /dev/null @@ -1,4 +0,0 @@ -from src.dsba.data_ingestion.data_ingestion import load_csv - -data = load_csv('data/BankChurners.csv') -print(data.head()) diff --git a/static/dashboard.gif b/static/dashboard.gif new file mode 100644 index 00000000..d2016426 Binary files /dev/null and b/static/dashboard.gif differ diff --git a/static/model_comparison.png b/static/model_comparison.png new file mode 100644 index 00000000..c4bd7ae3 Binary files /dev/null and b/static/model_comparison.png differ diff --git a/templates/dashboard.html b/templates/dashboard.html new file mode 100644 index 00000000..8e7391a6 --- /dev/null +++ b/templates/dashboard.html @@ -0,0 +1,222 @@ + + + + + + + ML Model Evaluation Dashboard + + + + + +
+

ML Model Evaluation Dashboard

+ +
+
Data Preview
+ + {#
#} + {#
    + {% for row in data_info["Show the first 5 records of the dataset"] %} +
  • {{ row }}
  • + {% endfor %} +
#} + {# + + + {% for key in data_info["Show the first 5 records of the dataset"][0].keys() %} + + {% endfor %} + + + + {% for row in data_info["Show the first 5 records of the dataset"] %} + + {% for value in row.values() %} + + {% endfor %} + + {% endfor %} + +
{{ key }}
{{ value }}
+
#} + +
+ {{ data_info | safe }} +
+
+ + +
+
Model Results
+ + {% for name, model in model_info["Show the model info"].items() %} +
+

{{ name }}

+

Model Info: {{ model }}

+ + + + + + + + + + + + + {% for dataset_type, metric in metrics_summary[name].items() %} + + + + + + + + {% endfor %} + +
DatasetAccuracyPrecisionRecallF1 Score
{{ dataset_type }}{{ metric.accuracy }}{{ metric.precision }}{{ metric.recall }}{{ metric.f1_score }}
+
+
+ {% endfor %} +
+ +

📈 Model Comparison Plot

+ Model Comparison + +
+ + + \ No newline at end of file diff --git a/tree_structure.txt b/tree_structure.txt new file mode 100644 index 00000000..9d6c8a04 --- /dev/null +++ b/tree_structure.txt @@ -0,0 +1,1962 @@ +Structure du dossier pour le volume Windows +Le numéro de série du volume est 30D2-7B30 +C:. +¦ .gitignore +¦ arborescence.txt +¦ data_utils +¦ poetry.lock +¦ pyproject.toml +¦ README.md +¦ requirements.txt +¦ ++---.pytest_cache +¦ ¦ .gitignore +¦ ¦ CACHEDIR.TAG +¦ ¦ README.md +¦ ¦ +¦ +---v +¦ +---cache +¦ lastfailed +¦ nodeids +¦ stepwise +¦ ++---data +¦ BankChurners.csv +¦ X_test.csv +¦ y_test.csv +¦ ++---models +¦ lgbm_model.pkl +¦ rf_model.pkl +¦ svm_model.pkl +¦ xgb_model.pkl +¦ ++---src +¦ +---api +¦ ¦ ¦ api.py +¦ ¦ ¦ Dockerfile.api +¦ ¦ ¦ +¦ ¦ +---__pycache__ +¦ ¦ api.cpython-312.pyc +¦ ¦ +¦ +---cli +¦ ¦ dsba_cli +¦ ¦ +¦ +---dsba +¦ ¦ ¦ model_creation.py +¦ ¦ ¦ model_evaluation.py +¦ ¦ ¦ model_prediction.py +¦ ¦ ¦ model_registry.py +¦ ¦ ¦ model_training.py +¦ ¦ ¦ preprocessing.py +¦ ¦ ¦ preprocessing2.py +¦ ¦ ¦ preprocessing_a.py +¦ ¦ ¦ __init__.py +¦ ¦ ¦ +¦ ¦ +---data_ingestion +¦ ¦ ¦ databases.py +¦ ¦ ¦ data_ingestion.py +¦ ¦ ¦ files.py +¦ ¦ ¦ __init__.py +¦ ¦ ¦ +¦ ¦ +---__pycache__ +¦ ¦ model_evaluation.cpython-312.pyc +¦ ¦ model_prediction.cpython-312.pyc +¦ ¦ model_registry.cpython-312.pyc +¦ ¦ preprocessing.cpython-312.pyc +¦ ¦ __init__.cpython-312.pyc +¦ ¦ +¦ +---notebooks +¦ Bank_MLOps.ipynb +¦ model_training_example.ipynb +¦ ++---tests +¦ ¦ __init__.py +¦ ¦ +¦ +---__pycache__ +¦ test_1.cpython-312-pytest-8.3.5.pyc +¦ __init__.cpython-312.pyc +¦ ++---venv + ¦ pyvenv.cfg + ¦ + +---Include + +---Lib + ¦ +---site-packages + ¦ +---annotated_types + ¦ ¦ +---__pycache__ + ¦ ¦ test_cases.cpython-312.pyc + ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ + ¦ +---anyio + ¦ ¦ +---abc + ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ _eventloop.cpython-312.pyc + ¦ ¦ ¦ _resources.cpython-312.pyc + ¦ ¦ ¦ _sockets.cpython-312.pyc + ¦ ¦ ¦ _streams.cpython-312.pyc + ¦ ¦ ¦ _subprocesses.cpython-312.pyc + ¦ ¦ ¦ _tasks.cpython-312.pyc + ¦ ¦ ¦ _testing.cpython-312.pyc + ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ + ¦ ¦ +---streams + ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ buffered.cpython-312.pyc + ¦ ¦ ¦ file.cpython-312.pyc + ¦ ¦ ¦ memory.cpython-312.pyc + ¦ ¦ ¦ stapled.cpython-312.pyc + ¦ ¦ ¦ text.cpython-312.pyc + ¦ ¦ ¦ tls.cpython-312.pyc + ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ + ¦ ¦ +---_backends + ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ _asyncio.cpython-312.pyc + ¦ ¦ ¦ _trio.cpython-312.pyc + ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ + ¦ ¦ +---_core + ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ _asyncio_selector_thread.cpython-312.pyc + ¦ ¦ ¦ _eventloop.cpython-312.pyc + ¦ ¦ ¦ _exceptions.cpython-312.pyc + ¦ ¦ ¦ _fileio.cpython-312.pyc + ¦ ¦ ¦ _resources.cpython-312.pyc + ¦ ¦ ¦ _signals.cpython-312.pyc + ¦ ¦ ¦ _sockets.cpython-312.pyc + ¦ ¦ ¦ _streams.cpython-312.pyc + ¦ ¦ ¦ _subprocesses.cpython-312.pyc + ¦ ¦ ¦ _synchronization.cpython-312.pyc + ¦ ¦ ¦ _tasks.cpython-312.pyc + ¦ ¦ ¦ _tempfile.cpython-312.pyc + ¦ ¦ ¦ _testing.cpython-312.pyc + ¦ ¦ ¦ _typedattr.cpython-312.pyc + ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ + ¦ ¦ +---__pycache__ + ¦ ¦ from_thread.cpython-312.pyc + ¦ ¦ lowlevel.cpython-312.pyc + ¦ ¦ pytest_plugin.cpython-312.pyc + ¦ ¦ to_interpreter.cpython-312.pyc + ¦ ¦ to_process.cpython-312.pyc + ¦ ¦ to_thread.cpython-312.pyc + ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ + ¦ +---api + ¦ ¦ +---__pycache__ + ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ + ¦ +---certifi + ¦ ¦ +---__pycache__ + ¦ ¦ core.cpython-312.pyc + ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ __main__.cpython-312.pyc + ¦ ¦ + ¦ +---charset_normalizer + ¦ ¦ +---cli + ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ __main__.cpython-312.pyc + ¦ ¦ ¦ + ¦ ¦ +---__pycache__ + ¦ ¦ api.cpython-312.pyc + ¦ ¦ cd.cpython-312.pyc + ¦ ¦ constant.cpython-312.pyc + ¦ ¦ legacy.cpython-312.pyc + ¦ ¦ md.cpython-312.pyc + ¦ ¦ models.cpython-312.pyc + ¦ ¦ utils.cpython-312.pyc + ¦ ¦ version.cpython-312.pyc + ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ __main__.cpython-312.pyc + ¦ ¦ + ¦ +---click + ¦ ¦ +---__pycache__ + ¦ ¦ core.cpython-312.pyc + ¦ ¦ decorators.cpython-312.pyc + ¦ ¦ exceptions.cpython-312.pyc + ¦ ¦ formatting.cpython-312.pyc + ¦ ¦ globals.cpython-312.pyc + ¦ ¦ parser.cpython-312.pyc + ¦ ¦ shell_completion.cpython-312.pyc + ¦ ¦ termui.cpython-312.pyc + ¦ ¦ testing.cpython-312.pyc + ¦ ¦ types.cpython-312.pyc + ¦ ¦ utils.cpython-312.pyc + ¦ ¦ _compat.cpython-312.pyc + ¦ ¦ _termui_impl.cpython-312.pyc + ¦ ¦ _textwrap.cpython-312.pyc + ¦ ¦ _winconsole.cpython-312.pyc + ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ + ¦ +---colorama + ¦ ¦ +---tests + ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ansitowin32_test.cpython-312.pyc + ¦ ¦ ¦ ansi_test.cpython-312.pyc + ¦ ¦ ¦ initialise_test.cpython-312.pyc + ¦ ¦ ¦ isatty_test.cpython-312.pyc + ¦ ¦ ¦ utils.cpython-312.pyc + ¦ ¦ ¦ winterm_test.cpython-312.pyc + ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ + ¦ ¦ +---__pycache__ + ¦ ¦ ansi.cpython-312.pyc + ¦ ¦ ansitowin32.cpython-312.pyc + ¦ ¦ initialise.cpython-312.pyc + ¦ ¦ win32.cpython-312.pyc + ¦ ¦ winterm.cpython-312.pyc + ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ + ¦ +---fastapi + ¦ ¦ +---dependencies + ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ models.cpython-312.pyc + ¦ ¦ ¦ utils.cpython-312.pyc + ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ + ¦ ¦ +---middleware + ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ cors.cpython-312.pyc + ¦ ¦ ¦ gzip.cpython-312.pyc + ¦ ¦ ¦ httpsredirect.cpython-312.pyc + ¦ ¦ ¦ trustedhost.cpython-312.pyc + ¦ ¦ ¦ wsgi.cpython-312.pyc + ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ + ¦ ¦ +---openapi + ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ constants.cpython-312.pyc + ¦ ¦ ¦ docs.cpython-312.pyc + ¦ ¦ ¦ models.cpython-312.pyc + ¦ ¦ ¦ utils.cpython-312.pyc + ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ + ¦ ¦ +---security + ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ api_key.cpython-312.pyc + ¦ ¦ ¦ base.cpython-312.pyc + ¦ ¦ ¦ http.cpython-312.pyc + ¦ ¦ ¦ oauth2.cpython-312.pyc + ¦ ¦ ¦ open_id_connect_url.cpython-312.pyc + ¦ ¦ ¦ utils.cpython-312.pyc + ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ + ¦ ¦ +---__pycache__ + ¦ ¦ applications.cpython-312.pyc + ¦ ¦ background.cpython-312.pyc + ¦ ¦ cli.cpython-312.pyc + ¦ ¦ concurrency.cpython-312.pyc + ¦ ¦ datastructures.cpython-312.pyc + ¦ ¦ encoders.cpython-312.pyc + ¦ ¦ exceptions.cpython-312.pyc + ¦ ¦ exception_handlers.cpython-312.pyc + ¦ ¦ logger.cpython-312.pyc + ¦ ¦ params.cpython-312.pyc + ¦ ¦ param_functions.cpython-312.pyc + ¦ ¦ requests.cpython-312.pyc + ¦ ¦ responses.cpython-312.pyc + ¦ ¦ routing.cpython-312.pyc + ¦ ¦ staticfiles.cpython-312.pyc + ¦ ¦ templating.cpython-312.pyc + ¦ ¦ testclient.cpython-312.pyc + ¦ ¦ types.cpython-312.pyc + ¦ ¦ utils.cpython-312.pyc + ¦ ¦ websockets.cpython-312.pyc + ¦ ¦ _compat.cpython-312.pyc + ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ __main__.cpython-312.pyc + ¦ ¦ + ¦ +---h11 + ¦ ¦ +---tests + ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ helpers.cpython-312.pyc + ¦ ¦ ¦ test_against_stdlib_http.cpython-312.pyc + ¦ ¦ ¦ test_connection.cpython-312.pyc + ¦ ¦ ¦ test_events.cpython-312.pyc + ¦ ¦ ¦ test_headers.cpython-312.pyc + ¦ ¦ ¦ test_helpers.cpython-312.pyc + ¦ ¦ ¦ test_io.cpython-312.pyc + ¦ ¦ ¦ test_receivebuffer.cpython-312.pyc + ¦ ¦ ¦ test_state.cpython-312.pyc + ¦ ¦ ¦ test_util.cpython-312.pyc + ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ + ¦ ¦ +---__pycache__ + ¦ ¦ _abnf.cpython-312.pyc + ¦ ¦ _connection.cpython-312.pyc + ¦ ¦ _events.cpython-312.pyc + ¦ ¦ _headers.cpython-312.pyc + ¦ ¦ _readers.cpython-312.pyc + ¦ ¦ _receivebuffer.cpython-312.pyc + ¦ ¦ _state.cpython-312.pyc + ¦ ¦ _util.cpython-312.pyc + ¦ ¦ _version.cpython-312.pyc + ¦ ¦ _writers.cpython-312.pyc + ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ + ¦ +---idna + ¦ ¦ +---__pycache__ + ¦ ¦ codec.cpython-312.pyc + ¦ ¦ compat.cpython-312.pyc + ¦ ¦ core.cpython-312.pyc + ¦ ¦ idnadata.cpython-312.pyc + ¦ ¦ intranges.cpython-312.pyc + ¦ ¦ package_data.cpython-312.pyc + ¦ ¦ uts46data.cpython-312.pyc + ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ + ¦ +---nose + ¦ ¦ +---ext + ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ dtcompat.cpython-312.pyc + ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ + ¦ ¦ +---plugins + ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ allmodules.cpython-312.pyc + ¦ ¦ ¦ attrib.cpython-312.pyc + ¦ ¦ ¦ base.cpython-312.pyc + ¦ ¦ ¦ builtin.cpython-312.pyc + ¦ ¦ ¦ capture.cpython-312.pyc + ¦ ¦ ¦ collect.cpython-312.pyc + ¦ ¦ ¦ cover.cpython-312.pyc + ¦ ¦ ¦ debug.cpython-312.pyc + ¦ ¦ ¦ deprecated.cpython-312.pyc + ¦ ¦ ¦ doctests.cpython-312.pyc + ¦ ¦ ¦ errorclass.cpython-312.pyc + ¦ ¦ ¦ failuredetail.cpython-312.pyc + ¦ ¦ ¦ isolate.cpython-312.pyc + ¦ ¦ ¦ logcapture.cpython-312.pyc + ¦ ¦ ¦ manager.cpython-312.pyc + ¦ ¦ ¦ multiprocess.cpython-312.pyc + ¦ ¦ ¦ plugintest.cpython-312.pyc + ¦ ¦ ¦ prof.cpython-312.pyc + ¦ ¦ ¦ skip.cpython-312.pyc + ¦ ¦ ¦ testid.cpython-312.pyc + ¦ ¦ ¦ xunit.cpython-312.pyc + ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ + ¦ ¦ +---sphinx + ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ pluginopts.cpython-312.pyc + ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ + ¦ ¦ +---tools + ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ nontrivial.cpython-312.pyc + ¦ ¦ ¦ trivial.cpython-312.pyc + ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ + ¦ ¦ +---__pycache__ + ¦ ¦ case.cpython-312.pyc + ¦ ¦ commands.cpython-312.pyc + ¦ ¦ config.cpython-312.pyc + ¦ ¦ core.cpython-312.pyc + ¦ ¦ exc.cpython-312.pyc + ¦ ¦ failure.cpython-312.pyc + ¦ ¦ importer.cpython-312.pyc + ¦ ¦ inspector.cpython-312.pyc + ¦ ¦ loader.cpython-312.pyc + ¦ ¦ proxy.cpython-312.pyc + ¦ ¦ pyversion.cpython-312.pyc + ¦ ¦ result.cpython-312.pyc + ¦ ¦ selector.cpython-312.pyc + ¦ ¦ suite.cpython-312.pyc + ¦ ¦ twistedtools.cpython-312.pyc + ¦ ¦ util.cpython-312.pyc + ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ __main__.cpython-312.pyc + ¦ ¦ + ¦ +---pip + ¦ ¦ ¦ py.typed + ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ __main__.py + ¦ ¦ ¦ __pip-runner__.py + ¦ ¦ ¦ + ¦ ¦ +---_internal + ¦ ¦ ¦ ¦ build_env.py + ¦ ¦ ¦ ¦ cache.py + ¦ ¦ ¦ ¦ configuration.py + ¦ ¦ ¦ ¦ exceptions.py + ¦ ¦ ¦ ¦ main.py + ¦ ¦ ¦ ¦ pyproject.py + ¦ ¦ ¦ ¦ self_outdated_check.py + ¦ ¦ ¦ ¦ wheel_builder.py + ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ + ¦ ¦ ¦ +---cli + ¦ ¦ ¦ ¦ ¦ autocompletion.py + ¦ ¦ ¦ ¦ ¦ base_command.py + ¦ ¦ ¦ ¦ ¦ cmdoptions.py + ¦ ¦ ¦ ¦ ¦ command_context.py + ¦ ¦ ¦ ¦ ¦ main.py + ¦ ¦ ¦ ¦ ¦ main_parser.py + ¦ ¦ ¦ ¦ ¦ parser.py + ¦ ¦ ¦ ¦ ¦ progress_bars.py + ¦ ¦ ¦ ¦ ¦ req_command.py + ¦ ¦ ¦ ¦ ¦ spinners.py + ¦ ¦ ¦ ¦ ¦ status_codes.py + ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ autocompletion.cpython-312.pyc + ¦ ¦ ¦ ¦ base_command.cpython-312.pyc + ¦ ¦ ¦ ¦ cmdoptions.cpython-312.pyc + ¦ ¦ ¦ ¦ command_context.cpython-312.pyc + ¦ ¦ ¦ ¦ main.cpython-312.pyc + ¦ ¦ ¦ ¦ main_parser.cpython-312.pyc + ¦ ¦ ¦ ¦ parser.cpython-312.pyc + ¦ ¦ ¦ ¦ progress_bars.cpython-312.pyc + ¦ ¦ ¦ ¦ req_command.cpython-312.pyc + ¦ ¦ ¦ ¦ spinners.cpython-312.pyc + ¦ ¦ ¦ ¦ status_codes.cpython-312.pyc + ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ + ¦ ¦ ¦ +---commands + ¦ ¦ ¦ ¦ ¦ cache.py + ¦ ¦ ¦ ¦ ¦ check.py + ¦ ¦ ¦ ¦ ¦ completion.py + ¦ ¦ ¦ ¦ ¦ configuration.py + ¦ ¦ ¦ ¦ ¦ debug.py + ¦ ¦ ¦ ¦ ¦ download.py + ¦ ¦ ¦ ¦ ¦ freeze.py + ¦ ¦ ¦ ¦ ¦ hash.py + ¦ ¦ ¦ ¦ ¦ help.py + ¦ ¦ ¦ ¦ ¦ index.py + ¦ ¦ ¦ ¦ ¦ inspect.py + ¦ ¦ ¦ ¦ ¦ install.py + ¦ ¦ ¦ ¦ ¦ list.py + ¦ ¦ ¦ ¦ ¦ search.py + ¦ ¦ ¦ ¦ ¦ show.py + ¦ ¦ ¦ ¦ ¦ uninstall.py + ¦ ¦ ¦ ¦ ¦ wheel.py + ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ cache.cpython-312.pyc + ¦ ¦ ¦ ¦ check.cpython-312.pyc + ¦ ¦ ¦ ¦ completion.cpython-312.pyc + ¦ ¦ ¦ ¦ configuration.cpython-312.pyc + ¦ ¦ ¦ ¦ debug.cpython-312.pyc + ¦ ¦ ¦ ¦ download.cpython-312.pyc + ¦ ¦ ¦ ¦ freeze.cpython-312.pyc + ¦ ¦ ¦ ¦ hash.cpython-312.pyc + ¦ ¦ ¦ ¦ help.cpython-312.pyc + ¦ ¦ ¦ ¦ index.cpython-312.pyc + ¦ ¦ ¦ ¦ inspect.cpython-312.pyc + ¦ ¦ ¦ ¦ install.cpython-312.pyc + ¦ ¦ ¦ ¦ list.cpython-312.pyc + ¦ ¦ ¦ ¦ search.cpython-312.pyc + ¦ ¦ ¦ ¦ show.cpython-312.pyc + ¦ ¦ ¦ ¦ uninstall.cpython-312.pyc + ¦ ¦ ¦ ¦ wheel.cpython-312.pyc + ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ + ¦ ¦ ¦ +---distributions + ¦ ¦ ¦ ¦ ¦ base.py + ¦ ¦ ¦ ¦ ¦ installed.py + ¦ ¦ ¦ ¦ ¦ sdist.py + ¦ ¦ ¦ ¦ ¦ wheel.py + ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ base.cpython-312.pyc + ¦ ¦ ¦ ¦ installed.cpython-312.pyc + ¦ ¦ ¦ ¦ sdist.cpython-312.pyc + ¦ ¦ ¦ ¦ wheel.cpython-312.pyc + ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ + ¦ ¦ ¦ +---index + ¦ ¦ ¦ ¦ ¦ collector.py + ¦ ¦ ¦ ¦ ¦ package_finder.py + ¦ ¦ ¦ ¦ ¦ sources.py + ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ collector.cpython-312.pyc + ¦ ¦ ¦ ¦ package_finder.cpython-312.pyc + ¦ ¦ ¦ ¦ sources.cpython-312.pyc + ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ + ¦ ¦ ¦ +---locations + ¦ ¦ ¦ ¦ ¦ base.py + ¦ ¦ ¦ ¦ ¦ _distutils.py + ¦ ¦ ¦ ¦ ¦ _sysconfig.py + ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ base.cpython-312.pyc + ¦ ¦ ¦ ¦ _distutils.cpython-312.pyc + ¦ ¦ ¦ ¦ _sysconfig.cpython-312.pyc + ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ + ¦ ¦ ¦ +---metadata + ¦ ¦ ¦ ¦ ¦ base.py + ¦ ¦ ¦ ¦ ¦ pkg_resources.py + ¦ ¦ ¦ ¦ ¦ _json.py + ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---importlib + ¦ ¦ ¦ ¦ ¦ ¦ _compat.py + ¦ ¦ ¦ ¦ ¦ ¦ _dists.py + ¦ ¦ ¦ ¦ ¦ ¦ _envs.py + ¦ ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ ¦ _compat.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ _dists.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ _envs.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ base.cpython-312.pyc + ¦ ¦ ¦ ¦ pkg_resources.cpython-312.pyc + ¦ ¦ ¦ ¦ _json.cpython-312.pyc + ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ + ¦ ¦ ¦ +---models + ¦ ¦ ¦ ¦ ¦ candidate.py + ¦ ¦ ¦ ¦ ¦ direct_url.py + ¦ ¦ ¦ ¦ ¦ format_control.py + ¦ ¦ ¦ ¦ ¦ index.py + ¦ ¦ ¦ ¦ ¦ installation_report.py + ¦ ¦ ¦ ¦ ¦ link.py + ¦ ¦ ¦ ¦ ¦ scheme.py + ¦ ¦ ¦ ¦ ¦ search_scope.py + ¦ ¦ ¦ ¦ ¦ selection_prefs.py + ¦ ¦ ¦ ¦ ¦ target_python.py + ¦ ¦ ¦ ¦ ¦ wheel.py + ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ candidate.cpython-312.pyc + ¦ ¦ ¦ ¦ direct_url.cpython-312.pyc + ¦ ¦ ¦ ¦ format_control.cpython-312.pyc + ¦ ¦ ¦ ¦ index.cpython-312.pyc + ¦ ¦ ¦ ¦ installation_report.cpython-312.pyc + ¦ ¦ ¦ ¦ link.cpython-312.pyc + ¦ ¦ ¦ ¦ scheme.cpython-312.pyc + ¦ ¦ ¦ ¦ search_scope.cpython-312.pyc + ¦ ¦ ¦ ¦ selection_prefs.cpython-312.pyc + ¦ ¦ ¦ ¦ target_python.cpython-312.pyc + ¦ ¦ ¦ ¦ wheel.cpython-312.pyc + ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ + ¦ ¦ ¦ +---network + ¦ ¦ ¦ ¦ ¦ auth.py + ¦ ¦ ¦ ¦ ¦ cache.py + ¦ ¦ ¦ ¦ ¦ download.py + ¦ ¦ ¦ ¦ ¦ lazy_wheel.py + ¦ ¦ ¦ ¦ ¦ session.py + ¦ ¦ ¦ ¦ ¦ utils.py + ¦ ¦ ¦ ¦ ¦ xmlrpc.py + ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ auth.cpython-312.pyc + ¦ ¦ ¦ ¦ cache.cpython-312.pyc + ¦ ¦ ¦ ¦ download.cpython-312.pyc + ¦ ¦ ¦ ¦ lazy_wheel.cpython-312.pyc + ¦ ¦ ¦ ¦ session.cpython-312.pyc + ¦ ¦ ¦ ¦ utils.cpython-312.pyc + ¦ ¦ ¦ ¦ xmlrpc.cpython-312.pyc + ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ + ¦ ¦ ¦ +---operations + ¦ ¦ ¦ ¦ ¦ check.py + ¦ ¦ ¦ ¦ ¦ freeze.py + ¦ ¦ ¦ ¦ ¦ prepare.py + ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---build + ¦ ¦ ¦ ¦ ¦ ¦ build_tracker.py + ¦ ¦ ¦ ¦ ¦ ¦ metadata.py + ¦ ¦ ¦ ¦ ¦ ¦ metadata_editable.py + ¦ ¦ ¦ ¦ ¦ ¦ metadata_legacy.py + ¦ ¦ ¦ ¦ ¦ ¦ wheel.py + ¦ ¦ ¦ ¦ ¦ ¦ wheel_editable.py + ¦ ¦ ¦ ¦ ¦ ¦ wheel_legacy.py + ¦ ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ ¦ build_tracker.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ metadata.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ metadata_editable.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ metadata_legacy.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ wheel.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ wheel_editable.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ wheel_legacy.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---install + ¦ ¦ ¦ ¦ ¦ ¦ editable_legacy.py + ¦ ¦ ¦ ¦ ¦ ¦ wheel.py + ¦ ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ ¦ editable_legacy.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ wheel.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ check.cpython-312.pyc + ¦ ¦ ¦ ¦ freeze.cpython-312.pyc + ¦ ¦ ¦ ¦ prepare.cpython-312.pyc + ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ + ¦ ¦ ¦ +---req + ¦ ¦ ¦ ¦ ¦ constructors.py + ¦ ¦ ¦ ¦ ¦ req_file.py + ¦ ¦ ¦ ¦ ¦ req_install.py + ¦ ¦ ¦ ¦ ¦ req_set.py + ¦ ¦ ¦ ¦ ¦ req_uninstall.py + ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ constructors.cpython-312.pyc + ¦ ¦ ¦ ¦ req_file.cpython-312.pyc + ¦ ¦ ¦ ¦ req_install.cpython-312.pyc + ¦ ¦ ¦ ¦ req_set.cpython-312.pyc + ¦ ¦ ¦ ¦ req_uninstall.cpython-312.pyc + ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ + ¦ ¦ ¦ +---resolution + ¦ ¦ ¦ ¦ ¦ base.py + ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---legacy + ¦ ¦ ¦ ¦ ¦ ¦ resolver.py + ¦ ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ ¦ resolver.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---resolvelib + ¦ ¦ ¦ ¦ ¦ ¦ base.py + ¦ ¦ ¦ ¦ ¦ ¦ candidates.py + ¦ ¦ ¦ ¦ ¦ ¦ factory.py + ¦ ¦ ¦ ¦ ¦ ¦ found_candidates.py + ¦ ¦ ¦ ¦ ¦ ¦ provider.py + ¦ ¦ ¦ ¦ ¦ ¦ reporter.py + ¦ ¦ ¦ ¦ ¦ ¦ requirements.py + ¦ ¦ ¦ ¦ ¦ ¦ resolver.py + ¦ ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ ¦ base.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ candidates.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ factory.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ found_candidates.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ provider.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ reporter.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ requirements.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ resolver.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ base.cpython-312.pyc + ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ + ¦ ¦ ¦ +---utils + ¦ ¦ ¦ ¦ ¦ appdirs.py + ¦ ¦ ¦ ¦ ¦ compat.py + ¦ ¦ ¦ ¦ ¦ compatibility_tags.py + ¦ ¦ ¦ ¦ ¦ datetime.py + ¦ ¦ ¦ ¦ ¦ deprecation.py + ¦ ¦ ¦ ¦ ¦ direct_url_helpers.py + ¦ ¦ ¦ ¦ ¦ egg_link.py + ¦ ¦ ¦ ¦ ¦ encoding.py + ¦ ¦ ¦ ¦ ¦ entrypoints.py + ¦ ¦ ¦ ¦ ¦ filesystem.py + ¦ ¦ ¦ ¦ ¦ filetypes.py + ¦ ¦ ¦ ¦ ¦ glibc.py + ¦ ¦ ¦ ¦ ¦ hashes.py + ¦ ¦ ¦ ¦ ¦ logging.py + ¦ ¦ ¦ ¦ ¦ misc.py + ¦ ¦ ¦ ¦ ¦ models.py + ¦ ¦ ¦ ¦ ¦ packaging.py + ¦ ¦ ¦ ¦ ¦ setuptools_build.py + ¦ ¦ ¦ ¦ ¦ subprocess.py + ¦ ¦ ¦ ¦ ¦ temp_dir.py + ¦ ¦ ¦ ¦ ¦ unpacking.py + ¦ ¦ ¦ ¦ ¦ urls.py + ¦ ¦ ¦ ¦ ¦ virtualenv.py + ¦ ¦ ¦ ¦ ¦ wheel.py + ¦ ¦ ¦ ¦ ¦ _jaraco_text.py + ¦ ¦ ¦ ¦ ¦ _log.py + ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ appdirs.cpython-312.pyc + ¦ ¦ ¦ ¦ compat.cpython-312.pyc + ¦ ¦ ¦ ¦ compatibility_tags.cpython-312.pyc + ¦ ¦ ¦ ¦ datetime.cpython-312.pyc + ¦ ¦ ¦ ¦ deprecation.cpython-312.pyc + ¦ ¦ ¦ ¦ direct_url_helpers.cpython-312.pyc + ¦ ¦ ¦ ¦ egg_link.cpython-312.pyc + ¦ ¦ ¦ ¦ encoding.cpython-312.pyc + ¦ ¦ ¦ ¦ entrypoints.cpython-312.pyc + ¦ ¦ ¦ ¦ filesystem.cpython-312.pyc + ¦ ¦ ¦ ¦ filetypes.cpython-312.pyc + ¦ ¦ ¦ ¦ glibc.cpython-312.pyc + ¦ ¦ ¦ ¦ hashes.cpython-312.pyc + ¦ ¦ ¦ ¦ logging.cpython-312.pyc + ¦ ¦ ¦ ¦ misc.cpython-312.pyc + ¦ ¦ ¦ ¦ models.cpython-312.pyc + ¦ ¦ ¦ ¦ packaging.cpython-312.pyc + ¦ ¦ ¦ ¦ setuptools_build.cpython-312.pyc + ¦ ¦ ¦ ¦ subprocess.cpython-312.pyc + ¦ ¦ ¦ ¦ temp_dir.cpython-312.pyc + ¦ ¦ ¦ ¦ unpacking.cpython-312.pyc + ¦ ¦ ¦ ¦ urls.cpython-312.pyc + ¦ ¦ ¦ ¦ virtualenv.cpython-312.pyc + ¦ ¦ ¦ ¦ wheel.cpython-312.pyc + ¦ ¦ ¦ ¦ _jaraco_text.cpython-312.pyc + ¦ ¦ ¦ ¦ _log.cpython-312.pyc + ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ + ¦ ¦ ¦ +---vcs + ¦ ¦ ¦ ¦ ¦ bazaar.py + ¦ ¦ ¦ ¦ ¦ git.py + ¦ ¦ ¦ ¦ ¦ mercurial.py + ¦ ¦ ¦ ¦ ¦ subversion.py + ¦ ¦ ¦ ¦ ¦ versioncontrol.py + ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ bazaar.cpython-312.pyc + ¦ ¦ ¦ ¦ git.cpython-312.pyc + ¦ ¦ ¦ ¦ mercurial.cpython-312.pyc + ¦ ¦ ¦ ¦ subversion.cpython-312.pyc + ¦ ¦ ¦ ¦ versioncontrol.cpython-312.pyc + ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ + ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ build_env.cpython-312.pyc + ¦ ¦ ¦ cache.cpython-312.pyc + ¦ ¦ ¦ configuration.cpython-312.pyc + ¦ ¦ ¦ exceptions.cpython-312.pyc + ¦ ¦ ¦ main.cpython-312.pyc + ¦ ¦ ¦ pyproject.cpython-312.pyc + ¦ ¦ ¦ self_outdated_check.cpython-312.pyc + ¦ ¦ ¦ wheel_builder.cpython-312.pyc + ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ + ¦ ¦ +---_vendor + ¦ ¦ ¦ ¦ six.py + ¦ ¦ ¦ ¦ typing_extensions.py + ¦ ¦ ¦ ¦ vendor.txt + ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ + ¦ ¦ ¦ +---cachecontrol + ¦ ¦ ¦ ¦ ¦ adapter.py + ¦ ¦ ¦ ¦ ¦ cache.py + ¦ ¦ ¦ ¦ ¦ controller.py + ¦ ¦ ¦ ¦ ¦ filewrapper.py + ¦ ¦ ¦ ¦ ¦ heuristics.py + ¦ ¦ ¦ ¦ ¦ py.typed + ¦ ¦ ¦ ¦ ¦ serialize.py + ¦ ¦ ¦ ¦ ¦ wrapper.py + ¦ ¦ ¦ ¦ ¦ _cmd.py + ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---caches + ¦ ¦ ¦ ¦ ¦ ¦ file_cache.py + ¦ ¦ ¦ ¦ ¦ ¦ redis_cache.py + ¦ ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ ¦ file_cache.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ redis_cache.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ adapter.cpython-312.pyc + ¦ ¦ ¦ ¦ cache.cpython-312.pyc + ¦ ¦ ¦ ¦ controller.cpython-312.pyc + ¦ ¦ ¦ ¦ filewrapper.cpython-312.pyc + ¦ ¦ ¦ ¦ heuristics.cpython-312.pyc + ¦ ¦ ¦ ¦ serialize.cpython-312.pyc + ¦ ¦ ¦ ¦ wrapper.cpython-312.pyc + ¦ ¦ ¦ ¦ _cmd.cpython-312.pyc + ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ + ¦ ¦ ¦ +---certifi + ¦ ¦ ¦ ¦ ¦ cacert.pem + ¦ ¦ ¦ ¦ ¦ core.py + ¦ ¦ ¦ ¦ ¦ py.typed + ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ __main__.py + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ core.cpython-312.pyc + ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ __main__.cpython-312.pyc + ¦ ¦ ¦ ¦ + ¦ ¦ ¦ +---chardet + ¦ ¦ ¦ ¦ ¦ big5freq.py + ¦ ¦ ¦ ¦ ¦ big5prober.py + ¦ ¦ ¦ ¦ ¦ chardistribution.py + ¦ ¦ ¦ ¦ ¦ charsetgroupprober.py + ¦ ¦ ¦ ¦ ¦ charsetprober.py + ¦ ¦ ¦ ¦ ¦ codingstatemachine.py + ¦ ¦ ¦ ¦ ¦ codingstatemachinedict.py + ¦ ¦ ¦ ¦ ¦ cp949prober.py + ¦ ¦ ¦ ¦ ¦ enums.py + ¦ ¦ ¦ ¦ ¦ escprober.py + ¦ ¦ ¦ ¦ ¦ escsm.py + ¦ ¦ ¦ ¦ ¦ eucjpprober.py + ¦ ¦ ¦ ¦ ¦ euckrfreq.py + ¦ ¦ ¦ ¦ ¦ euckrprober.py + ¦ ¦ ¦ ¦ ¦ euctwfreq.py + ¦ ¦ ¦ ¦ ¦ euctwprober.py + ¦ ¦ ¦ ¦ ¦ gb2312freq.py + ¦ ¦ ¦ ¦ ¦ gb2312prober.py + ¦ ¦ ¦ ¦ ¦ hebrewprober.py + ¦ ¦ ¦ ¦ ¦ jisfreq.py + ¦ ¦ ¦ ¦ ¦ johabfreq.py + ¦ ¦ ¦ ¦ ¦ johabprober.py + ¦ ¦ ¦ ¦ ¦ jpcntx.py + ¦ ¦ ¦ ¦ ¦ langbulgarianmodel.py + ¦ ¦ ¦ ¦ ¦ langgreekmodel.py + ¦ ¦ ¦ ¦ ¦ langhebrewmodel.py + ¦ ¦ ¦ ¦ ¦ langhungarianmodel.py + ¦ ¦ ¦ ¦ ¦ langrussianmodel.py + ¦ ¦ ¦ ¦ ¦ langthaimodel.py + ¦ ¦ ¦ ¦ ¦ langturkishmodel.py + ¦ ¦ ¦ ¦ ¦ latin1prober.py + ¦ ¦ ¦ ¦ ¦ macromanprober.py + ¦ ¦ ¦ ¦ ¦ mbcharsetprober.py + ¦ ¦ ¦ ¦ ¦ mbcsgroupprober.py + ¦ ¦ ¦ ¦ ¦ mbcssm.py + ¦ ¦ ¦ ¦ ¦ py.typed + ¦ ¦ ¦ ¦ ¦ resultdict.py + ¦ ¦ ¦ ¦ ¦ sbcharsetprober.py + ¦ ¦ ¦ ¦ ¦ sbcsgroupprober.py + ¦ ¦ ¦ ¦ ¦ sjisprober.py + ¦ ¦ ¦ ¦ ¦ universaldetector.py + ¦ ¦ ¦ ¦ ¦ utf1632prober.py + ¦ ¦ ¦ ¦ ¦ utf8prober.py + ¦ ¦ ¦ ¦ ¦ version.py + ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---cli + ¦ ¦ ¦ ¦ ¦ ¦ chardetect.py + ¦ ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ ¦ chardetect.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---metadata + ¦ ¦ ¦ ¦ ¦ ¦ languages.py + ¦ ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ ¦ languages.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ big5freq.cpython-312.pyc + ¦ ¦ ¦ ¦ big5prober.cpython-312.pyc + ¦ ¦ ¦ ¦ chardistribution.cpython-312.pyc + ¦ ¦ ¦ ¦ charsetgroupprober.cpython-312.pyc + ¦ ¦ ¦ ¦ charsetprober.cpython-312.pyc + ¦ ¦ ¦ ¦ codingstatemachine.cpython-312.pyc + ¦ ¦ ¦ ¦ codingstatemachinedict.cpython-312.pyc + ¦ ¦ ¦ ¦ cp949prober.cpython-312.pyc + ¦ ¦ ¦ ¦ enums.cpython-312.pyc + ¦ ¦ ¦ ¦ escprober.cpython-312.pyc + ¦ ¦ ¦ ¦ escsm.cpython-312.pyc + ¦ ¦ ¦ ¦ eucjpprober.cpython-312.pyc + ¦ ¦ ¦ ¦ euckrfreq.cpython-312.pyc + ¦ ¦ ¦ ¦ euckrprober.cpython-312.pyc + ¦ ¦ ¦ ¦ euctwfreq.cpython-312.pyc + ¦ ¦ ¦ ¦ euctwprober.cpython-312.pyc + ¦ ¦ ¦ ¦ gb2312freq.cpython-312.pyc + ¦ ¦ ¦ ¦ gb2312prober.cpython-312.pyc + ¦ ¦ ¦ ¦ hebrewprober.cpython-312.pyc + ¦ ¦ ¦ ¦ jisfreq.cpython-312.pyc + ¦ ¦ ¦ ¦ johabfreq.cpython-312.pyc + ¦ ¦ ¦ ¦ johabprober.cpython-312.pyc + ¦ ¦ ¦ ¦ jpcntx.cpython-312.pyc + ¦ ¦ ¦ ¦ langbulgarianmodel.cpython-312.pyc + ¦ ¦ ¦ ¦ langgreekmodel.cpython-312.pyc + ¦ ¦ ¦ ¦ langhebrewmodel.cpython-312.pyc + ¦ ¦ ¦ ¦ langhungarianmodel.cpython-312.pyc + ¦ ¦ ¦ ¦ langrussianmodel.cpython-312.pyc + ¦ ¦ ¦ ¦ langthaimodel.cpython-312.pyc + ¦ ¦ ¦ ¦ langturkishmodel.cpython-312.pyc + ¦ ¦ ¦ ¦ latin1prober.cpython-312.pyc + ¦ ¦ ¦ ¦ macromanprober.cpython-312.pyc + ¦ ¦ ¦ ¦ mbcharsetprober.cpython-312.pyc + ¦ ¦ ¦ ¦ mbcsgroupprober.cpython-312.pyc + ¦ ¦ ¦ ¦ mbcssm.cpython-312.pyc + ¦ ¦ ¦ ¦ resultdict.cpython-312.pyc + ¦ ¦ ¦ ¦ sbcharsetprober.cpython-312.pyc + ¦ ¦ ¦ ¦ sbcsgroupprober.cpython-312.pyc + ¦ ¦ ¦ ¦ sjisprober.cpython-312.pyc + ¦ ¦ ¦ ¦ universaldetector.cpython-312.pyc + ¦ ¦ ¦ ¦ utf1632prober.cpython-312.pyc + ¦ ¦ ¦ ¦ utf8prober.cpython-312.pyc + ¦ ¦ ¦ ¦ version.cpython-312.pyc + ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ + ¦ ¦ ¦ +---colorama + ¦ ¦ ¦ ¦ ¦ ansi.py + ¦ ¦ ¦ ¦ ¦ ansitowin32.py + ¦ ¦ ¦ ¦ ¦ initialise.py + ¦ ¦ ¦ ¦ ¦ win32.py + ¦ ¦ ¦ ¦ ¦ winterm.py + ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---tests + ¦ ¦ ¦ ¦ ¦ ¦ ansitowin32_test.py + ¦ ¦ ¦ ¦ ¦ ¦ ansi_test.py + ¦ ¦ ¦ ¦ ¦ ¦ initialise_test.py + ¦ ¦ ¦ ¦ ¦ ¦ isatty_test.py + ¦ ¦ ¦ ¦ ¦ ¦ utils.py + ¦ ¦ ¦ ¦ ¦ ¦ winterm_test.py + ¦ ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ ¦ ansitowin32_test.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ ansi_test.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ initialise_test.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ isatty_test.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ utils.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ winterm_test.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ ansi.cpython-312.pyc + ¦ ¦ ¦ ¦ ansitowin32.cpython-312.pyc + ¦ ¦ ¦ ¦ initialise.cpython-312.pyc + ¦ ¦ ¦ ¦ win32.cpython-312.pyc + ¦ ¦ ¦ ¦ winterm.cpython-312.pyc + ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ + ¦ ¦ ¦ +---distlib + ¦ ¦ ¦ ¦ ¦ compat.py + ¦ ¦ ¦ ¦ ¦ database.py + ¦ ¦ ¦ ¦ ¦ index.py + ¦ ¦ ¦ ¦ ¦ locators.py + ¦ ¦ ¦ ¦ ¦ manifest.py + ¦ ¦ ¦ ¦ ¦ markers.py + ¦ ¦ ¦ ¦ ¦ metadata.py + ¦ ¦ ¦ ¦ ¦ resources.py + ¦ ¦ ¦ ¦ ¦ scripts.py + ¦ ¦ ¦ ¦ ¦ t32.exe + ¦ ¦ ¦ ¦ ¦ t64-arm.exe + ¦ ¦ ¦ ¦ ¦ t64.exe + ¦ ¦ ¦ ¦ ¦ util.py + ¦ ¦ ¦ ¦ ¦ version.py + ¦ ¦ ¦ ¦ ¦ w32.exe + ¦ ¦ ¦ ¦ ¦ w64-arm.exe + ¦ ¦ ¦ ¦ ¦ w64.exe + ¦ ¦ ¦ ¦ ¦ wheel.py + ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ compat.cpython-312.pyc + ¦ ¦ ¦ ¦ database.cpython-312.pyc + ¦ ¦ ¦ ¦ index.cpython-312.pyc + ¦ ¦ ¦ ¦ locators.cpython-312.pyc + ¦ ¦ ¦ ¦ manifest.cpython-312.pyc + ¦ ¦ ¦ ¦ markers.cpython-312.pyc + ¦ ¦ ¦ ¦ metadata.cpython-312.pyc + ¦ ¦ ¦ ¦ resources.cpython-312.pyc + ¦ ¦ ¦ ¦ scripts.cpython-312.pyc + ¦ ¦ ¦ ¦ util.cpython-312.pyc + ¦ ¦ ¦ ¦ version.cpython-312.pyc + ¦ ¦ ¦ ¦ wheel.cpython-312.pyc + ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ + ¦ ¦ ¦ +---distro + ¦ ¦ ¦ ¦ ¦ distro.py + ¦ ¦ ¦ ¦ ¦ py.typed + ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ __main__.py + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ distro.cpython-312.pyc + ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ __main__.cpython-312.pyc + ¦ ¦ ¦ ¦ + ¦ ¦ ¦ +---idna + ¦ ¦ ¦ ¦ ¦ codec.py + ¦ ¦ ¦ ¦ ¦ compat.py + ¦ ¦ ¦ ¦ ¦ core.py + ¦ ¦ ¦ ¦ ¦ idnadata.py + ¦ ¦ ¦ ¦ ¦ intranges.py + ¦ ¦ ¦ ¦ ¦ package_data.py + ¦ ¦ ¦ ¦ ¦ py.typed + ¦ ¦ ¦ ¦ ¦ uts46data.py + ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ codec.cpython-312.pyc + ¦ ¦ ¦ ¦ compat.cpython-312.pyc + ¦ ¦ ¦ ¦ core.cpython-312.pyc + ¦ ¦ ¦ ¦ idnadata.cpython-312.pyc + ¦ ¦ ¦ ¦ intranges.cpython-312.pyc + ¦ ¦ ¦ ¦ package_data.cpython-312.pyc + ¦ ¦ ¦ ¦ uts46data.cpython-312.pyc + ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ + ¦ ¦ ¦ +---msgpack + ¦ ¦ ¦ ¦ ¦ exceptions.py + ¦ ¦ ¦ ¦ ¦ ext.py + ¦ ¦ ¦ ¦ ¦ fallback.py + ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ exceptions.cpython-312.pyc + ¦ ¦ ¦ ¦ ext.cpython-312.pyc + ¦ ¦ ¦ ¦ fallback.cpython-312.pyc + ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ + ¦ ¦ ¦ +---packaging + ¦ ¦ ¦ ¦ ¦ markers.py + ¦ ¦ ¦ ¦ ¦ py.typed + ¦ ¦ ¦ ¦ ¦ requirements.py + ¦ ¦ ¦ ¦ ¦ specifiers.py + ¦ ¦ ¦ ¦ ¦ tags.py + ¦ ¦ ¦ ¦ ¦ utils.py + ¦ ¦ ¦ ¦ ¦ version.py + ¦ ¦ ¦ ¦ ¦ _manylinux.py + ¦ ¦ ¦ ¦ ¦ _musllinux.py + ¦ ¦ ¦ ¦ ¦ _structures.py + ¦ ¦ ¦ ¦ ¦ __about__.py + ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ markers.cpython-312.pyc + ¦ ¦ ¦ ¦ requirements.cpython-312.pyc + ¦ ¦ ¦ ¦ specifiers.cpython-312.pyc + ¦ ¦ ¦ ¦ tags.cpython-312.pyc + ¦ ¦ ¦ ¦ utils.cpython-312.pyc + ¦ ¦ ¦ ¦ version.cpython-312.pyc + ¦ ¦ ¦ ¦ _manylinux.cpython-312.pyc + ¦ ¦ ¦ ¦ _musllinux.cpython-312.pyc + ¦ ¦ ¦ ¦ _structures.cpython-312.pyc + ¦ ¦ ¦ ¦ __about__.cpython-312.pyc + ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ + ¦ ¦ ¦ +---pkg_resources + ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ + ¦ ¦ ¦ +---platformdirs + ¦ ¦ ¦ ¦ ¦ android.py + ¦ ¦ ¦ ¦ ¦ api.py + ¦ ¦ ¦ ¦ ¦ macos.py + ¦ ¦ ¦ ¦ ¦ py.typed + ¦ ¦ ¦ ¦ ¦ unix.py + ¦ ¦ ¦ ¦ ¦ version.py + ¦ ¦ ¦ ¦ ¦ windows.py + ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ __main__.py + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ android.cpython-312.pyc + ¦ ¦ ¦ ¦ api.cpython-312.pyc + ¦ ¦ ¦ ¦ macos.cpython-312.pyc + ¦ ¦ ¦ ¦ unix.cpython-312.pyc + ¦ ¦ ¦ ¦ version.cpython-312.pyc + ¦ ¦ ¦ ¦ windows.cpython-312.pyc + ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ __main__.cpython-312.pyc + ¦ ¦ ¦ ¦ + ¦ ¦ ¦ +---pygments + ¦ ¦ ¦ ¦ ¦ cmdline.py + ¦ ¦ ¦ ¦ ¦ console.py + ¦ ¦ ¦ ¦ ¦ filter.py + ¦ ¦ ¦ ¦ ¦ formatter.py + ¦ ¦ ¦ ¦ ¦ lexer.py + ¦ ¦ ¦ ¦ ¦ modeline.py + ¦ ¦ ¦ ¦ ¦ plugin.py + ¦ ¦ ¦ ¦ ¦ regexopt.py + ¦ ¦ ¦ ¦ ¦ scanner.py + ¦ ¦ ¦ ¦ ¦ sphinxext.py + ¦ ¦ ¦ ¦ ¦ style.py + ¦ ¦ ¦ ¦ ¦ token.py + ¦ ¦ ¦ ¦ ¦ unistring.py + ¦ ¦ ¦ ¦ ¦ util.py + ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ __main__.py + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---filters + ¦ ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---formatters + ¦ ¦ ¦ ¦ ¦ ¦ bbcode.py + ¦ ¦ ¦ ¦ ¦ ¦ groff.py + ¦ ¦ ¦ ¦ ¦ ¦ html.py + ¦ ¦ ¦ ¦ ¦ ¦ img.py + ¦ ¦ ¦ ¦ ¦ ¦ irc.py + ¦ ¦ ¦ ¦ ¦ ¦ latex.py + ¦ ¦ ¦ ¦ ¦ ¦ other.py + ¦ ¦ ¦ ¦ ¦ ¦ pangomarkup.py + ¦ ¦ ¦ ¦ ¦ ¦ rtf.py + ¦ ¦ ¦ ¦ ¦ ¦ svg.py + ¦ ¦ ¦ ¦ ¦ ¦ terminal.py + ¦ ¦ ¦ ¦ ¦ ¦ terminal256.py + ¦ ¦ ¦ ¦ ¦ ¦ _mapping.py + ¦ ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ ¦ bbcode.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ groff.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ html.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ img.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ irc.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ latex.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ other.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ pangomarkup.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ rtf.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ svg.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ terminal.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ terminal256.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ _mapping.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---lexers + ¦ ¦ ¦ ¦ ¦ ¦ python.py + ¦ ¦ ¦ ¦ ¦ ¦ _mapping.py + ¦ ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ ¦ python.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ _mapping.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---styles + ¦ ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ cmdline.cpython-312.pyc + ¦ ¦ ¦ ¦ console.cpython-312.pyc + ¦ ¦ ¦ ¦ filter.cpython-312.pyc + ¦ ¦ ¦ ¦ formatter.cpython-312.pyc + ¦ ¦ ¦ ¦ lexer.cpython-312.pyc + ¦ ¦ ¦ ¦ modeline.cpython-312.pyc + ¦ ¦ ¦ ¦ plugin.cpython-312.pyc + ¦ ¦ ¦ ¦ regexopt.cpython-312.pyc + ¦ ¦ ¦ ¦ scanner.cpython-312.pyc + ¦ ¦ ¦ ¦ sphinxext.cpython-312.pyc + ¦ ¦ ¦ ¦ style.cpython-312.pyc + ¦ ¦ ¦ ¦ token.cpython-312.pyc + ¦ ¦ ¦ ¦ unistring.cpython-312.pyc + ¦ ¦ ¦ ¦ util.cpython-312.pyc + ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ __main__.cpython-312.pyc + ¦ ¦ ¦ ¦ + ¦ ¦ ¦ +---pyparsing + ¦ ¦ ¦ ¦ ¦ actions.py + ¦ ¦ ¦ ¦ ¦ common.py + ¦ ¦ ¦ ¦ ¦ core.py + ¦ ¦ ¦ ¦ ¦ exceptions.py + ¦ ¦ ¦ ¦ ¦ helpers.py + ¦ ¦ ¦ ¦ ¦ py.typed + ¦ ¦ ¦ ¦ ¦ results.py + ¦ ¦ ¦ ¦ ¦ testing.py + ¦ ¦ ¦ ¦ ¦ unicode.py + ¦ ¦ ¦ ¦ ¦ util.py + ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---diagram + ¦ ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ actions.cpython-312.pyc + ¦ ¦ ¦ ¦ common.cpython-312.pyc + ¦ ¦ ¦ ¦ core.cpython-312.pyc + ¦ ¦ ¦ ¦ exceptions.cpython-312.pyc + ¦ ¦ ¦ ¦ helpers.cpython-312.pyc + ¦ ¦ ¦ ¦ results.cpython-312.pyc + ¦ ¦ ¦ ¦ testing.cpython-312.pyc + ¦ ¦ ¦ ¦ unicode.cpython-312.pyc + ¦ ¦ ¦ ¦ util.cpython-312.pyc + ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ + ¦ ¦ ¦ +---pyproject_hooks + ¦ ¦ ¦ ¦ ¦ _compat.py + ¦ ¦ ¦ ¦ ¦ _impl.py + ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---_in_process + ¦ ¦ ¦ ¦ ¦ ¦ _in_process.py + ¦ ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ ¦ _in_process.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ _compat.cpython-312.pyc + ¦ ¦ ¦ ¦ _impl.cpython-312.pyc + ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ + ¦ ¦ ¦ +---requests + ¦ ¦ ¦ ¦ ¦ adapters.py + ¦ ¦ ¦ ¦ ¦ api.py + ¦ ¦ ¦ ¦ ¦ auth.py + ¦ ¦ ¦ ¦ ¦ certs.py + ¦ ¦ ¦ ¦ ¦ compat.py + ¦ ¦ ¦ ¦ ¦ cookies.py + ¦ ¦ ¦ ¦ ¦ exceptions.py + ¦ ¦ ¦ ¦ ¦ help.py + ¦ ¦ ¦ ¦ ¦ hooks.py + ¦ ¦ ¦ ¦ ¦ models.py + ¦ ¦ ¦ ¦ ¦ packages.py + ¦ ¦ ¦ ¦ ¦ sessions.py + ¦ ¦ ¦ ¦ ¦ status_codes.py + ¦ ¦ ¦ ¦ ¦ structures.py + ¦ ¦ ¦ ¦ ¦ utils.py + ¦ ¦ ¦ ¦ ¦ _internal_utils.py + ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ __version__.py + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ adapters.cpython-312.pyc + ¦ ¦ ¦ ¦ api.cpython-312.pyc + ¦ ¦ ¦ ¦ auth.cpython-312.pyc + ¦ ¦ ¦ ¦ certs.cpython-312.pyc + ¦ ¦ ¦ ¦ compat.cpython-312.pyc + ¦ ¦ ¦ ¦ cookies.cpython-312.pyc + ¦ ¦ ¦ ¦ exceptions.cpython-312.pyc + ¦ ¦ ¦ ¦ help.cpython-312.pyc + ¦ ¦ ¦ ¦ hooks.cpython-312.pyc + ¦ ¦ ¦ ¦ models.cpython-312.pyc + ¦ ¦ ¦ ¦ packages.cpython-312.pyc + ¦ ¦ ¦ ¦ sessions.cpython-312.pyc + ¦ ¦ ¦ ¦ status_codes.cpython-312.pyc + ¦ ¦ ¦ ¦ structures.cpython-312.pyc + ¦ ¦ ¦ ¦ utils.cpython-312.pyc + ¦ ¦ ¦ ¦ _internal_utils.cpython-312.pyc + ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ __version__.cpython-312.pyc + ¦ ¦ ¦ ¦ + ¦ ¦ ¦ +---resolvelib + ¦ ¦ ¦ ¦ ¦ providers.py + ¦ ¦ ¦ ¦ ¦ py.typed + ¦ ¦ ¦ ¦ ¦ reporters.py + ¦ ¦ ¦ ¦ ¦ resolvers.py + ¦ ¦ ¦ ¦ ¦ structs.py + ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---compat + ¦ ¦ ¦ ¦ ¦ ¦ collections_abc.py + ¦ ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ ¦ collections_abc.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ providers.cpython-312.pyc + ¦ ¦ ¦ ¦ reporters.cpython-312.pyc + ¦ ¦ ¦ ¦ resolvers.cpython-312.pyc + ¦ ¦ ¦ ¦ structs.cpython-312.pyc + ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ + ¦ ¦ ¦ +---rich + ¦ ¦ ¦ ¦ ¦ abc.py + ¦ ¦ ¦ ¦ ¦ align.py + ¦ ¦ ¦ ¦ ¦ ansi.py + ¦ ¦ ¦ ¦ ¦ bar.py + ¦ ¦ ¦ ¦ ¦ box.py + ¦ ¦ ¦ ¦ ¦ cells.py + ¦ ¦ ¦ ¦ ¦ color.py + ¦ ¦ ¦ ¦ ¦ color_triplet.py + ¦ ¦ ¦ ¦ ¦ columns.py + ¦ ¦ ¦ ¦ ¦ console.py + ¦ ¦ ¦ ¦ ¦ constrain.py + ¦ ¦ ¦ ¦ ¦ containers.py + ¦ ¦ ¦ ¦ ¦ control.py + ¦ ¦ ¦ ¦ ¦ default_styles.py + ¦ ¦ ¦ ¦ ¦ diagnose.py + ¦ ¦ ¦ ¦ ¦ emoji.py + ¦ ¦ ¦ ¦ ¦ errors.py + ¦ ¦ ¦ ¦ ¦ filesize.py + ¦ ¦ ¦ ¦ ¦ file_proxy.py + ¦ ¦ ¦ ¦ ¦ highlighter.py + ¦ ¦ ¦ ¦ ¦ json.py + ¦ ¦ ¦ ¦ ¦ jupyter.py + ¦ ¦ ¦ ¦ ¦ layout.py + ¦ ¦ ¦ ¦ ¦ live.py + ¦ ¦ ¦ ¦ ¦ live_render.py + ¦ ¦ ¦ ¦ ¦ logging.py + ¦ ¦ ¦ ¦ ¦ markup.py + ¦ ¦ ¦ ¦ ¦ measure.py + ¦ ¦ ¦ ¦ ¦ padding.py + ¦ ¦ ¦ ¦ ¦ pager.py + ¦ ¦ ¦ ¦ ¦ palette.py + ¦ ¦ ¦ ¦ ¦ panel.py + ¦ ¦ ¦ ¦ ¦ pretty.py + ¦ ¦ ¦ ¦ ¦ progress.py + ¦ ¦ ¦ ¦ ¦ progress_bar.py + ¦ ¦ ¦ ¦ ¦ prompt.py + ¦ ¦ ¦ ¦ ¦ protocol.py + ¦ ¦ ¦ ¦ ¦ py.typed + ¦ ¦ ¦ ¦ ¦ region.py + ¦ ¦ ¦ ¦ ¦ repr.py + ¦ ¦ ¦ ¦ ¦ rule.py + ¦ ¦ ¦ ¦ ¦ scope.py + ¦ ¦ ¦ ¦ ¦ screen.py + ¦ ¦ ¦ ¦ ¦ segment.py + ¦ ¦ ¦ ¦ ¦ spinner.py + ¦ ¦ ¦ ¦ ¦ status.py + ¦ ¦ ¦ ¦ ¦ style.py + ¦ ¦ ¦ ¦ ¦ styled.py + ¦ ¦ ¦ ¦ ¦ syntax.py + ¦ ¦ ¦ ¦ ¦ table.py + ¦ ¦ ¦ ¦ ¦ terminal_theme.py + ¦ ¦ ¦ ¦ ¦ text.py + ¦ ¦ ¦ ¦ ¦ theme.py + ¦ ¦ ¦ ¦ ¦ themes.py + ¦ ¦ ¦ ¦ ¦ traceback.py + ¦ ¦ ¦ ¦ ¦ tree.py + ¦ ¦ ¦ ¦ ¦ _cell_widths.py + ¦ ¦ ¦ ¦ ¦ _emoji_codes.py + ¦ ¦ ¦ ¦ ¦ _emoji_replace.py + ¦ ¦ ¦ ¦ ¦ _export_format.py + ¦ ¦ ¦ ¦ ¦ _extension.py + ¦ ¦ ¦ ¦ ¦ _fileno.py + ¦ ¦ ¦ ¦ ¦ _inspect.py + ¦ ¦ ¦ ¦ ¦ _log_render.py + ¦ ¦ ¦ ¦ ¦ _loop.py + ¦ ¦ ¦ ¦ ¦ _null_file.py + ¦ ¦ ¦ ¦ ¦ _palettes.py + ¦ ¦ ¦ ¦ ¦ _pick.py + ¦ ¦ ¦ ¦ ¦ _ratio.py + ¦ ¦ ¦ ¦ ¦ _spinners.py + ¦ ¦ ¦ ¦ ¦ _stack.py + ¦ ¦ ¦ ¦ ¦ _timer.py + ¦ ¦ ¦ ¦ ¦ _win32_console.py + ¦ ¦ ¦ ¦ ¦ _windows.py + ¦ ¦ ¦ ¦ ¦ _windows_renderer.py + ¦ ¦ ¦ ¦ ¦ _wrap.py + ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ __main__.py + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ abc.cpython-312.pyc + ¦ ¦ ¦ ¦ align.cpython-312.pyc + ¦ ¦ ¦ ¦ ansi.cpython-312.pyc + ¦ ¦ ¦ ¦ bar.cpython-312.pyc + ¦ ¦ ¦ ¦ box.cpython-312.pyc + ¦ ¦ ¦ ¦ cells.cpython-312.pyc + ¦ ¦ ¦ ¦ color.cpython-312.pyc + ¦ ¦ ¦ ¦ color_triplet.cpython-312.pyc + ¦ ¦ ¦ ¦ columns.cpython-312.pyc + ¦ ¦ ¦ ¦ console.cpython-312.pyc + ¦ ¦ ¦ ¦ constrain.cpython-312.pyc + ¦ ¦ ¦ ¦ containers.cpython-312.pyc + ¦ ¦ ¦ ¦ control.cpython-312.pyc + ¦ ¦ ¦ ¦ default_styles.cpython-312.pyc + ¦ ¦ ¦ ¦ diagnose.cpython-312.pyc + ¦ ¦ ¦ ¦ emoji.cpython-312.pyc + ¦ ¦ ¦ ¦ errors.cpython-312.pyc + ¦ ¦ ¦ ¦ filesize.cpython-312.pyc + ¦ ¦ ¦ ¦ file_proxy.cpython-312.pyc + ¦ ¦ ¦ ¦ highlighter.cpython-312.pyc + ¦ ¦ ¦ ¦ json.cpython-312.pyc + ¦ ¦ ¦ ¦ jupyter.cpython-312.pyc + ¦ ¦ ¦ ¦ layout.cpython-312.pyc + ¦ ¦ ¦ ¦ live.cpython-312.pyc + ¦ ¦ ¦ ¦ live_render.cpython-312.pyc + ¦ ¦ ¦ ¦ logging.cpython-312.pyc + ¦ ¦ ¦ ¦ markup.cpython-312.pyc + ¦ ¦ ¦ ¦ measure.cpython-312.pyc + ¦ ¦ ¦ ¦ padding.cpython-312.pyc + ¦ ¦ ¦ ¦ pager.cpython-312.pyc + ¦ ¦ ¦ ¦ palette.cpython-312.pyc + ¦ ¦ ¦ ¦ panel.cpython-312.pyc + ¦ ¦ ¦ ¦ pretty.cpython-312.pyc + ¦ ¦ ¦ ¦ progress.cpython-312.pyc + ¦ ¦ ¦ ¦ progress_bar.cpython-312.pyc + ¦ ¦ ¦ ¦ prompt.cpython-312.pyc + ¦ ¦ ¦ ¦ protocol.cpython-312.pyc + ¦ ¦ ¦ ¦ region.cpython-312.pyc + ¦ ¦ ¦ ¦ repr.cpython-312.pyc + ¦ ¦ ¦ ¦ rule.cpython-312.pyc + ¦ ¦ ¦ ¦ scope.cpython-312.pyc + ¦ ¦ ¦ ¦ screen.cpython-312.pyc + ¦ ¦ ¦ ¦ segment.cpython-312.pyc + ¦ ¦ ¦ ¦ spinner.cpython-312.pyc + ¦ ¦ ¦ ¦ status.cpython-312.pyc + ¦ ¦ ¦ ¦ style.cpython-312.pyc + ¦ ¦ ¦ ¦ styled.cpython-312.pyc + ¦ ¦ ¦ ¦ syntax.cpython-312.pyc + ¦ ¦ ¦ ¦ table.cpython-312.pyc + ¦ ¦ ¦ ¦ terminal_theme.cpython-312.pyc + ¦ ¦ ¦ ¦ text.cpython-312.pyc + ¦ ¦ ¦ ¦ theme.cpython-312.pyc + ¦ ¦ ¦ ¦ themes.cpython-312.pyc + ¦ ¦ ¦ ¦ traceback.cpython-312.pyc + ¦ ¦ ¦ ¦ tree.cpython-312.pyc + ¦ ¦ ¦ ¦ _cell_widths.cpython-312.pyc + ¦ ¦ ¦ ¦ _emoji_codes.cpython-312.pyc + ¦ ¦ ¦ ¦ _emoji_replace.cpython-312.pyc + ¦ ¦ ¦ ¦ _export_format.cpython-312.pyc + ¦ ¦ ¦ ¦ _extension.cpython-312.pyc + ¦ ¦ ¦ ¦ _fileno.cpython-312.pyc + ¦ ¦ ¦ ¦ _inspect.cpython-312.pyc + ¦ ¦ ¦ ¦ _log_render.cpython-312.pyc + ¦ ¦ ¦ ¦ _loop.cpython-312.pyc + ¦ ¦ ¦ ¦ _null_file.cpython-312.pyc + ¦ ¦ ¦ ¦ _palettes.cpython-312.pyc + ¦ ¦ ¦ ¦ _pick.cpython-312.pyc + ¦ ¦ ¦ ¦ _ratio.cpython-312.pyc + ¦ ¦ ¦ ¦ _spinners.cpython-312.pyc + ¦ ¦ ¦ ¦ _stack.cpython-312.pyc + ¦ ¦ ¦ ¦ _timer.cpython-312.pyc + ¦ ¦ ¦ ¦ _win32_console.cpython-312.pyc + ¦ ¦ ¦ ¦ _windows.cpython-312.pyc + ¦ ¦ ¦ ¦ _windows_renderer.cpython-312.pyc + ¦ ¦ ¦ ¦ _wrap.cpython-312.pyc + ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ __main__.cpython-312.pyc + ¦ ¦ ¦ ¦ + ¦ ¦ ¦ +---tenacity + ¦ ¦ ¦ ¦ ¦ after.py + ¦ ¦ ¦ ¦ ¦ before.py + ¦ ¦ ¦ ¦ ¦ before_sleep.py + ¦ ¦ ¦ ¦ ¦ nap.py + ¦ ¦ ¦ ¦ ¦ py.typed + ¦ ¦ ¦ ¦ ¦ retry.py + ¦ ¦ ¦ ¦ ¦ stop.py + ¦ ¦ ¦ ¦ ¦ tornadoweb.py + ¦ ¦ ¦ ¦ ¦ wait.py + ¦ ¦ ¦ ¦ ¦ _asyncio.py + ¦ ¦ ¦ ¦ ¦ _utils.py + ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ after.cpython-312.pyc + ¦ ¦ ¦ ¦ before.cpython-312.pyc + ¦ ¦ ¦ ¦ before_sleep.cpython-312.pyc + ¦ ¦ ¦ ¦ nap.cpython-312.pyc + ¦ ¦ ¦ ¦ retry.cpython-312.pyc + ¦ ¦ ¦ ¦ stop.cpython-312.pyc + ¦ ¦ ¦ ¦ tornadoweb.cpython-312.pyc + ¦ ¦ ¦ ¦ wait.cpython-312.pyc + ¦ ¦ ¦ ¦ _asyncio.cpython-312.pyc + ¦ ¦ ¦ ¦ _utils.cpython-312.pyc + ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ + ¦ ¦ ¦ +---tomli + ¦ ¦ ¦ ¦ ¦ py.typed + ¦ ¦ ¦ ¦ ¦ _parser.py + ¦ ¦ ¦ ¦ ¦ _re.py + ¦ ¦ ¦ ¦ ¦ _types.py + ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ _parser.cpython-312.pyc + ¦ ¦ ¦ ¦ _re.cpython-312.pyc + ¦ ¦ ¦ ¦ _types.cpython-312.pyc + ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ + ¦ ¦ ¦ +---truststore + ¦ ¦ ¦ ¦ ¦ py.typed + ¦ ¦ ¦ ¦ ¦ _api.py + ¦ ¦ ¦ ¦ ¦ _macos.py + ¦ ¦ ¦ ¦ ¦ _openssl.py + ¦ ¦ ¦ ¦ ¦ _ssl_constants.py + ¦ ¦ ¦ ¦ ¦ _windows.py + ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ _api.cpython-312.pyc + ¦ ¦ ¦ ¦ _macos.cpython-312.pyc + ¦ ¦ ¦ ¦ _openssl.cpython-312.pyc + ¦ ¦ ¦ ¦ _ssl_constants.cpython-312.pyc + ¦ ¦ ¦ ¦ _windows.cpython-312.pyc + ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ + ¦ ¦ ¦ +---urllib3 + ¦ ¦ ¦ ¦ ¦ connection.py + ¦ ¦ ¦ ¦ ¦ connectionpool.py + ¦ ¦ ¦ ¦ ¦ exceptions.py + ¦ ¦ ¦ ¦ ¦ fields.py + ¦ ¦ ¦ ¦ ¦ filepost.py + ¦ ¦ ¦ ¦ ¦ poolmanager.py + ¦ ¦ ¦ ¦ ¦ request.py + ¦ ¦ ¦ ¦ ¦ response.py + ¦ ¦ ¦ ¦ ¦ _collections.py + ¦ ¦ ¦ ¦ ¦ _version.py + ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---contrib + ¦ ¦ ¦ ¦ ¦ ¦ appengine.py + ¦ ¦ ¦ ¦ ¦ ¦ ntlmpool.py + ¦ ¦ ¦ ¦ ¦ ¦ pyopenssl.py + ¦ ¦ ¦ ¦ ¦ ¦ securetransport.py + ¦ ¦ ¦ ¦ ¦ ¦ socks.py + ¦ ¦ ¦ ¦ ¦ ¦ _appengine_environ.py + ¦ ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ ¦ +---_securetransport + ¦ ¦ ¦ ¦ ¦ ¦ ¦ bindings.py + ¦ ¦ ¦ ¦ ¦ ¦ ¦ low_level.py + ¦ ¦ ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ ¦ ¦ bindings.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ ¦ low_level.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ ¦ appengine.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ ntlmpool.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ pyopenssl.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ securetransport.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ socks.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ _appengine_environ.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---packages + ¦ ¦ ¦ ¦ ¦ ¦ six.py + ¦ ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ ¦ +---backports + ¦ ¦ ¦ ¦ ¦ ¦ ¦ makefile.py + ¦ ¦ ¦ ¦ ¦ ¦ ¦ weakref_finalize.py + ¦ ¦ ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ ¦ ¦ makefile.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ ¦ weakref_finalize.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ ¦ six.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---util + ¦ ¦ ¦ ¦ ¦ ¦ connection.py + ¦ ¦ ¦ ¦ ¦ ¦ proxy.py + ¦ ¦ ¦ ¦ ¦ ¦ queue.py + ¦ ¦ ¦ ¦ ¦ ¦ request.py + ¦ ¦ ¦ ¦ ¦ ¦ response.py + ¦ ¦ ¦ ¦ ¦ ¦ retry.py + ¦ ¦ ¦ ¦ ¦ ¦ ssltransport.py + ¦ ¦ ¦ ¦ ¦ ¦ ssl_.py + ¦ ¦ ¦ ¦ ¦ ¦ ssl_match_hostname.py + ¦ ¦ ¦ ¦ ¦ ¦ timeout.py + ¦ ¦ ¦ ¦ ¦ ¦ url.py + ¦ ¦ ¦ ¦ ¦ ¦ wait.py + ¦ ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ ¦ connection.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ proxy.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ queue.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ request.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ response.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ retry.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ ssltransport.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ ssl_.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ ssl_match_hostname.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ timeout.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ url.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ wait.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ connection.cpython-312.pyc + ¦ ¦ ¦ ¦ connectionpool.cpython-312.pyc + ¦ ¦ ¦ ¦ exceptions.cpython-312.pyc + ¦ ¦ ¦ ¦ fields.cpython-312.pyc + ¦ ¦ ¦ ¦ filepost.cpython-312.pyc + ¦ ¦ ¦ ¦ poolmanager.cpython-312.pyc + ¦ ¦ ¦ ¦ request.cpython-312.pyc + ¦ ¦ ¦ ¦ response.cpython-312.pyc + ¦ ¦ ¦ ¦ _collections.cpython-312.pyc + ¦ ¦ ¦ ¦ _version.cpython-312.pyc + ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ + ¦ ¦ ¦ +---webencodings + ¦ ¦ ¦ ¦ ¦ labels.py + ¦ ¦ ¦ ¦ ¦ mklabels.py + ¦ ¦ ¦ ¦ ¦ tests.py + ¦ ¦ ¦ ¦ ¦ x_user_defined.py + ¦ ¦ ¦ ¦ ¦ __init__.py + ¦ ¦ ¦ ¦ ¦ + ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ labels.cpython-312.pyc + ¦ ¦ ¦ ¦ mklabels.cpython-312.pyc + ¦ ¦ ¦ ¦ tests.cpython-312.pyc + ¦ ¦ ¦ ¦ x_user_defined.cpython-312.pyc + ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ + ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ six.cpython-312.pyc + ¦ ¦ ¦ typing_extensions.cpython-312.pyc + ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ + ¦ ¦ +---__pycache__ + ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ __main__.cpython-312.pyc + ¦ ¦ __pip-runner__.cpython-312.pyc + ¦ ¦ + ¦ +---pip-24.0.dist-info + ¦ ¦ AUTHORS.txt + ¦ ¦ entry_points.txt + ¦ ¦ INSTALLER + ¦ ¦ LICENSE.txt + ¦ ¦ METADATA + ¦ ¦ RECORD + ¦ ¦ REQUESTED + ¦ ¦ top_level.txt + ¦ ¦ WHEEL + ¦ ¦ + ¦ +---pydantic + ¦ ¦ +---deprecated + ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ class_validators.cpython-312.pyc + ¦ ¦ ¦ config.cpython-312.pyc + ¦ ¦ ¦ copy_internals.cpython-312.pyc + ¦ ¦ ¦ decorator.cpython-312.pyc + ¦ ¦ ¦ json.cpython-312.pyc + ¦ ¦ ¦ parse.cpython-312.pyc + ¦ ¦ ¦ tools.cpython-312.pyc + ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ + ¦ ¦ +---experimental + ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ arguments_schema.cpython-312.pyc + ¦ ¦ ¦ pipeline.cpython-312.pyc + ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ + ¦ ¦ +---plugin + ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ _loader.cpython-312.pyc + ¦ ¦ ¦ _schema_validator.cpython-312.pyc + ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ + ¦ ¦ +---v1 + ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ annotated_types.cpython-312.pyc + ¦ ¦ ¦ class_validators.cpython-312.pyc + ¦ ¦ ¦ color.cpython-312.pyc + ¦ ¦ ¦ config.cpython-312.pyc + ¦ ¦ ¦ dataclasses.cpython-312.pyc + ¦ ¦ ¦ datetime_parse.cpython-312.pyc + ¦ ¦ ¦ decorator.cpython-312.pyc + ¦ ¦ ¦ env_settings.cpython-312.pyc + ¦ ¦ ¦ errors.cpython-312.pyc + ¦ ¦ ¦ error_wrappers.cpython-312.pyc + ¦ ¦ ¦ fields.cpython-312.pyc + ¦ ¦ ¦ generics.cpython-312.pyc + ¦ ¦ ¦ json.cpython-312.pyc + ¦ ¦ ¦ main.cpython-312.pyc + ¦ ¦ ¦ mypy.cpython-312.pyc + ¦ ¦ ¦ networks.cpython-312.pyc + ¦ ¦ ¦ parse.cpython-312.pyc + ¦ ¦ ¦ schema.cpython-312.pyc + ¦ ¦ ¦ tools.cpython-312.pyc + ¦ ¦ ¦ types.cpython-312.pyc + ¦ ¦ ¦ typing.cpython-312.pyc + ¦ ¦ ¦ utils.cpython-312.pyc + ¦ ¦ ¦ validators.cpython-312.pyc + ¦ ¦ ¦ version.cpython-312.pyc + ¦ ¦ ¦ _hypothesis_plugin.cpython-312.pyc + ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ + ¦ ¦ +---_internal + ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ _config.cpython-312.pyc + ¦ ¦ ¦ _core_metadata.cpython-312.pyc + ¦ ¦ ¦ _core_utils.cpython-312.pyc + ¦ ¦ ¦ _dataclasses.cpython-312.pyc + ¦ ¦ ¦ _decorators.cpython-312.pyc + ¦ ¦ ¦ _decorators_v1.cpython-312.pyc + ¦ ¦ ¦ _discriminated_union.cpython-312.pyc + ¦ ¦ ¦ _docs_extraction.cpython-312.pyc + ¦ ¦ ¦ _fields.cpython-312.pyc + ¦ ¦ ¦ _forward_ref.cpython-312.pyc + ¦ ¦ ¦ _generate_schema.cpython-312.pyc + ¦ ¦ ¦ _generics.cpython-312.pyc + ¦ ¦ ¦ _git.cpython-312.pyc + ¦ ¦ ¦ _import_utils.cpython-312.pyc + ¦ ¦ ¦ _internal_dataclass.cpython-312.pyc + ¦ ¦ ¦ _known_annotated_metadata.cpython-312.pyc + ¦ ¦ ¦ _mock_val_ser.cpython-312.pyc + ¦ ¦ ¦ _model_construction.cpython-312.pyc + ¦ ¦ ¦ _namespace_utils.cpython-312.pyc + ¦ ¦ ¦ _repr.cpython-312.pyc + ¦ ¦ ¦ _schema_gather.cpython-312.pyc + ¦ ¦ ¦ _schema_generation_shared.cpython-312.pyc + ¦ ¦ ¦ _serializers.cpython-312.pyc + ¦ ¦ ¦ _signature.cpython-312.pyc + ¦ ¦ ¦ _typing_extra.cpython-312.pyc + ¦ ¦ ¦ _utils.cpython-312.pyc + ¦ ¦ ¦ _validate_call.cpython-312.pyc + ¦ ¦ ¦ _validators.cpython-312.pyc + ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ + ¦ ¦ +---__pycache__ + ¦ ¦ aliases.cpython-312.pyc + ¦ ¦ alias_generators.cpython-312.pyc + ¦ ¦ annotated_handlers.cpython-312.pyc + ¦ ¦ class_validators.cpython-312.pyc + ¦ ¦ color.cpython-312.pyc + ¦ ¦ config.cpython-312.pyc + ¦ ¦ dataclasses.cpython-312.pyc + ¦ ¦ datetime_parse.cpython-312.pyc + ¦ ¦ decorator.cpython-312.pyc + ¦ ¦ env_settings.cpython-312.pyc + ¦ ¦ errors.cpython-312.pyc + ¦ ¦ error_wrappers.cpython-312.pyc + ¦ ¦ fields.cpython-312.pyc + ¦ ¦ functional_serializers.cpython-312.pyc + ¦ ¦ functional_validators.cpython-312.pyc + ¦ ¦ generics.cpython-312.pyc + ¦ ¦ json.cpython-312.pyc + ¦ ¦ json_schema.cpython-312.pyc + ¦ ¦ main.cpython-312.pyc + ¦ ¦ mypy.cpython-312.pyc + ¦ ¦ networks.cpython-312.pyc + ¦ ¦ parse.cpython-312.pyc + ¦ ¦ root_model.cpython-312.pyc + ¦ ¦ schema.cpython-312.pyc + ¦ ¦ tools.cpython-312.pyc + ¦ ¦ types.cpython-312.pyc + ¦ ¦ type_adapter.cpython-312.pyc + ¦ ¦ typing.cpython-312.pyc + ¦ ¦ utils.cpython-312.pyc + ¦ ¦ validate_call_decorator.cpython-312.pyc + ¦ ¦ validators.cpython-312.pyc + ¦ ¦ version.cpython-312.pyc + ¦ ¦ warnings.cpython-312.pyc + ¦ ¦ _migration.cpython-312.pyc + ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ + ¦ +---pydantic_core + ¦ ¦ +---__pycache__ + ¦ ¦ core_schema.cpython-312.pyc + ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ + ¦ +---requests + ¦ ¦ +---__pycache__ + ¦ ¦ adapters.cpython-312.pyc + ¦ ¦ api.cpython-312.pyc + ¦ ¦ auth.cpython-312.pyc + ¦ ¦ certs.cpython-312.pyc + ¦ ¦ compat.cpython-312.pyc + ¦ ¦ cookies.cpython-312.pyc + ¦ ¦ exceptions.cpython-312.pyc + ¦ ¦ help.cpython-312.pyc + ¦ ¦ hooks.cpython-312.pyc + ¦ ¦ models.cpython-312.pyc + ¦ ¦ packages.cpython-312.pyc + ¦ ¦ sessions.cpython-312.pyc + ¦ ¦ status_codes.cpython-312.pyc + ¦ ¦ structures.cpython-312.pyc + ¦ ¦ utils.cpython-312.pyc + ¦ ¦ _internal_utils.cpython-312.pyc + ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ __version__.cpython-312.pyc + ¦ ¦ + ¦ +---sniffio + ¦ ¦ +---_tests + ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ test_sniffio.cpython-312.pyc + ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ + ¦ ¦ +---__pycache__ + ¦ ¦ _impl.cpython-312.pyc + ¦ ¦ _version.cpython-312.pyc + ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ + ¦ +---starlette + ¦ ¦ +---middleware + ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ authentication.cpython-312.pyc + ¦ ¦ ¦ base.cpython-312.pyc + ¦ ¦ ¦ cors.cpython-312.pyc + ¦ ¦ ¦ errors.cpython-312.pyc + ¦ ¦ ¦ exceptions.cpython-312.pyc + ¦ ¦ ¦ gzip.cpython-312.pyc + ¦ ¦ ¦ httpsredirect.cpython-312.pyc + ¦ ¦ ¦ sessions.cpython-312.pyc + ¦ ¦ ¦ trustedhost.cpython-312.pyc + ¦ ¦ ¦ wsgi.cpython-312.pyc + ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ + ¦ ¦ +---__pycache__ + ¦ ¦ applications.cpython-312.pyc + ¦ ¦ authentication.cpython-312.pyc + ¦ ¦ background.cpython-312.pyc + ¦ ¦ concurrency.cpython-312.pyc + ¦ ¦ config.cpython-312.pyc + ¦ ¦ convertors.cpython-312.pyc + ¦ ¦ datastructures.cpython-312.pyc + ¦ ¦ endpoints.cpython-312.pyc + ¦ ¦ exceptions.cpython-312.pyc + ¦ ¦ formparsers.cpython-312.pyc + ¦ ¦ requests.cpython-312.pyc + ¦ ¦ responses.cpython-312.pyc + ¦ ¦ routing.cpython-312.pyc + ¦ ¦ schemas.cpython-312.pyc + ¦ ¦ staticfiles.cpython-312.pyc + ¦ ¦ status.cpython-312.pyc + ¦ ¦ templating.cpython-312.pyc + ¦ ¦ testclient.cpython-312.pyc + ¦ ¦ types.cpython-312.pyc + ¦ ¦ websockets.cpython-312.pyc + ¦ ¦ _exception_handler.cpython-312.pyc + ¦ ¦ _utils.cpython-312.pyc + ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ + ¦ +---typing_inspection + ¦ ¦ +---__pycache__ + ¦ ¦ introspection.cpython-312.pyc + ¦ ¦ typing_objects.cpython-312.pyc + ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ + ¦ +---urllib3 + ¦ ¦ +---contrib + ¦ ¦ ¦ +---emscripten + ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ connection.cpython-312.pyc + ¦ ¦ ¦ ¦ fetch.cpython-312.pyc + ¦ ¦ ¦ ¦ request.cpython-312.pyc + ¦ ¦ ¦ ¦ response.cpython-312.pyc + ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ + ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ pyopenssl.cpython-312.pyc + ¦ ¦ ¦ socks.cpython-312.pyc + ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ + ¦ ¦ +---http2 + ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ connection.cpython-312.pyc + ¦ ¦ ¦ probe.cpython-312.pyc + ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ + ¦ ¦ +---util + ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ connection.cpython-312.pyc + ¦ ¦ ¦ proxy.cpython-312.pyc + ¦ ¦ ¦ request.cpython-312.pyc + ¦ ¦ ¦ response.cpython-312.pyc + ¦ ¦ ¦ retry.cpython-312.pyc + ¦ ¦ ¦ ssltransport.cpython-312.pyc + ¦ ¦ ¦ ssl_.cpython-312.pyc + ¦ ¦ ¦ ssl_match_hostname.cpython-312.pyc + ¦ ¦ ¦ timeout.cpython-312.pyc + ¦ ¦ ¦ url.cpython-312.pyc + ¦ ¦ ¦ util.cpython-312.pyc + ¦ ¦ ¦ wait.cpython-312.pyc + ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ + ¦ ¦ +---__pycache__ + ¦ ¦ connection.cpython-312.pyc + ¦ ¦ connectionpool.cpython-312.pyc + ¦ ¦ exceptions.cpython-312.pyc + ¦ ¦ fields.cpython-312.pyc + ¦ ¦ filepost.cpython-312.pyc + ¦ ¦ poolmanager.cpython-312.pyc + ¦ ¦ response.cpython-312.pyc + ¦ ¦ _base_connection.cpython-312.pyc + ¦ ¦ _collections.cpython-312.pyc + ¦ ¦ _request_methods.cpython-312.pyc + ¦ ¦ _version.cpython-312.pyc + ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ + ¦ +---uvicorn + ¦ ¦ +---lifespan + ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ off.cpython-312.pyc + ¦ ¦ ¦ on.cpython-312.pyc + ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ + ¦ ¦ +---loops + ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ asyncio.cpython-312.pyc + ¦ ¦ ¦ auto.cpython-312.pyc + ¦ ¦ ¦ uvloop.cpython-312.pyc + ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ + ¦ ¦ +---middleware + ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ asgi2.cpython-312.pyc + ¦ ¦ ¦ message_logger.cpython-312.pyc + ¦ ¦ ¦ proxy_headers.cpython-312.pyc + ¦ ¦ ¦ wsgi.cpython-312.pyc + ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ + ¦ ¦ +---protocols + ¦ ¦ ¦ +---http + ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ auto.cpython-312.pyc + ¦ ¦ ¦ ¦ flow_control.cpython-312.pyc + ¦ ¦ ¦ ¦ h11_impl.cpython-312.pyc + ¦ ¦ ¦ ¦ httptools_impl.cpython-312.pyc + ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ + ¦ ¦ ¦ +---websockets + ¦ ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ ¦ auto.cpython-312.pyc + ¦ ¦ ¦ ¦ websockets_impl.cpython-312.pyc + ¦ ¦ ¦ ¦ wsproto_impl.cpython-312.pyc + ¦ ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ ¦ + ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ utils.cpython-312.pyc + ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ + ¦ ¦ +---supervisors + ¦ ¦ ¦ +---__pycache__ + ¦ ¦ ¦ basereload.cpython-312.pyc + ¦ ¦ ¦ multiprocess.cpython-312.pyc + ¦ ¦ ¦ statreload.cpython-312.pyc + ¦ ¦ ¦ watchfilesreload.cpython-312.pyc + ¦ ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ ¦ + ¦ ¦ +---__pycache__ + ¦ ¦ config.cpython-312.pyc + ¦ ¦ importer.cpython-312.pyc + ¦ ¦ logging.cpython-312.pyc + ¦ ¦ main.cpython-312.pyc + ¦ ¦ server.cpython-312.pyc + ¦ ¦ workers.cpython-312.pyc + ¦ ¦ _subprocess.cpython-312.pyc + ¦ ¦ _types.cpython-312.pyc + ¦ ¦ __init__.cpython-312.pyc + ¦ ¦ __main__.cpython-312.pyc + ¦ ¦ + ¦ +---__pycache__ + ¦ typing_extensions.cpython-312.pyc + ¦ + +---Scripts + activate + activate.bat + Activate.ps1 + deactivate.bat + pip.exe + pip3.12.exe + pip3.exe + python.exe + pythonw.exe +