From 6dac93d04cf7b09447ce4129eb7a5ddd11ec69ad Mon Sep 17 00:00:00 2001 From: Saquib Saifee Date: Sat, 18 Apr 2026 16:34:29 -0400 Subject: [PATCH] feat(tooling): add pre-commit hooks with ruff, bandit, mypy, and CI integration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds comprehensive pre-commit configuration enforcing code quality on every commit, with a dedicated GitHub Actions lint workflow running on all PRs. Builds on #74 by @emmanuelgjr — thank you for the initial implementation! Closes #51. Co-Authored-By: emmanuelgjr Co-Authored-By: Claude Sonnet 4.6 Signed-off-by: Saquib Saifee --- .github/workflows/lint.yml | 18 +++ .pre-commit-config.yaml | 55 +++++++ CONTRIBUTING.md | 32 +++- README.md | 41 +++-- pyproject.toml | 140 +++++++++------- requirements.txt | 320 +++++++++++++++++++++++++++++++++---- uv.lock | 189 ++++++++++------------ 7 files changed, 596 insertions(+), 199 deletions(-) create mode 100644 .github/workflows/lint.yml create mode 100644 .pre-commit-config.yaml diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..276d33f --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,18 @@ +name: Linting & Code Quality + +on: + push: + branches: [v0.2, main] + pull_request: + branches: [v0.2, main] + +jobs: + lint: + name: pre-commit + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: "3.11" + - uses: pre-commit/action@v3.0.1 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..7c2f12e --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,55 @@ +default_language_version: + python: python3.11 + +exclude: "tests/" + +fail_fast: true + +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v6.0.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-yaml + - id: check-added-large-files + args: ["--maxkb=500"] + - id: check-merge-conflict + + - repo: https://github.com/tox-dev/pyproject-fmt + rev: v2.21.1 + hooks: + - id: pyproject-fmt + name: Format and validate pyproject.toml + files: ^pyproject\.toml$ + + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.15.11 + hooks: + - id: ruff-check + args: [--fix] + - id: ruff-format + + - repo: https://github.com/PyCQA/bandit + rev: 1.9.4 + hooks: + - id: bandit + args: ["-c", "pyproject.toml"] + additional_dependencies: ["bandit[toml]"] + + - repo: https://github.com/pre-commit/mirrors-mypy + rev: v1.20.1 + hooks: + - id: mypy + name: Static type checking + args: ["--config-file=pyproject.toml"] + additional_dependencies: [types-requests, "pydantic>=2.4"] + + - repo: https://github.com/astral-sh/uv-pre-commit + rev: 0.11.7 + hooks: + - id: uv-lock + files: ^pyproject\.toml$ + - id: uv-export + args: ["--frozen", "--no-dev", "--no-hashes", "-o", "requirements.txt"] + files: ^pyproject\.toml$ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d077d97..c4cdc03 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -13,8 +13,19 @@ Thank you for your interest in contributing to the OWASP AIBOM Generator! This p 3. **Set up your environment**: ```bash - # Local Python setup - pip install -r requirements.txt + pip install -e ".[dev]" + ``` + +4. **Install pre-commit hooks**: + + ```bash + pre-commit install + ``` + + Hooks run automatically on every `git commit`. To run them manually against all files: + + ```bash + pre-commit run --all-files ``` ## Development Workflow @@ -66,9 +77,24 @@ type(scope): description ## Code Standards +### Pre-commit Hooks + +This project uses [pre-commit](https://pre-commit.com) to enforce code quality automatically. The following hooks run on every commit: + +| Hook | Purpose | +|------|---------| +| `trailing-whitespace`, `end-of-file-fixer`, `check-yaml`, `check-merge-conflict` | File hygiene | +| `pyproject-fmt` | Normalizes and validates `pyproject.toml` | +| `ruff` (check + format) | Linting and formatting (replaces flake8, isort, autopep8) | +| `bandit` | Security vulnerability scanning | +| `mypy` | Static type checking | +| `uv-lock` + `uv-export` | Keeps `uv.lock` and `requirements.txt` in sync with `pyproject.toml` | + +If a hook fails, fix the reported issues and re-commit. + ### Python Style -- **Python 3.8+** compatibility required +- **Python 3.11+** required - Follow existing patterns in the codebase - Use type hints for function signatures diff --git a/README.md b/README.md index 51515a3..3960216 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ # 🤖 OWASP GenAI Security Project - AIBOM Generator -This is the official GitHub repository for the **OWASP AIBOM Generator** — an open-source tool for generating **AI Bills of Materials (AIBOMs)** in [CycloneDX](https://cyclonedx.org) format. +This is the official GitHub repository for the **OWASP AIBOM Generator** — an open-source tool for generating **AI Bills of Materials (AIBOMs)** in [CycloneDX](https://cyclonedx.org) format. The tool is also listed in the official **[CycloneDX Tool Center](https://cyclonedx.org/tool-center/)**. -🚀 **Try the tool live:** -👉 https://owasp-genai-aibom.org -🔖 Bookmark and share: https://owasp-genai-aibom.org +🚀 **Try the tool live:** +👉 https://owasp-genai-aibom.org +🔖 Bookmark and share: https://owasp-genai-aibom.org 🌐 OWASP AIBOM Initiative: [genai.owasp.org](https://genai.owasp.org/) @@ -16,19 +16,19 @@ The tool is also listed in the official **[CycloneDX Tool Center](https://cyclon ## 📦 What It Does -- Extracts metadata from models hosted on Hugging Face 🤗 -- Generates an **AIBOM** (AI Bill of Materials) in CycloneDX 1.6 JSON format -- Calculates **AIBOM completeness scoring** with recommendations -- Supports metadata extraction from model cards, configurations, and repository files +- Extracts metadata from models hosted on Hugging Face 🤗 +- Generates an **AIBOM** (AI Bill of Materials) in CycloneDX 1.6 JSON format +- Calculates **AIBOM completeness scoring** with recommendations +- Supports metadata extraction from model cards, configurations, and repository files --- ## 🛠 Features -- Human-readable AIBOM viewer -- JSON download -- Completeness scoring & improvement tips -- API endpoints for automation +- Human-readable AIBOM viewer +- JSON download +- Completeness scoring & improvement tips +- API endpoints for automation - Standards-aligned generation (CycloneDX 1.6, compatible with SPDX AI Profile) --- @@ -91,11 +91,26 @@ python3 -m src.cli google-bert/bert-base-uncased \ We welcome contributions and feedback. -➡ **Log an issue:** +➡ **Log an issue:** https://github.com/GenAI-Security-Project/aibom-generator/issues --- +## 🤝 Contributing + +We welcome contributions! See [CONTRIBUTING.md](CONTRIBUTING.md) for the full guide. + +Quick setup for contributors: + +```bash +pip install -e ".[dev]" +pre-commit install +``` + +Pre-commit hooks enforce code quality (ruff, bandit, mypy, pyproject-fmt) automatically on every commit. CI also runs them on all PRs. + +--- + ## 📄 License This project is open-source and available under the [Apache 2.0 License](LICENSE). diff --git a/pyproject.toml b/pyproject.toml index 468a424..c16abc2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,75 +1,107 @@ +[build-system] +build-backend = "setuptools.build_meta" +requires = [ "setuptools>=61", "wheel" ] [project] name = "owasp-aibom-generator" version = "1.0.2" description = "A comprehensive AI Bill of Materials (AIBOM) generation tool for Hugging Face models." -authors = [ - { name = "OWASP GenAI Security Project", email = "genai-security@owasp.org" } -] readme = "README.md" -requires-python = ">=3.11" license = { text = "Apache-2.0" } +authors = [ { name = "OWASP GenAI Security Project", email = "genai-security@owasp.org" } ] +requires-python = ">=3.11" classifiers = [ - "Programming Language :: Python :: 3", - "License :: OSI Approved :: Apache Software License", - "Operating System :: OS Independent", - "Topic :: Security", - "Topic :: Scientific/Engineering :: Artificial Intelligence" + "License :: OSI Approved :: Apache Software License", + "Operating System :: OS Independent", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", + "Topic :: Scientific/Engineering :: Artificial Intelligence", + "Topic :: Security", ] dependencies = [ - "beautifulsoup4>=4.11.0", - "datasets>=2.0.0", - "fastapi>=0.104.0", - "flask>=2.3.0", - "gunicorn>=21.2.0", - "httpx>=0.25.0", - "huggingface_hub>=0.19.0", - "jinja2>=3.0.0", - "jsonschema>=4.17.0", - "license-expression>=30.4.4", - "packageurl-python>=0.11.1", - "pydantic>=2.4.0", - "python-multipart", - "PyYAML>=6.0.1", - "requests>=2.31.0", - "sentencepiece>=0.1.99", - "torch>=2.0.0", - "transformers>=4.36.0", - "uvicorn>=0.24.0", + "beautifulsoup4>=4.11", + "datasets>=2", + "fastapi>=0.104", + "flask>=2.3", + "gunicorn>=21.2", + "httpx>=0.25", + "huggingface-hub>=0.19", + "jinja2>=3", + "jsonschema>=4.17", + "license-expression>=30.4.4", + "packageurl-python>=0.11.1", + "pydantic>=2.4", + "python-multipart", + "pyyaml>=6.0.1", + "requests>=2.31", + "sentencepiece>=0.1.99", + "torch>=2", + "transformers>=4.36", + "uvicorn>=0.24", +] +optional-dependencies.dev = [ + "gguf>=0.6", + "pre-commit>=3", + "pytest>=7", + "pytest-cov>=4", + "pytest-mock>=3.10", ] +scripts.aibom = "src.cli:main" -[project.optional-dependencies] +[dependency-groups] dev = [ - "pytest>=7.0.0", - "pytest-cov>=4.0.0", - "pytest-mock>=3.10.0", - "ruff", - "gguf>=0.6.0" + "gguf>=0.6", ] -[project.scripts] -aibom = "src.cli:main" +[tool.setuptools] +packages.find.where = [ "." ] +packages.find.include = [ "src*" ] +packages.find.namespaces = false -[build-system] -requires = ["setuptools>=61.0", "wheel"] -build-backend = "setuptools.build_meta" +[tool.ruff] +target-version = "py311" +line-length = 120 +lint.select = [ + "B", # flake8-bugbear + "E", # pycodestyle errors + "F", # pyflakes + "I", # isort + "T10", # flake8-debugger + "UP", # pyupgrade + "W", # pycodestyle warnings +] -[tool.setuptools.packages.find] -where = ["."] -include = ["src*"] -namespaces = false +[tool.bandit] +exclude_dirs = [ "tests" ] +skips = [ "B101" ] -[tool.pytest.ini_options] -minversion = "6.0" -addopts = "-ra -q --cov=src" -testpaths = [ - "tests", -] -pythonpath = [ - "." +[tool.mypy] +python_version = "3.11" +ignore_missing_imports = true +install_types = true +non_interactive = true +check_untyped_defs = true +warn_unreachable = true +warn_unused_ignores = true +exclude = "tests/" +plugins = [ "pydantic.mypy" ] + +[[tool.mypy.overrides]] +ignore_errors = true +module = [ + "src.models.extractor", + "src.models.gguf_metadata", + "src.models.registry", + "src.models.service", ] -[dependency-groups] -dev = [ - "gguf>=0.6.0", +[tool.pytest] +ini_options.minversion = "6.0" +ini_options.addopts = "-ra -q --cov=src" +ini_options.testpaths = [ + "tests", ] +ini_options.pythonpath = [ "." ] diff --git a/requirements.txt b/requirements.txt index 1db1c00..f6914f7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,27 +1,293 @@ -huggingface_hub>=0.19.0 -transformers>=4.36.0 -torch>=2.0.0 -fastapi>=0.104.0 -uvicorn>=0.24.0 -pydantic>=2.4.0 -requests>=2.31.0 -python-dotenv>=1.0.0 -PyYAML>=6.0.1 -flask>=2.3.0 -gunicorn>=21.2.0 -cyclonedx-python-lib>=4.0.0 -packageurl-python>=0.17.6 -python-multipart -jinja2>=3.0.0 -datasets>=2.0.0 -beautifulsoup4>=4.11.0 -nltk>=3.8.0 -python-dateutil>=2.8.0 -jsonschema>=4.17.0 -sentencepiece>=0.1.99 - -# Test dependencies -pytest>=7.0.0 -pytest-mock>=3.10.0 -pytest-cov>=4.0.0 -gguf>=0.6.0 +# This file was autogenerated by uv via the following command: +# uv export --frozen --no-dev --no-hashes -o requirements.txt +-e . +aiohappyeyeballs==2.6.1 + # via aiohttp +aiohttp==3.13.3 + # via fsspec +aiosignal==1.4.0 + # via aiohttp +annotated-doc==0.0.4 + # via + # fastapi + # typer +annotated-types==0.7.0 + # via pydantic +anyio==4.12.1 + # via + # httpx + # starlette +attrs==25.4.0 + # via + # aiohttp + # jsonschema + # referencing +beautifulsoup4==4.14.3 + # via owasp-aibom-generator +blinker==1.9.0 + # via flask +boolean-py==5.0 + # via license-expression +certifi==2026.1.4 + # via + # httpcore + # httpx + # requests +charset-normalizer==3.4.4 + # via requests +click==8.3.1 + # via + # flask + # typer + # uvicorn +colorama==0.4.6 ; sys_platform == 'win32' + # via + # click + # tqdm +cuda-bindings==12.9.4 ; platform_machine == 'x86_64' and sys_platform == 'linux' + # via torch +cuda-pathfinder==1.3.5 ; platform_machine == 'x86_64' and sys_platform == 'linux' + # via cuda-bindings +datasets==4.5.0 + # via owasp-aibom-generator +dill==0.4.0 + # via + # datasets + # multiprocess +fastapi==0.132.0 + # via owasp-aibom-generator +filelock==3.24.3 + # via + # datasets + # huggingface-hub + # torch +flask==3.1.3 + # via owasp-aibom-generator +frozenlist==1.8.0 + # via + # aiohttp + # aiosignal +fsspec==2025.10.0 + # via + # datasets + # huggingface-hub + # torch +gunicorn==25.1.0 + # via owasp-aibom-generator +h11==0.16.0 + # via + # httpcore + # uvicorn +hf-xet==1.3.0 ; platform_machine == 'AMD64' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'arm64' or platform_machine == 'x86_64' + # via huggingface-hub +httpcore==1.0.9 + # via httpx +httpx==0.28.1 + # via + # datasets + # huggingface-hub + # owasp-aibom-generator +huggingface-hub==1.4.1 + # via + # datasets + # owasp-aibom-generator + # tokenizers + # transformers +idna==3.11 + # via + # anyio + # httpx + # requests + # yarl +itsdangerous==2.2.0 + # via flask +jinja2==3.1.6 + # via + # flask + # owasp-aibom-generator + # torch +jsonschema==4.26.0 + # via owasp-aibom-generator +jsonschema-specifications==2025.9.1 + # via jsonschema +license-expression==30.4.4 + # via owasp-aibom-generator +markdown-it-py==4.0.0 + # via rich +markupsafe==3.0.3 + # via + # flask + # jinja2 + # werkzeug +mdurl==0.1.2 + # via markdown-it-py +mpmath==1.3.0 + # via sympy +multidict==6.7.1 + # via + # aiohttp + # yarl +multiprocess==0.70.18 + # via datasets +networkx==3.6.1 + # via torch +numpy==2.4.2 + # via + # datasets + # pandas + # transformers +nvidia-cublas-cu12==12.8.4.1 ; platform_machine == 'x86_64' and sys_platform == 'linux' + # via + # nvidia-cudnn-cu12 + # nvidia-cusolver-cu12 + # torch +nvidia-cuda-cupti-cu12==12.8.90 ; platform_machine == 'x86_64' and sys_platform == 'linux' + # via torch +nvidia-cuda-nvrtc-cu12==12.8.93 ; platform_machine == 'x86_64' and sys_platform == 'linux' + # via torch +nvidia-cuda-runtime-cu12==12.8.90 ; platform_machine == 'x86_64' and sys_platform == 'linux' + # via torch +nvidia-cudnn-cu12==9.10.2.21 ; platform_machine == 'x86_64' and sys_platform == 'linux' + # via torch +nvidia-cufft-cu12==11.3.3.83 ; platform_machine == 'x86_64' and sys_platform == 'linux' + # via torch +nvidia-cufile-cu12==1.13.1.3 ; platform_machine == 'x86_64' and sys_platform == 'linux' + # via torch +nvidia-curand-cu12==10.3.9.90 ; platform_machine == 'x86_64' and sys_platform == 'linux' + # via torch +nvidia-cusolver-cu12==11.7.3.90 ; platform_machine == 'x86_64' and sys_platform == 'linux' + # via torch +nvidia-cusparse-cu12==12.5.8.93 ; platform_machine == 'x86_64' and sys_platform == 'linux' + # via + # nvidia-cusolver-cu12 + # torch +nvidia-cusparselt-cu12==0.7.1 ; platform_machine == 'x86_64' and sys_platform == 'linux' + # via torch +nvidia-nccl-cu12==2.27.5 ; platform_machine == 'x86_64' and sys_platform == 'linux' + # via torch +nvidia-nvjitlink-cu12==12.8.93 ; platform_machine == 'x86_64' and sys_platform == 'linux' + # via + # nvidia-cufft-cu12 + # nvidia-cusolver-cu12 + # nvidia-cusparse-cu12 + # torch +nvidia-nvshmem-cu12==3.4.5 ; platform_machine == 'x86_64' and sys_platform == 'linux' + # via torch +nvidia-nvtx-cu12==12.8.90 ; platform_machine == 'x86_64' and sys_platform == 'linux' + # via torch +packageurl-python==0.17.6 + # via owasp-aibom-generator +packaging==26.0 + # via + # datasets + # gunicorn + # huggingface-hub + # transformers +pandas==3.0.1 + # via datasets +propcache==0.4.1 + # via + # aiohttp + # yarl +pyarrow==23.0.1 + # via datasets +pydantic==2.12.5 + # via + # fastapi + # owasp-aibom-generator +pydantic-core==2.41.5 + # via pydantic +pygments==2.19.2 + # via rich +python-dateutil==2.9.0.post0 + # via pandas +python-multipart==0.0.22 + # via owasp-aibom-generator +pyyaml==6.0.3 + # via + # datasets + # huggingface-hub + # owasp-aibom-generator + # transformers +referencing==0.37.0 + # via + # jsonschema + # jsonschema-specifications +regex==2026.2.19 + # via transformers +requests==2.32.5 + # via + # datasets + # owasp-aibom-generator +rich==14.3.3 + # via typer +rpds-py==0.30.0 + # via + # jsonschema + # referencing +safetensors==0.7.0 + # via transformers +sentencepiece==0.2.1 + # via owasp-aibom-generator +setuptools==82.0.0 ; python_full_version >= '3.12' + # via torch +shellingham==1.5.4 + # via + # huggingface-hub + # typer +six==1.17.0 + # via python-dateutil +soupsieve==2.8.3 + # via beautifulsoup4 +starlette==0.52.1 + # via fastapi +sympy==1.14.0 + # via torch +tokenizers==0.22.2 + # via transformers +torch==2.10.0 + # via owasp-aibom-generator +tqdm==4.67.3 + # via + # datasets + # huggingface-hub + # transformers +transformers==5.2.0 + # via owasp-aibom-generator +triton==3.6.0 ; platform_machine == 'x86_64' and sys_platform == 'linux' + # via torch +typer==0.24.1 + # via typer-slim +typer-slim==0.24.0 + # via + # huggingface-hub + # transformers +typing-extensions==4.15.0 + # via + # aiosignal + # anyio + # beautifulsoup4 + # fastapi + # huggingface-hub + # pydantic + # pydantic-core + # referencing + # starlette + # torch + # typing-inspection +typing-inspection==0.4.2 + # via + # fastapi + # pydantic +tzdata==2025.3 ; sys_platform == 'emscripten' or sys_platform == 'win32' + # via pandas +urllib3==2.6.3 + # via requests +uvicorn==0.41.0 + # via owasp-aibom-generator +werkzeug==3.1.6 + # via flask +xxhash==3.6.0 + # via datasets +yarl==1.22.0 + # via aiohttp diff --git a/uv.lock b/uv.lock index 903eeba..3722293 100644 --- a/uv.lock +++ b/uv.lock @@ -217,6 +217,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e6/ad/3cc14f097111b4de0040c83a525973216457bbeeb63739ef1ed275c1c021/certifi-2026.1.4-py3-none-any.whl", hash = "sha256:9943707519e4add1115f44c2bc244f782c0249876bf51b6599fee1ffbedd685c", size = 152900, upload-time = "2026-01-04T02:42:40.15Z" }, ] +[[package]] +name = "cfgv" +version = "3.5.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4e/b5/721b8799b04bf9afe054a3899c6cf4e880fcf8563cc71c15610242490a0c/cfgv-3.5.0.tar.gz", hash = "sha256:d5b1034354820651caa73ede66a6294d6e95c1b00acc5e9b098e917404669132", size = 7334, upload-time = "2025-11-19T20:55:51.612Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl", hash = "sha256:a8dc6b26ad22ff227d2634a65cb388215ce6cc96bbcc5cfde7641ae87e8dacc0", size = 7445, upload-time = "2025-11-19T20:55:50.744Z" }, +] + [[package]] name = "charset-normalizer" version = "3.4.4" @@ -439,22 +448,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ca/b5/e4056e4058fb56519fcddf1face6fe3ff2398953b41615fafe9fb1540bf2/cuda_pathfinder-1.3.5-py3-none-any.whl", hash = "sha256:6c88220f8637cb35d2a75c620d72efebf683b248b923713d8fbe235844c1a4b9", size = 33711, upload-time = "2026-02-23T18:34:27.253Z" }, ] -[[package]] -name = "cyclonedx-python-lib" -version = "11.6.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "license-expression" }, - { name = "packageurl-python" }, - { name = "py-serializable" }, - { name = "sortedcontainers" }, - { name = "typing-extensions", marker = "python_full_version < '3.13'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/89/ed/54ecfa25fc145c58bf4f98090f7b6ffe5188d0759248c57dde44427ea239/cyclonedx_python_lib-11.6.0.tar.gz", hash = "sha256:7fb85a4371fa3a203e5be577ac22b7e9a7157f8b0058b7448731474d6dea7bf0", size = 1408147, upload-time = "2025-12-02T12:28:46.446Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/c7/1b/534ad8a5e0f9470522811a8e5a9bc5d328fb7738ba29faf357467a4ef6d0/cyclonedx_python_lib-11.6.0-py3-none-any.whl", hash = "sha256:94f4aae97db42a452134dafdddcfab9745324198201c4777ed131e64c8380759", size = 511157, upload-time = "2025-12-02T12:28:44.158Z" }, -] - [[package]] name = "datasets" version = "4.5.0" @@ -481,21 +474,21 @@ wheels = [ ] [[package]] -name = "defusedxml" -version = "0.7.1" +name = "dill" +version = "0.4.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/0f/d5/c66da9b79e5bdb124974bfe172b4daf3c984ebd9c2a06e2b8a4dc7331c72/defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69", size = 75520, upload-time = "2021-03-08T10:59:26.269Z" } +sdist = { url = "https://files.pythonhosted.org/packages/12/80/630b4b88364e9a8c8c5797f4602d0f76ef820909ee32f0bacb9f90654042/dill-0.4.0.tar.gz", hash = "sha256:0633f1d2df477324f53a895b02c901fb961bdbf65a17122586ea7019292cbcf0", size = 186976, upload-time = "2025-04-16T00:41:48.867Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/07/6c/aa3f2f849e01cb6a001cd8554a88d4c77c5c1a31c95bdf1cf9301e6d9ef4/defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61", size = 25604, upload-time = "2021-03-08T10:59:24.45Z" }, + { url = "https://files.pythonhosted.org/packages/50/3d/9373ad9c56321fdab5b41197068e1d8c25883b3fea29dd361f9b55116869/dill-0.4.0-py3-none-any.whl", hash = "sha256:44f54bf6412c2c8464c14e8243eb163690a9800dbe2c367330883b19c7561049", size = 119668, upload-time = "2025-04-16T00:41:47.671Z" }, ] [[package]] -name = "dill" +name = "distlib" version = "0.4.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/12/80/630b4b88364e9a8c8c5797f4602d0f76ef820909ee32f0bacb9f90654042/dill-0.4.0.tar.gz", hash = "sha256:0633f1d2df477324f53a895b02c901fb961bdbf65a17122586ea7019292cbcf0", size = 186976, upload-time = "2025-04-16T00:41:48.867Z" } +sdist = { url = "https://files.pythonhosted.org/packages/96/8e/709914eb2b5749865801041647dc7f4e6d00b549cfe88b65ca192995f07c/distlib-0.4.0.tar.gz", hash = "sha256:feec40075be03a04501a973d81f633735b4b69f98b05450592310c0f401a4e0d", size = 614605, upload-time = "2025-07-17T16:52:00.465Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/50/3d/9373ad9c56321fdab5b41197068e1d8c25883b3fea29dd361f9b55116869/dill-0.4.0-py3-none-any.whl", hash = "sha256:44f54bf6412c2c8464c14e8243eb163690a9800dbe2c367330883b19c7561049", size = 119668, upload-time = "2025-04-16T00:41:47.671Z" }, + { url = "https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl", hash = "sha256:9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16", size = 469047, upload-time = "2025-07-17T16:51:58.613Z" }, ] [[package]] @@ -772,6 +765,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d5/ae/2f6d96b4e6c5478d87d606a1934b5d436c4a2bce6bb7c6fdece891c128e3/huggingface_hub-1.4.1-py3-none-any.whl", hash = "sha256:9931d075fb7a79af5abc487106414ec5fba2c0ae86104c0c62fd6cae38873d18", size = 553326, upload-time = "2026-02-06T09:20:00.728Z" }, ] +[[package]] +name = "identify" +version = "2.6.19" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/52/63/51723b5f116cc04b061cb6f5a561790abf249d25931d515cd375e063e0f4/identify-2.6.19.tar.gz", hash = "sha256:6be5020c38fcb07da56c53733538a3081ea5aa70d36a156f83044bfbf9173842", size = 99567, upload-time = "2026-04-17T18:39:50.265Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/94/84/d9273cd09688070a6523c4aee4663a8538721b2b755c4962aafae0011e72/identify-2.6.19-py2.py3-none-any.whl", hash = "sha256:20e6a87f786f768c092a721ad107fc9df0eb89347be9396cadf3f4abbd1fb78a", size = 99397, upload-time = "2026-04-17T18:39:49.221Z" }, +] + [[package]] name = "idna" version = "3.11" @@ -811,15 +813,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" }, ] -[[package]] -name = "joblib" -version = "1.5.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/41/f2/d34e8b3a08a9cc79a50b2208a93dce981fe615b64d5a4d4abee421d898df/joblib-1.5.3.tar.gz", hash = "sha256:8561a3269e6801106863fd0d6d84bb737be9e7631e33aaed3fb9ce5953688da3", size = 331603, upload-time = "2025-12-15T08:41:46.427Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/7b/91/984aca2ec129e2757d1e4e3c81c3fcda9d0f85b74670a094cc443d9ee949/joblib-1.5.3-py3-none-any.whl", hash = "sha256:5fc3c5039fc5ca8c0276333a188bbd59d6b7ab37fe6632daa76bc7f9ec18e713", size = 309071, upload-time = "2025-12-15T08:41:44.973Z" }, -] - [[package]] name = "jsonschema" version = "4.26.0" @@ -1110,18 +1103,12 @@ wheels = [ ] [[package]] -name = "nltk" -version = "3.9.2" +name = "nodeenv" +version = "1.10.0" source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "click" }, - { name = "joblib" }, - { name = "regex" }, - { name = "tqdm" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/f9/76/3a5e4312c19a028770f86fd7c058cf9f4ec4321c6cf7526bab998a5b683c/nltk-3.9.2.tar.gz", hash = "sha256:0f409e9b069ca4177c1903c3e843eef90c7e92992fa4931ae607da6de49e1419", size = 2887629, upload-time = "2025-10-01T07:19:23.764Z" } +sdist = { url = "https://files.pythonhosted.org/packages/24/bf/d1bda4f6168e0b2e9e5958945e01910052158313224ada5ce1fb2e1113b8/nodeenv-1.10.0.tar.gz", hash = "sha256:996c191ad80897d076bdfba80a41994c2b47c68e224c542b48feba42ba00f8bb", size = 55611, upload-time = "2025-12-20T14:08:54.006Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/60/90/81ac364ef94209c100e12579629dc92bf7a709a84af32f8c551b02c07e94/nltk-3.9.2-py3-none-any.whl", hash = "sha256:1e209d2b3009110635ed9709a67a1a3e33a10f799490fa71cf4bec218c11c88a", size = 1513404, upload-time = "2025-10-01T07:19:21.648Z" }, + { url = "https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl", hash = "sha256:5bb13e3eed2923615535339b3c620e76779af4cb4c6a90deccc9e36b274d3827", size = 23438, upload-time = "2025-12-20T14:08:52.782Z" }, ] [[package]] @@ -1343,7 +1330,6 @@ version = "1.0.2" source = { editable = "." } dependencies = [ { name = "beautifulsoup4" }, - { name = "cyclonedx-python-lib" }, { name = "datasets" }, { name = "fastapi" }, { name = "flask" }, @@ -1353,11 +1339,8 @@ dependencies = [ { name = "jinja2" }, { name = "jsonschema" }, { name = "license-expression" }, - { name = "nltk" }, { name = "packageurl-python" }, { name = "pydantic" }, - { name = "python-dateutil" }, - { name = "python-dotenv" }, { name = "python-multipart" }, { name = "pyyaml" }, { name = "requests" }, @@ -1369,10 +1352,11 @@ dependencies = [ [package.optional-dependencies] dev = [ + { name = "gguf" }, + { name = "pre-commit" }, { name = "pytest" }, { name = "pytest-cov" }, { name = "pytest-mock" }, - { name = "ruff" }, ] [package.dev-dependencies] @@ -1383,28 +1367,25 @@ dev = [ [package.metadata] requires-dist = [ { name = "beautifulsoup4", specifier = ">=4.11.0" }, - { name = "cyclonedx-python-lib", specifier = ">=4.0.0" }, { name = "datasets", specifier = ">=2.0.0" }, { name = "fastapi", specifier = ">=0.104.0" }, { name = "flask", specifier = ">=2.3.0" }, + { name = "gguf", marker = "extra == 'dev'", specifier = ">=0.6.0" }, { name = "gunicorn", specifier = ">=21.2.0" }, { name = "httpx", specifier = ">=0.25.0" }, { name = "huggingface-hub", specifier = ">=0.19.0" }, { name = "jinja2", specifier = ">=3.0.0" }, { name = "jsonschema", specifier = ">=4.17.0" }, { name = "license-expression", specifier = ">=30.4.4" }, - { name = "nltk", specifier = ">=3.8.0" }, { name = "packageurl-python", specifier = ">=0.11.1" }, + { name = "pre-commit", marker = "extra == 'dev'", specifier = ">=3.0.0" }, { name = "pydantic", specifier = ">=2.4.0" }, { name = "pytest", marker = "extra == 'dev'", specifier = ">=7.0.0" }, { name = "pytest-cov", marker = "extra == 'dev'", specifier = ">=4.0.0" }, { name = "pytest-mock", marker = "extra == 'dev'", specifier = ">=3.10.0" }, - { name = "python-dateutil", specifier = ">=2.8.0" }, - { name = "python-dotenv", specifier = ">=1.0.0" }, { name = "python-multipart" }, { name = "pyyaml", specifier = ">=6.0.1" }, { name = "requests", specifier = ">=2.31.0" }, - { name = "ruff", marker = "extra == 'dev'" }, { name = "sentencepiece", specifier = ">=0.1.99" }, { name = "torch", specifier = ">=2.0.0" }, { name = "transformers", specifier = ">=4.36.0" }, @@ -1493,6 +1474,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/68/b0/34937815889fa982613775e4b97fddd13250f11012d769949c5465af2150/pandas-3.0.1-cp314-cp314t-win_arm64.whl", hash = "sha256:108dd1790337a494aa80e38def654ca3f0968cf4f362c85f44c15e471667102d", size = 9452085, upload-time = "2026-02-17T22:20:14.331Z" }, ] +[[package]] +name = "platformdirs" +version = "4.9.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/9f/4a/0883b8e3802965322523f0b200ecf33d31f10991d0401162f4b23c698b42/platformdirs-4.9.6.tar.gz", hash = "sha256:3bfa75b0ad0db84096ae777218481852c0ebc6c727b3168c1b9e0118e458cf0a", size = 29400, upload-time = "2026-04-09T00:04:10.812Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/75/a6/a0a304dc33b49145b21f4808d763822111e67d1c3a32b524a1baf947b6e1/platformdirs-4.9.6-py3-none-any.whl", hash = "sha256:e61adb1d5e5cb3441b4b7710bea7e4c12250ca49439228cc1021c00dcfac0917", size = 21348, upload-time = "2026-04-09T00:04:09.463Z" }, +] + [[package]] name = "pluggy" version = "1.6.0" @@ -1502,6 +1492,22 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, ] +[[package]] +name = "pre-commit" +version = "4.5.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cfgv" }, + { name = "identify" }, + { name = "nodeenv" }, + { name = "pyyaml" }, + { name = "virtualenv" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/40/f1/6d86a29246dfd2e9b6237f0b5823717f60cad94d47ddc26afa916d21f525/pre_commit-4.5.1.tar.gz", hash = "sha256:eb545fcff725875197837263e977ea257a402056661f09dae08e4b149b030a61", size = 198232, upload-time = "2025-12-16T21:14:33.552Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5d/19/fd3ef348460c80af7bb4669ea7926651d1f95c23ff2df18b9d24bab4f3fa/pre_commit-4.5.1-py2.py3-none-any.whl", hash = "sha256:3b3afd891e97337708c1674210f8eba659b52a38ea5f822ff142d10786221f77", size = 226437, upload-time = "2025-12-16T21:14:32.409Z" }, +] + [[package]] name = "propcache" version = "0.4.1" @@ -1601,18 +1607,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/5b/5a/bc7b4a4ef808fa59a816c17b20c4bef6884daebbdf627ff2a161da67da19/propcache-0.4.1-py3-none-any.whl", hash = "sha256:af2a6052aeb6cf17d3e46ee169099044fd8224cbaf75c76a2ef596e8163e2237", size = 13305, upload-time = "2025-10-08T19:49:00.792Z" }, ] -[[package]] -name = "py-serializable" -version = "2.1.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "defusedxml" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/73/21/d250cfca8ff30c2e5a7447bc13861541126ce9bd4426cd5d0c9f08b5547d/py_serializable-2.1.0.tar.gz", hash = "sha256:9d5db56154a867a9b897c0163b33a793c804c80cee984116d02d49e4578fc103", size = 52368, upload-time = "2025-07-21T09:56:48.07Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/9b/bf/7595e817906a29453ba4d99394e781b6fabe55d21f3c15d240f85dd06bb1/py_serializable-2.1.0-py3-none-any.whl", hash = "sha256:b56d5d686b5a03ba4f4db5e769dc32336e142fc3bd4d68a8c25579ebb0a67304", size = 23045, upload-time = "2025-07-21T09:56:46.848Z" }, -] - [[package]] name = "pyarrow" version = "23.0.1" @@ -1839,12 +1833,16 @@ wheels = [ ] [[package]] -name = "python-dotenv" -version = "1.2.1" +name = "python-discovery" +version = "1.2.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f0/26/19cadc79a718c5edbec86fd4919a6b6d3f681039a2f6d66d14be94e75fb9/python_dotenv-1.2.1.tar.gz", hash = "sha256:42667e897e16ab0d66954af0e60a9caa94f0fd4ecf3aaf6d2d260eec1aa36ad6", size = 44221, upload-time = "2025-10-26T15:12:10.434Z" } +dependencies = [ + { name = "filelock" }, + { name = "platformdirs" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/de/ef/3bae0e537cfe91e8431efcba4434463d2c5a65f5a89edd47c6cf2f03c55f/python_discovery-1.2.2.tar.gz", hash = "sha256:876e9c57139eb757cb5878cbdd9ae5379e5d96266c99ef731119e04fffe533bb", size = 58872, upload-time = "2026-04-07T17:28:49.249Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/14/1b/a298b06749107c305e1fe0f814c6c74aea7b2f1e10989cb30f544a1b3253/python_dotenv-1.2.1-py3-none-any.whl", hash = "sha256:b81ee9561e9ca4004139c6cbba3a238c32b03e4894671e181b671e8cb8425d61", size = 21230, upload-time = "2025-10-26T15:12:09.109Z" }, + { url = "https://files.pythonhosted.org/packages/d8/db/795879cc3ddfe338599bddea6388cc5100b088db0a4caf6e6c1af1c27e04/python_discovery-1.2.2-py3-none-any.whl", hash = "sha256:e1ae95d9af875e78f15e19aed0c6137ab1bb49c200f21f5061786490c9585c7a", size = 31894, upload-time = "2026-04-07T17:28:48.09Z" }, ] [[package]] @@ -2165,31 +2163,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d1/b7/b95708304cd49b7b6f82fdd039f1748b66ec2b21d6a45180910802f1abf1/rpds_py-0.30.0-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:ac37f9f516c51e5753f27dfdef11a88330f04de2d564be3991384b2f3535d02e", size = 562191, upload-time = "2025-11-30T20:24:36.853Z" }, ] -[[package]] -name = "ruff" -version = "0.15.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/06/04/eab13a954e763b0606f460443fcbf6bb5a0faf06890ea3754ff16523dce5/ruff-0.15.2.tar.gz", hash = "sha256:14b965afee0969e68bb871eba625343b8673375f457af4abe98553e8bbb98342", size = 4558148, upload-time = "2026-02-19T22:32:20.271Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/2f/70/3a4dc6d09b13cb3e695f28307e5d889b2e1a66b7af9c5e257e796695b0e6/ruff-0.15.2-py3-none-linux_armv6l.whl", hash = "sha256:120691a6fdae2f16d65435648160f5b81a9625288f75544dc40637436b5d3c0d", size = 10430565, upload-time = "2026-02-19T22:32:41.824Z" }, - { url = "https://files.pythonhosted.org/packages/71/0b/bb8457b56185ece1305c666dc895832946d24055be90692381c31d57466d/ruff-0.15.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:a89056d831256099658b6bba4037ac6dd06f49d194199215befe2bb10457ea5e", size = 10820354, upload-time = "2026-02-19T22:32:07.366Z" }, - { url = "https://files.pythonhosted.org/packages/2d/c1/e0532d7f9c9e0b14c46f61b14afd563298b8b83f337b6789ddd987e46121/ruff-0.15.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:e36dee3a64be0ebd23c86ffa3aa3fd3ac9a712ff295e192243f814a830b6bd87", size = 10170767, upload-time = "2026-02-19T22:32:13.188Z" }, - { url = "https://files.pythonhosted.org/packages/47/e8/da1aa341d3af017a21c7a62fb5ec31d4e7ad0a93ab80e3a508316efbcb23/ruff-0.15.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9fb47b6d9764677f8c0a193c0943ce9a05d6763523f132325af8a858eadc2b9", size = 10529591, upload-time = "2026-02-19T22:32:02.547Z" }, - { url = "https://files.pythonhosted.org/packages/93/74/184fbf38e9f3510231fbc5e437e808f0b48c42d1df9434b208821efcd8d6/ruff-0.15.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f376990f9d0d6442ea9014b19621d8f2aaf2b8e39fdbfc79220b7f0c596c9b80", size = 10260771, upload-time = "2026-02-19T22:32:36.938Z" }, - { url = "https://files.pythonhosted.org/packages/05/ac/605c20b8e059a0bc4b42360414baa4892ff278cec1c91fff4be0dceedefd/ruff-0.15.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2dcc987551952d73cbf5c88d9fdee815618d497e4df86cd4c4824cc59d5dd75f", size = 11045791, upload-time = "2026-02-19T22:32:31.642Z" }, - { url = "https://files.pythonhosted.org/packages/fd/52/db6e419908f45a894924d410ac77d64bdd98ff86901d833364251bd08e22/ruff-0.15.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:42a47fd785cbe8c01b9ff45031af875d101b040ad8f4de7bbb716487c74c9a77", size = 11879271, upload-time = "2026-02-19T22:32:29.305Z" }, - { url = "https://files.pythonhosted.org/packages/3e/d8/7992b18f2008bdc9231d0f10b16df7dda964dbf639e2b8b4c1b4e91b83af/ruff-0.15.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cbe9f49354866e575b4c6943856989f966421870e85cd2ac94dccb0a9dcb2fea", size = 11303707, upload-time = "2026-02-19T22:32:22.492Z" }, - { url = "https://files.pythonhosted.org/packages/d7/02/849b46184bcfdd4b64cde61752cc9a146c54759ed036edd11857e9b8443b/ruff-0.15.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b7a672c82b5f9887576087d97be5ce439f04bbaf548ee987b92d3a7dede41d3a", size = 11149151, upload-time = "2026-02-19T22:32:44.234Z" }, - { url = "https://files.pythonhosted.org/packages/70/04/f5284e388bab60d1d3b99614a5a9aeb03e0f333847e2429bebd2aaa1feec/ruff-0.15.2-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:72ecc64f46f7019e2bcc3cdc05d4a7da958b629a5ab7033195e11a438403d956", size = 11091132, upload-time = "2026-02-19T22:32:24.691Z" }, - { url = "https://files.pythonhosted.org/packages/fa/ae/88d844a21110e14d92cf73d57363fab59b727ebeabe78009b9ccb23500af/ruff-0.15.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:8dcf243b15b561c655c1ef2f2b0050e5d50db37fe90115507f6ff37d865dc8b4", size = 10504717, upload-time = "2026-02-19T22:32:26.75Z" }, - { url = "https://files.pythonhosted.org/packages/64/27/867076a6ada7f2b9c8292884ab44d08fd2ba71bd2b5364d4136f3cd537e1/ruff-0.15.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:dab6941c862c05739774677c6273166d2510d254dac0695c0e3f5efa1b5585de", size = 10263122, upload-time = "2026-02-19T22:32:10.036Z" }, - { url = "https://files.pythonhosted.org/packages/e7/ef/faf9321d550f8ebf0c6373696e70d1758e20ccdc3951ad7af00c0956be7c/ruff-0.15.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:1b9164f57fc36058e9a6806eb92af185b0697c9fe4c7c52caa431c6554521e5c", size = 10735295, upload-time = "2026-02-19T22:32:39.227Z" }, - { url = "https://files.pythonhosted.org/packages/2f/55/e8089fec62e050ba84d71b70e7834b97709ca9b7aba10c1a0b196e493f97/ruff-0.15.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:80d24fcae24d42659db7e335b9e1531697a7102c19185b8dc4a028b952865fd8", size = 11241641, upload-time = "2026-02-19T22:32:34.617Z" }, - { url = "https://files.pythonhosted.org/packages/23/01/1c30526460f4d23222d0fabd5888868262fd0e2b71a00570ca26483cd993/ruff-0.15.2-py3-none-win32.whl", hash = "sha256:fd5ff9e5f519a7e1bd99cbe8daa324010a74f5e2ebc97c6242c08f26f3714f6f", size = 10507885, upload-time = "2026-02-19T22:32:15.635Z" }, - { url = "https://files.pythonhosted.org/packages/5c/10/3d18e3bbdf8fc50bbb4ac3cc45970aa5a9753c5cb51bf9ed9a3cd8b79fa3/ruff-0.15.2-py3-none-win_amd64.whl", hash = "sha256:d20014e3dfa400f3ff84830dfb5755ece2de45ab62ecea4af6b7262d0fb4f7c5", size = 11623725, upload-time = "2026-02-19T22:32:04.947Z" }, - { url = "https://files.pythonhosted.org/packages/6d/78/097c0798b1dab9f8affe73da9642bb4500e098cb27fd8dc9724816ac747b/ruff-0.15.2-py3-none-win_arm64.whl", hash = "sha256:cabddc5822acdc8f7b5527b36ceac55cc51eec7b1946e60181de8fe83ca8876e", size = 10941649, upload-time = "2026-02-19T22:32:18.108Z" }, -] - [[package]] name = "safetensors" version = "0.7.0" @@ -2295,15 +2268,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, ] -[[package]] -name = "sortedcontainers" -version = "2.4.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e8/c4/ba2f8066cceb6f23394729afe52f3bf7adec04bf9ed2c820b39e19299111/sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88", size = 30594, upload-time = "2021-05-16T22:03:42.897Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/32/46/9cb0e58b2deb7f82b84065f37f3bffeb12413f947f9388e4cac22c4621ce/sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0", size = 29575, upload-time = "2021-05-16T22:03:41.177Z" }, -] - [[package]] name = "soupsieve" version = "2.8.3" @@ -2452,6 +2416,12 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/0f/8b/4b61d6e13f7108f36910df9ab4b58fd389cc2520d54d81b88660804aad99/torch-2.10.0-2-cp311-none-macosx_11_0_arm64.whl", hash = "sha256:418997cb02d0a0f1497cf6a09f63166f9f5df9f3e16c8a716ab76a72127c714f", size = 79423467, upload-time = "2026-02-10T21:44:48.711Z" }, { url = "https://files.pythonhosted.org/packages/d3/54/a2ba279afcca44bbd320d4e73675b282fcee3d81400ea1b53934efca6462/torch-2.10.0-2-cp312-none-macosx_11_0_arm64.whl", hash = "sha256:13ec4add8c3faaed8d13e0574f5cd4a323c11655546f91fbe6afa77b57423574", size = 79498202, upload-time = "2026-02-10T21:44:52.603Z" }, { url = "https://files.pythonhosted.org/packages/ec/23/2c9fe0c9c27f7f6cb865abcea8a4568f29f00acaeadfc6a37f6801f84cb4/torch-2.10.0-2-cp313-none-macosx_11_0_arm64.whl", hash = "sha256:e521c9f030a3774ed770a9c011751fb47c4d12029a3d6522116e48431f2ff89e", size = 79498254, upload-time = "2026-02-10T21:44:44.095Z" }, + { url = "https://files.pythonhosted.org/packages/36/ab/7b562f1808d3f65414cd80a4f7d4bb00979d9355616c034c171249e1a303/torch-2.10.0-3-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:ac5bdcbb074384c66fa160c15b1ead77839e3fe7ed117d667249afce0acabfac", size = 915518691, upload-time = "2026-03-11T14:15:43.147Z" }, + { url = "https://files.pythonhosted.org/packages/b3/7a/abada41517ce0011775f0f4eacc79659bc9bc6c361e6bfe6f7052a6b9363/torch-2.10.0-3-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:98c01b8bb5e3240426dcde1446eed6f40c778091c8544767ef1168fc663a05a6", size = 915622781, upload-time = "2026-03-11T14:17:11.354Z" }, + { url = "https://files.pythonhosted.org/packages/ab/c6/4dfe238342ffdcec5aef1c96c457548762d33c40b45a1ab7033bb26d2ff2/torch-2.10.0-3-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:80b1b5bfe38eb0e9f5ff09f206dcac0a87aadd084230d4a36eea5ec5232c115b", size = 915627275, upload-time = "2026-03-11T14:16:11.325Z" }, + { url = "https://files.pythonhosted.org/packages/d8/f0/72bf18847f58f877a6a8acf60614b14935e2f156d942483af1ffc081aea0/torch-2.10.0-3-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:46b3574d93a2a8134b3f5475cfb98e2eb46771794c57015f6ad1fb795ec25e49", size = 915523474, upload-time = "2026-03-11T14:17:44.422Z" }, + { url = "https://files.pythonhosted.org/packages/f4/39/590742415c3030551944edc2ddc273ea1fdfe8ffb2780992e824f1ebee98/torch-2.10.0-3-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:b1d5e2aba4eb7f8e87fbe04f86442887f9167a35f092afe4c237dfcaaef6e328", size = 915632474, upload-time = "2026-03-11T14:15:13.666Z" }, + { url = "https://files.pythonhosted.org/packages/b6/8e/34949484f764dde5b222b7fe3fede43e4a6f0da9d7f8c370bb617d629ee2/torch-2.10.0-3-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:0228d20b06701c05a8f978357f657817a4a63984b0c90745def81c18aedfa591", size = 915523882, upload-time = "2026-03-11T14:14:46.311Z" }, { url = "https://files.pythonhosted.org/packages/78/89/f5554b13ebd71e05c0b002f95148033e730d3f7067f67423026cc9c69410/torch-2.10.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:3282d9febd1e4e476630a099692b44fdc214ee9bf8ee5377732d9d9dfe5712e4", size = 145992610, upload-time = "2026-01-21T16:25:26.327Z" }, { url = "https://files.pythonhosted.org/packages/ae/30/a3a2120621bf9c17779b169fc17e3dc29b230c29d0f8222f499f5e159aa8/torch-2.10.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:a2f9edd8dbc99f62bc4dfb78af7bf89499bca3d753423ac1b4e06592e467b763", size = 915607863, upload-time = "2026-01-21T16:25:06.696Z" }, { url = "https://files.pythonhosted.org/packages/6f/3d/c87b33c5f260a2a8ad68da7147e105f05868c281c63d65ed85aa4da98c66/torch-2.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:29b7009dba4b7a1c960260fc8ac85022c784250af43af9fb0ebafc9883782ebd", size = 113723116, upload-time = "2026-01-21T16:25:21.916Z" }, @@ -2602,6 +2572,21 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/83/e4/d04a086285c20886c0daad0e026f250869201013d18f81d9ff5eada73a88/uvicorn-0.41.0-py3-none-any.whl", hash = "sha256:29e35b1d2c36a04b9e180d4007ede3bcb32a85fbdfd6c6aeb3f26839de088187", size = 68783, upload-time = "2026-02-16T23:07:22.357Z" }, ] +[[package]] +name = "virtualenv" +version = "21.2.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "distlib" }, + { name = "filelock" }, + { name = "platformdirs" }, + { name = "python-discovery" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0c/98/3a7e644e19cb26133488caff231be390579860bbbb3da35913c49a1d0a46/virtualenv-21.2.4.tar.gz", hash = "sha256:b294ef68192638004d72524ce7ef303e9d0cf5a44c95ce2e54a7500a6381cada", size = 5850742, upload-time = "2026-04-14T22:15:31.438Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/27/8d/edd0bd910ff803c308ee9a6b7778621af0d10252219ad9f19ef4d4982a61/virtualenv-21.2.4-py3-none-any.whl", hash = "sha256:29d21e941795206138d0f22f4e45ff7050e5da6c6472299fb7103318763861ac", size = 5831232, upload-time = "2026-04-14T22:15:29.342Z" }, +] + [[package]] name = "werkzeug" version = "3.1.6"