diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index a852d3c..7ed5608 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -19,7 +19,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v5 with: - python-version: '3.10' + python-version: '3.11' - name: Update uv lock run: uv lock diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml index 419830e..dbb5253 100644 --- a/.github/workflows/lint.yaml +++ b/.github/workflows/lint.yaml @@ -4,22 +4,18 @@ on: [push] jobs: lint: runs-on: ubuntu-latest - defaults: - run: - shell: bash -l {0} - steps: - uses: actions/checkout@v4 - - uses: actions/setup-python@v4 + - uses: actions/setup-python@v5 with: python-version: '3.11' - - name: Install packages - run: pip install -r requirements-dev.txt + - name: Install uv + uses: astral-sh/setup-uv@v5 - - name: Install pre-commit hooks - run: pre-commit install --install-hooks + - name: Install dependencies + run: uv sync --group dev - name: Run pre-commit - run: pre-commit run --all-files + run: uv run pre-commit run --all-files diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index fcaad86..d6856bb 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -17,7 +17,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v5 with: - python-version: '3.10' + python-version: '3.11' - name: Update uv lock run: uv lock @@ -55,7 +55,7 @@ jobs: needs: [build] environment: name: pypi - url: https://pypi.org/p/gemini-ocr + url: https://pypi.org/p/groundmark permissions: id-token: write # Required for trusted publishing steps: diff --git a/.gitignore b/.gitignore index c39406a..b7e4046 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,15 @@ wheels/ # Virtual environments .venv +# Tool caches +.mypy_cache/ +.pytest_cache/ +.ruff_cache/ + +# Specs (local working docs) +specs/ + # Output and Data output.md *.pdf +!tests/data/*.pdf diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 62e0e5a..ebb2dcc 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -22,11 +22,6 @@ repos: - id: markdownlint exclude: 'tests/fixtures' - - repo: https://github.com/populationgenomics/pre-commits - rev: "e37928f761f17d54aca5cedf93848b40ec7cff26" - hooks: - - id: cpg-id-checker - - repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. rev: v0.14.1 @@ -50,4 +45,4 @@ repos: --non-interactive, --config-file=./pyproject.toml ] - additional_dependencies: [types-PyYAML==6.0.4, types-toml] + additional_dependencies: [] diff --git a/.readthedocs.yaml b/.readthedocs.yaml deleted file mode 100644 index cd2208e..0000000 --- a/.readthedocs.yaml +++ /dev/null @@ -1,17 +0,0 @@ -version: 2 - -build: - os: ubuntu-lts-latest - tools: - python: "3.11" - -sphinx: - configuration: docs/source/conf.py - -formats: all - -python: - install: - - requirements: docs/requirements.txt - - method: pip - path: . diff --git a/LICENSE b/LICENSE index 5afde33..e7812f8 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2025 Tobias Sargeant +Copyright (c) 2025 Centre for Population Genomics Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 6bba287..500013f 100644 --- a/README.md +++ b/README.md @@ -1,93 +1,86 @@ -# Gemini OCR +# groundmark -gemini-ocr +groundmark -## Traceable Generative Markdown for PDFs +## Grounded Markdown for PDFs -Gemini OCR is a library designed to convert PDF documents into clean, semantic Markdown while maintaining precise traceability back to the source coordinates. It bridges the gap between the readability of Generative AI (Gemini, Document AI Chunking) and the grounded accuracy of traditional OCR (Google Document AI). +**groundmark is a thin, batteries-included wrapper around [anchorite](https://github.com/populationgenomics/anchorite).** It provides concrete implementations of anchorite's provider protocols — [Pydantic AI](https://ai.pydantic.dev/) for LLM-based Markdown generation and [pdfplumber](https://github.com/jsvine/pdfplumber) for bounding box extraction — so you can go from PDF bytes to annotated Markdown in a single call. All the heavy lifting (Smith-Waterman alignment, annotation, stripping, quote resolution) lives in anchorite. -## Key Features - -- **Generative Markdown**: Uses Google's Gemini Pro or Document AI Layout models to generate human-readable Markdown with proper structure (headers, tables, lists). -- **Precision Traceability**: Aligns the generated Markdown text back to the original PDF coordinates using detailed OCR data from Google Document AI. -- **Reverse-Alignment Algorithm**: Implements a robust "reverse-alignment" strategy that starts with the readable text and finds the corresponding bounding boxes, ensuring the Markdown is the ground truth for content. -- **Confidence Metrics**: (New) Includes coverage metrics to quantify how much of the Markdown content is successfully backed by OCR data. -- **Pagination Support**: Automatically handles PDF page splitting and merging logic. +Give it a PDF and a model string, get back Markdown with embedded bounding box coordinates that trace every text span back to its location in the source PDF. ## Architecture -The library processes documents in two parallel streams: - -1. **Semantic Stream**: The PDF is sent to a Generative AI model (e.g., Gemini 2.5 Flash) to produce a clean Markdown representation. -2. **Positional Stream**: The PDF is sent to Google Document AI to extract raw bounding boxes and text segments. - -These two streams are then merged using a custom alignment engine (`seq_smith` + `bbox_alignment.py`) which: +The library processes documents in two streams that are then merged: -1. Normalizes both text sources. -2. Identifies "anchor" comparisons for reliable alignment. -3. Computes a global alignment using the anchors to constrain the search space. -4. Identifies significant gaps or mismatches. -5. Recursively re-aligns mismatched regions until a high-quality alignment is achieved. +1. **Semantic Stream**: The PDF is sent to an LLM (via Pydantic AI) to produce clean Markdown with `` markers between pages. +2. **Positional Stream**: The PDF is parsed locally by pdfplumber to extract line-level text segments and their bounding boxes. +3. **Alignment**: Smith-Waterman alignment (via anchorite) maps each parsed line to its position in the Markdown, constrained by page boundaries. +4. **Annotation**: Bounding box coordinates are injected as HTML span attributes: -**Key Features:** - -- **Robust to Cleanliness Issues:** Handles extra headers/footers, watermarks, and noisy OCR artifacts. -- **Scale-Invariant:** Recursion ensures even small missed sections in large documents are recovered. + ```html + The patient presented with + ``` ## Quick Start ```python import asyncio -from pathlib import Path -from gemini_ocr import gemini_ocr, settings +import groundmark as gm async def main(): - # Configure settings - ocr_settings = settings.Settings( - project="my-gcp-project", - location="us", - gcp_project_id="my-gcp-project", - layout_processor_id="projects/.../processors/...", - ocr_processor_id="projects/.../processors/...", - mode=settings.OcrMode.GEMINI, - ) - - file_path = Path("path/to/document.pdf") - - # Process the document - result = await gemini_ocr.process_document(ocr_settings, file_path) - - # Access results + pdf_bytes = open("document.pdf", "rb").read() + + config = gm.Config(model="bedrock:au.anthropic.claude-sonnet-4-6") + + # PDF -> annotated Markdown (one call) + result = await gm.process(pdf_bytes, config) print(f"Coverage: {result.coverage_percent:.2%}") + print(result.annotated_markdown[:500]) + + # Strip for LLM consumption + stripped = gm.strip(result.annotated_markdown) + # stripped.plain_text: clean Markdown with spans removed + # stripped.validation_map: list of (start, end, Anchor) ranges - # Get annotated HTML-compatible Markdown - annotated_md = result.annotate() - print(annotated_md[:500]) # View first 500 chars + # Resolve verbatim quotes to PDF coordinates + resolved = gm.resolve(result.annotated_markdown, ["the patient presented with"]) + # -> {"the patient presented with": [(page, BBox), ...]} if __name__ == "__main__": asyncio.run(main()) ``` +## Debug Visualizer + +The included visualizer overlays extracted bounding boxes onto the source PDF, useful for diagnosing alignment issues. Blue highlights show raw extracted boxes from pdfplumber; red highlights show aligned boxes from the annotated Markdown. + +```bash +python -m groundmark.visualize input.pdf output.pdf --model "bedrock:au.anthropic.claude-sonnet-4-6" + +# Or with cached Markdown: +python -m groundmark.visualize input.pdf output.pdf --markdown cached.md +``` + +![Visualizer output showing blue (raw) and red (aligned) bounding box overlays](visualize_example.jpg) + +*Screenshot from Santoro et al., "Health outcomes and drug utilisation in children with Noonan syndrome: a European cohort study," Orphanet J Rare Dis 20:76 (2025). [doi:10.1186/s13023-025-03594-7](https://doi.org/10.1186/s13023-025-03594-7). CC-BY 4.0.* + ## Configuration -The `gemini_ocr.settings.Settings` class controls the behavior: - -| Parameter | Type | Description | -| :------------------------------- | :-------- | :--------------------------------------------------------------- | -| `project` | `str` | GCP Project Name | -| `location` | `str` | GCP Location (e.g., `us`, `eu`) | -| `gcp_project_id` | `str` | GCP Project ID (might be same as `project`) | -| `layout_processor_id` | `str` | Document AI Processor ID for Layout (if using `DOCUMENTAI` mode) | -| `ocr_processor_id` | `str` | Document AI Processor ID for OCR (required for bounding boxes) | -| `mode` | `OcrMode` | `GEMINI` (default), `DOCUMENTAI`, or `DOCLING` | -| `gemini_model_name` | `str` | Gemini model to use (default: `gemini-2.5-flash`) | -| `alignment_uniqueness_threshold` | `float` | Min score ratio for unique match (default: `0.5`) | -| `alignment_min_overlap` | `float` | Min overlap fraction for valid match (default: `0.9`) | -| `include_bboxes` | `bool` | Whether to perform alignment (default: `True`) | -| `markdown_page_batch_size` | `int` | Pages per batch for Markdown generation (default: `10`) | -| `ocr_page_batch_size` | `int` | Pages per batch for OCR (default: `10`) | -| `num_jobs` | `int` | Max concurrent jobs (default: `10`) | -| `cache_dir` | `str` | Directory to store API response cache (default: `.docai_cache`) | +### Timeouts + +The LLM call for PDF-to-Markdown conversion can take several minutes for large documents, especially with Opus on Bedrock. Timeout defaults by provider: + +| Provider | Default | Environment Variable | +|----------|---------|---------------------| +| Bedrock (boto3) | 300s | `AWS_READ_TIMEOUT` | +| Anthropic (httpx) | 600s | — (use `ModelSettings(timeout=...)`) | + +For Bedrock with Opus, 300s may not be enough. Set a higher timeout: + +```bash +export AWS_READ_TIMEOUT=600 +``` ## License diff --git a/docs/Makefile b/docs/Makefile deleted file mode 100644 index d0c3cbf..0000000 --- a/docs/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# Minimal makefile for Sphinx documentation -# - -# You can set these variables from the command line, and also -# from the environment for the first two. -SPHINXOPTS ?= -SPHINXBUILD ?= sphinx-build -SOURCEDIR = source -BUILDDIR = build - -# Put it first so that "make" without argument is like "make help". -help: - @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) - -.PHONY: help Makefile - -# Catch-all target: route all unknown targets to Sphinx using the new -# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). -%: Makefile - @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/make.bat b/docs/make.bat deleted file mode 100644 index 747ffb7..0000000 --- a/docs/make.bat +++ /dev/null @@ -1,35 +0,0 @@ -@ECHO OFF - -pushd %~dp0 - -REM Command file for Sphinx documentation - -if "%SPHINXBUILD%" == "" ( - set SPHINXBUILD=sphinx-build -) -set SOURCEDIR=source -set BUILDDIR=build - -%SPHINXBUILD% >NUL 2>NUL -if errorlevel 9009 ( - echo. - echo.The 'sphinx-build' command was not found. Make sure you have Sphinx - echo.installed, then set the SPHINXBUILD environment variable to point - echo.to the full path of the 'sphinx-build' executable. Alternatively you - echo.may add the Sphinx directory to PATH. - echo. - echo.If you don't have Sphinx installed, grab it from - echo.https://www.sphinx-doc.org/ - exit /b 1 -) - -if "%1" == "" goto help - -%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% -goto end - -:help -%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% - -:end -popd diff --git a/docs/requirements.txt b/docs/requirements.txt deleted file mode 100644 index 6f3ca6e..0000000 --- a/docs/requirements.txt +++ /dev/null @@ -1,4 +0,0 @@ -sphinx -sphinx-rtd-theme -myst-parser -numpy diff --git a/docs/source/_static/gemini-ocr.svg b/docs/source/_static/gemini-ocr.svg deleted file mode 100644 index 659425a..0000000 --- a/docs/source/_static/gemini-ocr.svg +++ /dev/null @@ -1,1525 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - GEMINI-OCR - diff --git a/docs/source/api.rst b/docs/source/api.rst deleted file mode 100644 index f8a141b..0000000 --- a/docs/source/api.rst +++ /dev/null @@ -1,27 +0,0 @@ -API Reference -============= - -.. automodule:: gemini_ocr - :members: - :undoc-members: - :show-inheritance: - -.. automodule:: gemini_ocr.gemini_ocr - :members: - :undoc-members: - :show-inheritance: - -.. automodule:: gemini_ocr.settings - :members: - :undoc-members: - :show-inheritance: - -.. automodule:: gemini_ocr.document - :members: - :undoc-members: - :show-inheritance: - -.. automodule:: gemini_ocr.bbox_alignment - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/conf.py b/docs/source/conf.py deleted file mode 100644 index 81fc0de..0000000 --- a/docs/source/conf.py +++ /dev/null @@ -1,36 +0,0 @@ -# Configuration file for the Sphinx documentation builder. -# -# For the full list of built-in configuration values, see the documentation: -# https://www.sphinx-doc.org/en/master/usage/configuration.html - -# -- Project information ----------------------------------------------------- -# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information - -import os -import sys - -sys.path.insert(0, os.path.abspath("../../src")) # Adjust path to include the project root - -project = "gemini-ocr" -copyright = "2025, Tobias Sargeant" -author = "Tobias Sargeant" - -# -- General configuration --------------------------------------------------- -# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration - -extensions = [ - "sphinx.ext.autodoc", - "sphinx.ext.napoleon", - "sphinx_rtd_theme", - "myst_parser", -] - -templates_path = ["_templates"] -exclude_patterns: list[str] = [] - - -# -- Options for HTML output ------------------------------------------------- -# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output - -html_theme = "sphinx_rtd_theme" -html_static_path = ["_static"] diff --git a/docs/source/index.rst b/docs/source/index.rst deleted file mode 100644 index f81a461..0000000 --- a/docs/source/index.rst +++ /dev/null @@ -1,16 +0,0 @@ -gemini-ocr documentation -======================== - -.. image:: _static/gemini-ocr.svg - :width: 200px - :alt: gemini-ocr hex sticker - :align: center - -Welcome to the documentation for `gemini-ocr`. - -.. toctree:: - :maxdepth: 2 - :caption: Contents: - - readme - api diff --git a/docs/source/readme.md b/docs/source/readme.md deleted file mode 100644 index e4b6d30..0000000 --- a/docs/source/readme.md +++ /dev/null @@ -1,3 +0,0 @@ - -.. include:: ../../README.md - :parser: myst_parser.sphinx_ diff --git a/groundmark.webp b/groundmark.webp new file mode 100644 index 0000000..0d7110a Binary files /dev/null and b/groundmark.webp differ diff --git a/pyproject.toml b/pyproject.toml index 8cd0599..f628eba 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,12 +3,12 @@ requires = ["hatchling"] build-backend = "hatchling.build" [project] -name = "gemini-ocr" -version = "0.4.0" +name = "groundmark" +version = "0.1.0" authors = [ { name = "Tobias Sargeant", email = "tobias.sargeant@gmail.com" }, ] -description = "Hybrid OCR with gemini and DocumentAI" +description = "PDF to grounded Markdown with bounding box annotations" readme = "README.md" license = { text = "MIT" } requires-python = ">=3.11" @@ -21,25 +21,24 @@ classifiers = [ "Operating System :: OS Independent", ] dependencies = [ - "google-genai", - "google-cloud-documentai", - "pymupdf", - "seq-smith>=0.5.1", - "python-dotenv>=1.2.1", - "fsspec", - "gcsfs", + "anchorite>=0.1.1", + "pydantic-ai-slim[anthropic,bedrock,google,openai]>=1.67.0", + "pdfplumber>=0.11.9", + "pypdf>=6.8.0", ] [dependency-groups] dev = [ + "pre-commit>=4.5.1", "pytest", "pytest-asyncio", "ruff>=0.14.6", + "typer>=0.24.1", ] [project.urls] -"Homepage" = "https://github.com/folded/gemini-ocr" -"Bug Tracker" = "https://github.com/folded/gemini-ocr/issues" +"Homepage" = "https://github.com/populationgenomics/groundmark" +"Bug Tracker" = "https://github.com/populationgenomics/groundmark/issues" [tool.ruff] line-length = 120 @@ -49,30 +48,28 @@ indent-width = 4 [tool.ruff.lint] select = ["A", "B", "C", "E", "F", "G", "I", "N", "Q", "S", "W", "ANN", "ARG", "BLE", "COM", "DJ", "DTZ", "ERA", "EXE", "ICN", "ISC", "NPY", "PD", "PGH", "PIE", "PL", "PT", "PYI", "RET", "RSE", "RUF", "SIM", "SLF", "TCH", "TID", "UP", "YTT"] ignore = [ - "ANN101", # missing-type-self + "C901", # function complexity — too aggressive for straightforward extraction loops + "COM812", # trailing comma — conflicts with ruff formatter "PD011", # pandas-use-of-dot-values (false positive) + "PLR0912", # too many branches — same as C901 + "PLR0913", # too many arguments — sometimes unavoidable ] fixable = ["A", "B", "C", "D", "E", "F", "G", "I", "N", "Q", "S", "T", "W", "ANN", "ARG", "BLE", "COM", "DJ", "DTZ", "ERA", "EXE", "FBT", "ICN", "ISC", "NPY", "PD", "PGH", "PIE", "PL", "PT", "PYI", "RET", "RSE", "RUF", "SIM", "SLF", "TCH", "TID", "UP", "YTT"] [tool.ruff.lint.isort] -known-first-party = ["gemini-ocr"] +known-first-party = ["groundmark"] [tool.ruff.lint.per-file-ignores] +"src/groundmark/markdown.py" = [ + "RUF001", # ambiguous unicode — intentional in LLM prompt about preserving unicode symbols +] "tests/*" = [ + "ARG001", # unused function arguments (mock.patch positional injection). "S101", # asserts. "S102", # exec(). "PLR2004", # magic value comparisons. "SLF001" # private method access. ] -"docs/*" = [ - "A001" -] -"app.py" = [ - "ALL" # Ignore all checks for app.py as it contains embedded HTML/JS/CSS in a string. -] [tool.mypy] python_version = "3.11" - -[tool.cibuildwheel] -build = "cp311-* cp312-* cp313-*" diff --git a/pyrefly.toml b/pyrefly.toml deleted file mode 100644 index e69de29..0000000 diff --git a/requirements-dev.txt b/requirements-dev.txt deleted file mode 100644 index b680b86..0000000 --- a/requirements-dev.txt +++ /dev/null @@ -1,5 +0,0 @@ -bump2version -black -pre-commit -pylint -cibuildwheel diff --git a/run_ocr.py b/run_ocr.py deleted file mode 100644 index 3934fd3..0000000 --- a/run_ocr.py +++ /dev/null @@ -1,156 +0,0 @@ -import argparse -import asyncio -import logging -import os -import pathlib -import sys -import traceback - -import dotenv -import google.auth -from google import genai - -from gemini_ocr import gemini_ocr, settings - - -def _list_models(project: str | None, location: str, quota_project: str | None) -> None: - if not project: - print("Error: --project or GOOGLE_CLOUD_PROJECT env var required.") - sys.exit(1) - - credentials, _ = google.auth.default() - if quota_project: - credentials = credentials.with_quota_project(quota_project) - elif project: - credentials = credentials.with_quota_project(project) - - client = genai.Client(vertexai=True, project=project, location=location, credentials=credentials) - print("Available Gemini Models:") - for model in client.models.list(): - if model.name and "gemini" in model.name: - print(f" - {model.name}") - sys.exit(0) - - -async def main() -> None: - logging.basicConfig(level=logging.DEBUG) - dotenv.load_dotenv() - parser = argparse.ArgumentParser(description="Run Gemini OCR on a PDF.") - parser.add_argument( - "input_pdf", - type=pathlib.Path, - nargs="?", - default=pathlib.Path("main.pdf"), - help="Input PDF file.", - ) - parser.add_argument( - "--project", - default=os.environ.get("GOOGLE_CLOUD_PROJECT"), - help="Vertex AI Project ID", - ) - parser.add_argument( - "--quota-project", - default=os.environ.get("GEMINI_OCR_QUOTA_PROJECT_ID"), - help="GCP Quota Project ID (for billing)", - ) - parser.add_argument( - "--location", - default="us-central1", - help="GCP Location", - ) - parser.add_argument( - "--processor-id", - default=os.environ.get("DOCUMENTAI_LAYOUT_PARSER_PROCESSOR_ID"), - help="Document AI Layout Parser Processor ID", - ) - parser.add_argument( - "--ocr-processor-id", - default=os.environ.get("DOCUMENTAI_OCR_PROCESSOR_ID"), - help="Document AI OCR Processor ID (for secondary bbox pass)", - ) - parser.add_argument( - "--model", - default=os.environ.get("GEMINI_OCR_GEMINI_MODEL_NAME"), - help="Gemini Model Name (e.g. gemini-2.0-flash-exp)", - ) - - parser.add_argument( - "--output", - type=pathlib.Path, - default=pathlib.Path("output.md"), - help="Output markdown file", - ) - parser.add_argument( - "--cache-dir", - type=pathlib.Path, - help="Directory to cache OCR results", - ) - parser.add_argument( - "--mode", - choices=["gemini", "documentai"], - default="gemini", - help="OCR generation mode", - ) - - parser.add_argument( - "--list-models", - action="store_true", - help="List available Gemini models and exit", - ) - - parser.add_argument( - "--no-bbox", - action="store_true", - help="Disable bounding box output in markdown", - ) - - args = parser.parse_args() - - if args.list_models: - _list_models(args.project, args.location, args.quota_project) - - if not args.input_pdf.exists(): - print(f"Error: Input file {args.input_pdf} not found.") - sys.exit(1) - - if not args.project: - print("Error: --project or GOOGLE_CLOUD_PROJECT env var required.") - sys.exit(1) - - if not args.processor_id: - print("Error: --processor-id or DOCUMENTAI_LAYOUT_PARSER_PROCESSOR_ID env var required.") - sys.exit(1) - - ocr_settings = settings.Settings( - project_id=args.project, - location=args.location, - quota_project_id=args.quota_project, - layout_processor_id=args.processor_id, - ocr_processor_id=args.ocr_processor_id, - gemini_model_name=args.model, - mode=args.mode, - include_bboxes=not args.no_bbox, - cache_dir=args.cache_dir, - ) - - print(f"Processing {args.input_pdf}...") - print(f"Settings: {ocr_settings}") - - try: - result = await gemini_ocr.process_document(args.input_pdf, settings=ocr_settings) - - output_content = result.annotate() if ocr_settings.include_bboxes else result.markdown_content - - output_path = args.output - output_path.write_text(output_content) - - print(f"Done! Output saved to {output_path}") - - except Exception as e: # noqa: BLE001 - print(f"Error processing document: {e}") - traceback.print_exc() - sys.exit(1) - - -if __name__ == "__main__": - asyncio.run(main()) diff --git a/scripts/capture_docai_fixtures.py b/scripts/capture_docai_fixtures.py deleted file mode 100644 index 187e8be..0000000 --- a/scripts/capture_docai_fixtures.py +++ /dev/null @@ -1,68 +0,0 @@ -import asyncio -import json -import os -from pathlib import Path - -import dotenv -from google.cloud import documentai - -from gemini_ocr import docai, document, settings - - -async def capture() -> None: - # Load .env - dotenv.load_dotenv() - - mapping = { - "GOOGLE_OCR_PROJECT": "GEMINI_OCR_PROJECT_ID", - "GOOGLE_OCR_LAYOUT_PARSER_PROCESSOR_ID": "GEMINI_OCR_LAYOUT_PROCESSOR_ID", - "GOOGLE_OCR_OCR_PROCESSOR_ID": "GEMINI_OCR_OCR_PROCESSOR_ID", - "GOOGLE_OCR_LOCATION": "GEMINI_OCR_LOCATION", - } - for src, dst in mapping.items(): - if os.getenv(src) and not os.getenv(dst): - os.environ[dst] = os.getenv(src) - - pdf_path = Path("tests/data/hubble-1929.pdf") - - ocr_settings = settings.Settings.from_env() - ocr_settings.mode = settings.OcrMode.DOCUMENTAI - - print(f"Processing with settings: {ocr_settings}") - - chunks = list(document.chunks(pdf_path, page_count=ocr_settings.markdown_page_batch_size)) - - documents = [] - for i, chunk in enumerate(chunks): - print(f"Calling DocAI Layout for chunk {i}...") - - # docai.process returns documentai.Document - # We need the processor ID. - if ocr_settings.layout_processor_id is None: - raise ValueError("Layout processor ID required") - - process_options = documentai.ProcessOptions( - layout_config=documentai.ProcessOptions.LayoutConfig( - return_bounding_boxes=True, - ), - ) - - doc = await docai.process(ocr_settings, process_options, ocr_settings.layout_processor_id, chunk) - - # Serialize to JSON using protojson (built-in to the class usually or via library) - # documentai.Document is a proto-plus wrapper. verify .to_json() or similar. - # Actually Google Proto objects usually have ._pb methods or we can use type(doc).to_json(doc) - - # Let's try standard serialization - json_str = type(doc).to_json(doc) - documents.append(json_str) - - # Save list of JSON strings - with open("tests/fixtures/hubble_docai_layout_responses.json", "w") as f: - json.dump(documents, f) - - print("Saved DocAI layout responses.") - - -if __name__ == "__main__": - asyncio.run(capture()) diff --git a/scripts/capture_fixtures.py b/scripts/capture_fixtures.py deleted file mode 100644 index d67e49f..0000000 --- a/scripts/capture_fixtures.py +++ /dev/null @@ -1,81 +0,0 @@ -import asyncio -import json -import os -import pickle - -# Add src to path so we can import gemini_ocr modules -import sys -from pathlib import Path - -import dotenv - -sys.path.append(str(Path.cwd() / "src")) - -import typing - -from gemini_ocr import docai_ocr, document, gemini, settings - -# For serializing BBox - - -async def capture() -> None: - # Load .env - dotenv.load_dotenv() - - # ... (skipping some unchanged lines in between) ... - - # Re-running DocAI OCR (bboxes) is safer. - # Note: process_document uses batched gather. - # We'll reproduce logic from extract_raw_data roughly but per chunk. - - # Map GOOGLE_OCR_ vars to GEMINI_OCR_ vars if needed - mapping = { - "GOOGLE_OCR_PROJECT": "GEMINI_OCR_PROJECT_ID", - "GOOGLE_OCR_LAYOUT_PARSER_PROCESSOR_ID": "GEMINI_OCR_LAYOUT_PROCESSOR_ID", - "GOOGLE_OCR_OCR_PROCESSOR_ID": "GEMINI_OCR_OCR_PROCESSOR_ID", - "GOOGLE_OCR_LOCATION": "GEMINI_OCR_LOCATION", - } - for src, dst in mapping.items(): - val = os.getenv(src) - if val and not os.getenv(dst): - os.environ[dst] = val - - pdf_path = Path("tests/data/hubble-1929.pdf") - - ocr_settings = settings.Settings.from_env() - # Ensure Gemini mode - ocr_settings.mode = settings.OcrMode.GEMINI - - print(f"Processing {pdf_path}...") - print(f"Settings: {ocr_settings}") - - chunks = list(document.chunks(pdf_path, page_count=ocr_settings.markdown_page_batch_size)) - - # 1. Capture Gemini Markdown Responses - gemini_responses = [] - for i, chunk in enumerate(chunks): - print(f"Generating Gemini markdown for chunk {i}...") - text = await gemini.generate_markdown(ocr_settings, chunk) - gemini_responses.append(text) - - with open("tests/fixtures/hubble_gemini_responses.json", "w") as f: - json.dump(gemini_responses, f) - print("Saved Gemini responses.") - - print("Generating DocAI BBoxes...") - - all_chunks_bboxes: list[typing.Any] = [] - - for i, chunk in enumerate(chunks): - print(f"Generating DocAI bboxes for chunk {i}...") - bboxes = await docai_ocr.generate_bounding_boxes(ocr_settings, chunk) - all_chunks_bboxes.append(bboxes) - - with open("tests/fixtures/hubble_docai_bboxes.pkl", "wb") as f: - pickle.dump(all_chunks_bboxes, f) - - print("Saved DocAI bboxes.") - - -if __name__ == "__main__": - asyncio.run(capture()) diff --git a/src/gemini_ocr/__init__.py b/src/gemini_ocr/__init__.py deleted file mode 100644 index 15c866b..0000000 --- a/src/gemini_ocr/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -from gemini_ocr.gemini_ocr import process_document -from gemini_ocr.settings import Settings - -__all__ = ["Settings", "process_document"] diff --git a/src/gemini_ocr/bbox_alignment.py b/src/gemini_ocr/bbox_alignment.py deleted file mode 100644 index d309ee9..0000000 --- a/src/gemini_ocr/bbox_alignment.py +++ /dev/null @@ -1,396 +0,0 @@ -import collections -import dataclasses -import logging -import re -import string -from collections.abc import Iterator, Sequence - -import seq_smith - -from gemini_ocr import document, range_ops - -_ALIGN_ALPHABET = string.ascii_lowercase + string.digits + " " -_NON_WORD_CHARS = seq_smith.encode(" ", _ALIGN_ALPHABET) -_GAP_OPEN, _GAP_EXTEND = -2, -2 -_SCORE_MATRIX = seq_smith.make_score_matrix(_ALIGN_ALPHABET, +1, -1) -_UNIQUENESS_THRESHOLD = 0.5 -_MIN_OVERLAP = 0.9 - - -@dataclasses.dataclass(frozen=True) -class _NormalizedSpan: - """A span of text with its normalized form and mapping.""" - - source: str - """The original source text.""" - normalized: bytes - """The normalized byte sequence used for alignment.""" - normalized_to_source: tuple[int, ...] - """Mapping from normalized indices to source indices.""" - - def __len__(self) -> int: - return len(self.normalized) - - def _trim(self) -> None: - normalized = self.normalized.lstrip(_NON_WORD_CHARS) - left_trimmed = len(self.normalized) - len(normalized) - normalized = normalized.rstrip(_NON_WORD_CHARS) - right_trimmed = len(self.normalized) - len(normalized) - left_trimmed - if right_trimmed == 0: - normalized_to_source = self.normalized_to_source[left_trimmed:] - else: - normalized_to_source = self.normalized_to_source[left_trimmed:-right_trimmed] - object.__setattr__(self, "normalized", normalized) - object.__setattr__(self, "normalized_to_source", normalized_to_source) - - def __post_init__(self) -> None: - self._trim() - - -@dataclasses.dataclass(frozen=True) -class _BBoxFragment(_NormalizedSpan): - """A normalized span derived from a bounding box.""" - - bbox: document.BoundingBox - """The original bounding box object.""" - - -@dataclasses.dataclass(frozen=True) -class _DocumentFragment(_NormalizedSpan): - """A normalized span derived from the markdown document.""" - - page_range: tuple[int, int] - """Range of pages (start, end) this fragment might span.""" - - -def _normalize(source: str, span: tuple[int, int] = (-1, -1)) -> tuple[bytes, tuple[int, ...]]: - if span == (-1, -1): - span = (0, len(source)) - - def _normalize_char(c: str) -> str: - if c.lower() in string.ascii_letters + string.digits: - return c.lower() - return " " - - s, e = span - normalized: list[str] = [] - normalized_to_source: list[int] = [] - - for i in range(s, e): - n = _normalize_char(source[i]) - if n == " " and normalized and normalized[-1] == " ": - continue - normalized.append(n) - normalized_to_source.append(i) - - normalized_to_source.append(e) - - span_bytes = seq_smith.encode("".join(normalized), _ALIGN_ALPHABET) - return span_bytes, tuple(normalized_to_source) - - -def _make_bbox_fragment(bbox: document.BoundingBox) -> _BBoxFragment: - span_bytes, normalized_to_source = _normalize(bbox.text) - return _BBoxFragment(bbox.text, span_bytes, normalized_to_source, bbox) - - -def _make_document_fragment( - source: str, - page_range: tuple[int, int], - span: tuple[int, int] = (-1, -1), -) -> _DocumentFragment: - span_bytes, normalized_to_source = _normalize(source, span) - return _DocumentFragment(source, span_bytes, normalized_to_source, page_range) - - -def _a_end(f: seq_smith.AlignmentFragment) -> int: - return f.sa_start if f.fragment_type == seq_smith.FragmentType.AGap else f.sa_start + f.len - - -def _b_end(f: seq_smith.AlignmentFragment) -> int: - return f.sb_start if f.fragment_type == seq_smith.FragmentType.BGap else f.sb_start + f.len - - -def _aligned_range(alignment: seq_smith.Alignment) -> tuple[int, int]: - return (alignment.fragments[0].sa_start, _a_end(alignment.fragments[-1])) - - -def _make_document_fragments(markdown_content: str, page_range: tuple[int, int]) -> Iterator[_DocumentFragment]: - start = 0 - for m in re.finditer(r"", markdown_content): - span = _make_document_fragment(markdown_content, page_range, (start, m.start())) - if len(span): - yield span - start = m.end() - if start < len(markdown_content): - span = _make_document_fragment(markdown_content, page_range, (start, len(markdown_content))) - if len(span): - yield span - - -def _slice_document_fragment( - span: _DocumentFragment, - start: int, - end: int, - page_range: tuple[int, int], -) -> _DocumentFragment: - if start >= end: - return _DocumentFragment(span.source, b"", (), page_range) - - n_sub = span.normalized[start:end] - # normalized_to_source has length len(normalized) + 1. - # slice it from start to end + 1 to include the end boundary - nts_sub = span.normalized_to_source[start : end + 1] - - return _DocumentFragment(span.source, n_sub, nts_sub, page_range) - - -def _compute_candidate_alignments( - document_fragments: list[_DocumentFragment], - bbox_spans: list[_BBoxFragment], - with_ungapped: bool, -) -> dict[_BBoxFragment, list[tuple[int, seq_smith.Alignment]]]: - bbox_span_hsps: dict[_BBoxFragment, list[tuple[int, seq_smith.Alignment]]] = collections.defaultdict(list) - - for i, fragment in enumerate(document_fragments): - spans = [b for b in bbox_spans if range_ops.in_range(b.bbox.page, fragment.page_range)] - if not spans: - continue - if with_ungapped: - alignments = seq_smith.top_k_ungapped_local_align_many( - fragment.normalized, - [s.normalized for s in spans], - _SCORE_MATRIX, - k=2, - filter_overlap_a=False, - filter_overlap_b=False, - ) - for s, a in zip(spans, alignments, strict=True): - bbox_span_hsps[s].extend((i, hsp) for hsp in a) - else: - alignments = seq_smith.local_global_align_many( - fragment.normalized, - [s.normalized for s in spans], - _SCORE_MATRIX, - _GAP_OPEN, - _GAP_EXTEND, - ) - for s, a in zip(spans, alignments, strict=True): - bbox_span_hsps[s].append((i, a)) - return bbox_span_hsps - - -def _assign_high_confidence_spans( - document_fragments: list[_DocumentFragment], - bbox_spans: Sequence[_BBoxFragment], - uniqueness_threshold: float = _UNIQUENESS_THRESHOLD, - min_overlap: float = _MIN_OVERLAP, - with_ungapped: bool = True, -) -> Iterator[tuple[_DocumentFragment, list[_BBoxFragment]]]: - bbox_spans_list = list(bbox_spans) - bbox_span_hsps = _compute_candidate_alignments(document_fragments, bbox_spans_list, with_ungapped) - - assignments = collections.defaultdict(list) - for bbox_span in bbox_spans_list: - bbox_hsps = sorted( - bbox_span_hsps[bbox_span], - key=lambda x: x[1].score, - reverse=True, - ) - - if not bbox_hsps: - continue - - span_idx, hsp = bbox_hsps[0] - if len(bbox_hsps) > 1 and bbox_hsps[1][1].score >= hsp.score * uniqueness_threshold: - continue - if hsp.stats.len >= min_overlap * len(bbox_span): - assignments[span_idx].append((bbox_span, hsp)) - - for i, assigned_bbox_spans in sorted(assignments.items()): - assigned_bbox_spans.sort(key=lambda x: x[1].score, reverse=True) - yield document_fragments[i], [x[0] for x in assigned_bbox_spans] - - -def _page_range_for_range( - page_range: tuple[int, int], - span_range: tuple[int, int], - page_ranges: dict[int, tuple[int, int]], -) -> tuple[int, int]: - """Return the page range for the span range.""" - page_start, page_end = page_range - - for page, r in page_ranges.items(): - if r[0] <= span_range[0]: - page_start = max(page_start, page) - if r[1] >= span_range[1]: - page_end = min(page_end, page + 1) - return page_start, page_end - - -def _is_consistent_with_page_ranges( - r: tuple[int, int], - page: int, - page_ranges: dict[int, Sequence[tuple[int, int]]], -) -> bool: - """Return true if range `r` inferred from a span on page `page` is consistent with `page_ranges`.""" - pre_ranges = [pr for p, pr in page_ranges.items() if p < page] - post_ranges = [pr for p, pr in page_ranges.items() if p > page] - lower_bound = max(pr[-1][1] for pr in pre_ranges) if pre_ranges else r[0] - upper_bound = min(pr[0][0] for pr in post_ranges) if post_ranges else r[1] - return range_ops.contained(r, (lower_bound, upper_bound)) - - -def _assign_spans( - document_fragment: _DocumentFragment, - candidates: list[_BBoxFragment], - match_fraction: float = 0.9, - new_coverage_fraction: float = 0.9, -) -> tuple[list[tuple[_BBoxFragment, tuple[int, int]]], list[_DocumentFragment]]: - candidates = [c for c in candidates if range_ops.in_range(c.bbox.page, document_fragment.page_range)] - - alignments = seq_smith.local_global_align_many( - document_fragment.normalized, - [c.normalized for c in candidates], - _SCORE_MATRIX, - _GAP_OPEN, - _GAP_EXTEND, - ) - - candidates_alignments = sorted(zip(candidates, alignments, strict=True), key=lambda x: x[1].score, reverse=True) - candidates = [x[0] for x in candidates_alignments] - alignments = [x[1] for x in candidates_alignments] - - assignments = [] - covered: list[tuple[int, int]] = [] - - page_ranges: dict[int, Sequence[tuple[int, int]]] = {} - - for candidate, alignment in zip(candidates, alignments, strict=True): - if alignment.stats.num_exact_matches < len(candidate) * match_fraction: - continue - r = _aligned_range(alignment) - if not _is_consistent_with_page_ranges(r, candidate.bbox.page, page_ranges): - continue - r_uncovered = range_ops.subtract_ranges([r], covered) - uncovered_chars = sum(r[1] - r[0] for r in r_uncovered) - if uncovered_chars < len(candidate) * new_coverage_fraction: - continue - - page_ranges[candidate.bbox.page] = range_ops.union_ranges(r_uncovered, page_ranges.get(candidate.bbox.page, [])) - - covered = range_ops.union_ranges(r_uncovered, covered) - - doc_start = document_fragment.normalized_to_source[r_uncovered[0][0]] - doc_end = document_fragment.normalized_to_source[r_uncovered[-1][1]] - - assignments.append((candidate, (doc_start, doc_end))) - - page_spans = {page: (r[0][0], r[-1][1]) for page, r in sorted(page_ranges.items())} - - new_spans = [] - uncovered = range_ops.subtract_ranges([(0, len(document_fragment.normalized))], covered) - - for start, end in uncovered: - page_range = _page_range_for_range(document_fragment.page_range, (start, end), page_spans) - frag = _slice_document_fragment(document_fragment, start, end, page_range) - if len(frag): - new_spans.append(frag) - - return assignments, new_spans - - -def _process_alignment_iteration( - iteration_num: int, - spans: list[_DocumentFragment], - bbox_spans: set[_BBoxFragment], - uniqueness_threshold: float, - min_overlap: float = 0.9, -) -> tuple[list[_DocumentFragment], list[tuple[_BBoxFragment, tuple[int, int]]]]: - logging.debug("--- Iteration %d (Threshold: %f, Overlap: %f) ---", iteration_num, uniqueness_threshold, min_overlap) - logging.debug("%d spans, %d bbox spans.", len(spans), len(bbox_spans)) - - candidates = list( - _assign_high_confidence_spans( - spans, - sorted(bbox_spans, key=lambda x: (x.bbox.page, x.bbox.rect.top, x.bbox.rect.left, x.bbox.text)), - uniqueness_threshold=uniqueness_threshold, - min_overlap=min_overlap, - with_ungapped=iteration_num == 1, - ), - ) - - if not candidates: - return spans, [] - - new_spans = [] - all_assigned_ranges_in_iteration = [] - matched_span_ids = set() - - for doc_span, bbox_candidates in candidates: - matched_span_ids.add(id(doc_span)) - assignments, holes = _assign_spans(doc_span, bbox_candidates) - - if assignments: - all_assigned_ranges_in_iteration.extend(assignments) - - new_spans.extend(holes) - - # Keep spans that weren't involved in any match - for s in spans: - if id(s) not in matched_span_ids: - new_spans.append(s) - - logging.debug("Assigned in this iteration: %s", bool(all_assigned_ranges_in_iteration)) - logging.debug("Remaining bboxes: %d", len(bbox_spans) - len({bbox for bbox, _ in all_assigned_ranges_in_iteration})) - logging.debug("New span count (holes + unvisited): %d", len(new_spans)) - return new_spans, all_assigned_ranges_in_iteration - - -def create_annotated_markdown( - markdown_content: str, - bounding_boxes: list[document.BoundingBox], - uniqueness_threshold: float = _UNIQUENESS_THRESHOLD, - min_overlap: float = _MIN_OVERLAP, -) -> dict[document.BoundingBox, tuple[int, int]]: - """Merges OCR bounding boxes into the markdown content.""" - - # Create initial spans (just the full content) - bbox_spans: set[_BBoxFragment] = {span for span in [_make_bbox_fragment(b) for b in bounding_boxes] if len(span)} - if not bbox_spans: - return {} - - max_page = max(b.page for b in bounding_boxes) - spans = list(_make_document_fragments(markdown_content, (0, max_page + 1))) - - logging.debug("initial span count %d; initial bbox count %d", len(spans), len(bbox_spans)) - - iteration = 0 - all_assigned_ranges: list[tuple[int, tuple[_BBoxFragment, tuple[int, int]]]] = [] - - while True: - iteration += 1 - spans, assigned_ranges = _process_alignment_iteration( - iteration, - spans, - bbox_spans, - uniqueness_threshold, - min_overlap, - ) - if assigned_ranges: - all_assigned_ranges.extend((iteration, s) for s in assigned_ranges) - - # Update bbox_spans to remove assigned ones for next iteration - assigned_set = {bbox for bbox, _ in assigned_ranges} - bbox_spans = {b for b in bbox_spans if b not in assigned_set} - - if not bbox_spans or (iteration > 1 and not assigned_ranges): - break - - logging.debug("Final remaining bbox count %d assigned count %d", len(bbox_spans), len(all_assigned_ranges)) - - # Apply replacements for debugging - # Sort ranges by start index descending to apply safely - all_assigned_ranges.sort(key=lambda x: x[1][1][0], reverse=True) - - return {bbox_span.bbox: (start, end) for iteration, (bbox_span, (start, end)) in all_assigned_ranges} diff --git a/src/gemini_ocr/docai.py b/src/gemini_ocr/docai.py deleted file mode 100644 index 0d65603..0000000 --- a/src/gemini_ocr/docai.py +++ /dev/null @@ -1,72 +0,0 @@ -import asyncio -import hashlib -import logging -import pathlib -import typing - -from google.api_core import client_options -from google.cloud import documentai - -from gemini_ocr import document, settings - - -def _call_docai( - ocr_settings: settings.Settings, - process_options: documentai.ProcessOptions, - processor_id: str, - chunk: document.DocumentChunk, -) -> documentai.Document: - location = ocr_settings.get_documentai_location() - - client = documentai.DocumentProcessorServiceClient( - client_options=client_options.ClientOptions(api_endpoint=f"{location}-documentai.googleapis.com"), - ) - - name = client.processor_path(ocr_settings.project_id, location, processor_id) - - raw_document = documentai.RawDocument(content=chunk.data, mime_type=chunk.mime_type) - request = documentai.ProcessRequest(name=name, raw_document=raw_document, process_options=process_options) - result = client.process_document(request=request) - return result.document - - -def _generate_cache_path( - ocr_settings: settings.Settings, - process_options: documentai.ProcessOptions, - processor_id: str, - chunk: document.DocumentChunk, -) -> pathlib.Path | None: - if not ocr_settings.cache_dir or not ocr_settings.cache_docai: - return None - hasher = hashlib.sha256() - hasher.update(documentai.ProcessOptions.to_json(process_options, sort_keys=True).encode()) - hasher.update(processor_id.encode()) - hasher.update(chunk.document_sha256.encode()) - cache_key = f"{hasher.hexdigest()}_{chunk.start_page}_{chunk.end_page}" - - return pathlib.Path(ocr_settings.cache_dir) / "docai" / f"{cache_key}.json" - - -async def process( - ocr_settings: settings.Settings, - process_options: documentai.ProcessOptions, - processor_id: str, - chunk: document.DocumentChunk, -) -> documentai.Document: - """Runs Document AI OCR.""" - - cache_path = _generate_cache_path(ocr_settings, process_options, processor_id, chunk) - - if cache_path and cache_path.exists(): - logging.debug("Loaded from DocAI cache: %s", cache_path) - return typing.cast("documentai.Document", documentai.Document.from_json(cache_path.read_text())) - - doc = await asyncio.to_thread(_call_docai, ocr_settings, process_options, processor_id, chunk) - - # Save to Cache - if cache_path: - cache_path.parent.mkdir(parents=True, exist_ok=True) - cache_path.write_text(documentai.Document.to_json(doc)) - logging.debug("Saved to DocAI cache: %s", cache_path) - - return doc diff --git a/src/gemini_ocr/docai_layout.py b/src/gemini_ocr/docai_layout.py deleted file mode 100644 index a0c1ccd..0000000 --- a/src/gemini_ocr/docai_layout.py +++ /dev/null @@ -1,209 +0,0 @@ -import dataclasses -import re -import textwrap -from collections.abc import Generator, Sequence - -from google.cloud import documentai - -from gemini_ocr import docai, document, settings - - -@dataclasses.dataclass -class TableCell: - """Represents a single cell within a table structure.""" - - content: str - """The text content of the cell.""" - row_pos: int - """The file-global row index.""" - col_pos: int - """The file-global column index.""" - row_span: int - """Number of rows this cell spans (>= 1).""" - col_span: int - """Number of columns this cell spans (>= 1).""" - is_header: bool - """True if this cell falls within a header row.""" - - -class LayoutProcessor: - def process( - self, - blocks: Sequence[documentai.Document.DocumentLayout.DocumentLayoutBlock], - ) -> Generator[str, None, None]: - yield from self._process_layout_blocks(blocks) - - def _process_text_block( - self, - block: documentai.Document.DocumentLayout.DocumentLayoutBlock, - ) -> Generator[str, None, None]: - text_type = block.text_block.type_ - text = block.text_block.text - # Fix math formatting: DocAI uses \(...\) for inline math, convert to $...$ - # We also trim whitespace inside the delimiters to ensure correct rendering (e.g. $ = 32$ instead of $ = 32 $) - text = re.sub(r"\\\(\s*(.*?)\s*\\\)", r"$\1$", text) - text = re.sub(r"\\\[\s*(.*?)\s*\\\]", r"$$\1$$", text) - - if text_type.startswith("heading-"): - level = int(text_type.split("-")[1]) - yield f"{'#' * level} {text}\n\n" - elif text_type == "title": - yield f"# {text}\n\n" - elif text_type == "subtitle": - yield f"## {text}\n\n" - elif text_type == "paragraph": - for line in textwrap.wrap(text): - yield line + "\n" - yield "\n" - - yield from self._process_layout_blocks(block.text_block.blocks) - - def _process_list_block( - self, - block: documentai.Document.DocumentLayout.DocumentLayoutBlock, - ) -> Generator[str, None, None]: - for entry in block.list_block.list_entries: - entry_text = "".join(self._process_layout_blocks(entry.blocks)).rstrip("\n") - entry_text = textwrap.indent(entry_text, " ") - - if entry_text: - yield f"- {entry_text[2:]}\n" - yield "\n" - - def _process_table_block( - self, - block: documentai.Document.DocumentLayout.DocumentLayoutBlock, - ) -> Generator[str, None, None]: - yield "\n" - - table_block = block.table_block - grid, num_rows, num_cols = self._build_table_grid(table_block) - - if num_rows == 0 or num_cols == 0: - yield "\n" - return - - yield from self._render_table( - grid, - num_rows, - num_cols, - len(table_block.header_rows) > 0, - len(table_block.header_rows), - ) - yield "\n" - - def _build_table_grid( - self, - table_block: documentai.Document.DocumentLayout.DocumentLayoutBlock.LayoutTableBlock, - ) -> tuple[dict[tuple[int, int], TableCell], int, int]: - all_rows = [(r, True) for r in table_block.header_rows] + [(r, False) for r in table_block.body_rows] - - occupied = set() - grid = {} - max_col = 0 - current_row_idx = 0 - - for row_obj, is_header in all_rows: - current_col_idx = 0 - for cell in row_obj.cells: - # Advance column pointer if current position is occupied - while (current_row_idx, current_col_idx) in occupied: - current_col_idx += 1 - - cell_text = "".join(self._process_layout_blocks(cell.blocks)).rstrip("\n") - cell_text = cell_text.replace("|", "\\|").replace("\n", "
") - - row_span = max(1, cell.row_span) - col_span = max(1, cell.col_span) - - grid[(current_row_idx, current_col_idx)] = TableCell( - content=cell_text, - row_pos=current_row_idx, - col_pos=current_col_idx, - row_span=row_span, - col_span=col_span, - is_header=is_header, - ) - - for r in range(row_span): - for c in range(col_span): - occupied.add((current_row_idx + r, current_col_idx + c)) - - current_col_idx += col_span - max_col = max(max_col, current_col_idx) - - current_row_idx += 1 - - return grid, current_row_idx, max_col - - def _render_table( - self, - grid: dict[tuple[int, int], TableCell], - num_rows: int, - num_cols: int, - has_header: bool, - header_row_count: int, - ) -> Generator[str, None, None]: - table_matrix = [["" for _ in range(num_cols)] for _ in range(num_rows)] - for (r, c), cell in grid.items(): - table_matrix[r][c] = cell.content - - def row_to_md(values: list[str]) -> str: - return "| " + " | ".join(values) + " |" - - if not has_header: - yield row_to_md(["" for _ in range(num_cols)]) + "\n" - yield row_to_md(["---" for _ in range(num_cols)]) + "\n" - - for r in range(num_rows): - yield row_to_md(table_matrix[r]) + "\n" - if has_header and r == header_row_count - 1: - yield row_to_md(["---" for _ in range(num_cols)]) + "\n" - - yield "\n" - - def _process_layout_blocks( - self, - blocks: Sequence[documentai.Document.DocumentLayout.DocumentLayoutBlock], - ) -> Generator[str, None, None]: - for block in blocks: - if block.text_block: - yield from self._process_text_block(block) - elif block.list_block: - yield from self._process_list_block(block) - elif block.table_block: - yield from self._process_table_block(block) - else: - raise ValueError(f"Unknown block type: {block}") - - -async def _run_document_ai(settings: settings.Settings, chunk: document.DocumentChunk) -> documentai.Document: - process_options = documentai.ProcessOptions( - layout_config=documentai.ProcessOptions.LayoutConfig( - return_bounding_boxes=True, - ), - ) - - if settings.layout_processor_id is None: - raise ValueError("Layout processor ID is not set") - - return await docai.process(settings, process_options, settings.layout_processor_id, chunk) - - -async def generate_markdown( - settings: settings.Settings, - chunk: document.DocumentChunk, -) -> str: - """Generates Markdown from a Document AI chunk. - - Args: - settings: OCR settings. - chunk: The document chunk (usually a single page or small range). - - Returns: - The generated Markdown string. - """ - doc_result = await _run_document_ai(settings, chunk) - processor = LayoutProcessor() - - return "".join(processor.process(doc_result.document_layout.blocks)) diff --git a/src/gemini_ocr/docai_ocr.py b/src/gemini_ocr/docai_ocr.py deleted file mode 100644 index ec82faa..0000000 --- a/src/gemini_ocr/docai_ocr.py +++ /dev/null @@ -1,52 +0,0 @@ -import logging - -from google.cloud import documentai - -from gemini_ocr import docai, document, settings - - -async def _run_document_ai(settings: settings.Settings, chunk: document.DocumentChunk) -> documentai.Document: - """Runs Document AI OCR.""" - - process_options = documentai.ProcessOptions( - ocr_config=documentai.OcrConfig( - enable_native_pdf_parsing=True, - premium_features=documentai.OcrConfig.PremiumFeatures( - compute_style_info=True, - enable_math_ocr=True, - ), - ), - ) - - return await docai.process(settings, process_options, settings.ocr_processor_id, chunk) - - -async def generate_bounding_boxes( - settings: settings.Settings, - chunk: document.DocumentChunk, -) -> list[document.BoundingBox]: - doc = await _run_document_ai(settings, chunk) - - def _get_text(text_anchor: documentai.Document.TextAnchor) -> str: - if not text_anchor.text_segments: - return "" - return "".join( - doc.text[int(segment.start_index) : int(segment.end_index)] for segment in text_anchor.text_segments - ) - - bboxes = [] - for page_num, page in enumerate(doc.pages): - for block in page.lines: - text = _get_text(block.layout.text_anchor).strip() - vertices = block.layout.bounding_poly.normalized_vertices - num_vertices = 4 - if len(vertices) == num_vertices: - top = int(vertices[0].y * 1000) - left = int(vertices[0].x * 1000) - bottom = int(vertices[2].y * 1000) - right = int(vertices[2].x * 1000) - rect = document.BBox(top, left, bottom, right) - bboxes.append(document.BoundingBox(page=page_num + chunk.start_page, rect=rect, text=text)) - - logging.debug("Generated %d bounding boxes", len(bboxes)) - return bboxes diff --git a/src/gemini_ocr/docling.py b/src/gemini_ocr/docling.py deleted file mode 100644 index 0a6c5db..0000000 --- a/src/gemini_ocr/docling.py +++ /dev/null @@ -1,8 +0,0 @@ -from gemini_ocr import document, settings - - -async def generate_markdown( - settings: settings.Settings, - chunk: document.DocumentChunk, -) -> str: - raise NotImplementedError diff --git a/src/gemini_ocr/document.py b/src/gemini_ocr/document.py deleted file mode 100644 index 9937375..0000000 --- a/src/gemini_ocr/document.py +++ /dev/null @@ -1,119 +0,0 @@ -import dataclasses -import hashlib -import mimetypes -import pathlib -from collections.abc import Iterator -from typing import BinaryIO, NamedTuple, TypeAlias - -import fitz -import fsspec - -DocumentInput: TypeAlias = pathlib.Path | str | bytes | BinaryIO - - -class BBox(NamedTuple): - """A bounding box tuple (top, left, bottom, right).""" - - top: int - """Top coordinate (y-min: [0-1000]).""" - left: int - """Left coordinate (x-min: [0-1000]).""" - bottom: int - """Bottom coordinate (y-max: [0-1000]).""" - right: int - """Right coordinate (x-max: [0-1000]).""" - - -@dataclasses.dataclass(frozen=True) -class BoundingBox: - """A text segment with its bounding box and page number.""" - - text: str - """The text content.""" - page: int - """Page number (0-indexed).""" - rect: BBox - """The bounding box coordinates.""" - - -@dataclasses.dataclass -class DocumentChunk: - """A chunk of a document (e.g., a subset of pages extracted from a PDF).""" - - document_sha256: str - """SHA256 hash of the original document.""" - start_page: int - """Start page number of this chunk in the original document.""" - end_page: int - """End page number (exclusive) of this chunk.""" - data: bytes - """Raw bytes of the chunk (PDF or image).""" - mime_type: str - """MIME type of the chunk data.""" - - -def _split_pdf_bytes(file_bytes: bytes, page_count: int | None = None) -> Iterator[DocumentChunk]: - doc = fitz.open(stream=file_bytes, filetype="pdf") - doc_page_count = len(doc) - document_sha256 = hashlib.sha256(file_bytes).hexdigest() - if page_count is None: - yield DocumentChunk(document_sha256, 0, doc_page_count, file_bytes, "application/pdf") - return - - for start_page in range(0, doc_page_count, page_count): - new_doc = fitz.open() - end_page = min(start_page + page_count, doc_page_count) - new_doc.insert_pdf(doc, from_page=start_page, to_page=end_page - 1) - yield DocumentChunk(document_sha256, start_page, end_page, new_doc.tobytes(), "application/pdf") - new_doc.close() - - -def _resolve_input(input_source: DocumentInput, mime_type: str | None) -> tuple[bytes, str | None]: - """Resolves input source to bytes and mime_type.""" - file_bytes: bytes - - match input_source: - case str() if "://" in input_source: - with fsspec.open(input_source, "rb") as f: - file_bytes = f.read() # type: ignore[attr-defined] - if mime_type is None: - mime_type, _ = mimetypes.guess_type(input_source) - case str() | pathlib.Path() as path: - path_obj = pathlib.Path(path) - file_bytes = path_obj.read_bytes() - if mime_type is None: - mime_type, _ = mimetypes.guess_type(path_obj) - case bytes(): - file_bytes = input_source - case BinaryIO(): - file_bytes = input_source.read() - case _: - raise ValueError(f"Unsupported input source: {input_source}") - - return file_bytes, mime_type - - -def chunks( - input_source: DocumentInput, - *, - page_count: int | None = None, - mime_type: str | None = None, -) -> Iterator[DocumentChunk]: - """Splits a Document into chunks. - - Supports PDF (splits by pages) and Images (single chunk). - """ - file_bytes, mime_type = _resolve_input(input_source, mime_type) - - # Auto-detect PDF if mime_type is unknown - if mime_type is None and file_bytes.startswith(b"%PDF"): - mime_type = "application/pdf" - - if mime_type and mime_type.startswith("image/"): - yield DocumentChunk(hashlib.sha256(file_bytes).hexdigest(), 0, 0, file_bytes, mime_type) - return - - if mime_type != "application/pdf": - raise ValueError(f"Unsupported file type: {mime_type}") - - yield from _split_pdf_bytes(file_bytes, page_count) diff --git a/src/gemini_ocr/gemini.py b/src/gemini_ocr/gemini.py deleted file mode 100644 index 0b63e9e..0000000 --- a/src/gemini_ocr/gemini.py +++ /dev/null @@ -1,117 +0,0 @@ -import asyncio -import hashlib -import logging -import pathlib -from typing import Final - -import google.auth -from google import genai - -from gemini_ocr import document, settings - -GEMINI_PROMPT: Final[str] = """ -Carefully transcribe the text for this pdf into a text file with -markdown annotations. - -**The final output must be formatted as text that visually -mimics in markdown the layout and hierarchy of the original PDF -when rendered.** - -* Do not include headers or footers that are repeated on each page. -* Do not include page numbers. -* Preserve the reading order of the text as it appears in the PDF. -* Remove hyphens that break words at the end of lines. - * e.g. "uti- lized" -> "utilized" -* Use Markdown headings (`#`, `##`, `###`) to reflect the size and - hierarchy of titles and subtitles in the PDF. -* Ensure that there are blank lines before and after headings, lists, - tables, and images. -* End each paragraph with a blank line. -* Do not break lines within paragraphs or headings. -* Render bullet points and numbered lettered lists as markdown lists. - * It is ok to remove brackets and other consistent punctuation around - list identifiers - * e.g. "a)" -> "a." -* Use blockquotes for any sidebars or highlighted text. -* Bold all words and phrases that appear bolded in the original - source material. Similarly, italicise all text in italics. -* Render tables as markdown, paying particular attention to copying - identifiers exactly. -* Break text into paragraphs and lists exactly as they appear in - the PDF. -* Replace any images with a text description of their content. - * Convert bar charts into markdown tables. -* Convert tables contained in images into markdown. -* Render all mathematical equations and symbols using LaTeX formatting. - * e.g. use `\alpha` instead of `α`, `\\cos` instead of `cos`. - * Enclose equations in `$` or `$$`. - * Pay close attention to distinguishing Latin and Greek characters, e.g. 'a' vs '\alpha'. -* Insert markers at the start of each page of the form `` -* Surround tables and figure descriptions with markers: - * `` ... `` - * `` ... `` -""" # noqa: RUF001 - -_GEMINI_PROMPT_SHA256: Final[bytes] = hashlib.sha256(GEMINI_PROMPT.encode()).digest() - - -def _call_gemini(settings: settings.Settings, chunk: document.DocumentChunk) -> genai.types.GenerateContentResponse: - # TODO: consider reusing client - credentials, _ = google.auth.default() - if settings.quota_project_id: - credentials = credentials.with_quota_project(settings.quota_project_id) - elif settings.project_id: - # Fallback to project if quota_project_id is not set - credentials = credentials.with_quota_project(settings.project_id) - - client = genai.Client( - vertexai=True, - project=settings.project_id, - location=settings.location, - credentials=credentials, - ) - - model_name = settings.gemini_model_name - if model_name is None: - raise ValueError("gemini_model_name is required for Gemini mode.") - - contents: list[genai.types.Part | str] = [] - contents.append(genai.types.Part(inline_data=genai.types.Blob(data=chunk.data, mime_type=chunk.mime_type))) - contents.append(GEMINI_PROMPT) - - return client.models.generate_content( - model=model_name, - contents=contents, - config=genai.types.GenerateContentConfig(response_mime_type="text/plain"), - ) - - -def _generate_cache_path(settings: settings.Settings, chunk: document.DocumentChunk) -> pathlib.Path | None: - if not settings.cache_dir or not settings.cache_gemini: - return None - hasher = hashlib.sha256() - hasher.update(_GEMINI_PROMPT_SHA256) - hasher.update(chunk.document_sha256.encode()) - hasher.update((settings.gemini_model_name or "").encode()) - cache_key = f"{hasher.hexdigest()}_{chunk.start_page}_{chunk.end_page}" - return pathlib.Path(settings.cache_dir) / "gemini" / f"{cache_key}.txt" - - -async def generate_markdown(settings: settings.Settings, chunk: document.DocumentChunk) -> str | None: - """Generates markdown for a chunk using the Gemini API.""" - - cache_path = _generate_cache_path(settings, chunk) - - if cache_path and cache_path.exists(): - logging.debug("Loaded from Gemini cache: %s", cache_path) - return cache_path.read_text() - - response = await asyncio.to_thread(_call_gemini, settings, chunk) - text = response.text - - if cache_path and text: - cache_path.parent.mkdir(parents=True, exist_ok=True) - cache_path.write_text(text) - logging.debug("Saved to Gemini cache: %s", cache_path) - - return text diff --git a/src/gemini_ocr/gemini_ocr.py b/src/gemini_ocr/gemini_ocr.py deleted file mode 100644 index a0f959d..0000000 --- a/src/gemini_ocr/gemini_ocr.py +++ /dev/null @@ -1,201 +0,0 @@ -import asyncio -import collections -import dataclasses -import itertools -import re -import typing - -from gemini_ocr import bbox_alignment, docai_layout, docai_ocr, docling, document, gemini -from gemini_ocr import settings as settings_module - -T = typing.TypeVar("T") - - -@dataclasses.dataclass -class RawOcrData: - """Intermediate data structure holding raw OCR/Markdown output.""" - - markdown_content: str - """The generated markdown string.""" - bounding_boxes: list[document.BoundingBox] - """List of all bounding boxes extracted from the document.""" - - -@dataclasses.dataclass -class OcrResult: - """The final result of the OCR and annotation process.""" - - markdown_content: str - """The generated markdown content.""" - bounding_boxes: dict[document.BoundingBox, tuple[int, int]] - """Mapping of bounding boxes to their span ranges in the markdown.""" - coverage_percent: float - """Percentage of markdown content covered by aligned bounding boxes.""" - - def annotate(self) -> str: - """Annotates the markdown content with bounding box spans.""" - - # 1. Identify math ranges to snap to (to avoid inserting tags inside math) - math_ranges = [] - # Pattern matches $$...$$ (DOTALL) or $...$ (inline, allowing newlines for wrapped text) - pattern = re.compile(r"(\$\$[\s\S]+?\$\$|\$(?:\\.|[^$])+?\$)") - for m in pattern.finditer(self.markdown_content): - math_ranges.append((m.start(), m.end())) - - insertions = [] - for bbox, (span_start, span_end) in self.bounding_boxes.items(): - start, end = span_start, span_end - # Check for overlap with math ranges - for m_start, m_end in math_ranges: - # If overlap (we check if the range intersects the math range) - if max(start, m_start) < min(end, m_end): - # Snap to the math range - start = m_start - end = m_end - break - - length = end - start - bbox_str = f"{bbox.rect.top},{bbox.rect.left},{bbox.rect.bottom},{bbox.rect.right}" - start_tag = f'' - end_tag = "" - - insertions.append((start, False, length, start_tag)) - insertions.append((end, True, length, end_tag)) - - # Sort: - # 1. Index Descending. - # 2. is_end Descending (True/End processed before False/Start). - # 3. Length Ascending (Short processed before Long). - - insertions.sort(key=lambda x: (x[0], x[1], -x[2]), reverse=True) - - chars = list(self.markdown_content) - for index, _, _, text in insertions: - chars.insert(index, text) - - return "".join(chars) - - -async def _generate_markdown_for_chunk( - ocr_settings: settings_module.Settings, - chunk: document.DocumentChunk, -) -> str: - """Generates markdown for a chunk using the Gemini API.""" - - match ocr_settings.mode: - case settings_module.OcrMode.GEMINI: - text = await gemini.generate_markdown(ocr_settings, chunk) - case settings_module.OcrMode.DOCUMENTAI: - text = await docai_layout.generate_markdown(ocr_settings, chunk) - case settings_module.OcrMode.DOCLING: - text = await docling.generate_markdown(ocr_settings, chunk) - case _: - text = None - - return text or "" - - -# --- Merging and Annotation --- - - -async def _batched_gather(tasks: collections.abc.Sequence[collections.abc.Awaitable[T]], batch_size: int) -> list[T]: - """Runs awaitables in batches.""" - results = [] - for i in range(0, len(tasks), batch_size): - batch = tasks[i : i + batch_size] - results.extend(await asyncio.gather(*batch)) - return results - - -async def extract_raw_data( - document_input: document.DocumentInput, - settings: settings_module.Settings | None = None, - markdown_content: str | None = None, -) -> RawOcrData: - """ - Extracts raw OCR data (markdown and bounding boxes) from a file. - - Args: - document_input: The document to process (Path, str, bytes, or stream). - settings: Configuration settings. - markdown_content: Optional existing markdown content. - - Returns: - RawOcrData containing markdown and bounding boxes. - """ - if settings is None: - settings = settings_module.Settings.from_env() - - chunks = list(document.chunks(document_input, page_count=settings.markdown_page_batch_size)) - if not markdown_content: - markdown_work = [_generate_markdown_for_chunk(settings, chunk) for chunk in chunks] - markdown_chunks = await _batched_gather(markdown_work, settings.num_jobs) - - # Renumber tables and figures - counters: collections.Counter[str] = collections.Counter() - - def _renumber(match: re.Match) -> str: - kind = match.group(1) - counters[kind] += 1 - return f"" - - markdown_chunks = [re.sub(r"", _renumber, chunk_text) for chunk_text in markdown_chunks] - markdown_content = "\n".join(markdown_chunks) - - bounding_box_work = [docai_ocr.generate_bounding_boxes(settings, chunk) for chunk in chunks] - bboxes = list(itertools.chain.from_iterable(await _batched_gather(bounding_box_work, settings.num_jobs))) - - return RawOcrData( - markdown_content=markdown_content, - bounding_boxes=bboxes, - ) - - -async def process_document( - document_input: document.DocumentInput, - settings: settings_module.Settings | None = None, - markdown_content: str | None = None, -) -> OcrResult: - """ - Processes a document to generate annotated markdown with OCR bounding boxes. - - Args: - document_input: The document to process (Path, str, bytes, or stream). - settings: Configuration settings. - markdown_content: Optional existing markdown content. - - Returns: - OcrResult containing annotated markdown and stats. - """ - if settings is None: - settings = settings_module.Settings.from_env() - - raw_data = await extract_raw_data(document_input, settings, markdown_content) - annotated_markdown = bbox_alignment.create_annotated_markdown( - raw_data.markdown_content, - raw_data.bounding_boxes, - uniqueness_threshold=settings.alignment_uniqueness_threshold, - min_overlap=settings.alignment_min_overlap, - ) - - # Calculate coverage - if not raw_data.markdown_content: - coverage_percent = 0.0 - else: - spans = list(annotated_markdown.values()) - spans.sort() - merged: list[tuple[int, int]] = [] - for start, end in spans: - if not merged or start > merged[-1][1]: - merged.append((start, end)) - else: - merged[-1] = (merged[-1][0], max(merged[-1][1], end)) - - covered_len = sum(end - start for start, end in merged) - coverage_percent = covered_len / len(raw_data.markdown_content) - - return OcrResult( - markdown_content=raw_data.markdown_content, - bounding_boxes=annotated_markdown, - coverage_percent=coverage_percent, - ) diff --git a/src/gemini_ocr/range_ops.py b/src/gemini_ocr/range_ops.py deleted file mode 100644 index 95d0d94..0000000 --- a/src/gemini_ocr/range_ops.py +++ /dev/null @@ -1,182 +0,0 @@ -import heapq -import itertools -from collections.abc import Callable, Iterator, Sequence -from operator import itemgetter - -_INTERSECTION_OVERLAP_COUNT = 2 - - -def _generate_range_edges( - ranges: Sequence[tuple[int, int]], - start_weight: int, - end_weight: int, -) -> Iterator[tuple[int, int]]: - """Generates edge events for a sweep-line algorithm. - - Yields (position, weight) pairs. - """ - for s, e in ranges: - yield s, start_weight - yield e, end_weight - - -def _sweep_operation( - ranges_a: Sequence[tuple[int, int]], - ranges_b: Sequence[tuple[int, int]], - weights_a: tuple[int, int], - weights_b: tuple[int, int], - predicate: Callable[[int], bool], -) -> list[tuple[int, int]]: - """Generic sweep-line operation. - - Args: - ranges_a: First sequence of intervals. - ranges_b: Second sequence of intervals. - weights_a: (start_weight, end_weight) for A. - weights_b: (start_weight, end_weight) for B. - predicate: Function taking current sum 's' and returning True if we should be outputting. - - Returns: - List of resulting intervals. - """ - # Merge sorted event streams - events = heapq.merge( - _generate_range_edges(ranges_a, *weights_a), - _generate_range_edges(ranges_b, *weights_b), - key=itemgetter(0), - ) - - s = 0 - result = [] - start_pos = -1 - - # Group events by position to handle simultaneous events (e.g. abutments) - for pos, group in itertools.groupby(events, key=itemgetter(0)): - # Calculate total weight change at this position - delta = sum(weight for _, weight in group) - s_next = s + delta - - was_active = predicate(s) - is_active = predicate(s_next) - - if not was_active and is_active: - # Started satisfying predicate - start_pos = pos - elif was_active and not is_active: - # Stopped satisfying predicate - assert start_pos != -1 # noqa: S101 - result.append((start_pos, pos)) - start_pos = -1 - - s = s_next - - return result - - -def subtract_ranges( - ranges_a: Sequence[tuple[int, int]], - ranges_b: Sequence[tuple[int, int]], -) -> list[tuple[int, int]]: - """Calculates the set difference of two sets of disjoint intervals (A - B). - - Args: - ranges_a: A sequence of half-open intervals [start, end), sorted and disjoint. - ranges_b: A sequence of half-open intervals [start, end), sorted and disjoint. - - Returns: - A list of intervals representing the parts of A that are not covered by B. - """ - # A adds 1, B subtracts 1. We want regions where sum == 1. - return _sweep_operation( - ranges_a, - ranges_b, - (+1, -1), - (-1, +1), - lambda s: s == 1, - ) - - -def union_ranges( - ranges_a: Sequence[tuple[int, int]], - ranges_b: Sequence[tuple[int, int]], -) -> list[tuple[int, int]]: - """Calculates the union of two sets of disjoint intervals (A | B). - - Args: - ranges_a: A sequence of half-open intervals [start, end), sorted and disjoint. - ranges_b: A sequence of half-open intervals [start, end), sorted and disjoint. - - Returns: - A list of intervals representing the union of A and B. - Overlapping or adjacent intervals are merged. - """ - # Both add 1. We want regions where sum > 0. - return _sweep_operation( - ranges_a, - ranges_b, - (+1, -1), - (+1, -1), - lambda s: s > 0, - ) - - -def intersect_ranges( - ranges_a: Sequence[tuple[int, int]], - ranges_b: Sequence[tuple[int, int]], -) -> list[tuple[int, int]]: - """Calculates the intersection of two sets of disjoint intervals (A & B). - - Args: - ranges_a: A sequence of half-open intervals [start, end), sorted and disjoint. - ranges_b: A sequence of half-open intervals [start, end), sorted and disjoint. - - Returns: - A list of intervals representing the overlapping parts of A and B. - """ - # Both add 1. We want regions where sum == _INTERSECTION_OVERLAP_COUNT. - return _sweep_operation( - ranges_a, - ranges_b, - (+1, -1), - (+1, -1), - lambda s: s == _INTERSECTION_OVERLAP_COUNT, - ) - - -def in_range(val: int, test_range: tuple[int, int]) -> bool: - """Return true if `val` is in `test_range`. - - Args: - val: The value to test. - test_range: The range to test against. - - Returns: - True if `val` is in `test_range`. - """ - return test_range[0] <= val < test_range[1] - - -def overlaps(r1: tuple[int, int], r2: tuple[int, int]) -> bool: - """Return true if `r1` overlaps `r2`. - - Args: - r1: The first range. - r2: The second range. - - Returns: - True if `r1` overlaps `r2`. - """ - return r1[0] < r2[1] and r1[1] > r2[0] - - -def contained(r1: tuple[int, int], r2: tuple[int, int]) -> bool: - """Return true if `r1` is contained in `r2`. - - Args: - r1: The first range. - r2: The second range. - - Returns: - True if `r1` is contained in `r2`. - """ - return r1[0] >= r2[0] and r1[1] <= r2[1] diff --git a/src/gemini_ocr/settings.py b/src/gemini_ocr/settings.py deleted file mode 100644 index ec30d51..0000000 --- a/src/gemini_ocr/settings.py +++ /dev/null @@ -1,87 +0,0 @@ -import dataclasses -import enum -import os -from typing import Self - - -class OcrMode(enum.StrEnum): - """Processing mode.""" - - GEMINI = "gemini" - """Use Gemini for markdown generation.""" - DOCUMENTAI = "documentai" - """Use Document AI layout mode for markdown generation.""" - DOCLING = "docling" - """Use Docling for markdown generation.""" - - -@dataclasses.dataclass -class Settings: - """gemini-ocr settings.""" - - location: str - """Gemini api endpoint location (e.g. 'us-central1').""" - layout_processor_id: str | None - """Document AI layout processor ID (required for Document AI mode).""" - ocr_processor_id: str | None - """Document AI OCR processor ID.""" - - project_id: str - """GCP project ID.""" - quota_project_id: str | None = None - """GCP quota project ID (defaults to project if None).""" - gemini_model_name: str | None = None - """Name of the Gemini model to use. (required for Gemini mode)""" - - mode: OcrMode = OcrMode.GEMINI - """Processing mode to use.""" - - documentai_location: str | None = None - """DocumentAI api endpoint location (e.g. 'us', 'eu'). If `None`, infers from `location`.""" - - alignment_uniqueness_threshold: float = 0.5 - """Minimum score ratio between best and second-best match.""" - alignment_min_overlap: float = 0.9 - """Minimum overlap fraction required for a valid match.""" - include_bboxes: bool = True - """Whether to perform bounding box alignment.""" - markdown_page_batch_size: int = 10 - """Pages per batch for Markdown generation.""" - ocr_page_batch_size: int = 10 - """Pages per batch for OCR.""" - num_jobs: int = 10 - """Max concurrent jobs.""" - cache_dir: str | None = None - """Directory to store API response cache. `None` disables caching.""" - cache_gemini: bool = True - """Whether to cache Gemini API responses.""" - cache_docai: bool = True - """Whether to cache DocAI API responses.""" - - def get_documentai_location(self) -> str: - if self.documentai_location is None: - return "eu" if self.location.startswith("eu") else "us" - return self.documentai_location - - @classmethod - def from_env(cls, prefix: str = "GEMINI_OCR_") -> Self: - """Create Settings from environment variables.""" - - def get(key: str) -> str | None: - return os.getenv(prefix + key.upper()) - - def getdefault(key: str, default: str) -> str: - return os.getenv(prefix + key.upper(), default) - - project_id = get("project_id") - if project_id is None: - raise ValueError(f"{prefix}PROJECT_ID environment variable is required.") - - return cls( - project_id=project_id, - location=getdefault("location", "us-central1"), - quota_project_id=get("quota_project_id"), - layout_processor_id=get("layout_processor_id"), - ocr_processor_id=get("ocr_processor_id"), - gemini_model_name=get("gemini_model_name"), - ) diff --git a/src/groundmark/__init__.py b/src/groundmark/__init__.py new file mode 100644 index 0000000..0ca4f71 --- /dev/null +++ b/src/groundmark/__init__.py @@ -0,0 +1,6 @@ +from anchorite import Anchor, BBox, annotate, resolve, strip + +from groundmark.markdown import PROMPT +from groundmark.process import Config, ProcessResult, process + +__all__ = ["PROMPT", "Anchor", "BBox", "Config", "ProcessResult", "annotate", "process", "resolve", "strip"] diff --git a/src/groundmark/markdown.py b/src/groundmark/markdown.py new file mode 100644 index 0000000..7493acc --- /dev/null +++ b/src/groundmark/markdown.py @@ -0,0 +1,104 @@ +"""PDF to Markdown conversion via Pydantic AI (any supported LLM).""" + +import re +import unicodedata +from typing import Final + +from anchorite.document import DocumentChunk +from pydantic_ai import Agent +from pydantic_ai.messages import BinaryContent + +# Apparently, faithfully analyzing a PDF's complicated layout and transcribing +# it into well-structured Markdown isn't creative enough for Claude's content +# filter. Asking the model to add line numbers gives it something "original" +# to contribute, which satisfies the anti-regurgitation heuristic. We strip +# them right after. +# https://privacy.claude.com/en/articles/10023638-why-am-i-receiving-an-output-blocked-by-content-filtering-policy-error +_LINE_NUM_PREFIX = """ +IMPORTANT: Prefix every output line with its line number followed by a +pipe character (no trailing space), e.g.: + 1|# Heading + 2| + 3|Some paragraph text here. +Start numbering at 1. This is required for all output. +""" + +_LINE_NUM_RE = re.compile(r"^\d+\|", re.MULTILINE) + +PROMPT: Final[str] = ( + """ +Carefully transcribe the text for this pdf into a text file with +markdown annotations. +""" + + _LINE_NUM_PREFIX + + """ +**The final output must be formatted as text that visually +mimics in markdown the layout and hierarchy of the original PDF +when rendered (ignoring the line-number prefixes).** + +* Do not include headers or footers that are repeated on each page. +* Do not include page numbers. +* Preserve the reading order of the text as it appears in the PDF. +* Remove hyphens that break words at the end of lines. + * e.g. "uti- lized" -> "utilized" +* Use Markdown headings (`#`, `##`, `###`) to reflect the size and + hierarchy of titles and subtitles in the PDF. +* Ensure that there are blank lines before and after headings, lists, + tables, and images. +* End each paragraph with a blank line. +* Do not break lines within paragraphs or headings. +* Render bullet points and numbered lettered lists as markdown lists. + * It is ok to remove brackets and other consistent punctuation around + list identifiers + * e.g. "a)" -> "a." +* Use blockquotes for any sidebars or highlighted text. +* Bold all words and phrases that appear bolded in the original + source material. Similarly, italicise all text in italics. +* Render tables as markdown, paying particular attention to copying + identifiers exactly. +* Break text into paragraphs and lists exactly as they appear in + the PDF. +* Preserve figure/chart captions verbatim — do not paraphrase, extend, + or interleave them with descriptions. If useful context is only visible + in the image (e.g. axis labels, legend entries, data values), add it + as a separate paragraph after the caption. +* Convert bar charts into markdown tables where possible. +* Convert tables contained in images into markdown. +* Keep mathematical expressions as close to the PDF's own characters as + possible — use the same Unicode symbols (×, ≥, α, β, etc.) rather than + converting to LaTeX commands. + * Only use LaTeX (`$...$` / `$$...$$`) for complex display equations + with fractions, integrals, summations, or multi-level notation that + cannot be represented legibly in plain text. +* Insert markers at the start of each page of the form `` +* Surround tables and figure descriptions with markers: + * `` ... `` + * `` ... `` +""" +) + +_agent: Agent[None, str] = Agent(output_type=str) + + +class PydanticAIMarkdownProvider: + """MarkdownProvider that converts PDF chunks to Markdown via a vision-capable LLM.""" + + def __init__(self, model: str, *, prompt: str | None = None) -> None: + self.model = model + self._prompt = prompt or PROMPT + + async def generate_markdown(self, chunk: DocumentChunk) -> str: + """Convert a document chunk to Markdown. + + Returns: + Markdown string with ```` markers between pages. + """ + result = await _agent.run( + [BinaryContent(data=chunk.data, media_type=chunk.mime_type), self._prompt], + model=self.model, + ) + # Strip the line-number prefixes added to bypass Claude's content filter. + markdown = _LINE_NUM_RE.sub("", result.output) + # NFKC-normalize so superscript digits, ligatures, etc. match the + # NFKC-normalized anchor text from pdfplumber extraction. + return unicodedata.normalize("NFKC", markdown) diff --git a/src/groundmark/parse.py b/src/groundmark/parse.py new file mode 100644 index 0000000..8c4f73e --- /dev/null +++ b/src/groundmark/parse.py @@ -0,0 +1,95 @@ +"""Bounding box extraction from PDFs using pdfplumber.""" + +import io +import logging +import unicodedata + +import pdfplumber +from anchorite import Anchor, BBox +from anchorite.document import DocumentChunk + + +class PdfplumberAnchorProvider: + """AnchorProvider that extracts line-level bounding boxes via pdfplumber. + + Body text lines are emitted individually; table rows are merged into + single anchors so that repeated short cell values (e.g. "Pathogenic") + become unique when combined with the full row. + + Coordinates are normalized to a 0-1000 scale with top-left origin. + """ + + async def generate_anchors(self, chunk: DocumentChunk) -> list[Anchor]: + pdf = pdfplumber.open(io.BytesIO(chunk.data)) + anchors: list[Anchor] = [] + + for page_offset, page in enumerate(pdf.pages): + pw, ph = page.width, page.height + if pw <= 0 or ph <= 0: + logging.warning( + "Page %d has invalid dimensions (%s x %s), skipping", + chunk.start_page + page_offset, + pw, + ph, + ) + continue + + page_num = chunk.start_page + page_offset + + # Detect table regions on this page. + table_bboxes = [table.bbox for table in page.find_tables()] + + lines = page.extract_text_lines(return_chars=False, use_text_flow=True) + + for line in lines: + x0, x1 = line["x0"], line["x1"] + # pdfplumber's top starts at baseline minus font size, + # missing the ascender portion above the glyph. Pad upward + # by ~30% of line height to approximate full glyph bounds. + line_h = line["bottom"] - line["top"] + y0 = line["top"] - 0.3 * line_h + y1 = line["bottom"] + text = unicodedata.normalize("NFKC", line["text"].strip()) + if not text: + continue + + in_table = any(_rects_intersect((x0, y0, x1, y1), tb) for tb in table_bboxes) + + if in_table: + # Table lines are already row-level from extract_text_lines. + anchors.append( + Anchor( + page=page_num, + box=_normalize(x0, y0, x1, y1, pw, ph), + text=text, + ) + ) + else: + anchors.append( + Anchor( + page=page_num, + box=_normalize(x0, y0, x1, y1, pw, ph), + text=text, + ) + ) + + pdf.close() + logging.debug("Generated %d bounding boxes", len(anchors)) + return anchors + + +def _rects_intersect(a: tuple[float, float, float, float], b: tuple[float, float, float, float]) -> bool: + """Check if two (x0, y0, x1, y1) rectangles overlap.""" + ax0, ay0, ax1, ay1 = a + bx0, by0, bx1, by1 = b + return ax0 < bx1 and ax1 > bx0 and ay0 < by1 and ay1 > by0 + + +def _normalize(x0: float, y0: float, x1: float, y1: float, pw: float, ph: float) -> BBox: + """Convert PDF coordinates to 0-1000 scale with top-left origin.""" + return BBox( + top=int(y0 / ph * 1000), + left=int(x0 / pw * 1000), + bottom=int(y1 / ph * 1000), + right=int(x1 / pw * 1000), + ) diff --git a/src/groundmark/process.py b/src/groundmark/process.py new file mode 100644 index 0000000..7a4ea40 --- /dev/null +++ b/src/groundmark/process.py @@ -0,0 +1,82 @@ +import dataclasses + +from anchorite import process_document +from anchorite.document import DocumentChunk, chunks + +from groundmark.markdown import PydanticAIMarkdownProvider +from groundmark.parse import PdfplumberAnchorProvider + + +@dataclasses.dataclass(frozen=True) +class Config: + """Configuration for the groundmark processing pipeline.""" + + model: str + """Pydantic AI model string (e.g. "bedrock:au.anthropic.claude-sonnet-4-6").""" + uniqueness_threshold: float = 0.5 + """Minimum score ratio between best and second-best alignment match.""" + min_overlap: float = 0.9 + """Minimum overlap fraction required for a valid alignment match.""" + page_count: int | None = None + """Pages per chunk (None = whole PDF in one chunk).""" + prompt: str | None = None + """Custom LLM prompt (None = use built-in default).""" + + +@dataclasses.dataclass +class ProcessResult: + """Result of processing a PDF into annotated Markdown.""" + + annotated_markdown: str + """Markdown with tags.""" + coverage_percent: float + """Fraction of markdown content covered by aligned bounding boxes.""" + + +async def process( + pdf_bytes: bytes, + config: Config, + *, + markdown: str | None = None, +) -> ProcessResult: + """Process a PDF into annotated Markdown with bounding box spans. + + Args: + pdf_bytes: Raw PDF file bytes. + config: Processing configuration. + markdown: Optional pre-generated markdown (skips LLM call). + + Returns: + ProcessResult with annotated markdown and coverage stats. + """ + md_provider: _CachedMarkdownProvider | PydanticAIMarkdownProvider + if markdown is not None: + # Cached markdown corresponds to the whole PDF — don't chunk. + md_provider = _CachedMarkdownProvider(markdown) + doc_chunks = chunks(pdf_bytes) + else: + md_provider = PydanticAIMarkdownProvider(config.model, prompt=config.prompt) + doc_chunks = chunks(pdf_bytes, page_count=config.page_count) + + result = await process_document( + doc_chunks, + markdown_provider=md_provider, + anchor_provider=PdfplumberAnchorProvider(), + alignment_uniqueness_threshold=config.uniqueness_threshold, + alignment_min_overlap=config.min_overlap, + ) + + return ProcessResult( + annotated_markdown=result.annotate(), + coverage_percent=result.coverage_percent, + ) + + +class _CachedMarkdownProvider: + """Returns pre-generated markdown, ignoring the chunk.""" + + def __init__(self, markdown: str) -> None: + self._markdown = markdown + + async def generate_markdown(self, _chunk: DocumentChunk) -> str: + return self._markdown diff --git a/src/groundmark/visualize.py b/src/groundmark/visualize.py new file mode 100644 index 0000000..ca57e8a --- /dev/null +++ b/src/groundmark/visualize.py @@ -0,0 +1,201 @@ +"""Debug visualizer: overlay bounding boxes from annotated Markdown onto the source PDF.""" + +import asyncio +import io +import logging +import re +import sys +import time +from pathlib import Path +from typing import Annotated + +import typer +from anchorite import Anchor, align, annotate +from anchorite.document import chunks +from pypdf import PdfReader, PdfWriter +from pypdf.annotations import Highlight +from pypdf.generic import ArrayObject, FloatObject + +from groundmark.markdown import PydanticAIMarkdownProvider +from groundmark.parse import PdfplumberAnchorProvider + +_SPAN_RE = re.compile( + r'(.*?)', + re.DOTALL, +) + +app = typer.Typer() + + +def _log(msg: str) -> None: + print(msg, file=sys.stderr) + + +def _add_highlight( + writer: PdfWriter, + page_num: int, + bbox: tuple[int, int, int, int], + page_width: float, + page_height: float, + *, + color: tuple[float, float, float], +) -> None: + top, left, bottom, right = bbox + # Convert from 0-1000 scale to PDF coordinates (bottom-left origin). + x0 = left / 1000 * page_width + x1 = right / 1000 * page_width + y0 = page_height - bottom / 1000 * page_height + y1 = page_height - top / 1000 * page_height + + hex_color = "".join(f"{int(c * 255):02x}" for c in color) + quad_points = ArrayObject( + [ + FloatObject(x0), + FloatObject(y1), # top-left + FloatObject(x1), + FloatObject(y1), # top-right + FloatObject(x0), + FloatObject(y0), # bottom-left + FloatObject(x1), + FloatObject(y0), # bottom-right + ] + ) + annotation = Highlight( + rect=(x0, y0, x1, y1), + quad_points=quad_points, + highlight_color=hex_color, + ) + writer.add_annotation(page_number=page_num, annotation=annotation) + + +def _overlay_bboxes( + pdf_bytes: bytes, + annotated_markdown: str, + raw_anchors: list[Anchor], +) -> bytes: + """Draw bounding box highlights onto the PDF. + + Blue = raw extracted boxes, Red = aligned (from annotated Markdown). + """ + reader = PdfReader(io.BytesIO(pdf_bytes)) + writer = PdfWriter() + writer.append_pages_from_reader(reader) + + # Blue: raw extracted boxes. + for anchor in raw_anchors: + if anchor.page >= len(reader.pages): + continue + page = reader.pages[anchor.page] + pw = float(page.mediabox.width) + ph = float(page.mediabox.height) + box = anchor.box + _add_highlight(writer, anchor.page, (box.top, box.left, box.bottom, box.right), pw, ph, color=(0.8, 0.9, 1)) + + # Red: aligned boxes from annotated Markdown. + for match in _SPAN_RE.finditer(annotated_markdown): + top, left, bottom, right = int(match[1]), int(match[2]), int(match[3]), int(match[4]) + page_num = int(match[5]) + if page_num >= len(reader.pages): + continue + page = reader.pages[page_num] + pw = float(page.mediabox.width) + ph = float(page.mediabox.height) + _add_highlight(writer, page_num, (top, left, bottom, right), pw, ph, color=(1, 0.85, 0.85)) + + buf = io.BytesIO() + writer.write(buf) + return buf.getvalue() + + +@app.command() +def visualize( + input_pdf: Annotated[Path, typer.Argument(help="Path to the source PDF.")], + output_pdf: Annotated[Path, typer.Argument(help="Path for the output PDF with bbox overlays.")], + model: Annotated[str, typer.Option(help="Pydantic AI model string.")] = "", + markdown_file: Annotated[Path | None, typer.Option("--markdown", "-m", help="Cached Markdown file.")] = None, + uniqueness_threshold: Annotated[float, typer.Option("--threshold", "-t")] = 0.5, + min_overlap: Annotated[float, typer.Option("--overlap", "-o")] = 0.9, + page_count: Annotated[int | None, typer.Option("--page-count", "-p", help="Pages per chunk.")] = None, + verbose: Annotated[bool, typer.Option("--verbose", "-v", help="Enable debug logging.")] = False, +) -> None: + """Run the groundmark pipeline on a PDF and overlay bounding boxes.""" + if verbose: + logging.basicConfig(level=logging.DEBUG, stream=sys.stderr) + + if not markdown_file and not model: + _log("Error: provide --model or --markdown") + raise SystemExit(1) + + asyncio.run( + _run( + input_pdf, + output_pdf, + model, + markdown_file, + uniqueness_threshold, + min_overlap, + page_count, + ) + ) + + +async def _run( + input_pdf: Path, + output_pdf: Path, + model: str, + markdown_file: Path | None, + uniqueness_threshold: float, + min_overlap: float, + page_count: int | None, +) -> None: + pdf_bytes = input_pdf.read_bytes() + doc_chunks = list(chunks(pdf_bytes, page_count=page_count)) + t0 = time.perf_counter() + + # Extract anchors (bounding boxes) from the PDF. + _log("Extracting bounding boxes...") + t = time.perf_counter() + provider = PdfplumberAnchorProvider() + all_anchors = await asyncio.gather(*(provider.generate_anchors(c) for c in doc_chunks)) + flat_anchors = [a for chunk_anchors in all_anchors for a in chunk_anchors] + _log(f" {len(flat_anchors)} bounding boxes ({time.perf_counter() - t:.1f}s)") + + # Generate or load Markdown. + if markdown_file: + markdown = markdown_file.read_text() + _log(f" Loaded cached Markdown from {markdown_file}") + else: + _log("Generating Markdown...") + t = time.perf_counter() + md_provider = PydanticAIMarkdownProvider(model) + md_chunks = await asyncio.gather(*(md_provider.generate_markdown(c) for c in doc_chunks)) + markdown = "\n\n\n\n".join(md_chunks) + _log(f" {len(markdown)} chars ({time.perf_counter() - t:.1f}s)") + + # Write plain markdown before alignment so it's available even if alignment hangs. + if not markdown_file: + md_path = output_pdf.with_suffix(".md") + md_path.write_text(markdown) + _log(f" Markdown written to {md_path}") + + # Align anchors to Markdown. + _log("Aligning...") + t = time.perf_counter() + alignment = align( + flat_anchors, + markdown, + uniqueness_threshold=uniqueness_threshold, + min_overlap=min_overlap, + ) + annotated_markdown = annotate(markdown, alignment) + coverage = sum(e - s for s, e in alignment.values()) / len(markdown) if markdown else 0.0 + _log(f" {coverage:.1%} coverage ({time.perf_counter() - t:.1f}s)") + + output_bytes = _overlay_bboxes(pdf_bytes, annotated_markdown, flat_anchors) + output_pdf.write_bytes(output_bytes) + _log(f" Output written to {output_pdf}") + _log(f"Total: {time.perf_counter() - t0:.1f}s") + + +if __name__ == "__main__": + app() diff --git a/tests/data/hello_world.pdf b/tests/data/hello_world.pdf new file mode 100644 index 0000000..985e3f0 Binary files /dev/null and b/tests/data/hello_world.pdf differ diff --git a/tests/data/hubble-1929.pdf b/tests/data/hubble-1929.pdf deleted file mode 100644 index 425e8c2..0000000 Binary files a/tests/data/hubble-1929.pdf and /dev/null differ diff --git a/tests/data/simple_hello.pdf b/tests/data/simple_hello.pdf new file mode 100644 index 0000000..da5f6e7 Binary files /dev/null and b/tests/data/simple_hello.pdf differ diff --git a/tests/data/table_2x2.pdf b/tests/data/table_2x2.pdf new file mode 100644 index 0000000..892cb58 Binary files /dev/null and b/tests/data/table_2x2.pdf differ diff --git a/tests/fixtures/hubble_docai_bboxes.pkl b/tests/fixtures/hubble_docai_bboxes.pkl deleted file mode 100644 index b93555b..0000000 Binary files a/tests/fixtures/hubble_docai_bboxes.pkl and /dev/null differ diff --git a/tests/fixtures/hubble_docai_golden.md b/tests/fixtures/hubble_docai_golden.md deleted file mode 100644 index 418d2fd..0000000 --- a/tests/fixtures/hubble_docai_golden.md +++ /dev/null @@ -1,275 +0,0 @@ -appearance the spectrum is very much like spectra of the Milky Way -clouds in Sagittarius and Cygnus, and is also similar to spectra of -binary stars of the W Ursae Majoris type, where the widening and depth -of the lines are affected by the rapid rotation of the stars involved. -The wide shallow absorption lines observed in the spectrum of N. G. C. -7619 have been noticed in the spectra of other extra-galactic nebulae, -and may be due to a dispersion in velocity and a blending of the -spectral types of the many stars which presumably exist in the central -parts of these nebulae. The lack of depth in the absorption lines -seems to be more pronounced among the smaller and fainter nebulae, and -in N. G. C. 7619 the absorption is very weak. It is hoped that -velocities of more of these interesting objects will soon be -available. - -## A RELATION BETWEEN DISTANCE AND RADIAL VELOCITY AMONG EXTRA-GALACTIC NEBULAE - -BY EDWIN HUBBLE MOUNT WILSON OBSERVATORY, CARNEGIE INSTITUTION OF -WASHINGTON Communicated January 17, 1929 Determinations of the motion -of the sun with respect to the extra-galactic nebulae have involved a -$K$ term of several hundred kilometers which appears to be variable. -Explanations of this paradox have been sought in a correlation between -apparent radial velocities and distances, but so far the results have -not been convincing. The present paper is a re-examination of the -question, based on only those nebular distances which are believed to -be fairly reliable. Distances of extra-galactic nebulae depend -ultimately upon the appli-cation of absolute-luminosity criteria to -involved stars whose types can be recognized. These include, among -others, Cepheid variables, novae, and blue stars involved in emission -nebulosity. Numerical values depend upon the zero point of the period- -luminosity relation among Cepheids, the other criteria merely check -the order of the distances. This method is restricted to the few -nebulae which are well resolved by existing instruments. A study of -these nebulae, together with those in which any stars at all can be -recognized, indicates the probability of an approximately uniform -upper limit to the absolute luminosity of stars, in the late-type -spirals and irregular nebulae at least, of the order of $M$ -(photographic) $=-6.3$. 1 The apparent luminosities of the brightest -stars in such nebulae are thus criteria which, although rough and to -be applied with caution, - -furnish reasonable estimates of the distances of all extra-galactic -systems in which even a few stars can be detected. - -## TABLE 1 - -NEBULAE WHOSE DISTANCES HAVE BEEN ESTIMATED FROM STARS INVOLVED OR -FROM MEAN LUMINOSITIES IN A CLUSTER - - -| OBJECT | $m$ | $r$ | | $m_{t}$ | $M$ | -| --- | --- | --- | --- | --- | --- | -| S. Mag. | | 0.032 | + 170 | 1.5 | -16.0 | -| L. Mag. | .. | 0.034 | + 290 | 0.5 | 17.2 | -| N. G. C. 6822 | | 0.214 | — 130 | 9.0 | 12.7 | -| 598 | .. | 0.263 | — 70 | 7.0 | 15.1 | -| 221 | .. | 0.275 | — 185 | 8.8 | 13.4 | -| 224 | .. | 0.275 | — 220 | 5.0 | 17.2 | -| 5457 | 17.0 | 0.45 | + 200 | 9.9 | 13.3 | -| 4736 | 17.3 | 0.5 | + 290 | 8.4 | 15.1 | -| 5194 | 17.3 | 0.5 | + 270 | 7.4 | 16.1 | -| 4449 | 17.8 | 0.63 | + 200 | 9.5 | 14.5 | -| 4214 | 18.3 | 0.8 | + 300 | 11.3 | 13.2 | -| 3031 | 18.5 | 0.9 | — 30 | 8.3 | 16.4 | -| 3627 | 18.5 | 0.9 | + 650 | 9.1 | 15.7 | -| 4826 | 18.5 | 0.9 | + 150 | 9.0 | 15.7 | -| 5236 | 18.5 | 0.9 | + 500 | 10.4 | 14.4 | -| 1068 | 18.7 | 1.0 | + 920 | 9.1 | 15.9 | -| 5055 | 19.0 | 1.1 | + 450 | 9.6 | 15.6 | -| 7331 | 19.0 | 1.1 | + 500 | 10.4 | 14.8 | -| 4258 | 19.5 | 1.4 | + 500 | 8.7 | 17.0 | -| 4151 | 20.0 | 1.7 | + 960 | 12.0 | 14.2 | -| 4382 | .. | 2.0 | + 500 | 10.0 | 16.5 | -| 4472 | .. | 2.0 | + 850 | 8.8 | 17.7 | -| 4486 | .. | 2.0 | + 800 | 9.7 | 16.8 | -| 4649 | .. | 2.0 | +1090 | 9.5 | 17.0 | -| Mean | | | | | -15.5 | - - -$m_{s}$= photographic magnitude of brightest stars involved. $r$= -distance in units of $10^{6}$ parsecs. The first two are Shapley's -values. $v$= measured velocities in km./sec. N. G. C. 6822, 221, 224 -and 5457 are recent determinations by Humason. $m_{i}$= Holetschek's -visual magnitude as corrected by Hopmann. The first three objects were -not measured by Holetschek, and the values of $m_{i}$ represent -estimates by the author based upon such data as are available. -$M_{t}$= total visual absolute magnitude computed from $m_{t}$ and -$r$. Finally, the nebulae themselves appear to be of a definite order -of absolute luminosity, exhibiting a range of four or five magnitudes -about an average value M (visual) = $-15.2.^{1}$ The application of -this statistical average to individual cases can rarely be used to -advantage, but where considerable numbers are involved, and especially -in the various clusters of nebulae, mean apparent luminosities of the -nebulae themselves offer reliable estimates of the mean distances. -Radial velocities of 46 extra-galactic nebulae are now available, but - -individual distances are estimated for only 24. For one other, N. G. -C. 3521, an estimate could probably be made, but no photographs are -available at Mount Wilson. The data are given in table 1. The first -seven distances are the most reliable, depending, except for M 32 the -companion of M 31, upon extensive investigations of many stars -involved. The next thirteen distances, depending upon the criterion of -a uniform upper limit of stellar luminosity, are subject to -considerable probable errors but are believed to be the most -reasonable values at present available. The last four objects appear -to be in the Virgo Cluster. The distance assigned to the cluster, $2 -\times 10^{6}$ parsecs, is derived from the distribution of nebular -luminosities, together with luminosities of stars in some of the -later-type spirals, and differs somewhat from the Harvard estimate of -ten million light years. 2 The data in the table indicate a linear -correlation between distances and velocities, whether the latter are -used directly or corrected for solar motion, according to the older -solutions. This suggests a new solution for the solar motion in which -the distances are introduced as coefficients of the K term, i. e., the -velocities are assumed to vary directly with the distances, and hence -K represents the velocity at unit distance due to this effect. The -equations of condition then take the form $rK + X \cos \alpha \cos -\delta + Y \sin \alpha \cos \delta + Z \sin \delta = v$ Two solutions -have been made, one using the 24 nebulae individually, the other -combining them into 9 groups according to proximity in direction and -in distance. The results are - - -| | | | -| --- | --- | --- | -| | 24 OBJECTS | 9 GROUPS | -| X | $- 65 \pm 50$ | $+ 3 \pm 70$ | -| Y | $+226 \pm 95$ | $+230 \pm 120$ | -| Z | $-195 \pm 40$ | $-133 \pm 70$ | -| K | $+465 \pm 50$ | $+513 \pm 60$ km./sec. per $10^{6}$ parsecs. | -| A | $286^{\circ}$ | $269^{\circ}$ | -| D | $+40^{\circ}$ | $+33^{\circ}$ | -| $V_{0}$ | 306 km./sec. | 247 km./sec. | - - -For such scanty material, so poorly distributed, the results are -fairly definite. Differences between the two solutions are due largely -to the four Virgo nebulae, which, being the most distant objects and -all sharing the peculiar motion of the cluster, unduly influence the -value of K and hence of $V_{0}$. New data on more distant objects will -be required to reduce the effect of such peculiar motion. Meanwhile -round numbers, intermediate between the two solutions, will represent -the probable order of the values. For instance, let $A = 277^{\circ}$, -$D = +36^{\circ}$ (Gal. long. $= 32^{\circ}$, lat. $= +18^{\circ}$), -$V_{0} = 280$ km./sec., $K = +500$ km./sec. per million par- - -secs. Mr. Strömberg has very kindly checked the general order of these -values by independent solutions for different groupings of the data. A -constant term, introduced into the equations, was found to be small -and negative. This seems to dispose of the necessity for the old -constant $K$ term. Solutions of this sort have been published by -Lundmark, who replaced the old $K$ by $k+lr+mr^{2}$. His favored -solution gave $k=513$, as against the former value of the order of -700, and hence offered little advantage. - - -| | | | | | | | -| --- | --- | --- | --- | --- | --- | --- | -| | | | $r$ | $m$ | $M_{c}$ | | -| N. G. C. | OBJECT | | | | | | -| | 278 | $+ 650$ | $-110$ | 1.52 | 12.0 | $–13.9$ | -| | 404 | $– 25$ | $– 65$ | ... | 11.1 | .. | -| | 584 | $+1800$ | $+ 75$ | 3.45 | 10.9 | 16.8 | -| | 936 | $+1300$ | $+115$ | 2.37 | 11.1 | 15.7 | -| | 1023 | $+ 300$ | $– 10$ | 0.62 | 10.2 | 13.8 | -| | 1700 | $+ 800$ | $+220$ | 1.16 | 12.5 | 12.8 | -| | 2681 | $+ 700$ | $– 10$ | 1.42 | 10.7 | 15.0 | -| | 2683 | $+ 400$ | $+ 65$ | 0.67 | 9.9 | 14.3 | -| | 2841 | $+ 600$ | $– 20$ | 1.24 | 9.4 | 16.1 | -| | 3034 | $+ 290$ | $–105$ | 0.79 | 9.0 | 15.5 | -| | 3115 | $+ 600$ | $+105$ | 1.00 | 9.5 | 15.5 | -| | 3368 | $+ 940$ | $+ 70$ | 1.74 | 10.0 | 16.2 | -| | 3379 | $+ 810$ | $+ 65$ | 1.49 | 9.4 | 16.4 | -| | 3489 | $+ 600$ | $+ 50$ | 1.10 | 11.2 | 14.0 | -| | 3521 | $+ 730$ | $+ 95$ | 1.27 | 10.1 | 15.4 | -| | 3623 | $+ 800$ | $+ 35$ | 1.53 | 9.9 | 16.0 | -| | 4111 | $+ 800$ | $– 95$ | 1.79 | 10.1 | 16.1 | -| | 4526 | $+ 580$ | $– 20$ | 1.20 | 11.1 | 14.3 | -| | 4565 | $+1100$ | $– 75$ | 2.35 | 11.0 | 15.9 | -| | 4594 | $+1140$ | $+ 25$ | 2.23 | 9.1 | 17.6 | -| | 5005 | $+ 900$ | $-130$ | 2.06 | 11.1 | 15.5 | -| | 5866 | $+ 650$ | $-215$ | 1.73 | 11.7 | $–14.5$ | -| Mean | | | | 10.5 | $–15.3$ | | - - -The residuals for the two solutions given above average 150 and 110 -km./sec. and should represent the average peculiar motions of the -individual nebulae and of the groups, respectively. In order to -exhibit the results in a graphical form, the solar motion has been -eliminated from the observed velocities and the remainders, the -distance terms plus the residuals, have been plotted against the -distances. The run of the residuals is about as smooth as can be -expected, and in general the form of the solutions appears to be -adequate. The 22 nebulae for which distances are not available can be -treated in two ways. First, the mean distance of the group derived -from the mean apparent magnitudes can be compared with the mean of the -velocities Downloaded from https://www.pnas.org by 45.113.94.70 on -January 5, 2026 from IP address 45.113.94.70. - -corrected for solar motion. The result, 745 km./sec. for a distance of -$1.4 \times 10^{6}$ parsecs, falls between the two previous solutions -and indicates a value for K of 530 as against the proposed value, 500 -km./sec. Secondly, the scatter of the individual nebulae can be -examined by assuming the relation between distances and velocities as -previously determined. Distances can then be calculated from the -velocities corrected for solar motion, and absolute magnitudes can be -derived from the apparent magnitudes. The results are given in table 2 -and may be compared with the distribution of absolute magnitudes among -the nebulae in talbe 1, whose distances are derived from other -criteria. N. G. C. 404 FIGURE 1 Velocity-Distance Relation among -Extra-Galactic Nebulae. Radial velocities, corrected for solar motion, -are plotted against distances estimated from involved stars and mean -luminosities of nebulae in a cluster. The black discs and full line -represent the solution for solar motion using the nebulae -individually; the circles and broken line represent the solution -combining the nebulae into groups; the cross represents the mean -velocity corresponding to the mean distance of 22 nebulae whose -distances could not be estimated individually. can be excluded, since -the observed velocity is so small that the peculiar motion must be -large in comparison with the distance effect. The object is not -necessarily an exception, however, since a distance can be assigned -for which the peculiar motion and the absolute magnitude are both -within the range previously determined. The two mean magnitudes, -15.3 -and -15.5, the ranges, 4.9 and 5.0 mag., and the frequency -distributions are closely similar for these two entirely independent -sets of data; and even the slight difference in mean magnitudes can be -attributed to the selected, very bright, nebulae in the Virgo Cluster. -This entirely unforced agreement supports the validity of the -velocity-distance relation in a very - -evident matter. Finally, it is worth recording that the frequency -distribution of absolute magnitudes in the two tables combined is -comparable with those found in the various clusters of nebulae. The -results establish a roughly linear relation between velocities and -distances among nebulae for which velocities have been previously -published, and the relation appears to dominate the distribution of -velocities. In order to investigate the matter on a much larger scale, -Mr. Humason at Mount Wilson has initiated a program of determining -velocities of the most distant nebulae that can be observed with -confidence. These, naturally, are the brightest nebulae in clusters of -nebulae. The first definite result, $v = +3779 ~km./sec.$ for N. G. C. -7619, is thoroughly consistent with the present conclusions. Corrected -for the solar motion, this velocity is $+3910$, which, with $K = 500$, -corresponds to a distance of $7.8 \times 10^{6}$ parsecs. Since the -apparent magnitude is 11.8, the absolute magnitude at such a distance -is $-17.65$, which is of the right order for the brightest nebulae in -a cluster. A preliminary distance, derived independently from the -cluster of which this nebula appears to be a member, is of the order -of $7 \times 10^{6}$ parsecs. New data to be expected in the near -future may modify the significance of the present investigation or, if -confirmatory, will lead to a solution having many times the weight. -For this reason it is thought premature to discuss in detail the -obvious consequences of the present results. For example, if the solar -motion with respect to the clusters represents the rotation of the -galactic system, this motion could be subtracted from the results for -the nebulae and the remainder would represent the motion of the -galactic system with respect to the extra-galactic nebulae. The -outstanding feature, however, is the possibility that the velocity- -distance relation may represent the de Sitter effect, and hence that -numerical data may be introduced into discussions of the general -curvature of space. In the de Sitter cosmology, displacements of the -spectra arise from two sources, an apparent slowing down of atomic -vibrations and a general tendency of material particles to scatter. -The latter involves an acceleration and hence introduces the element -of time. The relative importance of these two effects should determine -the form of the relation between distances and observed velocities; -and in this connection it may be emphasized that the linear relation -found in the present discussion is a first approximation representing -a restricted range in distance. - -- Mt. Wilson Contr., No. 324; Astroph. J., Chicago, Ill., 64, 1926 - (321). -- Harvard Coll. Obs. Circ., 294, 1926. -- Mon. Not. R. Astr. Soc., 85, 1925 (865-894). -- These PROCEEDINGS, 15, 1929 (167). - diff --git a/tests/fixtures/hubble_docai_layout_responses.json b/tests/fixtures/hubble_docai_layout_responses.json deleted file mode 100644 index ef71e9f..0000000 --- a/tests/fixtures/hubble_docai_layout_responses.json +++ /dev/null @@ -1 +0,0 @@ -["{\n \"documentLayout\": {\n \"blocks\": [\n {\n \"blockId\": \"1\",\n \"textBlock\": {\n \"text\": \"168 ASTRONOMY: E. HUBBLE PROC. N. A. S.\",\n \"type\": \"header\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 1,\n \"pageEnd\": 1\n }\n },\n {\n \"blockId\": \"2\",\n \"textBlock\": {\n \"text\": \"appearance the spectrum is very much like spectra of the Milky Way clouds in Sagittarius and Cygnus, and is also similar to spectra of binary stars of the W Ursae Majoris type, where the widening and depth of the lines are affected by the rapid rotation of the stars involved. The wide shallow absorption lines observed in the spectrum of N. G. C. 7619 have been noticed in the spectra of other extra-galactic nebulae, and may be due to a dispersion in velocity and a blending of the spectral types of the many stars which presumably exist in the central parts of these nebulae. The lack of depth in the absorption lines seems to be more pronounced among the smaller and fainter nebulae, and in N. G. C. 7619 the absorption is very weak. It is hoped that velocities of more of these interesting objects will soon be available.\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 1,\n \"pageEnd\": 1\n }\n },\n {\n \"blockId\": \"3\",\n \"textBlock\": {\n \"text\": \"A RELATION BETWEEN DISTANCE AND RADIAL VELOCITY AMONG EXTRA-GALACTIC NEBULAE\",\n \"type\": \"heading-2\",\n \"blocks\": [\n {\n \"blockId\": \"4\",\n \"textBlock\": {\n \"text\": \"BY EDWIN HUBBLE MOUNT WILSON OBSERVATORY, CARNEGIE INSTITUTION OF WASHINGTON Communicated January 17, 1929 Determinations of the motion of the sun with respect to the extra-galactic nebulae have involved a \\\\(K\\\\) term of several hundred kilometers which appears to be variable. Explanations of this paradox have been sought in a correlation between apparent radial velocities and distances, but so far the results have not been convincing. The present paper is a re-examination of the question, based on only those nebular distances which are believed to be fairly reliable. Distances of extra-galactic nebulae depend ultimately upon the appli-cation of absolute-luminosity criteria to involved stars whose types can be recognized. These include, among others, Cepheid variables, novae, and blue stars involved in emission nebulosity. Numerical values depend upon the zero point of the period-luminosity relation among Cepheids, the other criteria merely check the order of the distances. This method is restricted to the few nebulae which are well resolved by existing instruments. A study of these nebulae, together with those in which any stars at all can be recognized, indicates the probability of an approximately uniform upper limit to the absolute luminosity of stars, in the late-type spirals and irregular nebulae at least, of the order of \\\\(M\\\\) (photographic) \\\\(=-6.3\\\\). 1 The apparent luminosities of the brightest stars in such nebulae are thus criteria which, although rough and to be applied with caution,\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 1,\n \"pageEnd\": 1\n }\n },\n {\n \"blockId\": \"5\",\n \"textBlock\": {\n \"text\": \"Downloaded from https://www.pnas.org by 45.113.94.70 on January 5, 2026 from IP address 45.113.94.70.\",\n \"type\": \"footer\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 1,\n \"pageEnd\": 1\n }\n },\n {\n \"blockId\": \"6\",\n \"textBlock\": {\n \"text\": \"VOL. 15, 1929 ASTRONOMY: E. HUBBLE 169\",\n \"type\": \"header\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n },\n {\n \"blockId\": \"7\",\n \"textBlock\": {\n \"text\": \"furnish reasonable estimates of the distances of all extra-galactic systems in which even a few stars can be detected.\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ]\n },\n \"pageSpan\": {\n \"pageStart\": 1,\n \"pageEnd\": 2\n }\n },\n {\n \"blockId\": \"8\",\n \"textBlock\": {\n \"text\": \"TABLE 1\",\n \"type\": \"heading-2\",\n \"blocks\": [\n {\n \"blockId\": \"9\",\n \"textBlock\": {\n \"text\": \"NEBULAE WHOSE DISTANCES HAVE BEEN ESTIMATED FROM STARS INVOLVED OR FROM MEAN LUMINOSITIES IN A CLUSTER\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n },\n {\n \"blockId\": \"10\",\n \"tableBlock\": {\n \"headerRows\": [\n {\n \"cells\": [\n {\n \"blocks\": [\n {\n \"blockId\": \"155\",\n \"textBlock\": {\n \"text\": \"OBJECT\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"156\",\n \"textBlock\": {\n \"text\": \"\\\\(m\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"157\",\n \"textBlock\": {\n \"text\": \"\\\\(r\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"rowSpan\": 1,\n \"colSpan\": 1,\n \"blocks\": []\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"158\",\n \"textBlock\": {\n \"text\": \"\\\\(m_{t}\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"159\",\n \"textBlock\": {\n \"text\": \"\\\\(M\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n }\n ],\n \"bodyRows\": [\n {\n \"cells\": [\n {\n \"blocks\": [\n {\n \"blockId\": \"11\",\n \"textBlock\": {\n \"text\": \"S. Mag.\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"rowSpan\": 1,\n \"colSpan\": 1,\n \"blocks\": []\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"12\",\n \"textBlock\": {\n \"text\": \"0.032\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"13\",\n \"textBlock\": {\n \"text\": \"+ 170\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"14\",\n \"textBlock\": {\n \"text\": \"1.5\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"15\",\n \"textBlock\": {\n \"text\": \"-16.0\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"blocks\": [\n {\n \"blockId\": \"16\",\n \"textBlock\": {\n \"text\": \"L. Mag.\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"17\",\n \"textBlock\": {\n \"text\": \"..\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"18\",\n \"textBlock\": {\n \"text\": \"0.034\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"19\",\n \"textBlock\": {\n \"text\": \"+ 290\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"20\",\n \"textBlock\": {\n \"text\": \"0.5\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"21\",\n \"textBlock\": {\n \"text\": \"17.2\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"blocks\": [\n {\n \"blockId\": \"22\",\n \"textBlock\": {\n \"text\": \"N. G. C. 6822\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"rowSpan\": 1,\n \"colSpan\": 1,\n \"blocks\": []\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"23\",\n \"textBlock\": {\n \"text\": \"0.214\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"24\",\n \"textBlock\": {\n \"text\": \"\\u2014 130\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"25\",\n \"textBlock\": {\n \"text\": \"9.0\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"26\",\n \"textBlock\": {\n \"text\": \"12.7\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"blocks\": [\n {\n \"blockId\": \"27\",\n \"textBlock\": {\n \"text\": \"598\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"28\",\n \"textBlock\": {\n \"text\": \"..\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"29\",\n \"textBlock\": {\n \"text\": \"0.263\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"30\",\n \"textBlock\": {\n \"text\": \"\\u2014 70\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"31\",\n \"textBlock\": {\n \"text\": \"7.0\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"32\",\n \"textBlock\": {\n \"text\": \"15.1\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"blocks\": [\n {\n \"blockId\": \"33\",\n \"textBlock\": {\n \"text\": \"221\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"34\",\n \"textBlock\": {\n \"text\": \"..\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"35\",\n \"textBlock\": {\n \"text\": \"0.275\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"36\",\n \"textBlock\": {\n \"text\": \"\\u2014 185\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"37\",\n \"textBlock\": {\n \"text\": \"8.8\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"38\",\n \"textBlock\": {\n \"text\": \"13.4\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"blocks\": [\n {\n \"blockId\": \"39\",\n \"textBlock\": {\n \"text\": \"224\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"40\",\n \"textBlock\": {\n \"text\": \"..\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"41\",\n \"textBlock\": {\n \"text\": \"0.275\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"42\",\n \"textBlock\": {\n \"text\": \"\\u2014 220\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"43\",\n \"textBlock\": {\n \"text\": \"5.0\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"44\",\n \"textBlock\": {\n \"text\": \"17.2\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"blocks\": [\n {\n \"blockId\": \"45\",\n \"textBlock\": {\n \"text\": \"5457\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"46\",\n \"textBlock\": {\n \"text\": \"17.0\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"47\",\n \"textBlock\": {\n \"text\": \"0.45\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"48\",\n \"textBlock\": {\n \"text\": \"+ 200\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"49\",\n \"textBlock\": {\n \"text\": \"9.9\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"50\",\n \"textBlock\": {\n \"text\": \"13.3\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"blocks\": [\n {\n \"blockId\": \"51\",\n \"textBlock\": {\n \"text\": \"4736\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"52\",\n \"textBlock\": {\n \"text\": \"17.3\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"53\",\n \"textBlock\": {\n \"text\": \"0.5\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"54\",\n \"textBlock\": {\n \"text\": \"+ 290\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"55\",\n \"textBlock\": {\n \"text\": \"8.4\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"56\",\n \"textBlock\": {\n \"text\": \"15.1\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"blocks\": [\n {\n \"blockId\": \"57\",\n \"textBlock\": {\n \"text\": \"5194\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"58\",\n \"textBlock\": {\n \"text\": \"17.3\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"59\",\n \"textBlock\": {\n \"text\": \"0.5\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"60\",\n \"textBlock\": {\n \"text\": \"+ 270\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"61\",\n \"textBlock\": {\n \"text\": \"7.4\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"62\",\n \"textBlock\": {\n \"text\": \"16.1\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"blocks\": [\n {\n \"blockId\": \"63\",\n \"textBlock\": {\n \"text\": \"4449\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"64\",\n \"textBlock\": {\n \"text\": \"17.8\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"65\",\n \"textBlock\": {\n \"text\": \"0.63\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"66\",\n \"textBlock\": {\n \"text\": \"+ 200\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"67\",\n \"textBlock\": {\n \"text\": \"9.5\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"68\",\n \"textBlock\": {\n \"text\": \"14.5\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"blocks\": [\n {\n \"blockId\": \"69\",\n \"textBlock\": {\n \"text\": \"4214\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"70\",\n \"textBlock\": {\n \"text\": \"18.3\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"71\",\n \"textBlock\": {\n \"text\": \"0.8\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"72\",\n \"textBlock\": {\n \"text\": \"+ 300\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"73\",\n \"textBlock\": {\n \"text\": \"11.3\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"74\",\n \"textBlock\": {\n \"text\": \"13.2\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"blocks\": [\n {\n \"blockId\": \"75\",\n \"textBlock\": {\n \"text\": \"3031\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"76\",\n \"textBlock\": {\n \"text\": \"18.5\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"77\",\n \"textBlock\": {\n \"text\": \"0.9\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"78\",\n \"textBlock\": {\n \"text\": \"\\u2014 30\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"79\",\n \"textBlock\": {\n \"text\": \"8.3\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"80\",\n \"textBlock\": {\n \"text\": \"16.4\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"blocks\": [\n {\n \"blockId\": \"81\",\n \"textBlock\": {\n \"text\": \"3627\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"82\",\n \"textBlock\": {\n \"text\": \"18.5\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"83\",\n \"textBlock\": {\n \"text\": \"0.9\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"84\",\n \"textBlock\": {\n \"text\": \"+ 650\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"85\",\n \"textBlock\": {\n \"text\": \"9.1\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"86\",\n \"textBlock\": {\n \"text\": \"15.7\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"blocks\": [\n {\n \"blockId\": \"87\",\n \"textBlock\": {\n \"text\": \"4826\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"88\",\n \"textBlock\": {\n \"text\": \"18.5\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"89\",\n \"textBlock\": {\n \"text\": \"0.9\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"90\",\n \"textBlock\": {\n \"text\": \"+ 150\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"91\",\n \"textBlock\": {\n \"text\": \"9.0\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"92\",\n \"textBlock\": {\n \"text\": \"15.7\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"blocks\": [\n {\n \"blockId\": \"93\",\n \"textBlock\": {\n \"text\": \"5236\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"94\",\n \"textBlock\": {\n \"text\": \"18.5\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"95\",\n \"textBlock\": {\n \"text\": \"0.9\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"96\",\n \"textBlock\": {\n \"text\": \"+ 500\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"97\",\n \"textBlock\": {\n \"text\": \"10.4\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"98\",\n \"textBlock\": {\n \"text\": \"14.4\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"blocks\": [\n {\n \"blockId\": \"99\",\n \"textBlock\": {\n \"text\": \"1068\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"100\",\n \"textBlock\": {\n \"text\": \"18.7\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"101\",\n \"textBlock\": {\n \"text\": \"1.0\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"102\",\n \"textBlock\": {\n \"text\": \"+ 920\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"103\",\n \"textBlock\": {\n \"text\": \"9.1\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"104\",\n \"textBlock\": {\n \"text\": \"15.9\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"blocks\": [\n {\n \"blockId\": \"105\",\n \"textBlock\": {\n \"text\": \"5055\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"106\",\n \"textBlock\": {\n \"text\": \"19.0\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"107\",\n \"textBlock\": {\n \"text\": \"1.1\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"108\",\n \"textBlock\": {\n \"text\": \"+ 450\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"109\",\n \"textBlock\": {\n \"text\": \"9.6\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"110\",\n \"textBlock\": {\n \"text\": \"15.6\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"blocks\": [\n {\n \"blockId\": \"111\",\n \"textBlock\": {\n \"text\": \"7331\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"112\",\n \"textBlock\": {\n \"text\": \"19.0\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"113\",\n \"textBlock\": {\n \"text\": \"1.1\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"114\",\n \"textBlock\": {\n \"text\": \"+ 500\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"115\",\n \"textBlock\": {\n \"text\": \"10.4\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"116\",\n \"textBlock\": {\n \"text\": \"14.8\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"blocks\": [\n {\n \"blockId\": \"117\",\n \"textBlock\": {\n \"text\": \"4258\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"118\",\n \"textBlock\": {\n \"text\": \"19.5\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"119\",\n \"textBlock\": {\n \"text\": \"1.4\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"120\",\n \"textBlock\": {\n \"text\": \"+ 500\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"121\",\n \"textBlock\": {\n \"text\": \"8.7\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"122\",\n \"textBlock\": {\n \"text\": \"17.0\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"blocks\": [\n {\n \"blockId\": \"123\",\n \"textBlock\": {\n \"text\": \"4151\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"124\",\n \"textBlock\": {\n \"text\": \"20.0\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"125\",\n \"textBlock\": {\n \"text\": \"1.7\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"126\",\n \"textBlock\": {\n \"text\": \"+ 960\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"127\",\n \"textBlock\": {\n \"text\": \"12.0\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"128\",\n \"textBlock\": {\n \"text\": \"14.2\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"blocks\": [\n {\n \"blockId\": \"129\",\n \"textBlock\": {\n \"text\": \"4382\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"130\",\n \"textBlock\": {\n \"text\": \"..\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"131\",\n \"textBlock\": {\n \"text\": \"2.0\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"132\",\n \"textBlock\": {\n \"text\": \"+ 500\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"133\",\n \"textBlock\": {\n \"text\": \"10.0\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"134\",\n \"textBlock\": {\n \"text\": \"16.5\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"blocks\": [\n {\n \"blockId\": \"135\",\n \"textBlock\": {\n \"text\": \"4472\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"136\",\n \"textBlock\": {\n \"text\": \"..\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"137\",\n \"textBlock\": {\n \"text\": \"2.0\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"138\",\n \"textBlock\": {\n \"text\": \"+ 850\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"139\",\n \"textBlock\": {\n \"text\": \"8.8\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"140\",\n \"textBlock\": {\n \"text\": \"17.7\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"blocks\": [\n {\n \"blockId\": \"141\",\n \"textBlock\": {\n \"text\": \"4486\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"142\",\n \"textBlock\": {\n \"text\": \"..\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"143\",\n \"textBlock\": {\n \"text\": \"2.0\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"144\",\n \"textBlock\": {\n \"text\": \"+ 800\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"145\",\n \"textBlock\": {\n \"text\": \"9.7\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"146\",\n \"textBlock\": {\n \"text\": \"16.8\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"blocks\": [\n {\n \"blockId\": \"147\",\n \"textBlock\": {\n \"text\": \"4649\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"148\",\n \"textBlock\": {\n \"text\": \"..\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"149\",\n \"textBlock\": {\n \"text\": \"2.0\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"150\",\n \"textBlock\": {\n \"text\": \"+1090\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"151\",\n \"textBlock\": {\n \"text\": \"9.5\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"152\",\n \"textBlock\": {\n \"text\": \"17.0\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"blocks\": [\n {\n \"blockId\": \"153\",\n \"textBlock\": {\n \"text\": \"Mean\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"rowSpan\": 1,\n \"colSpan\": 1,\n \"blocks\": []\n },\n {\n \"rowSpan\": 1,\n \"colSpan\": 1,\n \"blocks\": []\n },\n {\n \"rowSpan\": 1,\n \"colSpan\": 1,\n \"blocks\": []\n },\n {\n \"rowSpan\": 1,\n \"colSpan\": 1,\n \"blocks\": []\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"154\",\n \"textBlock\": {\n \"text\": \"-15.5\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n }\n ],\n \"caption\": \"\"\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n },\n {\n \"blockId\": \"160\",\n \"textBlock\": {\n \"text\": \"\\\\(m_{s}\\\\)= photographic magnitude of brightest stars involved. \\\\(r\\\\)= distance in units of \\\\(10^{6}\\\\) parsecs. The first two are Shapley's values. \\\\(v\\\\)= measured velocities in km./sec. N. G. C. 6822, 221, 224 and 5457 are recent determinations by Humason. \\\\(m_{i}\\\\)= Holetschek's visual magnitude as corrected by Hopmann. The first three objects were not measured by Holetschek, and the values of \\\\(m_{i}\\\\) represent estimates by the author based upon such data as are available. \\\\(M_{t}\\\\)= total visual absolute magnitude computed from \\\\(m_{t}\\\\) and \\\\(r\\\\). Finally, the nebulae themselves appear to be of a definite order of absolute luminosity, exhibiting a range of four or five magnitudes about an average value M (visual) = \\\\(-15.2.^{1}\\\\) The application of this statistical average to individual cases can rarely be used to advantage, but where considerable numbers are involved, and especially in the various clusters of nebulae, mean apparent luminosities of the nebulae themselves offer reliable estimates of the mean distances. Radial velocities of 46 extra-galactic nebulae are now available, but\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n },\n {\n \"blockId\": \"161\",\n \"textBlock\": {\n \"text\": \"Downloaded from https://www.pnas.org by 45.113.94.70 on January 5, 2026 from IP address 45.113.94.70.\",\n \"type\": \"footer\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 2\n }\n },\n {\n \"blockId\": \"162\",\n \"textBlock\": {\n \"text\": \"170 ASTRONOMY: E. HUBBLE PROC. N. A. S.\",\n \"type\": \"header\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 3,\n \"pageEnd\": 3\n }\n },\n {\n \"blockId\": \"163\",\n \"textBlock\": {\n \"text\": \"individual distances are estimated for only 24. For one other, N. G. C. 3521, an estimate could probably be made, but no photographs are available at Mount Wilson. The data are given in table 1. The first seven distances are the most reliable, depending, except for M 32 the companion of M 31, upon extensive investigations of many stars involved. The next thirteen distances, depending upon the criterion of a uniform upper limit of stellar luminosity, are subject to considerable probable errors but are believed to be the most reasonable values at present available. The last four objects appear to be in the Virgo Cluster. The distance assigned to the cluster, \\\\(2 \\\\times 10^{6}\\\\) parsecs, is derived from the distribution of nebular luminosities, together with luminosities of stars in some of the later-type spirals, and differs somewhat from the Harvard estimate of ten million light years. 2 The data in the table indicate a linear correlation between distances and velocities, whether the latter are used directly or corrected for solar motion, according to the older solutions. This suggests a new solution for the solar motion in which the distances are introduced as coefficients of the K term, i. e., the velocities are assumed to vary directly with the distances, and hence K represents the velocity at unit distance due to this effect. The equations of condition then take the form \\\\(rK + X \\\\cos \\\\alpha \\\\cos \\\\delta + Y \\\\sin \\\\alpha \\\\cos \\\\delta + Z \\\\sin \\\\delta = v\\\\) Two solutions have been made, one using the 24 nebulae individually, the other combining them into 9 groups according to proximity in direction and in distance. The results are\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 3,\n \"pageEnd\": 3\n }\n },\n {\n \"blockId\": \"164\",\n \"tableBlock\": {\n \"bodyRows\": [\n {\n \"cells\": [\n {\n \"rowSpan\": 1,\n \"colSpan\": 1,\n \"blocks\": []\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"165\",\n \"textBlock\": {\n \"text\": \"24 OBJECTS\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 3,\n \"pageEnd\": 3\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"166\",\n \"textBlock\": {\n \"text\": \"9 GROUPS\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 3,\n \"pageEnd\": 3\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"blocks\": [\n {\n \"blockId\": \"167\",\n \"textBlock\": {\n \"text\": \"X\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 3,\n \"pageEnd\": 3\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"168\",\n \"textBlock\": {\n \"text\": \"\\\\(- 65 \\\\pm 50\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 3,\n \"pageEnd\": 3\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"169\",\n \"textBlock\": {\n \"text\": \"\\\\(+ 3 \\\\pm 70\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 3,\n \"pageEnd\": 3\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"blocks\": [\n {\n \"blockId\": \"170\",\n \"textBlock\": {\n \"text\": \"Y\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 3,\n \"pageEnd\": 3\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"171\",\n \"textBlock\": {\n \"text\": \"\\\\(+226 \\\\pm 95\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 3,\n \"pageEnd\": 3\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"172\",\n \"textBlock\": {\n \"text\": \"\\\\(+230 \\\\pm 120\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 3,\n \"pageEnd\": 3\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"blocks\": [\n {\n \"blockId\": \"173\",\n \"textBlock\": {\n \"text\": \"Z\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 3,\n \"pageEnd\": 3\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"174\",\n \"textBlock\": {\n \"text\": \"\\\\(-195 \\\\pm 40\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 3,\n \"pageEnd\": 3\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"175\",\n \"textBlock\": {\n \"text\": \"\\\\(-133 \\\\pm 70\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 3,\n \"pageEnd\": 3\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"blocks\": [\n {\n \"blockId\": \"176\",\n \"textBlock\": {\n \"text\": \"K\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 3,\n \"pageEnd\": 3\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"177\",\n \"textBlock\": {\n \"text\": \"\\\\(+465 \\\\pm 50\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 3,\n \"pageEnd\": 3\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"178\",\n \"textBlock\": {\n \"text\": \"\\\\(+513 \\\\pm 60\\\\) km./sec. per \\\\(10^{6}\\\\) parsecs.\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 3,\n \"pageEnd\": 3\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"blocks\": [\n {\n \"blockId\": \"179\",\n \"textBlock\": {\n \"text\": \"A\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 3,\n \"pageEnd\": 3\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"180\",\n \"textBlock\": {\n \"text\": \"\\\\(286^{\\\\circ}\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 3,\n \"pageEnd\": 3\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"181\",\n \"textBlock\": {\n \"text\": \"\\\\(269^{\\\\circ}\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 3,\n \"pageEnd\": 3\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"blocks\": [\n {\n \"blockId\": \"182\",\n \"textBlock\": {\n \"text\": \"D\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 3,\n \"pageEnd\": 3\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"183\",\n \"textBlock\": {\n \"text\": \"\\\\(+40^{\\\\circ}\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 3,\n \"pageEnd\": 3\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"184\",\n \"textBlock\": {\n \"text\": \"\\\\(+33^{\\\\circ}\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 3,\n \"pageEnd\": 3\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"blocks\": [\n {\n \"blockId\": \"185\",\n \"textBlock\": {\n \"text\": \"\\\\(V_{0}\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 3,\n \"pageEnd\": 3\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"186\",\n \"textBlock\": {\n \"text\": \"306 km./sec.\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 3,\n \"pageEnd\": 3\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"187\",\n \"textBlock\": {\n \"text\": \"247 km./sec.\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 3,\n \"pageEnd\": 3\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n }\n ],\n \"headerRows\": [],\n \"caption\": \"\"\n },\n \"pageSpan\": {\n \"pageStart\": 3,\n \"pageEnd\": 3\n }\n },\n {\n \"blockId\": \"188\",\n \"textBlock\": {\n \"text\": \"For such scanty material, so poorly distributed, the results are fairly definite. Differences between the two solutions are due largely to the four Virgo nebulae, which, being the most distant objects and all sharing the peculiar motion of the cluster, unduly influence the value of K and hence of \\\\(V_{0}\\\\). New data on more distant objects will be required to reduce the effect of such peculiar motion. Meanwhile round numbers, intermediate between the two solutions, will represent the probable order of the values. For instance, let \\\\(A = 277^{\\\\circ}\\\\), \\\\(D = +36^{\\\\circ}\\\\) (Gal. long. \\\\( = 32^{\\\\circ}\\\\), lat. \\\\( = +18^{\\\\circ}\\\\)), \\\\(V_{0} = 280\\\\) km./sec., \\\\(K = +500\\\\) km./sec. per million par-\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 3,\n \"pageEnd\": 3\n }\n },\n {\n \"blockId\": \"189\",\n \"textBlock\": {\n \"text\": \"Downloaded from https://www.pnas.org by 45.113.94.70 on January 5, 2026 from IP address 45.113.94.70.\",\n \"type\": \"footer\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 3,\n \"pageEnd\": 3\n }\n },\n {\n \"blockId\": \"190\",\n \"textBlock\": {\n \"text\": \"VOL. 15, 1929 ASTRONOMY: E. HUBBLE 171\",\n \"type\": \"header\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n },\n {\n \"blockId\": \"191\",\n \"textBlock\": {\n \"text\": \"secs. Mr. Str\\u00f6mberg has very kindly checked the general order of these values by independent solutions for different groupings of the data. A constant term, introduced into the equations, was found to be small and negative. This seems to dispose of the necessity for the old constant \\\\(K\\\\) term. Solutions of this sort have been published by Lundmark, who replaced the old \\\\(K\\\\) by \\\\(k+lr+mr^{2}\\\\). His favored solution gave \\\\(k=513\\\\), as against the former value of the order of 700, and hence offered little advantage.\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n },\n {\n \"blockId\": \"192\",\n \"tableBlock\": {\n \"bodyRows\": [\n {\n \"cells\": [\n {\n \"rowSpan\": 1,\n \"colSpan\": 1,\n \"blocks\": []\n },\n {\n \"rowSpan\": 1,\n \"colSpan\": 1,\n \"blocks\": []\n },\n {\n \"rowSpan\": 1,\n \"colSpan\": 1,\n \"blocks\": []\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"193\",\n \"textBlock\": {\n \"text\": \"\\\\(r\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"194\",\n \"textBlock\": {\n \"text\": \"\\\\(m\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"195\",\n \"textBlock\": {\n \"text\": \"\\\\(M_{c}\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"blocks\": [\n {\n \"blockId\": \"196\",\n \"textBlock\": {\n \"text\": \"N. G. C.\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"197\",\n \"textBlock\": {\n \"text\": \"OBJECT\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"rowSpan\": 1,\n \"colSpan\": 1,\n \"blocks\": []\n },\n {\n \"rowSpan\": 1,\n \"colSpan\": 1,\n \"blocks\": []\n },\n {\n \"rowSpan\": 1,\n \"colSpan\": 1,\n \"blocks\": []\n },\n {\n \"rowSpan\": 1,\n \"colSpan\": 1,\n \"blocks\": []\n }\n ]\n },\n {\n \"cells\": [\n {\n \"rowSpan\": 1,\n \"colSpan\": 1,\n \"blocks\": []\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"198\",\n \"textBlock\": {\n \"text\": \"278\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"199\",\n \"textBlock\": {\n \"text\": \"\\\\(+ 650\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"200\",\n \"textBlock\": {\n \"text\": \"\\\\(-110\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"201\",\n \"textBlock\": {\n \"text\": \"1.52\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"202\",\n \"textBlock\": {\n \"text\": \"12.0\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"203\",\n \"textBlock\": {\n \"text\": \"\\\\(\\u201313.9\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"rowSpan\": 1,\n \"colSpan\": 1,\n \"blocks\": []\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"204\",\n \"textBlock\": {\n \"text\": \"404\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"205\",\n \"textBlock\": {\n \"text\": \"\\\\(\\u2013 25\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"206\",\n \"textBlock\": {\n \"text\": \"\\\\(\\u2013 65\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"207\",\n \"textBlock\": {\n \"text\": \"...\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"208\",\n \"textBlock\": {\n \"text\": \"11.1\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"209\",\n \"textBlock\": {\n \"text\": \"..\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"rowSpan\": 1,\n \"colSpan\": 1,\n \"blocks\": []\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"210\",\n \"textBlock\": {\n \"text\": \"584\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"211\",\n \"textBlock\": {\n \"text\": \"\\\\(+1800\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"212\",\n \"textBlock\": {\n \"text\": \"\\\\(+ 75\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"213\",\n \"textBlock\": {\n \"text\": \"3.45\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"214\",\n \"textBlock\": {\n \"text\": \"10.9\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"215\",\n \"textBlock\": {\n \"text\": \"16.8\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"rowSpan\": 1,\n \"colSpan\": 1,\n \"blocks\": []\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"216\",\n \"textBlock\": {\n \"text\": \"936\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"217\",\n \"textBlock\": {\n \"text\": \"\\\\(+1300\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"218\",\n \"textBlock\": {\n \"text\": \"\\\\(+115\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"219\",\n \"textBlock\": {\n \"text\": \"2.37\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"220\",\n \"textBlock\": {\n \"text\": \"11.1\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"221\",\n \"textBlock\": {\n \"text\": \"15.7\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"rowSpan\": 1,\n \"colSpan\": 1,\n \"blocks\": []\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"222\",\n \"textBlock\": {\n \"text\": \"1023\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"223\",\n \"textBlock\": {\n \"text\": \"\\\\(+ 300\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"224\",\n \"textBlock\": {\n \"text\": \"\\\\(\\u2013 10\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"225\",\n \"textBlock\": {\n \"text\": \"0.62\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"226\",\n \"textBlock\": {\n \"text\": \"10.2\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"227\",\n \"textBlock\": {\n \"text\": \"13.8\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"rowSpan\": 1,\n \"colSpan\": 1,\n \"blocks\": []\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"228\",\n \"textBlock\": {\n \"text\": \"1700\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"229\",\n \"textBlock\": {\n \"text\": \"\\\\(+ 800\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"230\",\n \"textBlock\": {\n \"text\": \"\\\\(+220\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"231\",\n \"textBlock\": {\n \"text\": \"1.16\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"232\",\n \"textBlock\": {\n \"text\": \"12.5\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"233\",\n \"textBlock\": {\n \"text\": \"12.8\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"rowSpan\": 1,\n \"colSpan\": 1,\n \"blocks\": []\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"234\",\n \"textBlock\": {\n \"text\": \"2681\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"235\",\n \"textBlock\": {\n \"text\": \"\\\\(+ 700\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"236\",\n \"textBlock\": {\n \"text\": \"\\\\(\\u2013 10\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"237\",\n \"textBlock\": {\n \"text\": \"1.42\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"238\",\n \"textBlock\": {\n \"text\": \"10.7\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"239\",\n \"textBlock\": {\n \"text\": \"15.0\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"rowSpan\": 1,\n \"colSpan\": 1,\n \"blocks\": []\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"240\",\n \"textBlock\": {\n \"text\": \"2683\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"241\",\n \"textBlock\": {\n \"text\": \"\\\\(+ 400\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"242\",\n \"textBlock\": {\n \"text\": \"\\\\(+ 65\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"243\",\n \"textBlock\": {\n \"text\": \"0.67\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"244\",\n \"textBlock\": {\n \"text\": \"9.9\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"245\",\n \"textBlock\": {\n \"text\": \"14.3\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"rowSpan\": 1,\n \"colSpan\": 1,\n \"blocks\": []\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"246\",\n \"textBlock\": {\n \"text\": \"2841\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"247\",\n \"textBlock\": {\n \"text\": \"\\\\(+ 600\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"248\",\n \"textBlock\": {\n \"text\": \"\\\\(\\u2013 20\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"249\",\n \"textBlock\": {\n \"text\": \"1.24\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"250\",\n \"textBlock\": {\n \"text\": \"9.4\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"251\",\n \"textBlock\": {\n \"text\": \"16.1\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"rowSpan\": 1,\n \"colSpan\": 1,\n \"blocks\": []\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"252\",\n \"textBlock\": {\n \"text\": \"3034\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"253\",\n \"textBlock\": {\n \"text\": \"\\\\(+ 290\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"254\",\n \"textBlock\": {\n \"text\": \"\\\\(\\u2013105\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"255\",\n \"textBlock\": {\n \"text\": \"0.79\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"256\",\n \"textBlock\": {\n \"text\": \"9.0\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"257\",\n \"textBlock\": {\n \"text\": \"15.5\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"rowSpan\": 1,\n \"colSpan\": 1,\n \"blocks\": []\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"258\",\n \"textBlock\": {\n \"text\": \"3115\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"259\",\n \"textBlock\": {\n \"text\": \"\\\\(+ 600\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"260\",\n \"textBlock\": {\n \"text\": \"\\\\(+105\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"261\",\n \"textBlock\": {\n \"text\": \"1.00\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"262\",\n \"textBlock\": {\n \"text\": \"9.5\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"263\",\n \"textBlock\": {\n \"text\": \"15.5\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"rowSpan\": 1,\n \"colSpan\": 1,\n \"blocks\": []\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"264\",\n \"textBlock\": {\n \"text\": \"3368\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"265\",\n \"textBlock\": {\n \"text\": \"\\\\(+ 940\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"266\",\n \"textBlock\": {\n \"text\": \"\\\\(+ 70\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"267\",\n \"textBlock\": {\n \"text\": \"1.74\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"268\",\n \"textBlock\": {\n \"text\": \"10.0\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"269\",\n \"textBlock\": {\n \"text\": \"16.2\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"rowSpan\": 1,\n \"colSpan\": 1,\n \"blocks\": []\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"270\",\n \"textBlock\": {\n \"text\": \"3379\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"271\",\n \"textBlock\": {\n \"text\": \"\\\\(+ 810\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"272\",\n \"textBlock\": {\n \"text\": \"\\\\(+ 65\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"273\",\n \"textBlock\": {\n \"text\": \"1.49\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"274\",\n \"textBlock\": {\n \"text\": \"9.4\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"275\",\n \"textBlock\": {\n \"text\": \"16.4\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"rowSpan\": 1,\n \"colSpan\": 1,\n \"blocks\": []\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"276\",\n \"textBlock\": {\n \"text\": \"3489\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"277\",\n \"textBlock\": {\n \"text\": \"\\\\(+ 600\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"278\",\n \"textBlock\": {\n \"text\": \"\\\\(+ 50\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"279\",\n \"textBlock\": {\n \"text\": \"1.10\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"280\",\n \"textBlock\": {\n \"text\": \"11.2\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"281\",\n \"textBlock\": {\n \"text\": \"14.0\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"rowSpan\": 1,\n \"colSpan\": 1,\n \"blocks\": []\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"282\",\n \"textBlock\": {\n \"text\": \"3521\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"283\",\n \"textBlock\": {\n \"text\": \"\\\\(+ 730\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"284\",\n \"textBlock\": {\n \"text\": \"\\\\(+ 95\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"285\",\n \"textBlock\": {\n \"text\": \"1.27\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"286\",\n \"textBlock\": {\n \"text\": \"10.1\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"287\",\n \"textBlock\": {\n \"text\": \"15.4\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"rowSpan\": 1,\n \"colSpan\": 1,\n \"blocks\": []\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"288\",\n \"textBlock\": {\n \"text\": \"3623\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"289\",\n \"textBlock\": {\n \"text\": \"\\\\(+ 800\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"290\",\n \"textBlock\": {\n \"text\": \"\\\\(+ 35\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"291\",\n \"textBlock\": {\n \"text\": \"1.53\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"292\",\n \"textBlock\": {\n \"text\": \"9.9\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"293\",\n \"textBlock\": {\n \"text\": \"16.0\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"rowSpan\": 1,\n \"colSpan\": 1,\n \"blocks\": []\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"294\",\n \"textBlock\": {\n \"text\": \"4111\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"295\",\n \"textBlock\": {\n \"text\": \"\\\\(+ 800\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"296\",\n \"textBlock\": {\n \"text\": \"\\\\(\\u2013 95\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"297\",\n \"textBlock\": {\n \"text\": \"1.79\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"298\",\n \"textBlock\": {\n \"text\": \"10.1\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"299\",\n \"textBlock\": {\n \"text\": \"16.1\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"rowSpan\": 1,\n \"colSpan\": 1,\n \"blocks\": []\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"300\",\n \"textBlock\": {\n \"text\": \"4526\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"301\",\n \"textBlock\": {\n \"text\": \"\\\\(+ 580\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"302\",\n \"textBlock\": {\n \"text\": \"\\\\(\\u2013 20\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"303\",\n \"textBlock\": {\n \"text\": \"1.20\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"304\",\n \"textBlock\": {\n \"text\": \"11.1\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"305\",\n \"textBlock\": {\n \"text\": \"14.3\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"rowSpan\": 1,\n \"colSpan\": 1,\n \"blocks\": []\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"306\",\n \"textBlock\": {\n \"text\": \"4565\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"307\",\n \"textBlock\": {\n \"text\": \"\\\\(+1100\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"308\",\n \"textBlock\": {\n \"text\": \"\\\\(\\u2013 75\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"309\",\n \"textBlock\": {\n \"text\": \"2.35\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"310\",\n \"textBlock\": {\n \"text\": \"11.0\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"311\",\n \"textBlock\": {\n \"text\": \"15.9\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"rowSpan\": 1,\n \"colSpan\": 1,\n \"blocks\": []\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"312\",\n \"textBlock\": {\n \"text\": \"4594\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"313\",\n \"textBlock\": {\n \"text\": \"\\\\(+1140\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"314\",\n \"textBlock\": {\n \"text\": \"\\\\(+ 25\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"315\",\n \"textBlock\": {\n \"text\": \"2.23\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"316\",\n \"textBlock\": {\n \"text\": \"9.1\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"317\",\n \"textBlock\": {\n \"text\": \"17.6\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"rowSpan\": 1,\n \"colSpan\": 1,\n \"blocks\": []\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"318\",\n \"textBlock\": {\n \"text\": \"5005\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"319\",\n \"textBlock\": {\n \"text\": \"\\\\(+ 900\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"320\",\n \"textBlock\": {\n \"text\": \"\\\\(-130\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"321\",\n \"textBlock\": {\n \"text\": \"2.06\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"322\",\n \"textBlock\": {\n \"text\": \"11.1\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"323\",\n \"textBlock\": {\n \"text\": \"15.5\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"rowSpan\": 1,\n \"colSpan\": 1,\n \"blocks\": []\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"324\",\n \"textBlock\": {\n \"text\": \"5866\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"325\",\n \"textBlock\": {\n \"text\": \"\\\\(+ 650\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"326\",\n \"textBlock\": {\n \"text\": \"\\\\(-215\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"327\",\n \"textBlock\": {\n \"text\": \"1.73\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"328\",\n \"textBlock\": {\n \"text\": \"11.7\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"329\",\n \"textBlock\": {\n \"text\": \"\\\\(\\u201314.5\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n },\n {\n \"cells\": [\n {\n \"blocks\": [\n {\n \"blockId\": \"330\",\n \"textBlock\": {\n \"text\": \"Mean\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"rowSpan\": 1,\n \"colSpan\": 1,\n \"blocks\": []\n },\n {\n \"rowSpan\": 1,\n \"colSpan\": 1,\n \"blocks\": []\n },\n {\n \"rowSpan\": 1,\n \"colSpan\": 1,\n \"blocks\": []\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"331\",\n \"textBlock\": {\n \"text\": \"10.5\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"332\",\n \"textBlock\": {\n \"text\": \"\\\\(\\u201315.3\\\\)\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n }\n ],\n \"rowSpan\": 1,\n \"colSpan\": 1\n }\n ]\n }\n ],\n \"caption\": \"TABLE 2 NEBULAE WHOSE DITANCES ARE ESTIMATED FROM RADIAL VELOCITIES\",\n \"headerRows\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n },\n {\n \"blockId\": \"333\",\n \"textBlock\": {\n \"text\": \"The residuals for the two solutions given above average 150 and 110 km./sec. and should represent the average peculiar motions of the individual nebulae and of the groups, respectively. In order to exhibit the results in a graphical form, the solar motion has been eliminated from the observed velocities and the remainders, the distance terms plus the residuals, have been plotted against the distances. The run of the residuals is about as smooth as can be expected, and in general the form of the solutions appears to be adequate. The 22 nebulae for which distances are not available can be treated in two ways. First, the mean distance of the group derived from the mean apparent magnitudes can be compared with the mean of the velocities Downloaded from https://www.pnas.org by 45.113.94.70 on January 5, 2026 from IP address 45.113.94.70.\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 4,\n \"pageEnd\": 4\n }\n },\n {\n \"blockId\": \"334\",\n \"textBlock\": {\n \"text\": \"172 ASTRONOMY: E. HUBBLE PROC. N. A. S.\",\n \"type\": \"header\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 5,\n \"pageEnd\": 5\n }\n },\n {\n \"blockId\": \"335\",\n \"textBlock\": {\n \"text\": \"corrected for solar motion. The result, 745 km./sec. for a distance of \\\\(1.4 \\\\times 10^{6}\\\\) parsecs, falls between the two previous solutions and indicates a value for K of 530 as against the proposed value, 500 km./sec. Secondly, the scatter of the individual nebulae can be examined by assuming the relation between distances and velocities as previously determined. Distances can then be calculated from the velocities corrected for solar motion, and absolute magnitudes can be derived from the apparent magnitudes. The results are given in table 2 and may be compared with the distribution of absolute magnitudes among the nebulae in talbe 1, whose distances are derived from other criteria. N. G. C. 404 FIGURE 1 Velocity-Distance Relation among Extra-Galactic Nebulae. Radial velocities, corrected for solar motion, are plotted against distances estimated from involved stars and mean luminosities of nebulae in a cluster. The black discs and full line represent the solution for solar motion using the nebulae individually; the circles and broken line represent the solution combining the nebulae into groups; the cross represents the mean velocity corresponding to the mean distance of 22 nebulae whose distances could not be estimated individually. can be excluded, since the observed velocity is so small that the peculiar motion must be large in comparison with the distance effect. The object is not necessarily an exception, however, since a distance can be assigned for which the peculiar motion and the absolute magnitude are both within the range previously determined. The two mean magnitudes, -15.3 and -15.5, the ranges, 4.9 and 5.0 mag., and the frequency distributions are closely similar for these two entirely independent sets of data; and even the slight difference in mean magnitudes can be attributed to the selected, very bright, nebulae in the Virgo Cluster. This entirely unforced agreement supports the validity of the velocity-distance relation in a very\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 5,\n \"pageEnd\": 5\n }\n },\n {\n \"blockId\": \"336\",\n \"textBlock\": {\n \"text\": \"Downloaded from https://www.pnas.org by 45.113.94.70 on January 5, 2026 from IP address 45.113.94.70. Vol. 15, 1929 ASTRONOMY: E. HUBBLE 173\",\n \"type\": \"header\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 6,\n \"pageEnd\": 6\n }\n },\n {\n \"blockId\": \"337\",\n \"textBlock\": {\n \"text\": \"evident matter. Finally, it is worth recording that the frequency distribution of absolute magnitudes in the two tables combined is comparable with those found in the various clusters of nebulae. The results establish a roughly linear relation between velocities and distances among nebulae for which velocities have been previously published, and the relation appears to dominate the distribution of velocities. In order to investigate the matter on a much larger scale, Mr. Humason at Mount Wilson has initiated a program of determining velocities of the most distant nebulae that can be observed with confidence. These, naturally, are the brightest nebulae in clusters of nebulae. The first definite result, \\\\(v = +3779 ~km./sec.\\\\) for N. G. C. 7619, is thoroughly consistent with the present conclusions. Corrected for the solar motion, this velocity is \\\\(+3910\\\\), which, with \\\\(K = 500\\\\), corresponds to a distance of \\\\(7.8 \\\\times 10^{6}\\\\) parsecs. Since the apparent magnitude is 11.8, the absolute magnitude at such a distance is \\\\(-17.65\\\\), which is of the right order for the brightest nebulae in a cluster. A preliminary distance, derived independently from the cluster of which this nebula appears to be a member, is of the order of \\\\(7 \\\\times 10^{6}\\\\) parsecs. New data to be expected in the near future may modify the significance of the present investigation or, if confirmatory, will lead to a solution having many times the weight. For this reason it is thought premature to discuss in detail the obvious consequences of the present results. For example, if the solar motion with respect to the clusters represents the rotation of the galactic system, this motion could be subtracted from the results for the nebulae and the remainder would represent the motion of the galactic system with respect to the extra-galactic nebulae. The outstanding feature, however, is the possibility that the velocity-distance relation may represent the de Sitter effect, and hence that numerical data may be introduced into discussions of the general curvature of space. In the de Sitter cosmology, displacements of the spectra arise from two sources, an apparent slowing down of atomic vibrations and a general tendency of material particles to scatter. The latter involves an acceleration and hence introduces the element of time. The relative importance of these two effects should determine the form of the relation between distances and observed velocities; and in this connection it may be emphasized that the linear relation found in the present discussion is a first approximation representing a restricted range in distance.\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 6,\n \"pageEnd\": 6\n }\n },\n {\n \"blockId\": \"338\",\n \"listBlock\": {\n \"listEntries\": [\n {\n \"blocks\": [\n {\n \"blockId\": \"339\",\n \"textBlock\": {\n \"text\": \"Mt. Wilson Contr., No. 324; Astroph. J., Chicago, Ill., 64, 1926 (321).\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 6,\n \"pageEnd\": 6\n }\n }\n ]\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"340\",\n \"textBlock\": {\n \"text\": \"Harvard Coll. Obs. Circ., 294, 1926.\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 6,\n \"pageEnd\": 6\n }\n }\n ]\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"341\",\n \"textBlock\": {\n \"text\": \"Mon. Not. R. Astr. Soc., 85, 1925 (865-894).\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 6,\n \"pageEnd\": 6\n }\n }\n ]\n },\n {\n \"blocks\": [\n {\n \"blockId\": \"342\",\n \"textBlock\": {\n \"text\": \"These PROCEEDINGS, 15, 1929 (167).\",\n \"type\": \"paragraph\",\n \"blocks\": []\n },\n \"pageSpan\": {\n \"pageStart\": 6,\n \"pageEnd\": 6\n }\n }\n ]\n }\n ],\n \"type\": \"ordered\"\n },\n \"pageSpan\": {\n \"pageStart\": 6,\n \"pageEnd\": 6\n }\n }\n ]\n },\n \"pageSpan\": {\n \"pageStart\": 2,\n \"pageEnd\": 6\n }\n }\n ]\n },\n \"docid\": \"\",\n \"mimeType\": \"\",\n \"text\": \"\",\n \"textStyles\": [],\n \"pages\": [],\n \"entities\": [],\n \"entityRelations\": [],\n \"textChanges\": [],\n \"revisions\": [],\n \"entitiesRevisions\": [],\n \"entitiesRevisionId\": \"\"\n}"] diff --git a/tests/fixtures/hubble_gemini_responses.json b/tests/fixtures/hubble_gemini_responses.json deleted file mode 100644 index a73d4fb..0000000 --- a/tests/fixtures/hubble_gemini_responses.json +++ /dev/null @@ -1 +0,0 @@ -["\n168 ASTRONOMY: E. HUBBLE PROC. N. A. S.\n\nappearance the spectrum is very much like spectra of the Milky Way\nclouds in Sagittarius and Cygnus, and is also similar to spectra of binary\nstars of the W Ursae Majoris type, where the widening and depth of the\nlines are affected by the rapid rotation of the stars involved.\n\nThe wide shallow absorption lines observed in the spectrum of N. G. C.\n7619 have been noticed in the spectra of other extra-galactic nebulae, and\nmay be due to a dispersion in velocity and a blending of the spectral types\nof the many stars which presumably exist in the central parts of these\nnebulae. The lack of depth in the absorption lines seems to be more\npronounced among the smaller and fainter nebulae, and in N. G. C. 7619\nthe absorption is very weak.\n\nIt is hoped that velocities of more of these interesting objects will soon\nbe available.\n\n## A RELATION BETWEEN DISTANCE AND RADIAL VELOCITY AMONG EXTRA-GALACTIC NEBULAE\n\nBY EDWIN HUBBLE\nMOUNT WILSON OBSERVATORY, CARNEGIE INSTITUTION OF WASHINGTON\nCommunicated January 17, 1929\n\nDeterminations of the motion of the sun with respect to the extra-\ngalactic nebulae have involved a $K$ term of several hundred kilometers\nwhich appears to be variable. Explanations of this paradox have been\nsought in a correlation between apparent radial velocities and distances,\nbut so far the results have not been convincing. The present paper is a\nre-examination of the question, based on only those nebular distances\nwhich are believed to be fairly reliable.\n\nDistances of extra-galactic nebulae depend ultimately upon the appli-\ncation of absolute-luminosity criteria to involved stars whose types can\nbe recognized. These include, among others, Cepheid variables, novae,\nand blue stars involved in emission nebulosity. Numerical values depend\nupon the zero point of the period-luminosity relation among Cepheids,\nthe other criteria merely check the order of the distances. This method\nis restricted to the few nebulae which are well resolved by existing instru-\nments. A study of these nebulae, together with those in which any stars\nat all can be recognized, indicates the probability of an approximately\nuniform upper limit to the absolute luminosity of stars, in the late-type\nspirals and irregular nebulae at least, of the order of $M$ (photographic) =\n-6.3.1 The apparent luminosities of the brightest stars in such nebulae\nare thus criteria which, although rough and to be applied with caution,\n\n\nVOL. 15, 1929 ASTRONOMY: E. HUBBLE 169\n\nfurnish reasonable estimates of the distances of all extra-galactic systems\nin which even a few stars can be detected.\n\n\nTABLE 1\nNEBULAE WHOSE DISTANCES HAVE BEEN ESTIMATED FROM STARS INVOLVED OR FROM\nMEAN LUMINOSITIES IN A CLUSTER\n\n| OBJECT | $m_c$ | $r$ | $v_c$ | $m_v$ | $M_v$ |\n| :----------- | :---- | :---- | :------- | :---- | :------- |\n| S. Mag. | .. | 0.032 | + 170 | 1.5 | -16.0 |\n| L. Mag. | .. | 0.034 | + 290 | 0.5 | 17.2 |\n| N. G. C. 6822 | .. | 0.214 | - 130 | 9.0 | 12.7 |\n| 598 | .. | 0.263 | - 70 | 7.0 | 15.1 |\n| 221 | .. | 0.275 | - 185 | 8.8 | 13.4 |\n| 224 | .. | 0.275 | - 220 | 5.0 | 17.2 |\n| 5457 | 17.0 | 0.45 | + 200 | 9.9 | 13.3 |\n| 4736 | 17.3 | 0.5 | + 290 | 8.4 | 15.1 |\n| 5194 | 17.3 | 0.5 | + 270 | 7.4 | 16.1 |\n| 4449 | 17.8 | 0.63 | + 200 | 9.5 | 14.5 |\n| 4214 | 18.3 | 0.8 | + 300 | 11.3 | 13.2 |\n| 3031 | 18.5 | 0.9 | - 30 | 8.3 | 16.4 |\n| 3627 | 18.5 | 0.9 | + 650 | 9.1 | 15.7 |\n| 4826 | 18.5 | 0.9 | + 150 | 9.0 | 15.7 |\n| 5236 | 18.5 | 0.9 | + 500 | 10.4 | 14.4 |\n| 1068 | 18.7 | 1.0 | + 920 | 9.1 | 15.9 |\n| 5055 | 19.0 | 1.1 | + 450 | 9.6 | 15.6 |\n| 7331 | 19.0 | 1.1 | + 500 | 10.4 | 14.8 |\n| 4258 | 19.5 | 1.4 | + 500 | 8.7 | 17.0 |\n| 4151 | 20.0 | 1.7 | + 960 | 12.0 | 14.2 |\n| 4382 | .. | 2.0 | + 500 | 10.0 | 16.5 |\n| 4472 | .. | 2.0 | + 850 | 8.8 | 17.7 |\n| 4486 | .. | 2.0 | + 800 | 9.7 | 16.8 |\n| 4649 | .. | 2.0 | +1090 | 9.5 | 17.0 |\n| Mean | | | | | -15.5 |\n\n$m_c$ = photographic magnitude of brightest stars involved.\n$r$ = distance in units of $10^6$ parsecs. The first two are Shapley's values.\n$v_c$ = measured velocities in km./sec. N. G. C. 6822, 221, 224 and 5457 are recent\ndeterminations by Humason.\n$m_v$ = Holetschek's visual magnitude as corrected by Hopmann. The first three\nobjects were not measured by Holetschek, and the values of $m_v$ represent\nestimates by the author based upon such data as are available.\n$M_v$ = total visual absolute magnitude computed from $m_v$ and $r$.\n\n\nFinally, the nebulae themselves appear to be of a definite order of\nabsolute luminosity, exhibiting a range of four or five magnitudes about\nan average value $M$ (visual) = -15.2.1 The application of this statistical\naverage to individual cases can rarely be used to advantage, but where\nconsiderable numbers are involved, and especially in the various clusters\nof nebulae, mean apparent luminosities of the nebulae themselves offer\nreliable estimates of the mean distances.\n\nRadial velocities of 46 extra-galactic nebulae are now available, but\n\n\n170 ASTRONOMY: E. HUBBLE PROC. N. A. S.\n\nindividual distances are estimated for only 24. For one other, N. G. C.\n3521, an estimate could probably be made, but no photographs are avail-\nable at Mount Wilson. The data are given in table 1. The first seven\ndistances are the most reliable, depending, except for M 32 the companion of\nM 31, upon extensive investigations of many stars involved. The next\nthirteen distances, depending upon the criterion of a uniform upper limit\nof stellar luminosity, are subject to considerable probable errors but are\nbelieved to be the most reasonable values at present available. The last\nfour objects appear to be in the Virgo Cluster. The distance assigned\nto the cluster, $2 \\times 10^6$ parsecs, is derived from the distribution of nebular\nluminosities, together with luminosities of stars in some of the later-type\nspirals, and differs somewhat from the Harvard estimate of ten million\nlight years.2\n\nThe data in the table indicate a linear correlation between distances and\nvelocities, whether the latter are used directly or corrected for solar motion,\naccording to the older solutions. This suggests a new solution for the solar\nmotion in which the distances are introduced as coefficients of the $K$ term,\ni. e., the velocities are assumed to vary directly with the distances, and\nhence $K$ represents the velocity at unit distance due to this effect. The\nequations of condition then take the form\n\n$$ rK + X \\cos \\alpha \\cos \\delta + Y \\sin \\alpha \\cos \\delta + Z \\sin \\delta = v. $$\n\nTwo solutions have been made, one using the 24 nebulae individually,\nthe other combining them into 9 groups according to proximity in direc-\ntion and in distance. The results are\n\n24 OBJECTS\n$X$ = -65 $\\pm$ 50\n$Y$ = +226 $\\pm$ 95\n$Z$ = -195 $\\pm$ 40\n$K$ = +465 $\\pm$ 50\n$A$ = $286^{\\circ}$\n$D$ = $+40^{\\circ}$\n$V_o$ = 306 km./sec.\n\n9 GROUPS\n+3 $\\pm$ 70\n+230 $\\pm$ 120\n-133 $\\pm$ 70\n+513 $\\pm$ 60 km./sec. per $10^6$ parsecs.\n$269^{\\circ}$\n$+33^{\\circ}$\n247 km./sec.\n\nFor such scanty material, so poorly distributed, the results are fairly\ndefinite. Differences between the two solutions are due largely to the\nfour Virgo nebulae, which, being the most distant objects and all sharing\nthe peculiar motion of the cluster, unduly influence the value of $K$ and\nhence of $V_o$. New data on more distant objects will be required to reduce\nthe effect of such peculiar motion. Meanwhile round numbers, inter-\nmediate between the two solutions, will represent the probable order of\nthe values. For instance, let $A = 277^{\\circ}$, $D = +36^{\\circ}$ (Gal. long. = $32^{\\circ}$,\nlat. = $+18^{\\circ}$), $V_o = 280$ km./sec., $K = +500$ km./sec. per million par-\n\n\nVOL. 15, 1929 ASTRONOMY: E. HUBBLE 171\n\nsecs. Mr. Str\u00f6mberg has very kindly checked the general order of these\nvalues by independent solutions for different groupings of the data.\n\nA constant term, introduced into the equations, was found to be small\nand negative. This seems to dispose of the necessity for the old constant\n$K$ term. Solutions of this sort have been published by Lundmark,3 who\nreplaced the old $K$ by $k + lr + mr^2$. His favored solution gave $k = 513$,\nas against the former value of the order of 700, and hence offered little\nadvantage.\n\n\nTABLE 2\nNEBULAE WHOSE DISTANCES ARE ESTIMATED FROM RADIAL VELOCITIES\n\n| OBJECT | $v_c$ | $v_o$ | $r$ | $m_v$ | $M_v$ |\n| :----------- | :------ | :------- | :---- | :---- | :------- |\n| N. G. C. 278 | + 650 | -110 | 1.52 | 12.0 | -13.9 |\n| 404 | + 25 | - 65 | | 11.1 | |\n| 584 | +1800 | + 75 | 3.45 | 10.9 | 16.8 |\n| 936 | +1300 | +115 | 2.37 | 11.1 | 15.7 |\n| 1023 | + 300 | - 10 | 0.62 | 10.2 | 13.8 |\n| 1700 | + 800 | +220 | 1.16 | 12.5 | 12.8 |\n| 2681 | + 700 | - 10 | 1.42 | 10.7 | 15.0 |\n| 2683 | + 400 | + 65 | 0.67 | 9.9 | 14.3 |\n| 2841 | + 600 | - 20 | 1.24 | 9.4 | 16.1 |\n| 3034 | + 290 | -105 | 0.79 | 9.0 | 15.5 |\n| 3115 | + 600 | +105 | 1.00 | 9.5 | 15.5 |\n| 3368 | + 940 | + 70 | 1.74 | 10.0 | 16.2 |\n| 3379 | + 810 | + 65 | 1.49 | 9.4 | 16.4 |\n| 3489 | + 600 | + 50 | 1.10 | 11.2 | 14.0 |\n| 3521 | + 730 | + 95 | 1.27 | 10.1 | 15.4 |\n| 3623 | + 800 | + 35 | 1.53 | 9.9 | 16.0 |\n| 4111 | + 800 | - 95 | 1.79 | 10.1 | 16.1 |\n| 4526 | + 580 | - 20 | 1.20 | 11.1 | 14.3 |\n| 4565 | +1100 | - 75 | 2.35 | 11.0 | 15.9 |\n| 4594 | +1140 | + 25 | 2.23 | 9.1 | 17.6 |\n| 5005 | + 900 | -130 | 2.06 | 11.1 | 15.5 |\n| 5866 | + 650 | -215 | 1.73 | 11.7 | -14.5 |\n| Mean | | | | 10.5 | -15.3 |\n\n\nThe residuals for the two solutions given above average 150 and 110\nkm./sec. and should represent the average peculiar motions of the in-\ndividual nebulae and of the groups, respectively. In order to exhibit\nthe results in a graphical form, the solar motion has been eliminated from\nthe observed velocities and the remainders, the distance terms plus the\nresiduals, have been plotted against the distances. The run of the re-\nsiduals is about as smooth as can be expected, and in general the form of\nthe solutions appears to be adequate.\n\nThe 22 nebulae for which distances are not available can be treated in\ntwo ways. First, the mean distance of the group derived from the mean\napparent magnitudes can be compared with the mean of the velocities\n\n\n172 ASTRONOMY: E. HUBBLE PROC. N. A. S.\n\ncorrected for solar motion. The result, 745 km./sec. for a distance of\n$1.4 \\times 10^6$ parsecs, falls between the two previous solutions and indicates\na value for $K$ of 530 as against the proposed value, 500 km./sec.\n\nSecondly, the scatter of the individual nebulae can be examined by\nassuming the relation between distances and velocities as previously\ndetermined. Distances can then be calculated from the velocities cor-\nrected for solar motion, and absolute magnitudes can be derived from the\napparent magnitudes. The results are given in table 2 and may be\ncompared with the distribution of absolute magnitudes among the nebulae\nin table 1, whose distances are derived from other criteria. N. G. C. 404\n\n\n\"Graph\n\nFIGURE 1\nVelocity-Distance Relation among Extra-Galactic Nebulae.\n\nRadial velocities, corrected for solar motion, are plotted against\ndistances estimated from involved stars and mean luminosities of\nnebulae in a cluster. The black discs and full line represent the\nsolution for solar motion using the nebulae individually; the circles\nand broken line represent the solution combining the nebulae into\ngroups; the cross represents the mean velocity corresponding to\nthe mean distance of 22 nebulae whose distances could not be esti-\nmated individually.\n\n\ncan be excluded, since the observed velocity is so small that the peculiar\nmotion must be large in comparison with the distance effect. The object\nis not necessarily an exception, however, since a distance can be assigned\nfor which the peculiar motion and the absolute magnitude are both within\nthe range previously determined. The two mean magnitudes, -15.3\nand -15.5, the ranges, 4.9 and 5.0 mag., and the frequency distributions\nare closely similar for these two entirely independent sets of data; and\neven the slight difference in mean magnitudes can be attributed to the\nselected, very bright, nebulae in the Virgo Cluster. This entirely unforced\nagreement supports the validity of the velocity-distance relation in a very\n\n\nVOL. 15, 1929 ASTRONOMY: E. HUBBLE 173\n\nevident matter. Finally, it is worth recording that the frequency distribu-\ntion of absolute magnitudes in the two tables combined is comparable\nwith those found in the various clusters of nebulae.4\n\nThe results establish a roughly linear relation between velocities and\ndistances among nebulae for which velocities have been previously pub-\nlished, and the relation appears to dominate the distribution of velocities.\nIn order to investigate the matter on a much larger scale, Mr. Humason\nat Mount Wilson has initiated a program of determining velocities\nof the most distant nebulae that can be observed with confidence.\nThese, naturally, are the brightest nebulae in clusters of nebulae.\nThe first definite result, $v = + 3779$ km./sec. for N. G. C. 7619, is\nthoroughly consistent with the present conclusions. Corrected for the\nsolar motion, this velocity is +3910, which, with $K = 500$, corresponds to\na distance of $7.8 \\times 10^6$ parsecs. Since the apparent magnitude is 11.8,\nthe absolute magnitude at such a distance is -17.65, which is of the\nright order for the brightest nebulae in a cluster. A preliminary dis-\ntance, derived independently from the cluster of which this nebula appears\nto be a member, is of the order of $7 \\times 10^6$ parsecs.\n\nNew data to be expected in the near future may modify the significance\nof the present investigation or, if confirmatory, will lead to a solution\nhaving many times the weight. For this reason it is thought premature\nto discuss in detail the obvious consequences of the present results. For\nexample, if the solar motion with respect to the clusters represents the\nrotation of the galactic system, this motion could be subtracted from the\nresults for the nebulae and the remainder would represent the motion of\nthe galactic system with respect to the extra-galactic nebulae.\n\nThe outstanding feature, however, is the possibility that the velocity-\ndistance relation may represent the de Sitter effect, and hence that numer-\nical data may be introduced into discussions of the general curvature of\nspace. In the de Sitter cosmology, displacements of the spectra arise\nfrom two sources, an apparent slowing down of atomic vibrations and a\ngeneral tendency of material particles to scatter. The latter involves an\nacceleration and hence introduces the element of time. The relative im-\nportance of these two effects should determine the form of the relation\nbetween distances and observed velocities; and in this connection it may\nbe emphasized that the linear relation found in the present discussion is a\nfirst approximation representing a restricted range in distance.\n\n1. *Mt. Wilson Contr.*, No. 324; *Astroph. J.*, Chicago, Ill., 64, 1926 (321).\n2. *Harvard Coll. Obs. Circ.*, 294, 1926.\n3. *Mon. Not. R. Astr. Soc.*, 85, 1925 (865-894).\n4. These *PROCEEDINGS*, 15, 1929 (167)."] diff --git a/tests/fixtures/hubble_golden.md b/tests/fixtures/hubble_golden.md deleted file mode 100644 index b0f4c71..0000000 --- a/tests/fixtures/hubble_golden.md +++ /dev/null @@ -1,312 +0,0 @@ - -168 ASTRONOMY: E. HUBBLE PROC. N. A. S. - -appearance the spectrum is very much like spectra of the Milky Way -clouds in Sagittarius and Cygnus, and is also similar to spectra of binary -stars of the W Ursae Majoris type, where the widening and depth of the -lines are affected by the rapid rotation of the stars involved. - -The wide shallow absorption lines observed in the spectrum of N. G. C. -7619 have been noticed in the spectra of other extra-galactic nebulae, and -may be due to a dispersion in velocity and a blending of the spectral types -of the many stars which presumably exist in the central parts of these -nebulae. The lack of depth in the absorption lines seems to be more -pronounced among the smaller and fainter nebulae, and in N. G. C. 7619 -the absorption is very weak. - -It is hoped that velocities of more of these interesting objects will soon -be available. - -## A RELATION BETWEEN DISTANCE AND RADIAL VELOCITY AMONG EXTRA-GALACTIC NEBULAE - -BY EDWIN HUBBLE -MOUNT WILSON OBSERVATORY, CARNEGIE INSTITUTION OF WASHINGTON -Communicated January 17, 1929 - -Determinations of the motion of the sun with respect to the extra- -galactic nebulae have involved a $K$ term of several hundred kilometers -which appears to be variable. Explanations of this paradox have been -sought in a correlation between apparent radial velocities and distances, -but so far the results have not been convincing. The present paper is a -re-examination of the question, based on only those nebular distances -which are believed to be fairly reliable. - -Distances of extra-galactic nebulae depend ultimately upon the appli- -cation of absolute-luminosity criteria to involved stars whose types can -be recognized. These include, among others, Cepheid variables, novae, -and blue stars involved in emission nebulosity. Numerical values depend -upon the zero point of the period-luminosity relation among Cepheids, -the other criteria merely check the order of the distances. This method -is restricted to the few nebulae which are well resolved by existing instru- -ments. A study of these nebulae, together with those in which any stars -at all can be recognized, indicates the probability of an approximately -uniform upper limit to the absolute luminosity of stars, in the late-type -spirals and irregular nebulae at least, of the order of $M$ (photographic) = --6.3.1 The apparent luminosities of the brightest stars in such nebulae -are thus criteria which, although rough and to be applied with caution, - - -VOL. 15, 1929 ASTRONOMY: E. HUBBLE 169 - -furnish reasonable estimates of the distances of all extra-galactic systems -in which even a few stars can be detected. - - -TABLE 1 -NEBULAE WHOSE DISTANCES HAVE BEEN ESTIMATED FROM STARS INVOLVED OR FROM -MEAN LUMINOSITIES IN A CLUSTER - -| OBJECT | $m_c$ | $r$ | $v_c$ | $m_v$ | $M_v$ | -| :----------- | :---- | :---- | :------- | :---- | :------- | -| S. Mag. | .. | 0.032 | + 170 | 1.5 | -16.0 | -| L. Mag. | .. | 0.034 | + 290 | 0.5 | 17.2 | -| N. G. C. 6822 | .. | 0.214 | - 130 | 9.0 | 12.7 | -| 598 | .. | 0.263 | - 70 | 7.0 | 15.1 | -| 221 | .. | 0.275 | - 185 | 8.8 | 13.4 | -| 224 | .. | 0.275 | - 220 | 5.0 | 17.2 | -| 5457 | 17.0 | 0.45 | + 200 | 9.9 | 13.3 | -| 4736 | 17.3 | 0.5 | + 290 | 8.4 | 15.1 | -| 5194 | 17.3 | 0.5 | + 270 | 7.4 | 16.1 | -| 4449 | 17.8 | 0.63 | + 200 | 9.5 | 14.5 | -| 4214 | 18.3 | 0.8 | + 300 | 11.3 | 13.2 | -| 3031 | 18.5 | 0.9 | - 30 | 8.3 | 16.4 | -| 3627 | 18.5 | 0.9 | + 650 | 9.1 | 15.7 | -| 4826 | 18.5 | 0.9 | + 150 | 9.0 | 15.7 | -| 5236 | 18.5 | 0.9 | + 500 | 10.4 | 14.4 | -| 1068 | 18.7 | 1.0 | + 920 | 9.1 | 15.9 | -| 5055 | 19.0 | 1.1 | + 450 | 9.6 | 15.6 | -| 7331 | 19.0 | 1.1 | + 500 | 10.4 | 14.8 | -| 4258 | 19.5 | 1.4 | + 500 | 8.7 | 17.0 | -| 4151 | 20.0 | 1.7 | + 960 | 12.0 | 14.2 | -| 4382 | .. | 2.0 | + 500 | 10.0 | 16.5 | -| 4472 | .. | 2.0 | + 850 | 8.8 | 17.7 | -| 4486 | .. | 2.0 | + 800 | 9.7 | 16.8 | -| 4649 | .. | 2.0 | +1090 | 9.5 | 17.0 | -| Mean | | | | | -15.5 | - -$m_c$ = photographic magnitude of brightest stars involved. -$r$ = distance in units of $10^6$ parsecs. The first two are Shapley's values. -$v_c$ = measured velocities in km./sec. N. G. C. 6822, 221, 224 and 5457 are recent -determinations by Humason. -$m_v$ = Holetschek's visual magnitude as corrected by Hopmann. The first three -objects were not measured by Holetschek, and the values of $m_v$ represent -estimates by the author based upon such data as are available. -$M_v$ = total visual absolute magnitude computed from $m_v$ and $r$. - - -Finally, the nebulae themselves appear to be of a definite order of -absolute luminosity, exhibiting a range of four or five magnitudes about -an average value $M$ (visual) = -15.2.1 The application of this statistical -average to individual cases can rarely be used to advantage, but where -considerable numbers are involved, and especially in the various clusters -of nebulae, mean apparent luminosities of the nebulae themselves offer -reliable estimates of the mean distances. - -Radial velocities of 46 extra-galactic nebulae are now available, but - - -170 ASTRONOMY: E. HUBBLE PROC. N. A. S. - -individual distances are estimated for only 24. For one other, N. G. C. -3521, an estimate could probably be made, but no photographs are avail- -able at Mount Wilson. The data are given in table 1. The first seven -distances are the most reliable, depending, except for M 32 the companion of -M 31, upon extensive investigations of many stars involved. The next -thirteen distances, depending upon the criterion of a uniform upper limit -of stellar luminosity, are subject to considerable probable errors but are -believed to be the most reasonable values at present available. The last -four objects appear to be in the Virgo Cluster. The distance assigned -to the cluster, $2 \times 10^6$ parsecs, is derived from the distribution of nebular -luminosities, together with luminosities of stars in some of the later-type -spirals, and differs somewhat from the Harvard estimate of ten million -light years.2 - -The data in the table indicate a linear correlation between distances and -velocities, whether the latter are used directly or corrected for solar motion, -according to the older solutions. This suggests a new solution for the solar -motion in which the distances are introduced as coefficients of the $K$ term, -i. e., the velocities are assumed to vary directly with the distances, and -hence $K$ represents the velocity at unit distance due to this effect. The -equations of condition then take the form - -$$ rK + X \cos \alpha \cos \delta + Y \sin \alpha \cos \delta + Z \sin \delta = v. $$ - -Two solutions have been made, one using the 24 nebulae individually, -the other combining them into 9 groups according to proximity in direc- -tion and in distance. The results are - -24 OBJECTS -$X$ = -65 $\pm$ 50 -$Y$ = +226 $\pm$ 95 -$Z$ = -195 $\pm$ 40 -$K$ = +465 $\pm$ 50 -$A$ = $286^{\circ}$ -$D$ = $+40^{\circ}$ -$V_o$ = 306 km./sec. - -9 GROUPS -+3 $\pm$ 70 -+230 $\pm$ 120 --133 $\pm$ 70 -+513 $\pm$ 60 km./sec. per $10^6$ parsecs. -$269^{\circ}$ -$+33^{\circ}$ -247 km./sec. - -For such scanty material, so poorly distributed, the results are fairly -definite. Differences between the two solutions are due largely to the -four Virgo nebulae, which, being the most distant objects and all sharing -the peculiar motion of the cluster, unduly influence the value of $K$ and -hence of $V_o$. New data on more distant objects will be required to reduce -the effect of such peculiar motion. Meanwhile round numbers, inter- -mediate between the two solutions, will represent the probable order of -the values. For instance, let $A = 277^{\circ}$, $D = +36^{\circ}$ (Gal. long. = $32^{\circ}$, -lat. = $+18^{\circ}$), $V_o = 280$ km./sec., $K = +500$ km./sec. per million par- - - -VOL. 15, 1929 ASTRONOMY: E. HUBBLE 171 - -secs. Mr. Strömberg has very kindly checked the general order of these -values by independent solutions for different groupings of the data. - -A constant term, introduced into the equations, was found to be small -and negative. This seems to dispose of the necessity for the old constant -$K$ term. Solutions of this sort have been published by Lundmark,3 who -replaced the old $K$ by $k + lr + mr^2$. His favored solution gave $k = 513$, -as against the former value of the order of 700, and hence offered little -advantage. - - -TABLE 2 -NEBULAE WHOSE DISTANCES ARE ESTIMATED FROM RADIAL VELOCITIES - -| OBJECT | $v_c$ | $v_o$ | $r$ | $m_v$ | $M_v$ | -| :----------- | :------ | :------- | :---- | :---- | :------- | -| N. G. C. 278 | + 650 | -110 | 1.52 | 12.0 | -13.9 | -| 404 | + 25 | - 65 | | 11.1 | | -| 584 | +1800 | + 75 | 3.45 | 10.9 | 16.8 | -| 936 | +1300 | +115 | 2.37 | 11.1 | 15.7 | -| 1023 | + 300 | - 10 | 0.62 | 10.2 | 13.8 | -| 1700 | + 800 | +220 | 1.16 | 12.5 | 12.8 | -| 2681 | + 700 | - 10 | 1.42 | 10.7 | 15.0 | -| 2683 | + 400 | + 65 | 0.67 | 9.9 | 14.3 | -| 2841 | + 600 | - 20 | 1.24 | 9.4 | 16.1 | -| 3034 | + 290 | -105 | 0.79 | 9.0 | 15.5 | -| 3115 | + 600 | +105 | 1.00 | 9.5 | 15.5 | -| 3368 | + 940 | + 70 | 1.74 | 10.0 | 16.2 | -| 3379 | + 810 | + 65 | 1.49 | 9.4 | 16.4 | -| 3489 | + 600 | + 50 | 1.10 | 11.2 | 14.0 | -| 3521 | + 730 | + 95 | 1.27 | 10.1 | 15.4 | -| 3623 | + 800 | + 35 | 1.53 | 9.9 | 16.0 | -| 4111 | + 800 | - 95 | 1.79 | 10.1 | 16.1 | -| 4526 | + 580 | - 20 | 1.20 | 11.1 | 14.3 | -| 4565 | +1100 | - 75 | 2.35 | 11.0 | 15.9 | -| 4594 | +1140 | + 25 | 2.23 | 9.1 | 17.6 | -| 5005 | + 900 | -130 | 2.06 | 11.1 | 15.5 | -| 5866 | + 650 | -215 | 1.73 | 11.7 | -14.5 | -| Mean | | | | 10.5 | -15.3 | - - -The residuals for the two solutions given above average 150 and 110 -km./sec. and should represent the average peculiar motions of the in- -dividual nebulae and of the groups, respectively. In order to exhibit -the results in a graphical form, the solar motion has been eliminated from -the observed velocities and the remainders, the distance terms plus the -residuals, have been plotted against the distances. The run of the re- -siduals is about as smooth as can be expected, and in general the form of -the solutions appears to be adequate. - -The 22 nebulae for which distances are not available can be treated in -two ways. First, the mean distance of the group derived from the mean -apparent magnitudes can be compared with the mean of the velocities - - -172 ASTRONOMY: E. HUBBLE PROC. N. A. S. - -corrected for solar motion. The result, 745 km./sec. for a distance of -$1.4 \times 10^6$ parsecs, falls between the two previous solutions and indicates -a value for $K$ of 530 as against the proposed value, 500 km./sec. - -Secondly, the scatter of the individual nebulae can be examined by -assuming the relation between distances and velocities as previously -determined. Distances can then be calculated from the velocities cor- -rected for solar motion, and absolute magnitudes can be derived from the -apparent magnitudes. The results are given in table 2 and may be -compared with the distribution of absolute magnitudes among the nebulae -in table 1, whose distances are derived from other criteria. N. G. C. 404 - - -Graph showing Velocity-Distance Relation among Extra-Galactic Nebulae. The x-axis is Dis<span class=tance, ranging from 0 to 2x10^6 Parsecs. The y-axis is Velocity, ranging from 0 to 2000 KM. Black discs represent individual nebulae, with a solid line showing the solution for solar motion using individual nebulae. Circles represent nebulae combined into groups, with a broken line showing the solution for these groups. A cross represents the mean velocity corresponding to the mean distance of 22 nebulae whose distances could not be estimated individually. The graph shows a roughly linear increase in velocity with distance."> - -FIGURE 1 -Velocity-Distance Relation among Extra-Galactic Nebulae. - -Radial velocities, corrected for solar motion, are plotted against -distances estimated from involved stars and mean luminosities of -nebulae in a cluster. The black discs and full line represent the -solution for solar motion using the nebulae individually; the circles -and broken line represent the solution combining the nebulae into -groups; the cross represents the mean velocity corresponding to -the mean distance of 22 nebulae whose distances could not be esti- -mated individually. - - -can be excluded, since the observed velocity is so small that the peculiar -motion must be large in comparison with the distance effect. The object -is not necessarily an exception, however, since a distance can be assigned -for which the peculiar motion and the absolute magnitude are both within -the range previously determined. The two mean magnitudes, -15.3 -and -15.5, the ranges, 4.9 and 5.0 mag., and the frequency distributions -are closely similar for these two entirely independent sets of data; and -even the slight difference in mean magnitudes can be attributed to the -selected, very bright, nebulae in the Virgo Cluster. This entirely unforced -agreement supports the validity of the velocity-distance relation in a very - - -VOL. 15, 1929 ASTRONOMY: E. HUBBLE 173 - -evident matter. Finally, it is worth recording that the frequency distribu- -tion of absolute magnitudes in the two tables combined is comparable -with those found in the various clusters of nebulae.4 - -The results establish a roughly linear relation between velocities and -distances among nebulae for which velocities have been previously pub- -lished, and the relation appears to dominate the distribution of velocities. -In order to investigate the matter on a much larger scale, Mr. Humason -at Mount Wilson has initiated a program of determining velocities -of the most distant nebulae that can be observed with confidence. -These, naturally, are the brightest nebulae in clusters of nebulae. -The first definite result, $v = + 3779$ km./sec. for N. G. C. 7619, is -thoroughly consistent with the present conclusions. Corrected for the -solar motion, this velocity is +3910, which, with $K = 500$, corresponds to -a distance of $7.8 \times 10^6$ parsecs. Since the apparent magnitude is 11.8, -the absolute magnitude at such a distance is -17.65, which is of the -right order for the brightest nebulae in a cluster. A preliminary dis- -tance, derived independently from the cluster of which this nebula appears -to be a member, is of the order of $7 \times 10^6$ parsecs. - -New data to be expected in the near future may modify the significance -of the present investigation or, if confirmatory, will lead to a solution -having many times the weight. For this reason it is thought premature -to discuss in detail the obvious consequences of the present results. For -example, if the solar motion with respect to the clusters represents the -rotation of the galactic system, this motion could be subtracted from the -results for the nebulae and the remainder would represent the motion of -the galactic system with respect to the extra-galactic nebulae. - -The outstanding feature, however, is the possibility that the velocity- -distance relation may represent the de Sitter effect, and hence that numer- -ical data may be introduced into discussions of the general curvature of -space. In the de Sitter cosmology, displacements of the spectra arise -from two sources, an apparent slowing down of atomic vibrations and a -general tendency of material particles to scatter. The latter involves an -acceleration and hence introduces the element of time. The relative im- -portance of these two effects should determine the form of the relation -between distances and observed velocities; and in this connection it may -be emphasized that the linear relation found in the present discussion is a -first approximation representing a restricted range in distance. - -1. *Mt. Wilson Contr.*, No. 324; *Astroph. J.*, Chicago, Ill., 64, 1926 (321). -2. *Harvard Coll. Obs. Circ.*, 294, 1926. -3. *Mon. Not. R. Astr. Soc.*, 85, 1925 (865-894). -4. These *PROCEEDINGS*, 15, 1929 (167). \ No newline at end of file diff --git a/tests/test_bbox_alignment.py b/tests/test_bbox_alignment.py deleted file mode 100644 index 9b168ea..0000000 --- a/tests/test_bbox_alignment.py +++ /dev/null @@ -1,54 +0,0 @@ -from gemini_ocr import bbox_alignment, document - - -def test_missing_assignment_hyphenation_and_hole_filling() -> None: - markdown_content = """\ -we enter an era of precision cancer medicine, where many drugs are -active in small molecularly defined subgroups of patients (e.g., only -3%-7% of lung cancer patients harbor the drug sensi- tizing EML4-ALK -gene fusion (Soda et al., 2007)), the scarcity of models for many -cancer genotypes and tissues is a limitation. New cell culturing tech- -nologies enable derivation of patient cell lines with high efficiency -and thus make derivation of a larger set of cell lines encompassing -the molecular diversity of cancer a realistic possibility (Liu et al., -2012; Sato et al., 2011). -""" - - bbox_texts = [ - "set of cell lines encompassing the molecular diversity of cancer", - "lines with high efficiency and thus make derivation of a larger", - "are active in small molecularly defined subgroups of patients", - "we enter an era of precision cancer medicine, where many drugs", - "models for many cancer genotypes and tissues is a limitation.", - "tizing EML4-ALK gene fusion [Soda et al., 2007]), the scarcity of", - "(e.g., only 3%-7% of lung cancer patients harbor the drug sensi-", - "a realistic possibility (Liu et al., 2012; Sato et al., 2011).", - "New cell culturing technologies enable derivation of patient cell", - ] - - dummy_rect = document.BBox(0, 0, 0, 0) - bboxes = [document.BoundingBox(text=t, page=0, rect=dummy_rect) for t in bbox_texts] - - # Run alignment - assignments = bbox_alignment.create_annotated_markdown(markdown_content, bboxes) - - # Verify all bboxes are assigned - assert len(assignments) == len(bboxes) - - # Ensure every original bbox is in the assignment dictionary - for bbox in bboxes: - assert bbox in assignments - - -def test_hyphen_match_simple() -> None: - # A simpler unit test for the hyphen logic specifically via Gapped Alignment - markdown = "hyphen- ated" - bbox_text = "hyphenated" - - bboxes = [document.BoundingBox(text=bbox_text, page=1, rect=document.BBox(0, 0, 0, 0))] - - # Run - assignments = bbox_alignment.create_annotated_markdown(markdown, bboxes) - - # Verify assignment - assert bboxes[0] in assignments diff --git a/tests/test_coverage.py b/tests/test_coverage.py deleted file mode 100644 index 444fa71..0000000 --- a/tests/test_coverage.py +++ /dev/null @@ -1,69 +0,0 @@ -from unittest.mock import MagicMock - -import pytest - -from gemini_ocr import bbox_alignment, document, gemini_ocr - - -@pytest.mark.asyncio -async def test_coverage_calculation() -> None: - # Setup - markdown = "Hello World" # length 11 - # Spans: "Hello" (0-5), "World" (6-11). Space (5-6) is missing. - # Total covered: 5 + 5 = 10. Coverage: 10/11 ~ 0.909 - - bbox1 = document.BoundingBox(text="Hello", page=1, rect=document.BBox(0, 0, 0, 0)) - bbox2 = document.BoundingBox(text="World", page=1, rect=document.BBox(0, 0, 0, 0)) - - annotated = {bbox1: (0, 5), bbox2: (6, 11)} - - raw_data = gemini_ocr.RawOcrData(markdown, [bbox1, bbox2]) - - # We need to mock extract_raw_data or just test the logic directly if possible. - # gemini_ocr.process_document calls extract_raw_data then bbox_alignment.create_annotated_markdown - # (which is slow/complex). Since the logic is inside process_document, we should mock the deps. - - # Easier: Mock extract_raw_data and bbox_alignment.create_annotated_markdown - - with pytest.MonkeyPatch.context() as m: - - async def mock_extract(*_args: object, **_kwargs: object) -> gemini_ocr.RawOcrData: - return raw_data - - m.setattr(gemini_ocr, "extract_raw_data", mock_extract) - m.setattr(bbox_alignment, "create_annotated_markdown", lambda *_, **__: annotated) - - settings = MagicMock() - - result = await gemini_ocr.process_document("dummy_path", settings=settings, markdown_content=markdown) # type: ignore[arg-type] - - expected_coverage = 10.0 / 11.0 - assert result.coverage_percent == pytest.approx(expected_coverage) - - -@pytest.mark.asyncio -async def test_coverage_overlap() -> None: - markdown = "Hello" # 5 - # Span 1: 0-3 "Hel" - # Span 2: 2-5 "llo" - # Union: 0-5. Covered: 5/5 = 1.0 - - bbox1 = document.BoundingBox(text="Hel", page=1, rect=document.BBox(0, 0, 0, 0)) - bbox2 = document.BoundingBox(text="llo", page=1, rect=document.BBox(0, 0, 0, 0)) - - annotated = {bbox1: (0, 3), bbox2: (2, 5)} - - raw_data = gemini_ocr.RawOcrData(markdown, [bbox1, bbox2]) - - with pytest.MonkeyPatch.context() as m: - - async def mock_extract(*_args: object, **_kwargs: object) -> gemini_ocr.RawOcrData: - return raw_data - - m.setattr(gemini_ocr, "extract_raw_data", mock_extract) - m.setattr(bbox_alignment, "create_annotated_markdown", lambda *_, **__: annotated) - - settings = MagicMock() - result = await gemini_ocr.process_document("dummy_path", settings=settings, markdown_content=markdown) # type: ignore[arg-type] - - assert result.coverage_percent == 1.0 diff --git a/tests/test_docai_layout.py b/tests/test_docai_layout.py deleted file mode 100644 index e9746d5..0000000 --- a/tests/test_docai_layout.py +++ /dev/null @@ -1,77 +0,0 @@ -from unittest.mock import Mock - -from gemini_ocr import docai_layout - - -def test_layout_processor_table_tags() -> None: - # Text block mock - text_block = Mock() - text_block.text_block.type_ = "paragraph" - text_block.text_block.text = "Header text" - text_block.text_block.blocks = [] - # Ensure other types are False - text_block.list_block = None - text_block.table_block = None - - # Table block mock - # 2x2 Table: 1 Header row, 1 Body row - - # Helper to make a cell mock - def make_cell(text: str) -> Mock: - cell = Mock() - cell.row_span = 1 - cell.col_span = 1 - block = Mock() - block.text_block.type_ = "paragraph" - block.text_block.text = text - block.text_block.blocks = [] - block.list_block = None - block.table_block = None - # The recursion check in _process_table_block iterates cell.blocks - cell.blocks = [block] - return cell - - cell_h1 = make_cell("H1") - cell_h2 = make_cell("H2") - cell_c1 = make_cell("C1") - cell_c2 = make_cell("C2") - - row_1 = Mock() - row_1.cells = [cell_h1, cell_h2] - - row_2 = Mock() - row_2.cells = [cell_c1, cell_c2] - - table_block = Mock() - table_block.text_block = None - table_block.list_block = None - table_block.table_block = Mock() - table_block.table_block.header_rows = [row_1] - table_block.table_block.body_rows = [row_2] - - processor = docai_layout.LayoutProcessor() - # Processor expects a list of blocks - result = "".join(processor.process([text_block, table_block])) - - print(f"Result:\n{result}") - - assert "# Header text" not in result # Paragraphs don't get # - assert "Header text" in result - assert "" in result - assert "| H1 | H2 |" in result - assert "| C1 | C2 |" in result - assert "" in result - - -def test_multiple_tables() -> None: - table_block = Mock() - table_block.text_block = None - table_block.list_block = None - table_block.table_block = Mock() - table_block.table_block.header_rows = [] - table_block.table_block.body_rows = [] - - processor = docai_layout.LayoutProcessor() - result = "".join(processor.process([table_block, table_block])) - - assert result.count("") == 2 diff --git a/tests/test_docai_mode.py b/tests/test_docai_mode.py deleted file mode 100644 index 3fb8995..0000000 --- a/tests/test_docai_mode.py +++ /dev/null @@ -1,113 +0,0 @@ -import pathlib -from unittest.mock import MagicMock, patch - -import fitz -import pytest -from google.cloud import documentai - -from gemini_ocr import gemini_ocr, settings - - -@pytest.fixture -def ocr_settings() -> settings.Settings: - return settings.Settings( - project_id="test-project", - location="us-central1", - ocr_processor_id="test-processor", - layout_processor_id="test-layout-processor", - mode=settings.OcrMode.DOCUMENTAI, - cache_dir=None, - ) - - -@patch("gemini_ocr.document.fitz.open") -@patch("gemini_ocr.docai.documentai.DocumentProcessorServiceClient") -@pytest.mark.asyncio -async def test_process_document_docai_mode( - mock_client_class: MagicMock, - mock_fitz_open: MagicMock, - ocr_settings: settings.Settings, - tmp_path: pathlib.Path, -) -> None: - # Create a dummy PDF file - dummy_pdf_path = tmp_path / "dummy.pdf" - dummy_pdf_path.write_bytes(b"%PDF-1.5\n%dummy") - - # Setup Mock API Client - mock_client = mock_client_class.return_value - mock_client.processor_path.return_value = "projects/p/locations/l/processors/p" - - # Create a mock Document object - mock_document = documentai.Document() - page = documentai.Document.Page() - page.dimension.width = 100 - page.dimension.height = 100 - - # Add a Line to the Page (docai_ocr uses page.lines) - line = documentai.Document.Page.Line() - line.layout.text_anchor.text_segments = [documentai.Document.TextAnchor.TextSegment(start_index=0, end_index=5)] - - # Bbox for line - v1 = documentai.NormalizedVertex(x=0.1, y=0.1) - v2 = documentai.NormalizedVertex(x=0.2, y=0.1) - v3 = documentai.NormalizedVertex(x=0.2, y=0.2) - v4 = documentai.NormalizedVertex(x=0.1, y=0.2) - line.layout.bounding_poly.normalized_vertices = [v1, v2, v3, v4] - - # Assign line to page for docai_ocr - page.lines = [line] - - # Setup DocumentLayout for docai_layout - layout_block = documentai.Document.DocumentLayout.DocumentLayoutBlock() - layout_block.text_block.text = "Hello" - layout_block.text_block.type_ = "paragraph" - mock_document.document_layout.blocks = [layout_block] - - mock_document.text = "Hello" - - # Add a Visual Element (Image) - image_el = documentai.Document.Page.VisualElement() - image_el.type_ = "image" - # 4 vertices - iv1 = documentai.NormalizedVertex(x=0.5, y=0.5) - iv2 = documentai.NormalizedVertex(x=0.6, y=0.5) - iv3 = documentai.NormalizedVertex(x=0.6, y=0.6) - iv4 = documentai.NormalizedVertex(x=0.5, y=0.6) - image_el.layout.bounding_poly.normalized_vertices = [iv1, iv2, iv3, iv4] - - page.visual_elements = [image_el] - mock_document.pages = [page] - mock_process_response = MagicMock() - mock_process_response.document = mock_document - mock_client.process_document.return_value = mock_process_response - - # Setup Mock fitz (PyMuPDF) - mock_doc = MagicMock() - mock_doc.__len__.return_value = 1 - mock_page = MagicMock() - mock_page.rect = fitz.Rect(0, 0, 1000, 1000) - # Mock get_pixmap to return bytes - mock_pix = MagicMock() - mock_pix.tobytes.return_value = b"fake_image_bytes" - mock_page.get_pixmap.return_value = mock_pix - - mock_doc.tobytes.return_value = b"fake_pdf_bytes" - mock_doc.__getitem__.return_value = mock_page - mock_fitz_open.return_value = mock_doc - - # Run process_document - result = await gemini_ocr.process_document(dummy_pdf_path, settings=ocr_settings) - - # Assertions - print("Markdown Content:", result.markdown_content) - - # We now look at result.markdown_content because OcrResult has markdown_content string field. - # The bounding_boxes is a dict mapping BoundingBox -> span (start, end). - - assert "Hello" in result.markdown_content - - # Check bounding box assignment - assert len(result.bounding_boxes) == 1 - bbox, span = next(iter(result.bounding_boxes.items())) - assert bbox.text == "Hello" - assert result.markdown_content[span[0] : span[1]] == "Hello" diff --git a/tests/test_gcs_support.py b/tests/test_gcs_support.py deleted file mode 100644 index 1d74be2..0000000 --- a/tests/test_gcs_support.py +++ /dev/null @@ -1,50 +0,0 @@ -import pathlib -from unittest.mock import MagicMock, patch - -import fitz -import pytest - -from gemini_ocr import document - - -@pytest.fixture -def valid_pdf_bytes() -> bytes: - doc = fitz.open() - doc.new_page() - return doc.tobytes() - - -def test_chunks_gcs_path(valid_pdf_bytes: bytes) -> None: - """Test chunks with a GCS path using mock fsspec.""" - gcs_path = "gs://bucket/file.pdf" - - # Mock fsspec.open - mock_file = MagicMock() - mock_file.read.return_value = valid_pdf_bytes - mock_file.__enter__.return_value = mock_file - mock_file.__exit__.return_value = None - - with patch("fsspec.open") as mock_open: - mock_open.return_value = mock_file - - # Call chunks - chunks = list(document.chunks(gcs_path)) - - # Verify fsspec.open called - mock_open.assert_called_once_with(gcs_path, "rb") - - # Verify chunks created - assert len(chunks) > 0 - assert chunks[0].data == valid_pdf_bytes - assert chunks[0].mime_type == "application/pdf" - - -def test_chunks_local_file(tmp_path: pathlib.Path, valid_pdf_bytes: bytes) -> None: - """Test chunks with local file path (not using fsspec logic in priority).""" - # This ensures we didn't break local file handling - pdf_path = tmp_path / "test.pdf" - pdf_path.write_bytes(valid_pdf_bytes) - - chunks = list(document.chunks(pdf_path)) - assert len(chunks) > 0 - assert chunks[0].data == valid_pdf_bytes diff --git a/tests/test_markdown.py b/tests/test_markdown.py new file mode 100644 index 0000000..3d97add --- /dev/null +++ b/tests/test_markdown.py @@ -0,0 +1,60 @@ +from unittest.mock import AsyncMock, patch + +import pytest +from anchorite.document import DocumentChunk + +from groundmark.markdown import PydanticAIMarkdownProvider, _agent + + +@pytest.fixture +def chunk() -> DocumentChunk: + return DocumentChunk( + document_sha256="abc", + start_page=0, + end_page=1, + data=b"fake-pdf-bytes", + mime_type="application/pdf", + ) + + +@patch.object(_agent, "run", new_callable=AsyncMock) +@pytest.mark.asyncio +async def test_calls_agent_with_chunk_data(mock_run: AsyncMock, chunk: DocumentChunk) -> None: + mock_run.return_value.output = "1|# Hello\n2|\n3|Some text" + + provider = PydanticAIMarkdownProvider(model="anthropic:claude-opus-4-6") + result = await provider.generate_markdown(chunk) + + mock_run.assert_called_once() + call_args = mock_run.call_args + user_prompt = call_args[0][0] + assert user_prompt[0].data == b"fake-pdf-bytes" + assert user_prompt[0].media_type == "application/pdf" + assert call_args[1]["model"] == "anthropic:claude-opus-4-6" + + # Line-number prefixes should be stripped. + assert result == "# Hello\n\nSome text" + + +@patch.object(_agent, "run", new_callable=AsyncMock) +@pytest.mark.asyncio +async def test_strips_line_numbers(mock_run: AsyncMock, chunk: DocumentChunk) -> None: + mock_run.return_value.output = "1|First line\n2|Second line\n3|\n4|Fourth" + + provider = PydanticAIMarkdownProvider(model="anthropic:claude-opus-4-6") + result = await provider.generate_markdown(chunk) + + assert result == "First line\nSecond line\n\nFourth" + + +@patch.object(_agent, "run", new_callable=AsyncMock) +@pytest.mark.asyncio +async def test_nfkc_normalizes_output(mock_run: AsyncMock, chunk: DocumentChunk) -> None: + # Superscript digits and ligatures should be decomposed to ASCII equivalents + # so that alignment matches the NFKC-normalized anchor text from pdfplumber. + mock_run.return_value.output = "1|overlap with NS\u00b9\u2070\u00b7\u00b9\u00b9 and findings" + + provider = PydanticAIMarkdownProvider(model="anthropic:claude-opus-4-6") + result = await provider.generate_markdown(chunk) + + assert result == "overlap with NS10·11 and findings" diff --git a/tests/test_missed_matches.py b/tests/test_missed_matches.py deleted file mode 100644 index 2ff71ec..0000000 --- a/tests/test_missed_matches.py +++ /dev/null @@ -1,62 +0,0 @@ -from gemini_ocr import bbox_alignment, document, gemini_ocr - - -def test_missed_match_histone_modifier() -> None: - markdown_content = """ -| Cell cycle | 3 | 34 | -| DNA repair | 4 | 52 | -| Histone modifier | 5 | 29 | -| OTHER GROWTH/PROLIFERATION SIGNALING | | | -""" - - bbox_text = "Histone modifier" - bbox = document.BoundingBox(text=bbox_text, page=1, rect=document.BBox(0, 0, 0, 0)) - bboxes = [bbox] - - alignments = bbox_alignment.create_annotated_markdown(markdown_content, bboxes) - - assert bbox in alignments - - result = gemini_ocr.OcrResult(markdown_content, alignments, coverage_percent=0.0) - annotated = result.annotate() - - assert 'Histone modifier" in annotated - - -def test_missed_match_mek12() -> None: - markdown_content = """ -| Trametinib | MEK1/2 | BRAF | SKCM | -| Vemurafenib | BRAF | BRAF | SKCM | -""" - bbox_text = "MEK1/2" - bbox = document.BoundingBox(text=bbox_text, page=1, rect=document.BBox(0, 0, 0, 0)) - bboxes = [bbox] - - alignments = bbox_alignment.create_annotated_markdown(markdown_content, bboxes) - - assert bbox in alignments - - result = gemini_ocr.OcrResult(markdown_content, alignments, coverage_percent=0.0) - annotated = result.annotate() - assert ">MEK1/2" in annotated - - -def test_missed_match_duplicate_handling() -> None: - markdown_content = """ -Here is duplicate. -Here is duplicate. -""" - bbox_text = "duplicate" - bbox = document.BoundingBox(text=bbox_text, page=1, rect=document.BBox(0, 0, 0, 0)) - bboxes = [bbox] - - alignments = bbox_alignment.create_annotated_markdown(markdown_content, bboxes) - - assert bbox in alignments - - result = gemini_ocr.OcrResult(markdown_content, alignments, coverage_percent=0.0) - annotated = result.annotate() - - assert annotated.count('duplicate" in annotated diff --git a/tests/test_model_config.py b/tests/test_model_config.py deleted file mode 100644 index 4a8913b..0000000 --- a/tests/test_model_config.py +++ /dev/null @@ -1,43 +0,0 @@ -from unittest.mock import MagicMock, patch - -import pytest - -from gemini_ocr import document, gemini, settings - - -@pytest.mark.asyncio -async def test_generate_markdown_uses_configured_model() -> None: - # Setup settings with custom model - ocr_settings = settings.Settings( - project_id="test-project", - location="us-central1", - layout_processor_id="layout-id", - ocr_processor_id="ocr-id", - gemini_model_name="gemini-1.5-pro-preview-0409", - ) - - chunk = document.DocumentChunk( - document_sha256="hash", - start_page=0, - end_page=1, - data=b"pdf-content", - mime_type="application/pdf", - ) - - # Mock genai.Client - with patch("google.genai.Client") as mock_client: - mock_client_instance = mock_client.return_value - mock_models = mock_client_instance.models - mock_response = MagicMock() - mock_response.text = "Markdown content" - mock_models.generate_content.return_value = mock_response - - # Execute - result = await gemini.generate_markdown(ocr_settings, chunk) - - # Verify - assert result == "Markdown content" - - # Check if generate_content was called with correct model - _args, kwargs = mock_models.generate_content.call_args - assert kwargs["model"] == "gemini-1.5-pro-preview-0409" diff --git a/tests/test_ocr_annotation.py b/tests/test_ocr_annotation.py deleted file mode 100644 index 006d8c0..0000000 --- a/tests/test_ocr_annotation.py +++ /dev/null @@ -1,73 +0,0 @@ -from gemini_ocr import document, gemini_ocr - - -def test_ocr_result_annotate() -> None: - markdown_content = "Hello World" - # span "Hello" is [0, 5) - # span "World" is [6, 11) - - bbox1 = document.BoundingBox(text="Hello", page=1, rect=document.BBox(0, 0, 5, 1)) - span1 = (0, 5) - - bbox2 = document.BoundingBox(text="World", page=1, rect=document.BBox(6, 6, 11, 1)) - span2 = (6, 11) - - result = gemini_ocr.OcrResult( - markdown_content=markdown_content, - bounding_boxes={bbox1: span1, bbox2: span2}, - coverage_percent=1.0, - ) - - annotated = result.annotate() - - # Expected format: {text} - # bbox1: 0,0,5,1 -> "0,0,5,1" - tag1_start = '' - tag_end = "" - - tag2_start = '' - - expected = f"{tag1_start}Hello{tag_end} {tag2_start}World{tag_end}" - - assert annotated == expected - - -def test_ocr_result_annotate_overlap() -> None: - # Test overlapping spans (nested) - content = "Hello" - bbox1 = document.BoundingBox(text="Hello", page=1, rect=document.BBox(0, 0, 5, 1)) - span1 = (0, 5) - - bbox2 = document.BoundingBox(text="He", page=1, rect=document.BBox(0, 0, 1, 1)) - span2 = (0, 2) - - result = gemini_ocr.OcrResult(content, {bbox1: span1, bbox2: span2}, coverage_percent=1.0) - - annotated = result.annotate() - - tag1_start = '' - tag2_start = '' - tag_end = "" - - expected = f"{tag1_start}{tag2_start}He{tag_end}llo{tag_end}" - assert annotated == expected - - -def test_ocr_result_annotate_zero_length() -> None: - # Test zero-length span - # Text content: "Hello" - # bbox1: "" [2, 2) (Insertion point at index 2) - - content = "Hello" - bbox1 = document.BoundingBox(text="", page=1, rect=document.BBox(0, 0, 0, 0)) - span1 = (2, 2) - - result = gemini_ocr.OcrResult(content, {bbox1: span1}, coverage_percent=0.0) - - annotated = result.annotate() - - tag_start = '' - tag_end = "" - - expected = f"He{tag_start}{tag_end}llo" - assert annotated == expected diff --git a/tests/test_ocr_nesting.py b/tests/test_ocr_nesting.py deleted file mode 100644 index e82a81e..0000000 --- a/tests/test_ocr_nesting.py +++ /dev/null @@ -1,29 +0,0 @@ -from gemini_ocr import document, gemini_ocr - - -def test_nested_zero_length_at_start() -> None: - content = "Hello" - bbox_a = document.BoundingBox(text="Hello", page=1, rect=document.BBox(0, 0, 5, 1)) - bbox_b = document.BoundingBox(text="", page=1, rect=document.BBox(0, 0, 0, 0)) - - result = gemini_ocr.OcrResult(content, {bbox_a: (0, 5), bbox_b: (0, 0)}, coverage_percent=0.0) - annotated = result.annotate() - - tag_a = '' - tag_b = '' - - assert f"{tag_a}{tag_b}Hello" == annotated - - -def test_nested_zero_length_at_end() -> None: - content = "Hello" - bbox_a = document.BoundingBox(text="Hello", page=1, rect=document.BBox(0, 0, 5, 1)) - bbox_c = document.BoundingBox(text="", page=1, rect=document.BBox(5, 5, 5, 5)) - - result = gemini_ocr.OcrResult(content, {bbox_a: (0, 5), bbox_c: (5, 5)}, coverage_percent=0.0) - annotated = result.annotate() - - tag_a = '' - tag_c = '' - - assert f"{tag_a}Hello{tag_c}" == annotated diff --git a/tests/test_parse.py b/tests/test_parse.py new file mode 100644 index 0000000..5dbcacb --- /dev/null +++ b/tests/test_parse.py @@ -0,0 +1,38 @@ +from pathlib import Path + +import pytest +from anchorite.document import chunks + +from groundmark.parse import PdfplumberAnchorProvider + +DATA_DIR = Path(__file__).parent / "data" + + +@pytest.fixture +def provider() -> PdfplumberAnchorProvider: + return PdfplumberAnchorProvider() + + +@pytest.mark.asyncio +async def test_extracts_lines(provider: PdfplumberAnchorProvider) -> None: + """Smoke test: basic line extraction works.""" + pdf_bytes = (DATA_DIR / "hello_world.pdf").read_bytes() + + chunk = next(chunks(pdf_bytes)) + anchors = await provider.generate_anchors(chunk) + texts = {a.text for a in anchors} + assert "Hello World" in texts + assert "Second line" in texts + + +@pytest.mark.asyncio +async def test_table_rows_detected(provider: PdfplumberAnchorProvider) -> None: + """Table cells on the same row should appear in a single anchor.""" + pdf_bytes = (DATA_DIR / "table_2x2.pdf").read_bytes() + + chunk = next(chunks(pdf_bytes)) + anchors = await provider.generate_anchors(chunk) + texts = {a.text for a in anchors} + + assert any("Cell A" in t and "Cell B" in t for t in texts), f"Row 1 not merged: {texts}" + assert any("Cell C" in t and "Cell D" in t for t in texts), f"Row 2 not merged: {texts}" diff --git a/tests/test_process.py b/tests/test_process.py new file mode 100644 index 0000000..03b2635 --- /dev/null +++ b/tests/test_process.py @@ -0,0 +1,42 @@ +from pathlib import Path +from unittest.mock import AsyncMock, patch + +import pytest +from anchorite import Anchor, BBox + +from groundmark.process import Config, process + +DATA_DIR = Path(__file__).parent / "data" + + +@pytest.fixture +def config() -> Config: + return Config(model="anthropic:claude-opus-4-6") + + +@pytest.fixture +def simple_pdf_bytes() -> bytes: + return (DATA_DIR / "simple_hello.pdf").read_bytes() + + +@patch("groundmark.parse.PdfplumberAnchorProvider.generate_anchors", new_callable=AsyncMock) +@patch("groundmark.markdown.PydanticAIMarkdownProvider.generate_markdown", new_callable=AsyncMock) +@pytest.mark.asyncio +async def test_process( + mock_generate_md: AsyncMock, + mock_generate_anchors: AsyncMock, + config: Config, + simple_pdf_bytes: bytes, +) -> None: + mock_generate_md.return_value = "Hello\n\n" + mock_generate_anchors.return_value = [ + Anchor(text="Hello", page=0, box=BBox(100, 100, 200, 200)), + ] + + result = await process(simple_pdf_bytes, config) + + assert "Hello" in result.annotated_markdown + assert " None: - assert range_ops.in_range(val, test_range) is expected - - -@pytest.mark.parametrize( - ("r1", "r2", "expected"), - [ - # Overlapping cases - ((0, 10), (5, 15), True), - ((5, 15), (0, 10), True), - ((0, 10), (0, 10), True), - ((0, 20), (5, 10), True), - ((5, 10), (0, 20), True), - # Non-overlapping cases / Touching - ((0, 10), (10, 20), False), - ((10, 20), (0, 10), False), - ((0, 5), (15, 20), False), - ], -) -def test_overlaps(r1: tuple[int, int], r2: tuple[int, int], expected: bool) -> None: - assert range_ops.overlaps(r1, r2) is expected - - -@pytest.mark.parametrize( - ("r1", "r2", "expected"), - [ - # Contained - ((5, 10), (0, 20), True), - ((0, 10), (0, 20), True), - ((10, 20), (0, 20), True), - ((0, 20), (0, 20), True), - # Not contained - ((0, 20), (5, 10), False), - ((0, 15), (10, 20), False), - ((-5, 5), (0, 10), False), - ((0, 10), (10, 20), False), - ], -) -def test_contained(r1: tuple[int, int], r2: tuple[int, int], expected: bool) -> None: - assert range_ops.contained(r1, r2) is expected diff --git a/tests/test_regression.py b/tests/test_regression.py deleted file mode 100644 index b2c05c4..0000000 --- a/tests/test_regression.py +++ /dev/null @@ -1,140 +0,0 @@ -import json -import os -import pathlib -import pickle -import typing -from unittest.mock import AsyncMock, patch - -import pytest -from google.cloud import documentai # type: ignore[import-untyped] - -from gemini_ocr import document, gemini_ocr, settings - -FIXTURES_DIR = pathlib.Path(__file__).parent / "fixtures" - - -@pytest.fixture -def regression_settings() -> settings.Settings: - return settings.Settings( - project_id="test-project", - location="us-central1", - layout_processor_id="test-layout", - ocr_processor_id="test-ocr", - mode=settings.OcrMode.GEMINI, - cache_dir=None, - ) - - -@pytest.mark.asyncio -async def test_hubble_regression(regression_settings: settings.Settings) -> None: - pdf_path = pathlib.Path("tests/data/hubble-1929.pdf") - if not pdf_path.exists(): - pytest.skip("Regression test PDF not found") - - # Load fixtures - # Load fixtures - with open(FIXTURES_DIR / "hubble_gemini_responses.json") as f: - gemini_responses = json.load(f) - - with open(FIXTURES_DIR / "hubble_docai_bboxes.pkl", "rb") as f_bin: - docai_bboxes = pickle.load(f_bin) # noqa: S301 - - async def mock_gemini_side_effect(_settings: settings.Settings, chunk: document.DocumentChunk) -> str: - idx = chunk.start_page // 10 - return str(gemini_responses[idx]) - - async def mock_ocr_side_effect( - _settings: settings.Settings, - chunk: document.DocumentChunk, - ) -> list[document.BoundingBox]: - idx = chunk.start_page // 10 - return typing.cast("list[document.BoundingBox]", docai_bboxes[idx]) - - # Patch - with patch("gemini_ocr.gemini.generate_markdown", new_callable=AsyncMock) as mock_gemini: - mock_gemini.side_effect = mock_gemini_side_effect - - with patch("gemini_ocr.docai_ocr.generate_bounding_boxes", new_callable=AsyncMock) as mock_ocr: - mock_ocr.side_effect = mock_ocr_side_effect - - # Run - result = await gemini_ocr.process_document(pdf_path, settings=regression_settings) - - # Annotate - output_md = result.annotate() - - # Compare with golden - golden_path = FIXTURES_DIR / "hubble_golden.md" - - if os.environ.get("UPDATE_GOLDEN"): - golden_path.write_text(output_md) - - if not golden_path.exists(): - pytest.fail("Golden file not found. Run with UPDATE_GOLDEN=1 to generate it.") - - expected = golden_path.read_text() - assert output_md == expected - - -@pytest.mark.asyncio -async def test_hubble_docai_regression(regression_settings: settings.Settings) -> None: - pdf_path = pathlib.Path("tests/data/hubble-1929.pdf") - if not pdf_path.exists(): - pytest.skip("Regression test PDF not found") - - docai_settings = regression_settings - docai_settings.mode = settings.OcrMode.DOCUMENTAI - docai_settings.layout_processor_id = "test-layout-id" # Mocked anyway - - # Load fixtures - with open(FIXTURES_DIR / "hubble_docai_layout_responses.json") as f: - docai_responses_json = json.load(f) - - # Deserialize list of JSON strings to documentai.Document objects - docai_responses = [ - typing.cast("documentai.Document", documentai.Document.from_json(j)) for j in docai_responses_json - ] - - with open(FIXTURES_DIR / "hubble_docai_bboxes.pkl", "rb") as f_bin: - docai_bboxes = pickle.load(f_bin) # noqa: S301 - - async def mock_docai_side_effect( - _settings: settings.Settings, - _process_options: documentai.ProcessOptions, - _processor_id: str, - chunk: document.DocumentChunk, - ) -> documentai.Document: - idx = chunk.start_page // 10 - return docai_responses[idx] - - async def mock_ocr_side_effect( - _settings: settings.Settings, - chunk: document.DocumentChunk, - ) -> list[document.BoundingBox]: - idx = chunk.start_page // 10 - return typing.cast("list[document.BoundingBox]", docai_bboxes[idx]) - - # Patch - with patch("gemini_ocr.docai.process", new_callable=AsyncMock) as mock_process: - mock_process.side_effect = mock_docai_side_effect - - with patch("gemini_ocr.docai_ocr.generate_bounding_boxes", new_callable=AsyncMock) as mock_ocr: - mock_ocr.side_effect = mock_ocr_side_effect - - # Run - result = await gemini_ocr.process_document(pdf_path, settings=docai_settings) - - # Annotate - output_md = result.annotate() - - # Compare with golden - golden_path = FIXTURES_DIR / "hubble_docai_golden.md" - - if os.environ.get("UPDATE_GOLDEN"): - golden_path.write_text(output_md) - - if not golden_path.exists(): - pytest.fail("Golden file not found. Run with UPDATE_GOLDEN=1 to generate it.") - - expected = golden_path.read_text() - assert output_md == expected diff --git a/tests/test_renumbering.py b/tests/test_renumbering.py deleted file mode 100644 index 6e2298b..0000000 --- a/tests/test_renumbering.py +++ /dev/null @@ -1,40 +0,0 @@ -import re -from unittest.mock import patch - -import pytest - -from gemini_ocr import gemini_ocr, settings - - -@pytest.mark.asyncio -async def test_multi_chunk_renumbering() -> None: - # multiple chunks with overlapping table/figure numbers - # Mock _generate_markdown_for_chunk to return specific text with generic markers - with ( - patch("gemini_ocr.gemini_ocr._generate_markdown_for_chunk") as mock_gen_md, - patch("gemini_ocr.document.chunks", return_value=["c1", "c2"]), - patch("gemini_ocr.docai_ocr.generate_bounding_boxes", return_value=[]), - ): - mock_gen_md.side_effect = [ - "Part 1: Content ", - "Part 2: Content ", - ] - res = await gemini_ocr.process_document( - "dummy.pdf", - settings=settings.Settings( - project_id="test", - location="us", - ocr_processor_id="id", - layout_processor_id="id", - ), - ) - - content = res.markdown_content - - # Check tables are 1, 2, 3 - tables = re.findall(r"", content) - assert tables == ["", "", ""] - - # Check figures are 1, 2, 3 - figures = re.findall(r"", content) - assert figures == ["", "", ""] diff --git a/tests/test_settings.py b/tests/test_settings.py deleted file mode 100644 index 01c4cac..0000000 --- a/tests/test_settings.py +++ /dev/null @@ -1,70 +0,0 @@ -import os -from unittest.mock import patch - -import pytest - -from gemini_ocr.settings import Settings - - -def test_settings_from_env() -> None: - """Test loading from environment variable using from_env factory.""" - env = { - "GEMINI_OCR_PROJECT_ID": "env-project", - "GEMINI_OCR_LOCATION": "eu", - "GEMINI_OCR_LAYOUT_PROCESSOR_ID": "env-layout", - "GEMINI_OCR_OCR_PROCESSOR_ID": "env-ocr", - } - with patch.dict(os.environ, env, clear=True): - s = Settings.from_env() - assert s.project_id == "env-project" - assert s.get_documentai_location() == "eu" - - assert s.layout_processor_id == "env-layout" - assert s.ocr_processor_id == "env-ocr" - assert s.quota_project_id is None - - # Test setting QUOTA_PROJECT_ID - env["GEMINI_OCR_QUOTA_PROJECT_ID"] = "env-quota" - with patch.dict(os.environ, env, clear=True): - s = Settings.from_env() - assert s.quota_project_id == "env-quota" - - # Test overridden locations - env_loc = { - "GEMINI_OCR_PROJECT_ID": "p", - "GEMINI_OCR_LOCATION": "europe-west1", - "GEMINI_OCR_DOCUMENTAI_LOCATION": "eu", - } - with patch.dict(os.environ, env_loc, clear=True): - s = Settings.from_env() - assert s.get_documentai_location() == "eu" - assert s.location == "europe-west1" - - -def test_settings_from_env_defaults() -> None: - """Test default values when using from_env.""" - with patch.dict( - os.environ, - { - "GEMINI_OCR_PROJECT_ID": "test-project", - # LOCATION allows defaults/fallback - }, - clear=True, - ): - # layout_processor_id and ocr_processor_id return None if missing in env - s = Settings.from_env() - assert s.project_id == "test-project" - assert s.get_documentai_location() == "us" # default - assert s.location == "us-central1" - - assert s.layout_processor_id is None - assert s.ocr_processor_id is None - - -def test_settings_validation_error() -> None: - """Test validation raises error if missing required env vars in from_env.""" - with ( - patch.dict(os.environ, {}, clear=True), - pytest.raises(ValueError, match="PROJECT_ID environment variable is required"), - ): - Settings.from_env() diff --git a/uv.lock b/uv.lock index 924c606..ed198bf 100644 --- a/uv.lock +++ b/uv.lock @@ -2,133 +2,38 @@ version = 1 revision = 3 requires-python = ">=3.11" resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version == '3.13.*'", - "python_full_version < '3.13'", + "python_full_version >= '3.14' and sys_platform == 'win32'", + "python_full_version >= '3.14' and sys_platform == 'emscripten'", + "python_full_version >= '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", + "python_full_version == '3.13.*' and sys_platform == 'win32'", + "python_full_version == '3.13.*' and sys_platform == 'emscripten'", + "python_full_version == '3.13.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", + "python_full_version < '3.13' and sys_platform == 'win32'", + "python_full_version < '3.13' and sys_platform == 'emscripten'", + "python_full_version < '3.13' and sys_platform != 'emscripten' and sys_platform != 'win32'", ] [[package]] -name = "aiohappyeyeballs" -version = "2.6.1" +name = "anchorite" +version = "0.1.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/26/30/f84a107a9c4331c14b2b586036f40965c128aa4fee4dda5d3d51cb14ad54/aiohappyeyeballs-2.6.1.tar.gz", hash = "sha256:c3f9d0113123803ccadfdf3f0faa505bc78e6a72d1cc4806cbd719826e943558", size = 22760, upload-time = "2025-03-12T01:42:48.764Z" } +dependencies = [ + { name = "fsspec" }, + { name = "pypdfium2" }, + { name = "seq-smith" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/aa/3a/80cae16d66d163de4fed0e9bfae5cbe3a35aa47ac611ef6a34fa5a531405/anchorite-0.1.1.tar.gz", hash = "sha256:466681448615b9e7f0fd661838547e6b03ea31b42bb5dfbc80f4f5d5a8e5fed8", size = 4259380, upload-time = "2026-03-14T06:27:57.551Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl", hash = "sha256:f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8", size = 15265, upload-time = "2025-03-12T01:42:47.083Z" }, + { url = "https://files.pythonhosted.org/packages/b7/c6/8b6760df7c78ebf3340b98b71dacb779f97cda45f09d504aa8d990262291/anchorite-0.1.1-py3-none-any.whl", hash = "sha256:4b3559f16df20017d636079c9baa5e183fea893027b154e425376e51e2f20ac6", size = 21476, upload-time = "2026-03-14T06:27:55.794Z" }, ] [[package]] -name = "aiohttp" -version = "3.13.3" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "aiohappyeyeballs" }, - { name = "aiosignal" }, - { name = "attrs" }, - { name = "frozenlist" }, - { name = "multidict" }, - { name = "propcache" }, - { name = "yarl" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/50/42/32cf8e7704ceb4481406eb87161349abb46a57fee3f008ba9cb610968646/aiohttp-3.13.3.tar.gz", hash = "sha256:a949eee43d3782f2daae4f4a2819b2cb9b0c5d3b7f7a927067cc84dafdbb9f88", size = 7844556, upload-time = "2026-01-03T17:33:05.204Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/f1/4c/a164164834f03924d9a29dc3acd9e7ee58f95857e0b467f6d04298594ebb/aiohttp-3.13.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5b6073099fb654e0a068ae678b10feff95c5cae95bbfcbfa7af669d361a8aa6b", size = 746051, upload-time = "2026-01-03T17:29:43.287Z" }, - { url = "https://files.pythonhosted.org/packages/82/71/d5c31390d18d4f58115037c432b7e0348c60f6f53b727cad33172144a112/aiohttp-3.13.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1cb93e166e6c28716c8c6aeb5f99dfb6d5ccf482d29fe9bf9a794110e6d0ab64", size = 499234, upload-time = "2026-01-03T17:29:44.822Z" }, - { url = "https://files.pythonhosted.org/packages/0e/c9/741f8ac91e14b1d2e7100690425a5b2b919a87a5075406582991fb7de920/aiohttp-3.13.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:28e027cf2f6b641693a09f631759b4d9ce9165099d2b5d92af9bd4e197690eea", size = 494979, upload-time = "2026-01-03T17:29:46.405Z" }, - { url = "https://files.pythonhosted.org/packages/75/b5/31d4d2e802dfd59f74ed47eba48869c1c21552c586d5e81a9d0d5c2ad640/aiohttp-3.13.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3b61b7169ababd7802f9568ed96142616a9118dd2be0d1866e920e77ec8fa92a", size = 1748297, upload-time = "2026-01-03T17:29:48.083Z" }, - { url = "https://files.pythonhosted.org/packages/1a/3e/eefad0ad42959f226bb79664826883f2687d602a9ae2941a18e0484a74d3/aiohttp-3.13.3-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:80dd4c21b0f6237676449c6baaa1039abae86b91636b6c91a7f8e61c87f89540", size = 1707172, upload-time = "2026-01-03T17:29:49.648Z" }, - { url = "https://files.pythonhosted.org/packages/c5/3a/54a64299fac2891c346cdcf2aa6803f994a2e4beeaf2e5a09dcc54acc842/aiohttp-3.13.3-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:65d2ccb7eabee90ce0503c17716fc77226be026dcc3e65cce859a30db715025b", size = 1805405, upload-time = "2026-01-03T17:29:51.244Z" }, - { url = "https://files.pythonhosted.org/packages/6c/70/ddc1b7169cf64075e864f64595a14b147a895a868394a48f6a8031979038/aiohttp-3.13.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5b179331a481cb5529fca8b432d8d3c7001cb217513c94cd72d668d1248688a3", size = 1899449, upload-time = "2026-01-03T17:29:53.938Z" }, - { url = "https://files.pythonhosted.org/packages/a1/7e/6815aab7d3a56610891c76ef79095677b8b5be6646aaf00f69b221765021/aiohttp-3.13.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d4c940f02f49483b18b079d1c27ab948721852b281f8b015c058100e9421dd1", size = 1748444, upload-time = "2026-01-03T17:29:55.484Z" }, - { url = "https://files.pythonhosted.org/packages/6b/f2/073b145c4100da5511f457dc0f7558e99b2987cf72600d42b559db856fbc/aiohttp-3.13.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f9444f105664c4ce47a2a7171a2418bce5b7bae45fb610f4e2c36045d85911d3", size = 1606038, upload-time = "2026-01-03T17:29:57.179Z" }, - { url = "https://files.pythonhosted.org/packages/0a/c1/778d011920cae03ae01424ec202c513dc69243cf2db303965615b81deeea/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:694976222c711d1d00ba131904beb60534f93966562f64440d0c9d41b8cdb440", size = 1724156, upload-time = "2026-01-03T17:29:58.914Z" }, - { url = "https://files.pythonhosted.org/packages/0e/cb/3419eabf4ec1e9ec6f242c32b689248365a1cf621891f6f0386632525494/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:f33ed1a2bf1997a36661874b017f5c4b760f41266341af36febaf271d179f6d7", size = 1722340, upload-time = "2026-01-03T17:30:01.962Z" }, - { url = "https://files.pythonhosted.org/packages/7a/e5/76cf77bdbc435bf233c1f114edad39ed4177ccbfab7c329482b179cff4f4/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e636b3c5f61da31a92bf0d91da83e58fdfa96f178ba682f11d24f31944cdd28c", size = 1783041, upload-time = "2026-01-03T17:30:03.609Z" }, - { url = "https://files.pythonhosted.org/packages/9d/d4/dd1ca234c794fd29c057ce8c0566b8ef7fd6a51069de5f06fa84b9a1971c/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:5d2d94f1f5fcbe40838ac51a6ab5704a6f9ea42e72ceda48de5e6b898521da51", size = 1596024, upload-time = "2026-01-03T17:30:05.132Z" }, - { url = "https://files.pythonhosted.org/packages/55/58/4345b5f26661a6180afa686c473620c30a66afdf120ed3dd545bbc809e85/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:2be0e9ccf23e8a94f6f0650ce06042cefc6ac703d0d7ab6c7a917289f2539ad4", size = 1804590, upload-time = "2026-01-03T17:30:07.135Z" }, - { url = "https://files.pythonhosted.org/packages/7b/06/05950619af6c2df7e0a431d889ba2813c9f0129cec76f663e547a5ad56f2/aiohttp-3.13.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9af5e68ee47d6534d36791bbe9b646d2a7c7deb6fc24d7943628edfbb3581f29", size = 1740355, upload-time = "2026-01-03T17:30:09.083Z" }, - { url = "https://files.pythonhosted.org/packages/3e/80/958f16de79ba0422d7c1e284b2abd0c84bc03394fbe631d0a39ffa10e1eb/aiohttp-3.13.3-cp311-cp311-win32.whl", hash = "sha256:a2212ad43c0833a873d0fb3c63fa1bacedd4cf6af2fee62bf4b739ceec3ab239", size = 433701, upload-time = "2026-01-03T17:30:10.869Z" }, - { url = "https://files.pythonhosted.org/packages/dc/f2/27cdf04c9851712d6c1b99df6821a6623c3c9e55956d4b1e318c337b5a48/aiohttp-3.13.3-cp311-cp311-win_amd64.whl", hash = "sha256:642f752c3eb117b105acbd87e2c143de710987e09860d674e068c4c2c441034f", size = 457678, upload-time = "2026-01-03T17:30:12.719Z" }, - { url = "https://files.pythonhosted.org/packages/a0/be/4fc11f202955a69e0db803a12a062b8379c970c7c84f4882b6da17337cc1/aiohttp-3.13.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:b903a4dfee7d347e2d87697d0713be59e0b87925be030c9178c5faa58ea58d5c", size = 739732, upload-time = "2026-01-03T17:30:14.23Z" }, - { url = "https://files.pythonhosted.org/packages/97/2c/621d5b851f94fa0bb7430d6089b3aa970a9d9b75196bc93bb624b0db237a/aiohttp-3.13.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a45530014d7a1e09f4a55f4f43097ba0fd155089372e105e4bff4ca76cb1b168", size = 494293, upload-time = "2026-01-03T17:30:15.96Z" }, - { url = "https://files.pythonhosted.org/packages/5d/43/4be01406b78e1be8320bb8316dc9c42dbab553d281c40364e0f862d5661c/aiohttp-3.13.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:27234ef6d85c914f9efeb77ff616dbf4ad2380be0cda40b4db086ffc7ddd1b7d", size = 493533, upload-time = "2026-01-03T17:30:17.431Z" }, - { url = "https://files.pythonhosted.org/packages/8d/a8/5a35dc56a06a2c90d4742cbf35294396907027f80eea696637945a106f25/aiohttp-3.13.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d32764c6c9aafb7fb55366a224756387cd50bfa720f32b88e0e6fa45b27dcf29", size = 1737839, upload-time = "2026-01-03T17:30:19.422Z" }, - { url = "https://files.pythonhosted.org/packages/bf/62/4b9eeb331da56530bf2e198a297e5303e1c1ebdceeb00fe9b568a65c5a0c/aiohttp-3.13.3-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b1a6102b4d3ebc07dad44fbf07b45bb600300f15b552ddf1851b5390202ea2e3", size = 1703932, upload-time = "2026-01-03T17:30:21.756Z" }, - { url = "https://files.pythonhosted.org/packages/7c/f6/af16887b5d419e6a367095994c0b1332d154f647e7dc2bd50e61876e8e3d/aiohttp-3.13.3-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c014c7ea7fb775dd015b2d3137378b7be0249a448a1612268b5a90c2d81de04d", size = 1771906, upload-time = "2026-01-03T17:30:23.932Z" }, - { url = "https://files.pythonhosted.org/packages/ce/83/397c634b1bcc24292fa1e0c7822800f9f6569e32934bdeef09dae7992dfb/aiohttp-3.13.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2b8d8ddba8f95ba17582226f80e2de99c7a7948e66490ef8d947e272a93e9463", size = 1871020, upload-time = "2026-01-03T17:30:26Z" }, - { url = "https://files.pythonhosted.org/packages/86/f6/a62cbbf13f0ac80a70f71b1672feba90fdb21fd7abd8dbf25c0105fb6fa3/aiohttp-3.13.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9ae8dd55c8e6c4257eae3a20fd2c8f41edaea5992ed67156642493b8daf3cecc", size = 1755181, upload-time = "2026-01-03T17:30:27.554Z" }, - { url = "https://files.pythonhosted.org/packages/0a/87/20a35ad487efdd3fba93d5843efdfaa62d2f1479eaafa7453398a44faf13/aiohttp-3.13.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:01ad2529d4b5035578f5081606a465f3b814c542882804e2e8cda61adf5c71bf", size = 1561794, upload-time = "2026-01-03T17:30:29.254Z" }, - { url = "https://files.pythonhosted.org/packages/de/95/8fd69a66682012f6716e1bc09ef8a1a2a91922c5725cb904689f112309c4/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:bb4f7475e359992b580559e008c598091c45b5088f28614e855e42d39c2f1033", size = 1697900, upload-time = "2026-01-03T17:30:31.033Z" }, - { url = "https://files.pythonhosted.org/packages/e5/66/7b94b3b5ba70e955ff597672dad1691333080e37f50280178967aff68657/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:c19b90316ad3b24c69cd78d5c9b4f3aa4497643685901185b65166293d36a00f", size = 1728239, upload-time = "2026-01-03T17:30:32.703Z" }, - { url = "https://files.pythonhosted.org/packages/47/71/6f72f77f9f7d74719692ab65a2a0252584bf8d5f301e2ecb4c0da734530a/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:96d604498a7c782cb15a51c406acaea70d8c027ee6b90c569baa6e7b93073679", size = 1740527, upload-time = "2026-01-03T17:30:34.695Z" }, - { url = "https://files.pythonhosted.org/packages/fa/b4/75ec16cbbd5c01bdaf4a05b19e103e78d7ce1ef7c80867eb0ace42ff4488/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:084911a532763e9d3dd95adf78a78f4096cd5f58cdc18e6fdbc1b58417a45423", size = 1554489, upload-time = "2026-01-03T17:30:36.864Z" }, - { url = "https://files.pythonhosted.org/packages/52/8f/bc518c0eea29f8406dcf7ed1f96c9b48e3bc3995a96159b3fc11f9e08321/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:7a4a94eb787e606d0a09404b9c38c113d3b099d508021faa615d70a0131907ce", size = 1767852, upload-time = "2026-01-03T17:30:39.433Z" }, - { url = "https://files.pythonhosted.org/packages/9d/f2/a07a75173124f31f11ea6f863dc44e6f09afe2bca45dd4e64979490deab1/aiohttp-3.13.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:87797e645d9d8e222e04160ee32aa06bc5c163e8499f24db719e7852ec23093a", size = 1722379, upload-time = "2026-01-03T17:30:41.081Z" }, - { url = "https://files.pythonhosted.org/packages/3c/4a/1a3fee7c21350cac78e5c5cef711bac1b94feca07399f3d406972e2d8fcd/aiohttp-3.13.3-cp312-cp312-win32.whl", hash = "sha256:b04be762396457bef43f3597c991e192ee7da460a4953d7e647ee4b1c28e7046", size = 428253, upload-time = "2026-01-03T17:30:42.644Z" }, - { url = "https://files.pythonhosted.org/packages/d9/b7/76175c7cb4eb73d91ad63c34e29fc4f77c9386bba4a65b53ba8e05ee3c39/aiohttp-3.13.3-cp312-cp312-win_amd64.whl", hash = "sha256:e3531d63d3bdfa7e3ac5e9b27b2dd7ec9df3206a98e0b3445fa906f233264c57", size = 455407, upload-time = "2026-01-03T17:30:44.195Z" }, - { url = "https://files.pythonhosted.org/packages/97/8a/12ca489246ca1faaf5432844adbfce7ff2cc4997733e0af120869345643a/aiohttp-3.13.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:5dff64413671b0d3e7d5918ea490bdccb97a4ad29b3f311ed423200b2203e01c", size = 734190, upload-time = "2026-01-03T17:30:45.832Z" }, - { url = "https://files.pythonhosted.org/packages/32/08/de43984c74ed1fca5c014808963cc83cb00d7bb06af228f132d33862ca76/aiohttp-3.13.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:87b9aab6d6ed88235aa2970294f496ff1a1f9adcd724d800e9b952395a80ffd9", size = 491783, upload-time = "2026-01-03T17:30:47.466Z" }, - { url = "https://files.pythonhosted.org/packages/17/f8/8dd2cf6112a5a76f81f81a5130c57ca829d101ad583ce57f889179accdda/aiohttp-3.13.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:425c126c0dc43861e22cb1c14ba4c8e45d09516d0a3ae0a3f7494b79f5f233a3", size = 490704, upload-time = "2026-01-03T17:30:49.373Z" }, - { url = "https://files.pythonhosted.org/packages/6d/40/a46b03ca03936f832bc7eaa47cfbb1ad012ba1be4790122ee4f4f8cba074/aiohttp-3.13.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7f9120f7093c2a32d9647abcaf21e6ad275b4fbec5b55969f978b1a97c7c86bf", size = 1720652, upload-time = "2026-01-03T17:30:50.974Z" }, - { url = "https://files.pythonhosted.org/packages/f7/7e/917fe18e3607af92657e4285498f500dca797ff8c918bd7d90b05abf6c2a/aiohttp-3.13.3-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:697753042d57f4bf7122cab985bf15d0cef23c770864580f5af4f52023a56bd6", size = 1692014, upload-time = "2026-01-03T17:30:52.729Z" }, - { url = "https://files.pythonhosted.org/packages/71/b6/cefa4cbc00d315d68973b671cf105b21a609c12b82d52e5d0c9ae61d2a09/aiohttp-3.13.3-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6de499a1a44e7de70735d0b39f67c8f25eb3d91eb3103be99ca0fa882cdd987d", size = 1759777, upload-time = "2026-01-03T17:30:54.537Z" }, - { url = "https://files.pythonhosted.org/packages/fb/e3/e06ee07b45e59e6d81498b591fc589629be1553abb2a82ce33efe2a7b068/aiohttp-3.13.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:37239e9f9a7ea9ac5bf6b92b0260b01f8a22281996da609206a84df860bc1261", size = 1861276, upload-time = "2026-01-03T17:30:56.512Z" }, - { url = "https://files.pythonhosted.org/packages/7c/24/75d274228acf35ceeb2850b8ce04de9dd7355ff7a0b49d607ee60c29c518/aiohttp-3.13.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f76c1e3fe7d7c8afad7ed193f89a292e1999608170dcc9751a7462a87dfd5bc0", size = 1743131, upload-time = "2026-01-03T17:30:58.256Z" }, - { url = "https://files.pythonhosted.org/packages/04/98/3d21dde21889b17ca2eea54fdcff21b27b93f45b7bb94ca029c31ab59dc3/aiohttp-3.13.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fc290605db2a917f6e81b0e1e0796469871f5af381ce15c604a3c5c7e51cb730", size = 1556863, upload-time = "2026-01-03T17:31:00.445Z" }, - { url = "https://files.pythonhosted.org/packages/9e/84/da0c3ab1192eaf64782b03971ab4055b475d0db07b17eff925e8c93b3aa5/aiohttp-3.13.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4021b51936308aeea0367b8f006dc999ca02bc118a0cc78c303f50a2ff6afb91", size = 1682793, upload-time = "2026-01-03T17:31:03.024Z" }, - { url = "https://files.pythonhosted.org/packages/ff/0f/5802ada182f575afa02cbd0ec5180d7e13a402afb7c2c03a9aa5e5d49060/aiohttp-3.13.3-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:49a03727c1bba9a97d3e93c9f93ca03a57300f484b6e935463099841261195d3", size = 1716676, upload-time = "2026-01-03T17:31:04.842Z" }, - { url = "https://files.pythonhosted.org/packages/3f/8c/714d53bd8b5a4560667f7bbbb06b20c2382f9c7847d198370ec6526af39c/aiohttp-3.13.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3d9908a48eb7416dc1f4524e69f1d32e5d90e3981e4e37eb0aa1cd18f9cfa2a4", size = 1733217, upload-time = "2026-01-03T17:31:06.868Z" }, - { url = "https://files.pythonhosted.org/packages/7d/79/e2176f46d2e963facea939f5be2d26368ce543622be6f00a12844d3c991f/aiohttp-3.13.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:2712039939ec963c237286113c68dbad80a82a4281543f3abf766d9d73228998", size = 1552303, upload-time = "2026-01-03T17:31:08.958Z" }, - { url = "https://files.pythonhosted.org/packages/ab/6a/28ed4dea1759916090587d1fe57087b03e6c784a642b85ef48217b0277ae/aiohttp-3.13.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:7bfdc049127717581866fa4708791220970ce291c23e28ccf3922c700740fdc0", size = 1763673, upload-time = "2026-01-03T17:31:10.676Z" }, - { url = "https://files.pythonhosted.org/packages/e8/35/4a3daeb8b9fab49240d21c04d50732313295e4bd813a465d840236dd0ce1/aiohttp-3.13.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8057c98e0c8472d8846b9c79f56766bcc57e3e8ac7bfd510482332366c56c591", size = 1721120, upload-time = "2026-01-03T17:31:12.575Z" }, - { url = "https://files.pythonhosted.org/packages/bc/9f/d643bb3c5fb99547323e635e251c609fbbc660d983144cfebec529e09264/aiohttp-3.13.3-cp313-cp313-win32.whl", hash = "sha256:1449ceddcdbcf2e0446957863af03ebaaa03f94c090f945411b61269e2cb5daf", size = 427383, upload-time = "2026-01-03T17:31:14.382Z" }, - { url = "https://files.pythonhosted.org/packages/4e/f1/ab0395f8a79933577cdd996dd2f9aa6014af9535f65dddcf88204682fe62/aiohttp-3.13.3-cp313-cp313-win_amd64.whl", hash = "sha256:693781c45a4033d31d4187d2436f5ac701e7bbfe5df40d917736108c1cc7436e", size = 453899, upload-time = "2026-01-03T17:31:15.958Z" }, - { url = "https://files.pythonhosted.org/packages/99/36/5b6514a9f5d66f4e2597e40dea2e3db271e023eb7a5d22defe96ba560996/aiohttp-3.13.3-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:ea37047c6b367fd4bd632bff8077449b8fa034b69e812a18e0132a00fae6e808", size = 737238, upload-time = "2026-01-03T17:31:17.909Z" }, - { url = "https://files.pythonhosted.org/packages/f7/49/459327f0d5bcd8c6c9ca69e60fdeebc3622861e696490d8674a6d0cb90a6/aiohttp-3.13.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:6fc0e2337d1a4c3e6acafda6a78a39d4c14caea625124817420abceed36e2415", size = 492292, upload-time = "2026-01-03T17:31:19.919Z" }, - { url = "https://files.pythonhosted.org/packages/e8/0b/b97660c5fd05d3495b4eb27f2d0ef18dc1dc4eff7511a9bf371397ff0264/aiohttp-3.13.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c685f2d80bb67ca8c3837823ad76196b3694b0159d232206d1e461d3d434666f", size = 493021, upload-time = "2026-01-03T17:31:21.636Z" }, - { url = "https://files.pythonhosted.org/packages/54/d4/438efabdf74e30aeceb890c3290bbaa449780583b1270b00661126b8aae4/aiohttp-3.13.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:48e377758516d262bde50c2584fc6c578af272559c409eecbdd2bae1601184d6", size = 1717263, upload-time = "2026-01-03T17:31:23.296Z" }, - { url = "https://files.pythonhosted.org/packages/71/f2/7bddc7fd612367d1459c5bcf598a9e8f7092d6580d98de0e057eb42697ad/aiohttp-3.13.3-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:34749271508078b261c4abb1767d42b8d0c0cc9449c73a4df494777dc55f0687", size = 1669107, upload-time = "2026-01-03T17:31:25.334Z" }, - { url = "https://files.pythonhosted.org/packages/00/5a/1aeaecca40e22560f97610a329e0e5efef5e0b5afdf9f857f0d93839ab2e/aiohttp-3.13.3-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:82611aeec80eb144416956ec85b6ca45a64d76429c1ed46ae1b5f86c6e0c9a26", size = 1760196, upload-time = "2026-01-03T17:31:27.394Z" }, - { url = "https://files.pythonhosted.org/packages/f8/f8/0ff6992bea7bd560fc510ea1c815f87eedd745fe035589c71ce05612a19a/aiohttp-3.13.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2fff83cfc93f18f215896e3a190e8e5cb413ce01553901aca925176e7568963a", size = 1843591, upload-time = "2026-01-03T17:31:29.238Z" }, - { url = "https://files.pythonhosted.org/packages/e3/d1/e30e537a15f53485b61f5be525f2157da719819e8377298502aebac45536/aiohttp-3.13.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bbe7d4cecacb439e2e2a8a1a7b935c25b812af7a5fd26503a66dadf428e79ec1", size = 1720277, upload-time = "2026-01-03T17:31:31.053Z" }, - { url = "https://files.pythonhosted.org/packages/84/45/23f4c451d8192f553d38d838831ebbc156907ea6e05557f39563101b7717/aiohttp-3.13.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b928f30fe49574253644b1ca44b1b8adbd903aa0da4b9054a6c20fc7f4092a25", size = 1548575, upload-time = "2026-01-03T17:31:32.87Z" }, - { url = "https://files.pythonhosted.org/packages/6a/ed/0a42b127a43712eda7807e7892c083eadfaf8429ca8fb619662a530a3aab/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7b5e8fe4de30df199155baaf64f2fcd604f4c678ed20910db8e2c66dc4b11603", size = 1679455, upload-time = "2026-01-03T17:31:34.76Z" }, - { url = "https://files.pythonhosted.org/packages/2e/b5/c05f0c2b4b4fe2c9d55e73b6d3ed4fd6c9dc2684b1d81cbdf77e7fad9adb/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:8542f41a62bcc58fc7f11cf7c90e0ec324ce44950003feb70640fc2a9092c32a", size = 1687417, upload-time = "2026-01-03T17:31:36.699Z" }, - { url = "https://files.pythonhosted.org/packages/c9/6b/915bc5dad66aef602b9e459b5a973529304d4e89ca86999d9d75d80cbd0b/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:5e1d8c8b8f1d91cd08d8f4a3c2b067bfca6ec043d3ff36de0f3a715feeedf926", size = 1729968, upload-time = "2026-01-03T17:31:38.622Z" }, - { url = "https://files.pythonhosted.org/packages/11/3b/e84581290a9520024a08640b63d07673057aec5ca548177a82026187ba73/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:90455115e5da1c3c51ab619ac57f877da8fd6d73c05aacd125c5ae9819582aba", size = 1545690, upload-time = "2026-01-03T17:31:40.57Z" }, - { url = "https://files.pythonhosted.org/packages/f5/04/0c3655a566c43fd647c81b895dfe361b9f9ad6d58c19309d45cff52d6c3b/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:042e9e0bcb5fba81886c8b4fbb9a09d6b8a00245fd8d88e4d989c1f96c74164c", size = 1746390, upload-time = "2026-01-03T17:31:42.857Z" }, - { url = "https://files.pythonhosted.org/packages/1f/53/71165b26978f719c3419381514c9690bd5980e764a09440a10bb816ea4ab/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2eb752b102b12a76ca02dff751a801f028b4ffbbc478840b473597fc91a9ed43", size = 1702188, upload-time = "2026-01-03T17:31:44.984Z" }, - { url = "https://files.pythonhosted.org/packages/29/a7/cbe6c9e8e136314fa1980da388a59d2f35f35395948a08b6747baebb6aa6/aiohttp-3.13.3-cp314-cp314-win32.whl", hash = "sha256:b556c85915d8efaed322bf1bdae9486aa0f3f764195a0fb6ee962e5c71ef5ce1", size = 433126, upload-time = "2026-01-03T17:31:47.463Z" }, - { url = "https://files.pythonhosted.org/packages/de/56/982704adea7d3b16614fc5936014e9af85c0e34b58f9046655817f04306e/aiohttp-3.13.3-cp314-cp314-win_amd64.whl", hash = "sha256:9bf9f7a65e7aa20dd764151fb3d616c81088f91f8df39c3893a536e279b4b984", size = 459128, upload-time = "2026-01-03T17:31:49.2Z" }, - { url = "https://files.pythonhosted.org/packages/6c/2a/3c79b638a9c3d4658d345339d22070241ea341ed4e07b5ac60fb0f418003/aiohttp-3.13.3-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:05861afbbec40650d8a07ea324367cb93e9e8cc7762e04dd4405df99fa65159c", size = 769512, upload-time = "2026-01-03T17:31:51.134Z" }, - { url = "https://files.pythonhosted.org/packages/29/b9/3e5014d46c0ab0db8707e0ac2711ed28c4da0218c358a4e7c17bae0d8722/aiohttp-3.13.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2fc82186fadc4a8316768d61f3722c230e2c1dcab4200d52d2ebdf2482e47592", size = 506444, upload-time = "2026-01-03T17:31:52.85Z" }, - { url = "https://files.pythonhosted.org/packages/90/03/c1d4ef9a054e151cd7839cdc497f2638f00b93cbe8043983986630d7a80c/aiohttp-3.13.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0add0900ff220d1d5c5ebbf99ed88b0c1bbf87aa7e4262300ed1376a6b13414f", size = 510798, upload-time = "2026-01-03T17:31:54.91Z" }, - { url = "https://files.pythonhosted.org/packages/ea/76/8c1e5abbfe8e127c893fe7ead569148a4d5a799f7cf958d8c09f3eedf097/aiohttp-3.13.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:568f416a4072fbfae453dcf9a99194bbb8bdeab718e08ee13dfa2ba0e4bebf29", size = 1868835, upload-time = "2026-01-03T17:31:56.733Z" }, - { url = "https://files.pythonhosted.org/packages/8e/ac/984c5a6f74c363b01ff97adc96a3976d9c98940b8969a1881575b279ac5d/aiohttp-3.13.3-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:add1da70de90a2569c5e15249ff76a631ccacfe198375eead4aadf3b8dc849dc", size = 1720486, upload-time = "2026-01-03T17:31:58.65Z" }, - { url = "https://files.pythonhosted.org/packages/b2/9a/b7039c5f099c4eb632138728828b33428585031a1e658d693d41d07d89d1/aiohttp-3.13.3-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:10b47b7ba335d2e9b1239fa571131a87e2d8ec96b333e68b2a305e7a98b0bae2", size = 1847951, upload-time = "2026-01-03T17:32:00.989Z" }, - { url = "https://files.pythonhosted.org/packages/3c/02/3bec2b9a1ba3c19ff89a43a19324202b8eb187ca1e928d8bdac9bbdddebd/aiohttp-3.13.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3dd4dce1c718e38081c8f35f323209d4c1df7d4db4bab1b5c88a6b4d12b74587", size = 1941001, upload-time = "2026-01-03T17:32:03.122Z" }, - { url = "https://files.pythonhosted.org/packages/37/df/d879401cedeef27ac4717f6426c8c36c3091c6e9f08a9178cc87549c537f/aiohttp-3.13.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:34bac00a67a812570d4a460447e1e9e06fae622946955f939051e7cc895cfab8", size = 1797246, upload-time = "2026-01-03T17:32:05.255Z" }, - { url = "https://files.pythonhosted.org/packages/8d/15/be122de1f67e6953add23335c8ece6d314ab67c8bebb3f181063010795a7/aiohttp-3.13.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a19884d2ee70b06d9204b2727a7b9f983d0c684c650254679e716b0b77920632", size = 1627131, upload-time = "2026-01-03T17:32:07.607Z" }, - { url = "https://files.pythonhosted.org/packages/12/12/70eedcac9134cfa3219ab7af31ea56bc877395b1ac30d65b1bc4b27d0438/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5f8ca7f2bb6ba8348a3614c7918cc4bb73268c5ac2a207576b7afea19d3d9f64", size = 1795196, upload-time = "2026-01-03T17:32:09.59Z" }, - { url = "https://files.pythonhosted.org/packages/32/11/b30e1b1cd1f3054af86ebe60df96989c6a414dd87e27ad16950eee420bea/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:b0d95340658b9d2f11d9697f59b3814a9d3bb4b7a7c20b131df4bcef464037c0", size = 1782841, upload-time = "2026-01-03T17:32:11.445Z" }, - { url = "https://files.pythonhosted.org/packages/88/0d/d98a9367b38912384a17e287850f5695c528cff0f14f791ce8ee2e4f7796/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:a1e53262fd202e4b40b70c3aff944a8155059beedc8a89bba9dc1f9ef06a1b56", size = 1795193, upload-time = "2026-01-03T17:32:13.705Z" }, - { url = "https://files.pythonhosted.org/packages/43/a5/a2dfd1f5ff5581632c7f6a30e1744deda03808974f94f6534241ef60c751/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:d60ac9663f44168038586cab2157e122e46bdef09e9368b37f2d82d354c23f72", size = 1621979, upload-time = "2026-01-03T17:32:15.965Z" }, - { url = "https://files.pythonhosted.org/packages/fa/f0/12973c382ae7c1cccbc4417e129c5bf54c374dfb85af70893646e1f0e749/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:90751b8eed69435bac9ff4e3d2f6b3af1f57e37ecb0fbeee59c0174c9e2d41df", size = 1822193, upload-time = "2026-01-03T17:32:18.219Z" }, - { url = "https://files.pythonhosted.org/packages/3c/5f/24155e30ba7f8c96918af1350eb0663e2430aad9e001c0489d89cd708ab1/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:fc353029f176fd2b3ec6cfc71be166aba1936fe5d73dd1992ce289ca6647a9aa", size = 1769801, upload-time = "2026-01-03T17:32:20.25Z" }, - { url = "https://files.pythonhosted.org/packages/eb/f8/7314031ff5c10e6ece114da79b338ec17eeff3a079e53151f7e9f43c4723/aiohttp-3.13.3-cp314-cp314t-win32.whl", hash = "sha256:2e41b18a58da1e474a057b3d35248d8320029f61d70a37629535b16a0c8f3767", size = 466523, upload-time = "2026-01-03T17:32:22.215Z" }, - { url = "https://files.pythonhosted.org/packages/b4/63/278a98c715ae467624eafe375542d8ba9b4383a016df8fdefe0ae28382a7/aiohttp-3.13.3-cp314-cp314t-win_amd64.whl", hash = "sha256:44531a36aa2264a1860089ffd4dce7baf875ee5a6079d5fb42e261c704ef7344", size = 499694, upload-time = "2026-01-03T17:32:24.546Z" }, -] - -[[package]] -name = "aiosignal" -version = "1.4.0" +name = "annotated-doc" +version = "0.0.4" source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "frozenlist" }, - { name = "typing-extensions", marker = "python_full_version < '3.13'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/61/62/06741b579156360248d1ec624842ad0edf697050bbaf7c3e46394e106ad1/aiosignal-1.4.0.tar.gz", hash = "sha256:f47eecd9468083c2029cc99945502cb7708b082c232f9aca65da147157b251c7", size = 25007, upload-time = "2025-07-03T22:54:43.528Z" } +sdist = { url = "https://files.pythonhosted.org/packages/57/ba/046ceea27344560984e26a590f90bc7f4a75b06701f653222458922b558c/annotated_doc-0.0.4.tar.gz", hash = "sha256:fbcda96e87e9c92ad167c2e53839e57503ecfda18804ea28102353485033faa4", size = 7288, upload-time = "2025-11-10T22:07:42.062Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl", hash = "sha256:053243f8b92b990551949e63930a839ff0cf0b0ebbe0597b0f3fb19e1a0fe82e", size = 7490, upload-time = "2025-07-03T22:54:42.156Z" }, + { url = "https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl", hash = "sha256:571ac1dc6991c450b25a9c2d84a3705e2ae7a53467b5d111c24fa8baabbed320", size = 5303, upload-time = "2025-11-10T22:07:40.673Z" }, ] [[package]] @@ -140,6 +45,25 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload-time = "2024-05-20T21:33:24.1Z" }, ] +[[package]] +name = "anthropic" +version = "0.84.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "distro" }, + { name = "docstring-parser" }, + { name = "httpx" }, + { name = "jiter" }, + { name = "pydantic" }, + { name = "sniffio" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/04/ea/0869d6df9ef83dcf393aeefc12dd81677d091c6ffc86f783e51cf44062f2/anthropic-0.84.0.tar.gz", hash = "sha256:72f5f90e5aebe62dca316cb013629cfa24996b0f5a4593b8c3d712bc03c43c37", size = 539457, upload-time = "2026-02-25T05:22:38.54Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/64/ca/218fa25002a332c0aa149ba18ffc0543175998b1f65de63f6d106689a345/anthropic-0.84.0-py3-none-any.whl", hash = "sha256:861c4c50f91ca45f942e091d83b60530ad6d4f98733bfe648065364da05d29e7", size = 455156, upload-time = "2026-02-25T05:22:40.468Z" }, +] + [[package]] name = "anyio" version = "4.12.0" @@ -154,12 +78,31 @@ wheels = [ ] [[package]] -name = "attrs" -version = "25.4.0" +name = "boto3" +version = "1.42.66" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/6b/5c/685e6633917e101e5dcb62b9dd76946cbb57c26e133bae9e0cd36033c0a9/attrs-25.4.0.tar.gz", hash = "sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11", size = 934251, upload-time = "2025-10-06T13:54:44.725Z" } +dependencies = [ + { name = "botocore" }, + { name = "jmespath" }, + { name = "s3transfer" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0a/2e/67206daa5acb6053157ae5241421713a84ed6015d33d0781985bd5558898/boto3-1.42.66.tar.gz", hash = "sha256:3bec5300fb2429c3be8e8961fdb1f11e85195922c8a980022332c20af05616d5", size = 112805, upload-time = "2026-03-11T19:58:19.17Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/3a/2a/7cc015f5b9f5db42b7d48157e23356022889fc354a2813c15934b7cb5c0e/attrs-25.4.0-py3-none-any.whl", hash = "sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373", size = 67615, upload-time = "2025-10-06T13:54:43.17Z" }, + { url = "https://files.pythonhosted.org/packages/4c/09/83224363c3f5e468e298e48beb577ffe8cb51f18c2116bc1ecf404796e60/boto3-1.42.66-py3-none-any.whl", hash = "sha256:7c6c60dc5500e8a2967a306372a5fdb4c7f9a5b8adc5eb9aa2ebb5081c51ff47", size = 140557, upload-time = "2026-03-11T19:58:17.61Z" }, +] + +[[package]] +name = "botocore" +version = "1.42.66" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jmespath" }, + { name = "python-dateutil" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/77/ef/1c8f89da69b0c3742120e19a6ea72ec46ac0596294466924fdd4cf0f36bb/botocore-1.42.66.tar.gz", hash = "sha256:39756a21142b646de552d798dde2105759b0b8fa0d881a34c26d15bd4c9448fa", size = 14977446, upload-time = "2026-03-11T19:58:07.714Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/13/6f/7b45ed2ca300c1ad38ecfc82c1368546d4a90512d9dff589ebbd182a7317/botocore-1.42.66-py3-none-any.whl", hash = "sha256:ac48af1ab527dfa08c4617c387413ca56a7f87780d7bfc1da34ef847a59219a5", size = 14653886, upload-time = "2026-03-11T19:58:04.922Z" }, ] [[package]] @@ -180,6 +123,85 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/70/7d/9bc192684cea499815ff478dfcdc13835ddf401365057044fb721ec6bddb/certifi-2025.11.12-py3-none-any.whl", hash = "sha256:97de8790030bbd5c2d96b7ec782fc2f7820ef8dba6db909ccf95449f2d062d4b", size = 159438, upload-time = "2025-11-12T02:54:49.735Z" }, ] +[[package]] +name = "cffi" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pycparser", marker = "implementation_name != 'PyPy'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/eb/56/b1ba7935a17738ae8453301356628e8147c79dbb825bcbc73dc7401f9846/cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529", size = 523588, upload-time = "2025-09-08T23:24:04.541Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/12/4a/3dfd5f7850cbf0d06dc84ba9aa00db766b52ca38d8b86e3a38314d52498c/cffi-2.0.0-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:b4c854ef3adc177950a8dfc81a86f5115d2abd545751a304c5bcf2c2c7283cfe", size = 184344, upload-time = "2025-09-08T23:22:26.456Z" }, + { url = "https://files.pythonhosted.org/packages/4f/8b/f0e4c441227ba756aafbe78f117485b25bb26b1c059d01f137fa6d14896b/cffi-2.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2de9a304e27f7596cd03d16f1b7c72219bd944e99cc52b84d0145aefb07cbd3c", size = 180560, upload-time = "2025-09-08T23:22:28.197Z" }, + { url = "https://files.pythonhosted.org/packages/b1/b7/1200d354378ef52ec227395d95c2576330fd22a869f7a70e88e1447eb234/cffi-2.0.0-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:baf5215e0ab74c16e2dd324e8ec067ef59e41125d3eade2b863d294fd5035c92", size = 209613, upload-time = "2025-09-08T23:22:29.475Z" }, + { url = "https://files.pythonhosted.org/packages/b8/56/6033f5e86e8cc9bb629f0077ba71679508bdf54a9a5e112a3c0b91870332/cffi-2.0.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:730cacb21e1bdff3ce90babf007d0a0917cc3e6492f336c2f0134101e0944f93", size = 216476, upload-time = "2025-09-08T23:22:31.063Z" }, + { url = "https://files.pythonhosted.org/packages/dc/7f/55fecd70f7ece178db2f26128ec41430d8720f2d12ca97bf8f0a628207d5/cffi-2.0.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:6824f87845e3396029f3820c206e459ccc91760e8fa24422f8b0c3d1731cbec5", size = 203374, upload-time = "2025-09-08T23:22:32.507Z" }, + { url = "https://files.pythonhosted.org/packages/84/ef/a7b77c8bdc0f77adc3b46888f1ad54be8f3b7821697a7b89126e829e676a/cffi-2.0.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:9de40a7b0323d889cf8d23d1ef214f565ab154443c42737dfe52ff82cf857664", size = 202597, upload-time = "2025-09-08T23:22:34.132Z" }, + { url = "https://files.pythonhosted.org/packages/d7/91/500d892b2bf36529a75b77958edfcd5ad8e2ce4064ce2ecfeab2125d72d1/cffi-2.0.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8941aaadaf67246224cee8c3803777eed332a19d909b47e29c9842ef1e79ac26", size = 215574, upload-time = "2025-09-08T23:22:35.443Z" }, + { url = "https://files.pythonhosted.org/packages/44/64/58f6255b62b101093d5df22dcb752596066c7e89dd725e0afaed242a61be/cffi-2.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a05d0c237b3349096d3981b727493e22147f934b20f6f125a3eba8f994bec4a9", size = 218971, upload-time = "2025-09-08T23:22:36.805Z" }, + { url = "https://files.pythonhosted.org/packages/ab/49/fa72cebe2fd8a55fbe14956f9970fe8eb1ac59e5df042f603ef7c8ba0adc/cffi-2.0.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:94698a9c5f91f9d138526b48fe26a199609544591f859c870d477351dc7b2414", size = 211972, upload-time = "2025-09-08T23:22:38.436Z" }, + { url = "https://files.pythonhosted.org/packages/0b/28/dd0967a76aab36731b6ebfe64dec4e981aff7e0608f60c2d46b46982607d/cffi-2.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5fed36fccc0612a53f1d4d9a816b50a36702c28a2aa880cb8a122b3466638743", size = 217078, upload-time = "2025-09-08T23:22:39.776Z" }, + { url = "https://files.pythonhosted.org/packages/2b/c0/015b25184413d7ab0a410775fdb4a50fca20f5589b5dab1dbbfa3baad8ce/cffi-2.0.0-cp311-cp311-win32.whl", hash = "sha256:c649e3a33450ec82378822b3dad03cc228b8f5963c0c12fc3b1e0ab940f768a5", size = 172076, upload-time = "2025-09-08T23:22:40.95Z" }, + { url = "https://files.pythonhosted.org/packages/ae/8f/dc5531155e7070361eb1b7e4c1a9d896d0cb21c49f807a6c03fd63fc877e/cffi-2.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:66f011380d0e49ed280c789fbd08ff0d40968ee7b665575489afa95c98196ab5", size = 182820, upload-time = "2025-09-08T23:22:42.463Z" }, + { url = "https://files.pythonhosted.org/packages/95/5c/1b493356429f9aecfd56bc171285a4c4ac8697f76e9bbbbb105e537853a1/cffi-2.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:c6638687455baf640e37344fe26d37c404db8b80d037c3d29f58fe8d1c3b194d", size = 177635, upload-time = "2025-09-08T23:22:43.623Z" }, + { url = "https://files.pythonhosted.org/packages/ea/47/4f61023ea636104d4f16ab488e268b93008c3d0bb76893b1b31db1f96802/cffi-2.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6d02d6655b0e54f54c4ef0b94eb6be0607b70853c45ce98bd278dc7de718be5d", size = 185271, upload-time = "2025-09-08T23:22:44.795Z" }, + { url = "https://files.pythonhosted.org/packages/df/a2/781b623f57358e360d62cdd7a8c681f074a71d445418a776eef0aadb4ab4/cffi-2.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8eca2a813c1cb7ad4fb74d368c2ffbbb4789d377ee5bb8df98373c2cc0dee76c", size = 181048, upload-time = "2025-09-08T23:22:45.938Z" }, + { url = "https://files.pythonhosted.org/packages/ff/df/a4f0fbd47331ceeba3d37c2e51e9dfc9722498becbeec2bd8bc856c9538a/cffi-2.0.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:21d1152871b019407d8ac3985f6775c079416c282e431a4da6afe7aefd2bccbe", size = 212529, upload-time = "2025-09-08T23:22:47.349Z" }, + { url = "https://files.pythonhosted.org/packages/d5/72/12b5f8d3865bf0f87cf1404d8c374e7487dcf097a1c91c436e72e6badd83/cffi-2.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b21e08af67b8a103c71a250401c78d5e0893beff75e28c53c98f4de42f774062", size = 220097, upload-time = "2025-09-08T23:22:48.677Z" }, + { url = "https://files.pythonhosted.org/packages/c2/95/7a135d52a50dfa7c882ab0ac17e8dc11cec9d55d2c18dda414c051c5e69e/cffi-2.0.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:1e3a615586f05fc4065a8b22b8152f0c1b00cdbc60596d187c2a74f9e3036e4e", size = 207983, upload-time = "2025-09-08T23:22:50.06Z" }, + { url = "https://files.pythonhosted.org/packages/3a/c8/15cb9ada8895957ea171c62dc78ff3e99159ee7adb13c0123c001a2546c1/cffi-2.0.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:81afed14892743bbe14dacb9e36d9e0e504cd204e0b165062c488942b9718037", size = 206519, upload-time = "2025-09-08T23:22:51.364Z" }, + { url = "https://files.pythonhosted.org/packages/78/2d/7fa73dfa841b5ac06c7b8855cfc18622132e365f5b81d02230333ff26e9e/cffi-2.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3e17ed538242334bf70832644a32a7aae3d83b57567f9fd60a26257e992b79ba", size = 219572, upload-time = "2025-09-08T23:22:52.902Z" }, + { url = "https://files.pythonhosted.org/packages/07/e0/267e57e387b4ca276b90f0434ff88b2c2241ad72b16d31836adddfd6031b/cffi-2.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3925dd22fa2b7699ed2617149842d2e6adde22b262fcbfada50e3d195e4b3a94", size = 222963, upload-time = "2025-09-08T23:22:54.518Z" }, + { url = "https://files.pythonhosted.org/packages/b6/75/1f2747525e06f53efbd878f4d03bac5b859cbc11c633d0fb81432d98a795/cffi-2.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2c8f814d84194c9ea681642fd164267891702542f028a15fc97d4674b6206187", size = 221361, upload-time = "2025-09-08T23:22:55.867Z" }, + { url = "https://files.pythonhosted.org/packages/7b/2b/2b6435f76bfeb6bbf055596976da087377ede68df465419d192acf00c437/cffi-2.0.0-cp312-cp312-win32.whl", hash = "sha256:da902562c3e9c550df360bfa53c035b2f241fed6d9aef119048073680ace4a18", size = 172932, upload-time = "2025-09-08T23:22:57.188Z" }, + { url = "https://files.pythonhosted.org/packages/f8/ed/13bd4418627013bec4ed6e54283b1959cf6db888048c7cf4b4c3b5b36002/cffi-2.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:da68248800ad6320861f129cd9c1bf96ca849a2771a59e0344e88681905916f5", size = 183557, upload-time = "2025-09-08T23:22:58.351Z" }, + { url = "https://files.pythonhosted.org/packages/95/31/9f7f93ad2f8eff1dbc1c3656d7ca5bfd8fb52c9d786b4dcf19b2d02217fa/cffi-2.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:4671d9dd5ec934cb9a73e7ee9676f9362aba54f7f34910956b84d727b0d73fb6", size = 177762, upload-time = "2025-09-08T23:22:59.668Z" }, + { url = "https://files.pythonhosted.org/packages/4b/8d/a0a47a0c9e413a658623d014e91e74a50cdd2c423f7ccfd44086ef767f90/cffi-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb", size = 185230, upload-time = "2025-09-08T23:23:00.879Z" }, + { url = "https://files.pythonhosted.org/packages/4a/d2/a6c0296814556c68ee32009d9c2ad4f85f2707cdecfd7727951ec228005d/cffi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:45d5e886156860dc35862657e1494b9bae8dfa63bf56796f2fb56e1679fc0bca", size = 181043, upload-time = "2025-09-08T23:23:02.231Z" }, + { url = "https://files.pythonhosted.org/packages/b0/1e/d22cc63332bd59b06481ceaac49d6c507598642e2230f201649058a7e704/cffi-2.0.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b", size = 212446, upload-time = "2025-09-08T23:23:03.472Z" }, + { url = "https://files.pythonhosted.org/packages/a9/f5/a2c23eb03b61a0b8747f211eb716446c826ad66818ddc7810cc2cc19b3f2/cffi-2.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d48a880098c96020b02d5a1f7d9251308510ce8858940e6fa99ece33f610838b", size = 220101, upload-time = "2025-09-08T23:23:04.792Z" }, + { url = "https://files.pythonhosted.org/packages/f2/7f/e6647792fc5850d634695bc0e6ab4111ae88e89981d35ac269956605feba/cffi-2.0.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f93fd8e5c8c0a4aa1f424d6173f14a892044054871c771f8566e4008eaa359d2", size = 207948, upload-time = "2025-09-08T23:23:06.127Z" }, + { url = "https://files.pythonhosted.org/packages/cb/1e/a5a1bd6f1fb30f22573f76533de12a00bf274abcdc55c8edab639078abb6/cffi-2.0.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:dd4f05f54a52fb558f1ba9f528228066954fee3ebe629fc1660d874d040ae5a3", size = 206422, upload-time = "2025-09-08T23:23:07.753Z" }, + { url = "https://files.pythonhosted.org/packages/98/df/0a1755e750013a2081e863e7cd37e0cdd02664372c754e5560099eb7aa44/cffi-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26", size = 219499, upload-time = "2025-09-08T23:23:09.648Z" }, + { url = "https://files.pythonhosted.org/packages/50/e1/a969e687fcf9ea58e6e2a928ad5e2dd88cc12f6f0ab477e9971f2309b57c/cffi-2.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d9b29c1f0ae438d5ee9acb31cadee00a58c46cc9c0b2f9038c6b0b3470877a8c", size = 222928, upload-time = "2025-09-08T23:23:10.928Z" }, + { url = "https://files.pythonhosted.org/packages/36/54/0362578dd2c9e557a28ac77698ed67323ed5b9775ca9d3fe73fe191bb5d8/cffi-2.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6d50360be4546678fc1b79ffe7a66265e28667840010348dd69a314145807a1b", size = 221302, upload-time = "2025-09-08T23:23:12.42Z" }, + { url = "https://files.pythonhosted.org/packages/eb/6d/bf9bda840d5f1dfdbf0feca87fbdb64a918a69bca42cfa0ba7b137c48cb8/cffi-2.0.0-cp313-cp313-win32.whl", hash = "sha256:74a03b9698e198d47562765773b4a8309919089150a0bb17d829ad7b44b60d27", size = 172909, upload-time = "2025-09-08T23:23:14.32Z" }, + { url = "https://files.pythonhosted.org/packages/37/18/6519e1ee6f5a1e579e04b9ddb6f1676c17368a7aba48299c3759bbc3c8b3/cffi-2.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:19f705ada2530c1167abacb171925dd886168931e0a7b78f5bffcae5c6b5be75", size = 183402, upload-time = "2025-09-08T23:23:15.535Z" }, + { url = "https://files.pythonhosted.org/packages/cb/0e/02ceeec9a7d6ee63bb596121c2c8e9b3a9e150936f4fbef6ca1943e6137c/cffi-2.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:256f80b80ca3853f90c21b23ee78cd008713787b1b1e93eae9f3d6a7134abd91", size = 177780, upload-time = "2025-09-08T23:23:16.761Z" }, + { url = "https://files.pythonhosted.org/packages/92/c4/3ce07396253a83250ee98564f8d7e9789fab8e58858f35d07a9a2c78de9f/cffi-2.0.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fc33c5141b55ed366cfaad382df24fe7dcbc686de5be719b207bb248e3053dc5", size = 185320, upload-time = "2025-09-08T23:23:18.087Z" }, + { url = "https://files.pythonhosted.org/packages/59/dd/27e9fa567a23931c838c6b02d0764611c62290062a6d4e8ff7863daf9730/cffi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c654de545946e0db659b3400168c9ad31b5d29593291482c43e3564effbcee13", size = 181487, upload-time = "2025-09-08T23:23:19.622Z" }, + { url = "https://files.pythonhosted.org/packages/d6/43/0e822876f87ea8a4ef95442c3d766a06a51fc5298823f884ef87aaad168c/cffi-2.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:24b6f81f1983e6df8db3adc38562c83f7d4a0c36162885ec7f7b77c7dcbec97b", size = 220049, upload-time = "2025-09-08T23:23:20.853Z" }, + { url = "https://files.pythonhosted.org/packages/b4/89/76799151d9c2d2d1ead63c2429da9ea9d7aac304603de0c6e8764e6e8e70/cffi-2.0.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:12873ca6cb9b0f0d3a0da705d6086fe911591737a59f28b7936bdfed27c0d47c", size = 207793, upload-time = "2025-09-08T23:23:22.08Z" }, + { url = "https://files.pythonhosted.org/packages/bb/dd/3465b14bb9e24ee24cb88c9e3730f6de63111fffe513492bf8c808a3547e/cffi-2.0.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:d9b97165e8aed9272a6bb17c01e3cc5871a594a446ebedc996e2397a1c1ea8ef", size = 206300, upload-time = "2025-09-08T23:23:23.314Z" }, + { url = "https://files.pythonhosted.org/packages/47/d9/d83e293854571c877a92da46fdec39158f8d7e68da75bf73581225d28e90/cffi-2.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:afb8db5439b81cf9c9d0c80404b60c3cc9c3add93e114dcae767f1477cb53775", size = 219244, upload-time = "2025-09-08T23:23:24.541Z" }, + { url = "https://files.pythonhosted.org/packages/2b/0f/1f177e3683aead2bb00f7679a16451d302c436b5cbf2505f0ea8146ef59e/cffi-2.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:737fe7d37e1a1bffe70bd5754ea763a62a066dc5913ca57e957824b72a85e205", size = 222828, upload-time = "2025-09-08T23:23:26.143Z" }, + { url = "https://files.pythonhosted.org/packages/c6/0f/cafacebd4b040e3119dcb32fed8bdef8dfe94da653155f9d0b9dc660166e/cffi-2.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:38100abb9d1b1435bc4cc340bb4489635dc2f0da7456590877030c9b3d40b0c1", size = 220926, upload-time = "2025-09-08T23:23:27.873Z" }, + { url = "https://files.pythonhosted.org/packages/3e/aa/df335faa45b395396fcbc03de2dfcab242cd61a9900e914fe682a59170b1/cffi-2.0.0-cp314-cp314-win32.whl", hash = "sha256:087067fa8953339c723661eda6b54bc98c5625757ea62e95eb4898ad5e776e9f", size = 175328, upload-time = "2025-09-08T23:23:44.61Z" }, + { url = "https://files.pythonhosted.org/packages/bb/92/882c2d30831744296ce713f0feb4c1cd30f346ef747b530b5318715cc367/cffi-2.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:203a48d1fb583fc7d78a4c6655692963b860a417c0528492a6bc21f1aaefab25", size = 185650, upload-time = "2025-09-08T23:23:45.848Z" }, + { url = "https://files.pythonhosted.org/packages/9f/2c/98ece204b9d35a7366b5b2c6539c350313ca13932143e79dc133ba757104/cffi-2.0.0-cp314-cp314-win_arm64.whl", hash = "sha256:dbd5c7a25a7cb98f5ca55d258b103a2054f859a46ae11aaf23134f9cc0d356ad", size = 180687, upload-time = "2025-09-08T23:23:47.105Z" }, + { url = "https://files.pythonhosted.org/packages/3e/61/c768e4d548bfa607abcda77423448df8c471f25dbe64fb2ef6d555eae006/cffi-2.0.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:9a67fc9e8eb39039280526379fb3a70023d77caec1852002b4da7e8b270c4dd9", size = 188773, upload-time = "2025-09-08T23:23:29.347Z" }, + { url = "https://files.pythonhosted.org/packages/2c/ea/5f76bce7cf6fcd0ab1a1058b5af899bfbef198bea4d5686da88471ea0336/cffi-2.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7a66c7204d8869299919db4d5069a82f1561581af12b11b3c9f48c584eb8743d", size = 185013, upload-time = "2025-09-08T23:23:30.63Z" }, + { url = "https://files.pythonhosted.org/packages/be/b4/c56878d0d1755cf9caa54ba71e5d049479c52f9e4afc230f06822162ab2f/cffi-2.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7cc09976e8b56f8cebd752f7113ad07752461f48a58cbba644139015ac24954c", size = 221593, upload-time = "2025-09-08T23:23:31.91Z" }, + { url = "https://files.pythonhosted.org/packages/e0/0d/eb704606dfe8033e7128df5e90fee946bbcb64a04fcdaa97321309004000/cffi-2.0.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:92b68146a71df78564e4ef48af17551a5ddd142e5190cdf2c5624d0c3ff5b2e8", size = 209354, upload-time = "2025-09-08T23:23:33.214Z" }, + { url = "https://files.pythonhosted.org/packages/d8/19/3c435d727b368ca475fb8742ab97c9cb13a0de600ce86f62eab7fa3eea60/cffi-2.0.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:b1e74d11748e7e98e2f426ab176d4ed720a64412b6a15054378afdb71e0f37dc", size = 208480, upload-time = "2025-09-08T23:23:34.495Z" }, + { url = "https://files.pythonhosted.org/packages/d0/44/681604464ed9541673e486521497406fadcc15b5217c3e326b061696899a/cffi-2.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:28a3a209b96630bca57cce802da70c266eb08c6e97e5afd61a75611ee6c64592", size = 221584, upload-time = "2025-09-08T23:23:36.096Z" }, + { url = "https://files.pythonhosted.org/packages/25/8e/342a504ff018a2825d395d44d63a767dd8ebc927ebda557fecdaca3ac33a/cffi-2.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7553fb2090d71822f02c629afe6042c299edf91ba1bf94951165613553984512", size = 224443, upload-time = "2025-09-08T23:23:37.328Z" }, + { url = "https://files.pythonhosted.org/packages/e1/5e/b666bacbbc60fbf415ba9988324a132c9a7a0448a9a8f125074671c0f2c3/cffi-2.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6c6c373cfc5c83a975506110d17457138c8c63016b563cc9ed6e056a82f13ce4", size = 223437, upload-time = "2025-09-08T23:23:38.945Z" }, + { url = "https://files.pythonhosted.org/packages/a0/1d/ec1a60bd1a10daa292d3cd6bb0b359a81607154fb8165f3ec95fe003b85c/cffi-2.0.0-cp314-cp314t-win32.whl", hash = "sha256:1fc9ea04857caf665289b7a75923f2c6ed559b8298a1b8c49e59f7dd95c8481e", size = 180487, upload-time = "2025-09-08T23:23:40.423Z" }, + { url = "https://files.pythonhosted.org/packages/bf/41/4c1168c74fac325c0c8156f04b6749c8b6a8f405bbf91413ba088359f60d/cffi-2.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:d68b6cef7827e8641e8ef16f4494edda8b36104d79773a334beaa1e3521430f6", size = 191726, upload-time = "2025-09-08T23:23:41.742Z" }, + { url = "https://files.pythonhosted.org/packages/ae/3a/dbeec9d1ee0844c679f6bb5d6ad4e9f198b1224f4e7a32825f47f6192b0c/cffi-2.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0a1527a803f0a659de1af2e1fd700213caba79377e27e4693648c2923da066f9", size = 184195, upload-time = "2025-09-08T23:23:43.004Z" }, +] + +[[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" @@ -253,6 +275,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/0a/4c/925909008ed5a988ccbb72dcc897407e5d6d3bd72410d69e051fc0c14647/charset_normalizer-3.4.4-py3-none-any.whl", hash = "sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f", size = 53402, upload-time = "2025-10-14T04:42:31.76Z" }, ] +[[package]] +name = "click" +version = "8.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3d/fa/656b739db8587d7b5dfa22e22ed02566950fbfbcdc20311993483657a5c0/click-8.3.1.tar.gz", hash = "sha256:12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a", size = 295065, upload-time = "2025-11-15T20:45:42.706Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl", hash = "sha256:981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6", size = 108274, upload-time = "2025-11-15T20:45:41.139Z" }, +] + [[package]] name = "colorama" version = "0.4.6" @@ -263,12 +297,71 @@ wheels = [ ] [[package]] -name = "decorator" -version = "5.2.1" +name = "cryptography" +version = "46.0.5" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/43/fa/6d96a0978d19e17b68d634497769987b16c8f4cd0a7a05048bec693caa6b/decorator-5.2.1.tar.gz", hash = "sha256:65f266143752f734b0a7cc83c46f4618af75b8c5911b00ccb61d0ac9b6da0360", size = 56711, upload-time = "2025-02-24T04:41:34.073Z" } +dependencies = [ + { name = "cffi", marker = "platform_python_implementation != 'PyPy'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/60/04/ee2a9e8542e4fa2773b81771ff8349ff19cdd56b7258a0cc442639052edb/cryptography-46.0.5.tar.gz", hash = "sha256:abace499247268e3757271b2f1e244b36b06f8515cf27c4d49468fc9eb16e93d", size = 750064, upload-time = "2026-02-10T19:18:38.255Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/4e/8c/f3147f5c4b73e7550fe5f9352eaa956ae838d5c51eb58e7a25b9f3e2643b/decorator-5.2.1-py3-none-any.whl", hash = "sha256:d316bb415a2d9e2d2b3abcc4084c6502fc09240e292cd76a76afc106a1c8e04a", size = 9190, upload-time = "2025-02-24T04:41:32.565Z" }, + { url = "https://files.pythonhosted.org/packages/f7/81/b0bb27f2ba931a65409c6b8a8b358a7f03c0e46eceacddff55f7c84b1f3b/cryptography-46.0.5-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:351695ada9ea9618b3500b490ad54c739860883df6c1f555e088eaf25b1bbaad", size = 7176289, upload-time = "2026-02-10T19:17:08.274Z" }, + { url = "https://files.pythonhosted.org/packages/ff/9e/6b4397a3e3d15123de3b1806ef342522393d50736c13b20ec4c9ea6693a6/cryptography-46.0.5-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:c18ff11e86df2e28854939acde2d003f7984f721eba450b56a200ad90eeb0e6b", size = 4275637, upload-time = "2026-02-10T19:17:10.53Z" }, + { url = "https://files.pythonhosted.org/packages/63/e7/471ab61099a3920b0c77852ea3f0ea611c9702f651600397ac567848b897/cryptography-46.0.5-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4d7e3d356b8cd4ea5aff04f129d5f66ebdc7b6f8eae802b93739ed520c47c79b", size = 4424742, upload-time = "2026-02-10T19:17:12.388Z" }, + { url = "https://files.pythonhosted.org/packages/37/53/a18500f270342d66bf7e4d9f091114e31e5ee9e7375a5aba2e85a91e0044/cryptography-46.0.5-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:50bfb6925eff619c9c023b967d5b77a54e04256c4281b0e21336a130cd7fc263", size = 4277528, upload-time = "2026-02-10T19:17:13.853Z" }, + { url = "https://files.pythonhosted.org/packages/22/29/c2e812ebc38c57b40e7c583895e73c8c5adb4d1e4a0cc4c5a4fdab2b1acc/cryptography-46.0.5-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:803812e111e75d1aa73690d2facc295eaefd4439be1023fefc4995eaea2af90d", size = 4947993, upload-time = "2026-02-10T19:17:15.618Z" }, + { url = "https://files.pythonhosted.org/packages/6b/e7/237155ae19a9023de7e30ec64e5d99a9431a567407ac21170a046d22a5a3/cryptography-46.0.5-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3ee190460e2fbe447175cda91b88b84ae8322a104fc27766ad09428754a618ed", size = 4456855, upload-time = "2026-02-10T19:17:17.221Z" }, + { url = "https://files.pythonhosted.org/packages/2d/87/fc628a7ad85b81206738abbd213b07702bcbdada1dd43f72236ef3cffbb5/cryptography-46.0.5-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:f145bba11b878005c496e93e257c1e88f154d278d2638e6450d17e0f31e558d2", size = 3984635, upload-time = "2026-02-10T19:17:18.792Z" }, + { url = "https://files.pythonhosted.org/packages/84/29/65b55622bde135aedf4565dc509d99b560ee4095e56989e815f8fd2aa910/cryptography-46.0.5-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:e9251e3be159d1020c4030bd2e5f84d6a43fe54b6c19c12f51cde9542a2817b2", size = 4277038, upload-time = "2026-02-10T19:17:20.256Z" }, + { url = "https://files.pythonhosted.org/packages/bc/36/45e76c68d7311432741faf1fbf7fac8a196a0a735ca21f504c75d37e2558/cryptography-46.0.5-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:47fb8a66058b80e509c47118ef8a75d14c455e81ac369050f20ba0d23e77fee0", size = 4912181, upload-time = "2026-02-10T19:17:21.825Z" }, + { url = "https://files.pythonhosted.org/packages/6d/1a/c1ba8fead184d6e3d5afcf03d569acac5ad063f3ac9fb7258af158f7e378/cryptography-46.0.5-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:4c3341037c136030cb46e4b1e17b7418ea4cbd9dd207e4a6f3b2b24e0d4ac731", size = 4456482, upload-time = "2026-02-10T19:17:25.133Z" }, + { url = "https://files.pythonhosted.org/packages/f9/e5/3fb22e37f66827ced3b902cf895e6a6bc1d095b5b26be26bd13c441fdf19/cryptography-46.0.5-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:890bcb4abd5a2d3f852196437129eb3667d62630333aacc13dfd470fad3aaa82", size = 4405497, upload-time = "2026-02-10T19:17:26.66Z" }, + { url = "https://files.pythonhosted.org/packages/1a/df/9d58bb32b1121a8a2f27383fabae4d63080c7ca60b9b5c88be742be04ee7/cryptography-46.0.5-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:80a8d7bfdf38f87ca30a5391c0c9ce4ed2926918e017c29ddf643d0ed2778ea1", size = 4667819, upload-time = "2026-02-10T19:17:28.569Z" }, + { url = "https://files.pythonhosted.org/packages/ea/ed/325d2a490c5e94038cdb0117da9397ece1f11201f425c4e9c57fe5b9f08b/cryptography-46.0.5-cp311-abi3-win32.whl", hash = "sha256:60ee7e19e95104d4c03871d7d7dfb3d22ef8a9b9c6778c94e1c8fcc8365afd48", size = 3028230, upload-time = "2026-02-10T19:17:30.518Z" }, + { url = "https://files.pythonhosted.org/packages/e9/5a/ac0f49e48063ab4255d9e3b79f5def51697fce1a95ea1370f03dc9db76f6/cryptography-46.0.5-cp311-abi3-win_amd64.whl", hash = "sha256:38946c54b16c885c72c4f59846be9743d699eee2b69b6988e0a00a01f46a61a4", size = 3480909, upload-time = "2026-02-10T19:17:32.083Z" }, + { url = "https://files.pythonhosted.org/packages/00/13/3d278bfa7a15a96b9dc22db5a12ad1e48a9eb3d40e1827ef66a5df75d0d0/cryptography-46.0.5-cp314-cp314t-macosx_10_9_universal2.whl", hash = "sha256:94a76daa32eb78d61339aff7952ea819b1734b46f73646a07decb40e5b3448e2", size = 7119287, upload-time = "2026-02-10T19:17:33.801Z" }, + { url = "https://files.pythonhosted.org/packages/67/c8/581a6702e14f0898a0848105cbefd20c058099e2c2d22ef4e476dfec75d7/cryptography-46.0.5-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5be7bf2fb40769e05739dd0046e7b26f9d4670badc7b032d6ce4db64dddc0678", size = 4265728, upload-time = "2026-02-10T19:17:35.569Z" }, + { url = "https://files.pythonhosted.org/packages/dd/4a/ba1a65ce8fc65435e5a849558379896c957870dd64fecea97b1ad5f46a37/cryptography-46.0.5-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fe346b143ff9685e40192a4960938545c699054ba11d4f9029f94751e3f71d87", size = 4408287, upload-time = "2026-02-10T19:17:36.938Z" }, + { url = "https://files.pythonhosted.org/packages/f8/67/8ffdbf7b65ed1ac224d1c2df3943553766914a8ca718747ee3871da6107e/cryptography-46.0.5-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:c69fd885df7d089548a42d5ec05be26050ebcd2283d89b3d30676eb32ff87dee", size = 4270291, upload-time = "2026-02-10T19:17:38.748Z" }, + { url = "https://files.pythonhosted.org/packages/f8/e5/f52377ee93bc2f2bba55a41a886fd208c15276ffbd2569f2ddc89d50e2c5/cryptography-46.0.5-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:8293f3dea7fc929ef7240796ba231413afa7b68ce38fd21da2995549f5961981", size = 4927539, upload-time = "2026-02-10T19:17:40.241Z" }, + { url = "https://files.pythonhosted.org/packages/3b/02/cfe39181b02419bbbbcf3abdd16c1c5c8541f03ca8bda240debc467d5a12/cryptography-46.0.5-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:1abfdb89b41c3be0365328a410baa9df3ff8a9110fb75e7b52e66803ddabc9a9", size = 4442199, upload-time = "2026-02-10T19:17:41.789Z" }, + { url = "https://files.pythonhosted.org/packages/c0/96/2fcaeb4873e536cf71421a388a6c11b5bc846e986b2b069c79363dc1648e/cryptography-46.0.5-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:d66e421495fdb797610a08f43b05269e0a5ea7f5e652a89bfd5a7d3c1dee3648", size = 3960131, upload-time = "2026-02-10T19:17:43.379Z" }, + { url = "https://files.pythonhosted.org/packages/d8/d2/b27631f401ddd644e94c5cf33c9a4069f72011821cf3dc7309546b0642a0/cryptography-46.0.5-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:4e817a8920bfbcff8940ecfd60f23d01836408242b30f1a708d93198393a80b4", size = 4270072, upload-time = "2026-02-10T19:17:45.481Z" }, + { url = "https://files.pythonhosted.org/packages/f4/a7/60d32b0370dae0b4ebe55ffa10e8599a2a59935b5ece1b9f06edb73abdeb/cryptography-46.0.5-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:68f68d13f2e1cb95163fa3b4db4bf9a159a418f5f6e7242564fc75fcae667fd0", size = 4892170, upload-time = "2026-02-10T19:17:46.997Z" }, + { url = "https://files.pythonhosted.org/packages/d2/b9/cf73ddf8ef1164330eb0b199a589103c363afa0cf794218c24d524a58eab/cryptography-46.0.5-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:a3d1fae9863299076f05cb8a778c467578262fae09f9dc0ee9b12eb4268ce663", size = 4441741, upload-time = "2026-02-10T19:17:48.661Z" }, + { url = "https://files.pythonhosted.org/packages/5f/eb/eee00b28c84c726fe8fa0158c65afe312d9c3b78d9d01daf700f1f6e37ff/cryptography-46.0.5-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c4143987a42a2397f2fc3b4d7e3a7d313fbe684f67ff443999e803dd75a76826", size = 4396728, upload-time = "2026-02-10T19:17:50.058Z" }, + { url = "https://files.pythonhosted.org/packages/65/f4/6bc1a9ed5aef7145045114b75b77c2a8261b4d38717bd8dea111a63c3442/cryptography-46.0.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:7d731d4b107030987fd61a7f8ab512b25b53cef8f233a97379ede116f30eb67d", size = 4652001, upload-time = "2026-02-10T19:17:51.54Z" }, + { url = "https://files.pythonhosted.org/packages/86/ef/5d00ef966ddd71ac2e6951d278884a84a40ffbd88948ef0e294b214ae9e4/cryptography-46.0.5-cp314-cp314t-win32.whl", hash = "sha256:c3bcce8521d785d510b2aad26ae2c966092b7daa8f45dd8f44734a104dc0bc1a", size = 3003637, upload-time = "2026-02-10T19:17:52.997Z" }, + { url = "https://files.pythonhosted.org/packages/b7/57/f3f4160123da6d098db78350fdfd9705057aad21de7388eacb2401dceab9/cryptography-46.0.5-cp314-cp314t-win_amd64.whl", hash = "sha256:4d8ae8659ab18c65ced284993c2265910f6c9e650189d4e3f68445ef82a810e4", size = 3469487, upload-time = "2026-02-10T19:17:54.549Z" }, + { url = "https://files.pythonhosted.org/packages/e2/fa/a66aa722105ad6a458bebd64086ca2b72cdd361fed31763d20390f6f1389/cryptography-46.0.5-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:4108d4c09fbbf2789d0c926eb4152ae1760d5a2d97612b92d508d96c861e4d31", size = 7170514, upload-time = "2026-02-10T19:17:56.267Z" }, + { url = "https://files.pythonhosted.org/packages/0f/04/c85bdeab78c8bc77b701bf0d9bdcf514c044e18a46dcff330df5448631b0/cryptography-46.0.5-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7d1f30a86d2757199cb2d56e48cce14deddf1f9c95f1ef1b64ee91ea43fe2e18", size = 4275349, upload-time = "2026-02-10T19:17:58.419Z" }, + { url = "https://files.pythonhosted.org/packages/5c/32/9b87132a2f91ee7f5223b091dc963055503e9b442c98fc0b8a5ca765fab0/cryptography-46.0.5-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:039917b0dc418bb9f6edce8a906572d69e74bd330b0b3fea4f79dab7f8ddd235", size = 4420667, upload-time = "2026-02-10T19:18:00.619Z" }, + { url = "https://files.pythonhosted.org/packages/a1/a6/a7cb7010bec4b7c5692ca6f024150371b295ee1c108bdc1c400e4c44562b/cryptography-46.0.5-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:ba2a27ff02f48193fc4daeadf8ad2590516fa3d0adeeb34336b96f7fa64c1e3a", size = 4276980, upload-time = "2026-02-10T19:18:02.379Z" }, + { url = "https://files.pythonhosted.org/packages/8e/7c/c4f45e0eeff9b91e3f12dbd0e165fcf2a38847288fcfd889deea99fb7b6d/cryptography-46.0.5-cp38-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:61aa400dce22cb001a98014f647dc21cda08f7915ceb95df0c9eaf84b4b6af76", size = 4939143, upload-time = "2026-02-10T19:18:03.964Z" }, + { url = "https://files.pythonhosted.org/packages/37/19/e1b8f964a834eddb44fa1b9a9976f4e414cbb7aa62809b6760c8803d22d1/cryptography-46.0.5-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3ce58ba46e1bc2aac4f7d9290223cead56743fa6ab94a5d53292ffaac6a91614", size = 4453674, upload-time = "2026-02-10T19:18:05.588Z" }, + { url = "https://files.pythonhosted.org/packages/db/ed/db15d3956f65264ca204625597c410d420e26530c4e2943e05a0d2f24d51/cryptography-46.0.5-cp38-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:420d0e909050490d04359e7fdb5ed7e667ca5c3c402b809ae2563d7e66a92229", size = 3978801, upload-time = "2026-02-10T19:18:07.167Z" }, + { url = "https://files.pythonhosted.org/packages/41/e2/df40a31d82df0a70a0daf69791f91dbb70e47644c58581d654879b382d11/cryptography-46.0.5-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:582f5fcd2afa31622f317f80426a027f30dc792e9c80ffee87b993200ea115f1", size = 4276755, upload-time = "2026-02-10T19:18:09.813Z" }, + { url = "https://files.pythonhosted.org/packages/33/45/726809d1176959f4a896b86907b98ff4391a8aa29c0aaaf9450a8a10630e/cryptography-46.0.5-cp38-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:bfd56bb4b37ed4f330b82402f6f435845a5f5648edf1ad497da51a8452d5d62d", size = 4901539, upload-time = "2026-02-10T19:18:11.263Z" }, + { url = "https://files.pythonhosted.org/packages/99/0f/a3076874e9c88ecb2ecc31382f6e7c21b428ede6f55aafa1aa272613e3cd/cryptography-46.0.5-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:a3d507bb6a513ca96ba84443226af944b0f7f47dcc9a399d110cd6146481d24c", size = 4452794, upload-time = "2026-02-10T19:18:12.914Z" }, + { url = "https://files.pythonhosted.org/packages/02/ef/ffeb542d3683d24194a38f66ca17c0a4b8bf10631feef44a7ef64e631b1a/cryptography-46.0.5-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:9f16fbdf4da055efb21c22d81b89f155f02ba420558db21288b3d0035bafd5f4", size = 4404160, upload-time = "2026-02-10T19:18:14.375Z" }, + { url = "https://files.pythonhosted.org/packages/96/93/682d2b43c1d5f1406ed048f377c0fc9fc8f7b0447a478d5c65ab3d3a66eb/cryptography-46.0.5-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:ced80795227d70549a411a4ab66e8ce307899fad2220ce5ab2f296e687eacde9", size = 4667123, upload-time = "2026-02-10T19:18:15.886Z" }, + { url = "https://files.pythonhosted.org/packages/45/2d/9c5f2926cb5300a8eefc3f4f0b3f3df39db7f7ce40c8365444c49363cbda/cryptography-46.0.5-cp38-abi3-win32.whl", hash = "sha256:02f547fce831f5096c9a567fd41bc12ca8f11df260959ecc7c3202555cc47a72", size = 3010220, upload-time = "2026-02-10T19:18:17.361Z" }, + { url = "https://files.pythonhosted.org/packages/48/ef/0c2f4a8e31018a986949d34a01115dd057bf536905dca38897bacd21fac3/cryptography-46.0.5-cp38-abi3-win_amd64.whl", hash = "sha256:556e106ee01aa13484ce9b0239bca667be5004efb0aabbed28d353df86445595", size = 3467050, upload-time = "2026-02-10T19:18:18.899Z" }, + { url = "https://files.pythonhosted.org/packages/eb/dd/2d9fdb07cebdf3d51179730afb7d5e576153c6744c3ff8fded23030c204e/cryptography-46.0.5-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:3b4995dc971c9fb83c25aa44cf45f02ba86f71ee600d81091c2f0cbae116b06c", size = 3476964, upload-time = "2026-02-10T19:18:20.687Z" }, + { url = "https://files.pythonhosted.org/packages/e9/6f/6cc6cc9955caa6eaf83660b0da2b077c7fe8ff9950a3c5e45d605038d439/cryptography-46.0.5-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:bc84e875994c3b445871ea7181d424588171efec3e185dced958dad9e001950a", size = 4218321, upload-time = "2026-02-10T19:18:22.349Z" }, + { url = "https://files.pythonhosted.org/packages/3e/5d/c4da701939eeee699566a6c1367427ab91a8b7088cc2328c09dbee940415/cryptography-46.0.5-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:2ae6971afd6246710480e3f15824ed3029a60fc16991db250034efd0b9fb4356", size = 4381786, upload-time = "2026-02-10T19:18:24.529Z" }, + { url = "https://files.pythonhosted.org/packages/ac/97/a538654732974a94ff96c1db621fa464f455c02d4bb7d2652f4edc21d600/cryptography-46.0.5-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:d861ee9e76ace6cf36a6a89b959ec08e7bc2493ee39d07ffe5acb23ef46d27da", size = 4217990, upload-time = "2026-02-10T19:18:25.957Z" }, + { url = "https://files.pythonhosted.org/packages/ae/11/7e500d2dd3ba891197b9efd2da5454b74336d64a7cc419aa7327ab74e5f6/cryptography-46.0.5-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:2b7a67c9cd56372f3249b39699f2ad479f6991e62ea15800973b956f4b73e257", size = 4381252, upload-time = "2026-02-10T19:18:27.496Z" }, + { url = "https://files.pythonhosted.org/packages/bc/58/6b3d24e6b9bc474a2dcdee65dfd1f008867015408a271562e4b690561a4d/cryptography-46.0.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:8456928655f856c6e1533ff59d5be76578a7157224dbd9ce6872f25055ab9ab7", size = 3407605, upload-time = "2026-02-10T19:18:29.233Z" }, +] + +[[package]] +name = "distlib" +version = "0.4.0" +source = { registry = "https://pypi.org/simple" } +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/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]] @@ -281,197 +374,43 @@ wheels = [ ] [[package]] -name = "frozenlist" -version = "1.8.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/2d/f5/c831fac6cc817d26fd54c7eaccd04ef7e0288806943f7cc5bbf69f3ac1f0/frozenlist-1.8.0.tar.gz", hash = "sha256:3ede829ed8d842f6cd48fc7081d7a41001a56f1f38603f9d49bf3020d59a31ad", size = 45875, upload-time = "2025-10-06T05:38:17.865Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/bc/03/077f869d540370db12165c0aa51640a873fb661d8b315d1d4d67b284d7ac/frozenlist-1.8.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:09474e9831bc2b2199fad6da3c14c7b0fbdd377cce9d3d77131be28906cb7d84", size = 86912, upload-time = "2025-10-06T05:35:45.98Z" }, - { url = "https://files.pythonhosted.org/packages/df/b5/7610b6bd13e4ae77b96ba85abea1c8cb249683217ef09ac9e0ae93f25a91/frozenlist-1.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:17c883ab0ab67200b5f964d2b9ed6b00971917d5d8a92df149dc2c9779208ee9", size = 50046, upload-time = "2025-10-06T05:35:47.009Z" }, - { url = "https://files.pythonhosted.org/packages/6e/ef/0e8f1fe32f8a53dd26bdd1f9347efe0778b0fddf62789ea683f4cc7d787d/frozenlist-1.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fa47e444b8ba08fffd1c18e8cdb9a75db1b6a27f17507522834ad13ed5922b93", size = 50119, upload-time = "2025-10-06T05:35:48.38Z" }, - { url = "https://files.pythonhosted.org/packages/11/b1/71a477adc7c36e5fb628245dfbdea2166feae310757dea848d02bd0689fd/frozenlist-1.8.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2552f44204b744fba866e573be4c1f9048d6a324dfe14475103fd51613eb1d1f", size = 231067, upload-time = "2025-10-06T05:35:49.97Z" }, - { url = "https://files.pythonhosted.org/packages/45/7e/afe40eca3a2dc19b9904c0f5d7edfe82b5304cb831391edec0ac04af94c2/frozenlist-1.8.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:957e7c38f250991e48a9a73e6423db1bb9dd14e722a10f6b8bb8e16a0f55f695", size = 233160, upload-time = "2025-10-06T05:35:51.729Z" }, - { url = "https://files.pythonhosted.org/packages/a6/aa/7416eac95603ce428679d273255ffc7c998d4132cfae200103f164b108aa/frozenlist-1.8.0-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:8585e3bb2cdea02fc88ffa245069c36555557ad3609e83be0ec71f54fd4abb52", size = 228544, upload-time = "2025-10-06T05:35:53.246Z" }, - { url = "https://files.pythonhosted.org/packages/8b/3d/2a2d1f683d55ac7e3875e4263d28410063e738384d3adc294f5ff3d7105e/frozenlist-1.8.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:edee74874ce20a373d62dc28b0b18b93f645633c2943fd90ee9d898550770581", size = 243797, upload-time = "2025-10-06T05:35:54.497Z" }, - { url = "https://files.pythonhosted.org/packages/78/1e/2d5565b589e580c296d3bb54da08d206e797d941a83a6fdea42af23be79c/frozenlist-1.8.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c9a63152fe95756b85f31186bddf42e4c02c6321207fd6601a1c89ebac4fe567", size = 247923, upload-time = "2025-10-06T05:35:55.861Z" }, - { url = "https://files.pythonhosted.org/packages/aa/c3/65872fcf1d326a7f101ad4d86285c403c87be7d832b7470b77f6d2ed5ddc/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b6db2185db9be0a04fecf2f241c70b63b1a242e2805be291855078f2b404dd6b", size = 230886, upload-time = "2025-10-06T05:35:57.399Z" }, - { url = "https://files.pythonhosted.org/packages/a0/76/ac9ced601d62f6956f03cc794f9e04c81719509f85255abf96e2510f4265/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:f4be2e3d8bc8aabd566f8d5b8ba7ecc09249d74ba3c9ed52e54dc23a293f0b92", size = 245731, upload-time = "2025-10-06T05:35:58.563Z" }, - { url = "https://files.pythonhosted.org/packages/b9/49/ecccb5f2598daf0b4a1415497eba4c33c1e8ce07495eb07d2860c731b8d5/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:c8d1634419f39ea6f5c427ea2f90ca85126b54b50837f31497f3bf38266e853d", size = 241544, upload-time = "2025-10-06T05:35:59.719Z" }, - { url = "https://files.pythonhosted.org/packages/53/4b/ddf24113323c0bbcc54cb38c8b8916f1da7165e07b8e24a717b4a12cbf10/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:1a7fa382a4a223773ed64242dbe1c9c326ec09457e6b8428efb4118c685c3dfd", size = 241806, upload-time = "2025-10-06T05:36:00.959Z" }, - { url = "https://files.pythonhosted.org/packages/a7/fb/9b9a084d73c67175484ba2789a59f8eebebd0827d186a8102005ce41e1ba/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:11847b53d722050808926e785df837353bd4d75f1d494377e59b23594d834967", size = 229382, upload-time = "2025-10-06T05:36:02.22Z" }, - { url = "https://files.pythonhosted.org/packages/95/a3/c8fb25aac55bf5e12dae5c5aa6a98f85d436c1dc658f21c3ac73f9fa95e5/frozenlist-1.8.0-cp311-cp311-win32.whl", hash = "sha256:27c6e8077956cf73eadd514be8fb04d77fc946a7fe9f7fe167648b0b9085cc25", size = 39647, upload-time = "2025-10-06T05:36:03.409Z" }, - { url = "https://files.pythonhosted.org/packages/0a/f5/603d0d6a02cfd4c8f2a095a54672b3cf967ad688a60fb9faf04fc4887f65/frozenlist-1.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:ac913f8403b36a2c8610bbfd25b8013488533e71e62b4b4adce9c86c8cea905b", size = 44064, upload-time = "2025-10-06T05:36:04.368Z" }, - { url = "https://files.pythonhosted.org/packages/5d/16/c2c9ab44e181f043a86f9a8f84d5124b62dbcb3a02c0977ec72b9ac1d3e0/frozenlist-1.8.0-cp311-cp311-win_arm64.whl", hash = "sha256:d4d3214a0f8394edfa3e303136d0575eece0745ff2b47bd2cb2e66dd92d4351a", size = 39937, upload-time = "2025-10-06T05:36:05.669Z" }, - { url = "https://files.pythonhosted.org/packages/69/29/948b9aa87e75820a38650af445d2ef2b6b8a6fab1a23b6bb9e4ef0be2d59/frozenlist-1.8.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:78f7b9e5d6f2fdb88cdde9440dc147259b62b9d3b019924def9f6478be254ac1", size = 87782, upload-time = "2025-10-06T05:36:06.649Z" }, - { url = "https://files.pythonhosted.org/packages/64/80/4f6e318ee2a7c0750ed724fa33a4bdf1eacdc5a39a7a24e818a773cd91af/frozenlist-1.8.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:229bf37d2e4acdaf808fd3f06e854a4a7a3661e871b10dc1f8f1896a3b05f18b", size = 50594, upload-time = "2025-10-06T05:36:07.69Z" }, - { url = "https://files.pythonhosted.org/packages/2b/94/5c8a2b50a496b11dd519f4a24cb5496cf125681dd99e94c604ccdea9419a/frozenlist-1.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f833670942247a14eafbb675458b4e61c82e002a148f49e68257b79296e865c4", size = 50448, upload-time = "2025-10-06T05:36:08.78Z" }, - { url = "https://files.pythonhosted.org/packages/6a/bd/d91c5e39f490a49df14320f4e8c80161cfcce09f1e2cde1edd16a551abb3/frozenlist-1.8.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:494a5952b1c597ba44e0e78113a7266e656b9794eec897b19ead706bd7074383", size = 242411, upload-time = "2025-10-06T05:36:09.801Z" }, - { url = "https://files.pythonhosted.org/packages/8f/83/f61505a05109ef3293dfb1ff594d13d64a2324ac3482be2cedc2be818256/frozenlist-1.8.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96f423a119f4777a4a056b66ce11527366a8bb92f54e541ade21f2374433f6d4", size = 243014, upload-time = "2025-10-06T05:36:11.394Z" }, - { url = "https://files.pythonhosted.org/packages/d8/cb/cb6c7b0f7d4023ddda30cf56b8b17494eb3a79e3fda666bf735f63118b35/frozenlist-1.8.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3462dd9475af2025c31cc61be6652dfa25cbfb56cbbf52f4ccfe029f38decaf8", size = 234909, upload-time = "2025-10-06T05:36:12.598Z" }, - { url = "https://files.pythonhosted.org/packages/31/c5/cd7a1f3b8b34af009fb17d4123c5a778b44ae2804e3ad6b86204255f9ec5/frozenlist-1.8.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c4c800524c9cd9bac5166cd6f55285957fcfc907db323e193f2afcd4d9abd69b", size = 250049, upload-time = "2025-10-06T05:36:14.065Z" }, - { url = "https://files.pythonhosted.org/packages/c0/01/2f95d3b416c584a1e7f0e1d6d31998c4a795f7544069ee2e0962a4b60740/frozenlist-1.8.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d6a5df73acd3399d893dafc71663ad22534b5aa4f94e8a2fabfe856c3c1b6a52", size = 256485, upload-time = "2025-10-06T05:36:15.39Z" }, - { url = "https://files.pythonhosted.org/packages/ce/03/024bf7720b3abaebcff6d0793d73c154237b85bdf67b7ed55e5e9596dc9a/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:405e8fe955c2280ce66428b3ca55e12b3c4e9c336fb2103a4937e891c69a4a29", size = 237619, upload-time = "2025-10-06T05:36:16.558Z" }, - { url = "https://files.pythonhosted.org/packages/69/fa/f8abdfe7d76b731f5d8bd217827cf6764d4f1d9763407e42717b4bed50a0/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:908bd3f6439f2fef9e85031b59fd4f1297af54415fb60e4254a95f75b3cab3f3", size = 250320, upload-time = "2025-10-06T05:36:17.821Z" }, - { url = "https://files.pythonhosted.org/packages/f5/3c/b051329f718b463b22613e269ad72138cc256c540f78a6de89452803a47d/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:294e487f9ec720bd8ffcebc99d575f7eff3568a08a253d1ee1a0378754b74143", size = 246820, upload-time = "2025-10-06T05:36:19.046Z" }, - { url = "https://files.pythonhosted.org/packages/0f/ae/58282e8f98e444b3f4dd42448ff36fa38bef29e40d40f330b22e7108f565/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:74c51543498289c0c43656701be6b077f4b265868fa7f8a8859c197006efb608", size = 250518, upload-time = "2025-10-06T05:36:20.763Z" }, - { url = "https://files.pythonhosted.org/packages/8f/96/007e5944694d66123183845a106547a15944fbbb7154788cbf7272789536/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:776f352e8329135506a1d6bf16ac3f87bc25b28e765949282dcc627af36123aa", size = 239096, upload-time = "2025-10-06T05:36:22.129Z" }, - { url = "https://files.pythonhosted.org/packages/66/bb/852b9d6db2fa40be96f29c0d1205c306288f0684df8fd26ca1951d461a56/frozenlist-1.8.0-cp312-cp312-win32.whl", hash = "sha256:433403ae80709741ce34038da08511d4a77062aa924baf411ef73d1146e74faf", size = 39985, upload-time = "2025-10-06T05:36:23.661Z" }, - { url = "https://files.pythonhosted.org/packages/b8/af/38e51a553dd66eb064cdf193841f16f077585d4d28394c2fa6235cb41765/frozenlist-1.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:34187385b08f866104f0c0617404c8eb08165ab1272e884abc89c112e9c00746", size = 44591, upload-time = "2025-10-06T05:36:24.958Z" }, - { url = "https://files.pythonhosted.org/packages/a7/06/1dc65480ab147339fecc70797e9c2f69d9cea9cf38934ce08df070fdb9cb/frozenlist-1.8.0-cp312-cp312-win_arm64.whl", hash = "sha256:fe3c58d2f5db5fbd18c2987cba06d51b0529f52bc3a6cdc33d3f4eab725104bd", size = 40102, upload-time = "2025-10-06T05:36:26.333Z" }, - { url = "https://files.pythonhosted.org/packages/2d/40/0832c31a37d60f60ed79e9dfb5a92e1e2af4f40a16a29abcc7992af9edff/frozenlist-1.8.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8d92f1a84bb12d9e56f818b3a746f3efba93c1b63c8387a73dde655e1e42282a", size = 85717, upload-time = "2025-10-06T05:36:27.341Z" }, - { url = "https://files.pythonhosted.org/packages/30/ba/b0b3de23f40bc55a7057bd38434e25c34fa48e17f20ee273bbde5e0650f3/frozenlist-1.8.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:96153e77a591c8adc2ee805756c61f59fef4cf4073a9275ee86fe8cba41241f7", size = 49651, upload-time = "2025-10-06T05:36:28.855Z" }, - { url = "https://files.pythonhosted.org/packages/0c/ab/6e5080ee374f875296c4243c381bbdef97a9ac39c6e3ce1d5f7d42cb78d6/frozenlist-1.8.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f21f00a91358803399890ab167098c131ec2ddd5f8f5fd5fe9c9f2c6fcd91e40", size = 49417, upload-time = "2025-10-06T05:36:29.877Z" }, - { url = "https://files.pythonhosted.org/packages/d5/4e/e4691508f9477ce67da2015d8c00acd751e6287739123113a9fca6f1604e/frozenlist-1.8.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fb30f9626572a76dfe4293c7194a09fb1fe93ba94c7d4f720dfae3b646b45027", size = 234391, upload-time = "2025-10-06T05:36:31.301Z" }, - { url = "https://files.pythonhosted.org/packages/40/76/c202df58e3acdf12969a7895fd6f3bc016c642e6726aa63bd3025e0fc71c/frozenlist-1.8.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:eaa352d7047a31d87dafcacbabe89df0aa506abb5b1b85a2fb91bc3faa02d822", size = 233048, upload-time = "2025-10-06T05:36:32.531Z" }, - { url = "https://files.pythonhosted.org/packages/f9/c0/8746afb90f17b73ca5979c7a3958116e105ff796e718575175319b5bb4ce/frozenlist-1.8.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:03ae967b4e297f58f8c774c7eabcce57fe3c2434817d4385c50661845a058121", size = 226549, upload-time = "2025-10-06T05:36:33.706Z" }, - { url = "https://files.pythonhosted.org/packages/7e/eb/4c7eefc718ff72f9b6c4893291abaae5fbc0c82226a32dcd8ef4f7a5dbef/frozenlist-1.8.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f6292f1de555ffcc675941d65fffffb0a5bcd992905015f85d0592201793e0e5", size = 239833, upload-time = "2025-10-06T05:36:34.947Z" }, - { url = "https://files.pythonhosted.org/packages/c2/4e/e5c02187cf704224f8b21bee886f3d713ca379535f16893233b9d672ea71/frozenlist-1.8.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:29548f9b5b5e3460ce7378144c3010363d8035cea44bc0bf02d57f5a685e084e", size = 245363, upload-time = "2025-10-06T05:36:36.534Z" }, - { url = "https://files.pythonhosted.org/packages/1f/96/cb85ec608464472e82ad37a17f844889c36100eed57bea094518bf270692/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ec3cc8c5d4084591b4237c0a272cc4f50a5b03396a47d9caaf76f5d7b38a4f11", size = 229314, upload-time = "2025-10-06T05:36:38.582Z" }, - { url = "https://files.pythonhosted.org/packages/5d/6f/4ae69c550e4cee66b57887daeebe006fe985917c01d0fff9caab9883f6d0/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:517279f58009d0b1f2e7c1b130b377a349405da3f7621ed6bfae50b10adf20c1", size = 243365, upload-time = "2025-10-06T05:36:40.152Z" }, - { url = "https://files.pythonhosted.org/packages/7a/58/afd56de246cf11780a40a2c28dc7cbabbf06337cc8ddb1c780a2d97e88d8/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:db1e72ede2d0d7ccb213f218df6a078a9c09a7de257c2fe8fcef16d5925230b1", size = 237763, upload-time = "2025-10-06T05:36:41.355Z" }, - { url = "https://files.pythonhosted.org/packages/cb/36/cdfaf6ed42e2644740d4a10452d8e97fa1c062e2a8006e4b09f1b5fd7d63/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:b4dec9482a65c54a5044486847b8a66bf10c9cb4926d42927ec4e8fd5db7fed8", size = 240110, upload-time = "2025-10-06T05:36:42.716Z" }, - { url = "https://files.pythonhosted.org/packages/03/a8/9ea226fbefad669f11b52e864c55f0bd57d3c8d7eb07e9f2e9a0b39502e1/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:21900c48ae04d13d416f0e1e0c4d81f7931f73a9dfa0b7a8746fb2fe7dd970ed", size = 233717, upload-time = "2025-10-06T05:36:44.251Z" }, - { url = "https://files.pythonhosted.org/packages/1e/0b/1b5531611e83ba7d13ccc9988967ea1b51186af64c42b7a7af465dcc9568/frozenlist-1.8.0-cp313-cp313-win32.whl", hash = "sha256:8b7b94a067d1c504ee0b16def57ad5738701e4ba10cec90529f13fa03c833496", size = 39628, upload-time = "2025-10-06T05:36:45.423Z" }, - { url = "https://files.pythonhosted.org/packages/d8/cf/174c91dbc9cc49bc7b7aab74d8b734e974d1faa8f191c74af9b7e80848e6/frozenlist-1.8.0-cp313-cp313-win_amd64.whl", hash = "sha256:878be833caa6a3821caf85eb39c5ba92d28e85df26d57afb06b35b2efd937231", size = 43882, upload-time = "2025-10-06T05:36:46.796Z" }, - { url = "https://files.pythonhosted.org/packages/c1/17/502cd212cbfa96eb1388614fe39a3fc9ab87dbbe042b66f97acb57474834/frozenlist-1.8.0-cp313-cp313-win_arm64.whl", hash = "sha256:44389d135b3ff43ba8cc89ff7f51f5a0bb6b63d829c8300f79a2fe4fe61bcc62", size = 39676, upload-time = "2025-10-06T05:36:47.8Z" }, - { url = "https://files.pythonhosted.org/packages/d2/5c/3bbfaa920dfab09e76946a5d2833a7cbdf7b9b4a91c714666ac4855b88b4/frozenlist-1.8.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:e25ac20a2ef37e91c1b39938b591457666a0fa835c7783c3a8f33ea42870db94", size = 89235, upload-time = "2025-10-06T05:36:48.78Z" }, - { url = "https://files.pythonhosted.org/packages/d2/d6/f03961ef72166cec1687e84e8925838442b615bd0b8854b54923ce5b7b8a/frozenlist-1.8.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:07cdca25a91a4386d2e76ad992916a85038a9b97561bf7a3fd12d5d9ce31870c", size = 50742, upload-time = "2025-10-06T05:36:49.837Z" }, - { url = "https://files.pythonhosted.org/packages/1e/bb/a6d12b7ba4c3337667d0e421f7181c82dda448ce4e7ad7ecd249a16fa806/frozenlist-1.8.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:4e0c11f2cc6717e0a741f84a527c52616140741cd812a50422f83dc31749fb52", size = 51725, upload-time = "2025-10-06T05:36:50.851Z" }, - { url = "https://files.pythonhosted.org/packages/bc/71/d1fed0ffe2c2ccd70b43714c6cab0f4188f09f8a67a7914a6b46ee30f274/frozenlist-1.8.0-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b3210649ee28062ea6099cfda39e147fa1bc039583c8ee4481cb7811e2448c51", size = 284533, upload-time = "2025-10-06T05:36:51.898Z" }, - { url = "https://files.pythonhosted.org/packages/c9/1f/fb1685a7b009d89f9bf78a42d94461bc06581f6e718c39344754a5d9bada/frozenlist-1.8.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:581ef5194c48035a7de2aefc72ac6539823bb71508189e5de01d60c9dcd5fa65", size = 292506, upload-time = "2025-10-06T05:36:53.101Z" }, - { url = "https://files.pythonhosted.org/packages/e6/3b/b991fe1612703f7e0d05c0cf734c1b77aaf7c7d321df4572e8d36e7048c8/frozenlist-1.8.0-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3ef2d026f16a2b1866e1d86fc4e1291e1ed8a387b2c333809419a2f8b3a77b82", size = 274161, upload-time = "2025-10-06T05:36:54.309Z" }, - { url = "https://files.pythonhosted.org/packages/ca/ec/c5c618767bcdf66e88945ec0157d7f6c4a1322f1473392319b7a2501ded7/frozenlist-1.8.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5500ef82073f599ac84d888e3a8c1f77ac831183244bfd7f11eaa0289fb30714", size = 294676, upload-time = "2025-10-06T05:36:55.566Z" }, - { url = "https://files.pythonhosted.org/packages/7c/ce/3934758637d8f8a88d11f0585d6495ef54b2044ed6ec84492a91fa3b27aa/frozenlist-1.8.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:50066c3997d0091c411a66e710f4e11752251e6d2d73d70d8d5d4c76442a199d", size = 300638, upload-time = "2025-10-06T05:36:56.758Z" }, - { url = "https://files.pythonhosted.org/packages/fc/4f/a7e4d0d467298f42de4b41cbc7ddaf19d3cfeabaf9ff97c20c6c7ee409f9/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:5c1c8e78426e59b3f8005e9b19f6ff46e5845895adbde20ece9218319eca6506", size = 283067, upload-time = "2025-10-06T05:36:57.965Z" }, - { url = "https://files.pythonhosted.org/packages/dc/48/c7b163063d55a83772b268e6d1affb960771b0e203b632cfe09522d67ea5/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:eefdba20de0d938cec6a89bd4d70f346a03108a19b9df4248d3cf0d88f1b0f51", size = 292101, upload-time = "2025-10-06T05:36:59.237Z" }, - { url = "https://files.pythonhosted.org/packages/9f/d0/2366d3c4ecdc2fd391e0afa6e11500bfba0ea772764d631bbf82f0136c9d/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:cf253e0e1c3ceb4aaff6df637ce033ff6535fb8c70a764a8f46aafd3d6ab798e", size = 289901, upload-time = "2025-10-06T05:37:00.811Z" }, - { url = "https://files.pythonhosted.org/packages/b8/94/daff920e82c1b70e3618a2ac39fbc01ae3e2ff6124e80739ce5d71c9b920/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:032efa2674356903cd0261c4317a561a6850f3ac864a63fc1583147fb05a79b0", size = 289395, upload-time = "2025-10-06T05:37:02.115Z" }, - { url = "https://files.pythonhosted.org/packages/e3/20/bba307ab4235a09fdcd3cc5508dbabd17c4634a1af4b96e0f69bfe551ebd/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6da155091429aeba16851ecb10a9104a108bcd32f6c1642867eadaee401c1c41", size = 283659, upload-time = "2025-10-06T05:37:03.711Z" }, - { url = "https://files.pythonhosted.org/packages/fd/00/04ca1c3a7a124b6de4f8a9a17cc2fcad138b4608e7a3fc5877804b8715d7/frozenlist-1.8.0-cp313-cp313t-win32.whl", hash = "sha256:0f96534f8bfebc1a394209427d0f8a63d343c9779cda6fc25e8e121b5fd8555b", size = 43492, upload-time = "2025-10-06T05:37:04.915Z" }, - { url = "https://files.pythonhosted.org/packages/59/5e/c69f733a86a94ab10f68e496dc6b7e8bc078ebb415281d5698313e3af3a1/frozenlist-1.8.0-cp313-cp313t-win_amd64.whl", hash = "sha256:5d63a068f978fc69421fb0e6eb91a9603187527c86b7cd3f534a5b77a592b888", size = 48034, upload-time = "2025-10-06T05:37:06.343Z" }, - { url = "https://files.pythonhosted.org/packages/16/6c/be9d79775d8abe79b05fa6d23da99ad6e7763a1d080fbae7290b286093fd/frozenlist-1.8.0-cp313-cp313t-win_arm64.whl", hash = "sha256:bf0a7e10b077bf5fb9380ad3ae8ce20ef919a6ad93b4552896419ac7e1d8e042", size = 41749, upload-time = "2025-10-06T05:37:07.431Z" }, - { url = "https://files.pythonhosted.org/packages/f1/c8/85da824b7e7b9b6e7f7705b2ecaf9591ba6f79c1177f324c2735e41d36a2/frozenlist-1.8.0-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:cee686f1f4cadeb2136007ddedd0aaf928ab95216e7691c63e50a8ec066336d0", size = 86127, upload-time = "2025-10-06T05:37:08.438Z" }, - { url = "https://files.pythonhosted.org/packages/8e/e8/a1185e236ec66c20afd72399522f142c3724c785789255202d27ae992818/frozenlist-1.8.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:119fb2a1bd47307e899c2fac7f28e85b9a543864df47aa7ec9d3c1b4545f096f", size = 49698, upload-time = "2025-10-06T05:37:09.48Z" }, - { url = "https://files.pythonhosted.org/packages/a1/93/72b1736d68f03fda5fdf0f2180fb6caaae3894f1b854d006ac61ecc727ee/frozenlist-1.8.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:4970ece02dbc8c3a92fcc5228e36a3e933a01a999f7094ff7c23fbd2beeaa67c", size = 49749, upload-time = "2025-10-06T05:37:10.569Z" }, - { url = "https://files.pythonhosted.org/packages/a7/b2/fabede9fafd976b991e9f1b9c8c873ed86f202889b864756f240ce6dd855/frozenlist-1.8.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:cba69cb73723c3f329622e34bdbf5ce1f80c21c290ff04256cff1cd3c2036ed2", size = 231298, upload-time = "2025-10-06T05:37:11.993Z" }, - { url = "https://files.pythonhosted.org/packages/3a/3b/d9b1e0b0eed36e70477ffb8360c49c85c8ca8ef9700a4e6711f39a6e8b45/frozenlist-1.8.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:778a11b15673f6f1df23d9586f83c4846c471a8af693a22e066508b77d201ec8", size = 232015, upload-time = "2025-10-06T05:37:13.194Z" }, - { url = "https://files.pythonhosted.org/packages/dc/94/be719d2766c1138148564a3960fc2c06eb688da592bdc25adcf856101be7/frozenlist-1.8.0-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:0325024fe97f94c41c08872db482cf8ac4800d80e79222c6b0b7b162d5b13686", size = 225038, upload-time = "2025-10-06T05:37:14.577Z" }, - { url = "https://files.pythonhosted.org/packages/e4/09/6712b6c5465f083f52f50cf74167b92d4ea2f50e46a9eea0523d658454ae/frozenlist-1.8.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:97260ff46b207a82a7567b581ab4190bd4dfa09f4db8a8b49d1a958f6aa4940e", size = 240130, upload-time = "2025-10-06T05:37:15.781Z" }, - { url = "https://files.pythonhosted.org/packages/f8/d4/cd065cdcf21550b54f3ce6a22e143ac9e4836ca42a0de1022da8498eac89/frozenlist-1.8.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:54b2077180eb7f83dd52c40b2750d0a9f175e06a42e3213ce047219de902717a", size = 242845, upload-time = "2025-10-06T05:37:17.037Z" }, - { url = "https://files.pythonhosted.org/packages/62/c3/f57a5c8c70cd1ead3d5d5f776f89d33110b1addae0ab010ad774d9a44fb9/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:2f05983daecab868a31e1da44462873306d3cbfd76d1f0b5b69c473d21dbb128", size = 229131, upload-time = "2025-10-06T05:37:18.221Z" }, - { url = "https://files.pythonhosted.org/packages/6c/52/232476fe9cb64f0742f3fde2b7d26c1dac18b6d62071c74d4ded55e0ef94/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:33f48f51a446114bc5d251fb2954ab0164d5be02ad3382abcbfe07e2531d650f", size = 240542, upload-time = "2025-10-06T05:37:19.771Z" }, - { url = "https://files.pythonhosted.org/packages/5f/85/07bf3f5d0fb5414aee5f47d33c6f5c77bfe49aac680bfece33d4fdf6a246/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:154e55ec0655291b5dd1b8731c637ecdb50975a2ae70c606d100750a540082f7", size = 237308, upload-time = "2025-10-06T05:37:20.969Z" }, - { url = "https://files.pythonhosted.org/packages/11/99/ae3a33d5befd41ac0ca2cc7fd3aa707c9c324de2e89db0e0f45db9a64c26/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:4314debad13beb564b708b4a496020e5306c7333fa9a3ab90374169a20ffab30", size = 238210, upload-time = "2025-10-06T05:37:22.252Z" }, - { url = "https://files.pythonhosted.org/packages/b2/60/b1d2da22f4970e7a155f0adde9b1435712ece01b3cd45ba63702aea33938/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:073f8bf8becba60aa931eb3bc420b217bb7d5b8f4750e6f8b3be7f3da85d38b7", size = 231972, upload-time = "2025-10-06T05:37:23.5Z" }, - { url = "https://files.pythonhosted.org/packages/3f/ab/945b2f32de889993b9c9133216c068b7fcf257d8595a0ac420ac8677cab0/frozenlist-1.8.0-cp314-cp314-win32.whl", hash = "sha256:bac9c42ba2ac65ddc115d930c78d24ab8d4f465fd3fc473cdedfccadb9429806", size = 40536, upload-time = "2025-10-06T05:37:25.581Z" }, - { url = "https://files.pythonhosted.org/packages/59/ad/9caa9b9c836d9ad6f067157a531ac48b7d36499f5036d4141ce78c230b1b/frozenlist-1.8.0-cp314-cp314-win_amd64.whl", hash = "sha256:3e0761f4d1a44f1d1a47996511752cf3dcec5bbdd9cc2b4fe595caf97754b7a0", size = 44330, upload-time = "2025-10-06T05:37:26.928Z" }, - { url = "https://files.pythonhosted.org/packages/82/13/e6950121764f2676f43534c555249f57030150260aee9dcf7d64efda11dd/frozenlist-1.8.0-cp314-cp314-win_arm64.whl", hash = "sha256:d1eaff1d00c7751b7c6662e9c5ba6eb2c17a2306ba5e2a37f24ddf3cc953402b", size = 40627, upload-time = "2025-10-06T05:37:28.075Z" }, - { url = "https://files.pythonhosted.org/packages/c0/c7/43200656ecc4e02d3f8bc248df68256cd9572b3f0017f0a0c4e93440ae23/frozenlist-1.8.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:d3bb933317c52d7ea5004a1c442eef86f426886fba134ef8cf4226ea6ee1821d", size = 89238, upload-time = "2025-10-06T05:37:29.373Z" }, - { url = "https://files.pythonhosted.org/packages/d1/29/55c5f0689b9c0fb765055629f472c0de484dcaf0acee2f7707266ae3583c/frozenlist-1.8.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:8009897cdef112072f93a0efdce29cd819e717fd2f649ee3016efd3cd885a7ed", size = 50738, upload-time = "2025-10-06T05:37:30.792Z" }, - { url = "https://files.pythonhosted.org/packages/ba/7d/b7282a445956506fa11da8c2db7d276adcbf2b17d8bb8407a47685263f90/frozenlist-1.8.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:2c5dcbbc55383e5883246d11fd179782a9d07a986c40f49abe89ddf865913930", size = 51739, upload-time = "2025-10-06T05:37:32.127Z" }, - { url = "https://files.pythonhosted.org/packages/62/1c/3d8622e60d0b767a5510d1d3cf21065b9db874696a51ea6d7a43180a259c/frozenlist-1.8.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:39ecbc32f1390387d2aa4f5a995e465e9e2f79ba3adcac92d68e3e0afae6657c", size = 284186, upload-time = "2025-10-06T05:37:33.21Z" }, - { url = "https://files.pythonhosted.org/packages/2d/14/aa36d5f85a89679a85a1d44cd7a6657e0b1c75f61e7cad987b203d2daca8/frozenlist-1.8.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:92db2bf818d5cc8d9c1f1fc56b897662e24ea5adb36ad1f1d82875bd64e03c24", size = 292196, upload-time = "2025-10-06T05:37:36.107Z" }, - { url = "https://files.pythonhosted.org/packages/05/23/6bde59eb55abd407d34f77d39a5126fb7b4f109a3f611d3929f14b700c66/frozenlist-1.8.0-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:2dc43a022e555de94c3b68a4ef0b11c4f747d12c024a520c7101709a2144fb37", size = 273830, upload-time = "2025-10-06T05:37:37.663Z" }, - { url = "https://files.pythonhosted.org/packages/d2/3f/22cff331bfad7a8afa616289000ba793347fcd7bc275f3b28ecea2a27909/frozenlist-1.8.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:cb89a7f2de3602cfed448095bab3f178399646ab7c61454315089787df07733a", size = 294289, upload-time = "2025-10-06T05:37:39.261Z" }, - { url = "https://files.pythonhosted.org/packages/a4/89/5b057c799de4838b6c69aa82b79705f2027615e01be996d2486a69ca99c4/frozenlist-1.8.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:33139dc858c580ea50e7e60a1b0ea003efa1fd42e6ec7fdbad78fff65fad2fd2", size = 300318, upload-time = "2025-10-06T05:37:43.213Z" }, - { url = "https://files.pythonhosted.org/packages/30/de/2c22ab3eb2a8af6d69dc799e48455813bab3690c760de58e1bf43b36da3e/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:168c0969a329b416119507ba30b9ea13688fafffac1b7822802537569a1cb0ef", size = 282814, upload-time = "2025-10-06T05:37:45.337Z" }, - { url = "https://files.pythonhosted.org/packages/59/f7/970141a6a8dbd7f556d94977858cfb36fa9b66e0892c6dd780d2219d8cd8/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:28bd570e8e189d7f7b001966435f9dac6718324b5be2990ac496cf1ea9ddb7fe", size = 291762, upload-time = "2025-10-06T05:37:46.657Z" }, - { url = "https://files.pythonhosted.org/packages/c1/15/ca1adae83a719f82df9116d66f5bb28bb95557b3951903d39135620ef157/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:b2a095d45c5d46e5e79ba1e5b9cb787f541a8dee0433836cea4b96a2c439dcd8", size = 289470, upload-time = "2025-10-06T05:37:47.946Z" }, - { url = "https://files.pythonhosted.org/packages/ac/83/dca6dc53bf657d371fbc88ddeb21b79891e747189c5de990b9dfff2ccba1/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:eab8145831a0d56ec9c4139b6c3e594c7a83c2c8be25d5bcf2d86136a532287a", size = 289042, upload-time = "2025-10-06T05:37:49.499Z" }, - { url = "https://files.pythonhosted.org/packages/96/52/abddd34ca99be142f354398700536c5bd315880ed0a213812bc491cff5e4/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:974b28cf63cc99dfb2188d8d222bc6843656188164848c4f679e63dae4b0708e", size = 283148, upload-time = "2025-10-06T05:37:50.745Z" }, - { url = "https://files.pythonhosted.org/packages/af/d3/76bd4ed4317e7119c2b7f57c3f6934aba26d277acc6309f873341640e21f/frozenlist-1.8.0-cp314-cp314t-win32.whl", hash = "sha256:342c97bf697ac5480c0a7ec73cd700ecfa5a8a40ac923bd035484616efecc2df", size = 44676, upload-time = "2025-10-06T05:37:52.222Z" }, - { url = "https://files.pythonhosted.org/packages/89/76/c615883b7b521ead2944bb3480398cbb07e12b7b4e4d073d3752eb721558/frozenlist-1.8.0-cp314-cp314t-win_amd64.whl", hash = "sha256:06be8f67f39c8b1dc671f5d83aaefd3358ae5cdcf8314552c57e7ed3e6475bdd", size = 49451, upload-time = "2025-10-06T05:37:53.425Z" }, - { url = "https://files.pythonhosted.org/packages/e0/a3/5982da14e113d07b325230f95060e2169f5311b1017ea8af2a29b374c289/frozenlist-1.8.0-cp314-cp314t-win_arm64.whl", hash = "sha256:102e6314ca4da683dca92e3b1355490fed5f313b768500084fbe6371fddfdb79", size = 42507, upload-time = "2025-10-06T05:37:54.513Z" }, - { url = "https://files.pythonhosted.org/packages/9a/9a/e35b4a917281c0b8419d4207f4334c8e8c5dbf4f3f5f9ada73958d937dcc/frozenlist-1.8.0-py3-none-any.whl", hash = "sha256:0c18a16eab41e82c295618a77502e17b195883241c563b00f0aa5106fc4eaa0d", size = 13409, upload-time = "2025-10-06T05:38:16.721Z" }, -] - -[[package]] -name = "fsspec" -version = "2025.12.0" +name = "docstring-parser" +version = "0.17.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b6/27/954057b0d1f53f086f681755207dda6de6c660ce133c829158e8e8fe7895/fsspec-2025.12.0.tar.gz", hash = "sha256:c505de011584597b1060ff778bb664c1bc022e87921b0e4f10cc9c44f9635973", size = 309748, upload-time = "2025-12-03T15:23:42.687Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b2/9d/c3b43da9515bd270df0f80548d9944e389870713cc1fe2b8fb35fe2bcefd/docstring_parser-0.17.0.tar.gz", hash = "sha256:583de4a309722b3315439bb31d64ba3eebada841f2e2cee23b99df001434c912", size = 27442, upload-time = "2025-07-21T07:35:01.868Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/51/c7/b64cae5dba3a1b138d7123ec36bb5ccd39d39939f18454407e5468f4763f/fsspec-2025.12.0-py3-none-any.whl", hash = "sha256:8bf1fe301b7d8acfa6e8571e3b1c3d158f909666642431cc78a1b7b4dbc5ec5b", size = 201422, upload-time = "2025-12-03T15:23:41.434Z" }, + { url = "https://files.pythonhosted.org/packages/55/e2/2537ebcff11c1ee1ff17d8d0b6f4db75873e3b0fb32c2d4a2ee31ecb310a/docstring_parser-0.17.0-py3-none-any.whl", hash = "sha256:cf2569abd23dce8099b300f9b4fa8191e9582dda731fd533daf54c4551658708", size = 36896, upload-time = "2025-07-21T07:35:00.684Z" }, ] [[package]] -name = "gcsfs" -version = "2025.12.0" +name = "filelock" +version = "3.25.2" source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "aiohttp" }, - { name = "decorator" }, - { name = "fsspec" }, - { name = "google-auth" }, - { name = "google-auth-oauthlib" }, - { name = "google-cloud-storage" }, - { name = "google-cloud-storage-control" }, - { name = "requests" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/3e/3e/453b42bbcda2177daba97ebc5202faf5c57cc0c2bb4aac7081c12b0471da/gcsfs-2025.12.0.tar.gz", hash = "sha256:9a9c1c32b7899a3967ba30a7e9422cdfda596266f03476cdf5545402b8af4cd5", size = 95148, upload-time = "2025-12-03T15:44:59.703Z" } +sdist = { url = "https://files.pythonhosted.org/packages/94/b8/00651a0f559862f3bb7d6f7477b192afe3f583cc5e26403b44e59a55ab34/filelock-3.25.2.tar.gz", hash = "sha256:b64ece2b38f4ca29dd3e810287aa8c48182bbecd1ae6e9ae126c9b35f1382694", size = 40480, upload-time = "2026-03-11T20:45:38.487Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b1/bf/e664cbeab8f2a8b097c0604252760410fde191fe6ac7d5081b29e601ac52/gcsfs-2025.12.0-py3-none-any.whl", hash = "sha256:e06aaec53797dc6b83d5cc90c4d3ae7247b4ee0cf8d8b1ce50e8d6b78e3a9aea", size = 41204, upload-time = "2025-12-03T15:44:58.464Z" }, + { url = "https://files.pythonhosted.org/packages/a4/a5/842ae8f0c08b61d6484b52f99a03510a3a72d23141942d216ebe81fefbce/filelock-3.25.2-py3-none-any.whl", hash = "sha256:ca8afb0da15f229774c9ad1b455ed96e85a81373065fb10446672f64444ddf70", size = 26759, upload-time = "2026-03-11T20:45:37.437Z" }, ] [[package]] -name = "gemini-ocr" -version = "0.4.0" -source = { editable = "." } -dependencies = [ - { name = "fsspec" }, - { name = "gcsfs" }, - { name = "google-cloud-documentai" }, - { name = "google-genai" }, - { name = "pymupdf" }, - { name = "python-dotenv" }, - { name = "seq-smith" }, -] - -[package.dev-dependencies] -dev = [ - { name = "pytest" }, - { name = "pytest-asyncio" }, - { name = "ruff" }, -] - -[package.metadata] -requires-dist = [ - { name = "fsspec" }, - { name = "gcsfs" }, - { name = "google-cloud-documentai" }, - { name = "google-genai" }, - { name = "pymupdf" }, - { name = "python-dotenv", specifier = ">=1.2.1" }, - { name = "seq-smith", specifier = ">=0.5.1" }, -] - -[package.metadata.requires-dev] -dev = [ - { name = "pytest" }, - { name = "pytest-asyncio" }, - { name = "ruff", specifier = ">=0.14.6" }, +name = "fsspec" +version = "2026.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/51/7c/f60c259dcbf4f0c47cc4ddb8f7720d2dcdc8888c8e5ad84c73ea4531cc5b/fsspec-2026.2.0.tar.gz", hash = "sha256:6544e34b16869f5aacd5b90bdf1a71acb37792ea3ddf6125ee69a22a53fb8bff", size = 313441, upload-time = "2026-02-05T21:50:53.743Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e6/ab/fb21f4c939bb440104cc2b396d3be1d9b7a9fd3c6c2a53d98c45b3d7c954/fsspec-2026.2.0-py3-none-any.whl", hash = "sha256:98de475b5cb3bd66bedd5c4679e87b4fdfe1a3bf4d707b151b3c07e58c9a2437", size = 202505, upload-time = "2026-02-05T21:50:51.819Z" }, ] [[package]] -name = "google-api-core" -version = "2.28.1" +name = "genai-prices" +version = "0.0.55" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "google-auth" }, - { name = "googleapis-common-protos" }, - { name = "proto-plus" }, - { name = "protobuf" }, - { name = "requests" }, + { name = "httpx" }, + { name = "pydantic" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/61/da/83d7043169ac2c8c7469f0e375610d78ae2160134bf1b80634c482fa079c/google_api_core-2.28.1.tar.gz", hash = "sha256:2b405df02d68e68ce0fbc138559e6036559e685159d148ae5861013dc201baf8", size = 176759, upload-time = "2025-10-28T21:34:51.529Z" } +sdist = { url = "https://files.pythonhosted.org/packages/77/67/de9d9be180db6d80b298c281dff71502095c0776d7cc9286f486f667f61a/genai_prices-0.0.55.tar.gz", hash = "sha256:8692c65d0deefe2ad0680d71841eb12822a35945a6060d2b6adbcbdf4945e1cb", size = 59987, upload-time = "2026-02-26T17:56:41.467Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ed/d4/90197b416cb61cefd316964fd9e7bd8324bcbafabf40eef14a9f20b81974/google_api_core-2.28.1-py3-none-any.whl", hash = "sha256:4021b0f8ceb77a6fb4de6fde4502cecab45062e66ff4f2895169e0b35bc9466c", size = 173706, upload-time = "2025-10-28T21:34:50.151Z" }, -] - -[package.optional-dependencies] -grpc = [ - { name = "grpcio" }, - { name = "grpcio-status" }, + { url = "https://files.pythonhosted.org/packages/c4/98/66a06b82a5c840f896490d5ef9c7691776b147589f2e8d2fa66c67a3db9c/genai_prices-0.0.55-py3-none-any.whl", hash = "sha256:ccd795c90c926b3c71066bf5656f14c67fc11fdba6d71e072c7fb4fa311e1b12", size = 62603, upload-time = "2026-02-26T17:56:40.502Z" }, ] [[package]] @@ -493,112 +432,6 @@ requests = [ { name = "requests" }, ] -[[package]] -name = "google-auth-oauthlib" -version = "1.2.2" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "google-auth" }, - { name = "requests-oauthlib" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/fb/87/e10bf24f7bcffc1421b84d6f9c3377c30ec305d082cd737ddaa6d8f77f7c/google_auth_oauthlib-1.2.2.tar.gz", hash = "sha256:11046fb8d3348b296302dd939ace8af0a724042e8029c1b872d87fabc9f41684", size = 20955, upload-time = "2025-04-22T16:40:29.172Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ac/84/40ee070be95771acd2f4418981edb834979424565c3eec3cd88b6aa09d24/google_auth_oauthlib-1.2.2-py3-none-any.whl", hash = "sha256:fd619506f4b3908b5df17b65f39ca8d66ea56986e5472eb5978fd8f3786f00a2", size = 19072, upload-time = "2025-04-22T16:40:28.174Z" }, -] - -[[package]] -name = "google-cloud-core" -version = "2.5.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "google-api-core" }, - { name = "google-auth" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/a6/03/ef0bc99d0e0faf4fdbe67ac445e18cdaa74824fd93cd069e7bb6548cb52d/google_cloud_core-2.5.0.tar.gz", hash = "sha256:7c1b7ef5c92311717bd05301aa1a91ffbc565673d3b0b4163a52d8413a186963", size = 36027, upload-time = "2025-10-29T23:17:39.513Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/89/20/bfa472e327c8edee00f04beecc80baeddd2ab33ee0e86fd7654da49d45e9/google_cloud_core-2.5.0-py3-none-any.whl", hash = "sha256:67d977b41ae6c7211ee830c7912e41003ea8194bff15ae7d72fd6f51e57acabc", size = 29469, upload-time = "2025-10-29T23:17:38.548Z" }, -] - -[[package]] -name = "google-cloud-documentai" -version = "3.7.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "google-api-core", extra = ["grpc"] }, - { name = "google-auth" }, - { name = "grpcio" }, - { name = "proto-plus" }, - { name = "protobuf" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/02/58/0d22b0a315aac8716cdc66c690595a7397dc91499177039171426450de34/google_cloud_documentai-3.7.0.tar.gz", hash = "sha256:be4a912acfdbeb1f03d48d8bb869ad85e6bc4e38b57a88d9a894e8950f5883bf", size = 352699, upload-time = "2025-10-17T02:34:41.232Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/82/af/eea48c24cea7da859d0ca4fdbbbb449bf31cbad66bb57287e2fba06765aa/google_cloud_documentai-3.7.0-py3-none-any.whl", hash = "sha256:ff1dc9aacbf4e0e1807ef7a47d2ea0ac9b441ddbff18548d49cdc6dcb5368183", size = 303041, upload-time = "2025-10-17T02:32:49.014Z" }, -] - -[[package]] -name = "google-cloud-storage" -version = "3.7.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "google-api-core" }, - { name = "google-auth" }, - { name = "google-cloud-core" }, - { name = "google-crc32c" }, - { name = "google-resumable-media" }, - { name = "requests" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/d2/8e/fab2de1a0ab7fdbd452eaae5a9a5c933d0911c26b04efa0c76ddfd921259/google_cloud_storage-3.7.0.tar.gz", hash = "sha256:9ce59c65f4d6e372effcecc0456680a8d73cef4f2dc9212a0704799cb3d69237", size = 17258914, upload-time = "2025-12-09T18:24:48.97Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/2d/80/6e5c7c83cea15ed4dfc4843b9df9db0716bc551ac938f7b5dd18a72bd5e4/google_cloud_storage-3.7.0-py3-none-any.whl", hash = "sha256:469bc9540936e02f8a4bfd1619e9dca1e42dec48f95e4204d783b36476a15093", size = 303364, upload-time = "2025-12-09T18:24:47.343Z" }, -] - -[[package]] -name = "google-cloud-storage-control" -version = "1.8.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "google-api-core", extra = ["grpc"] }, - { name = "google-auth" }, - { name = "grpc-google-iam-v1" }, - { name = "grpcio" }, - { name = "proto-plus" }, - { name = "protobuf" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/56/24/ea82cba156377fb270d024c2b13e397d6e57663e0db529978736bc444d67/google_cloud_storage_control-1.8.0.tar.gz", hash = "sha256:e77f1365667e9cf8b6fbb0fc0de725a6045ee4b42220c3e6f863adace6c4033f", size = 112056, upload-time = "2025-10-20T14:57:18.086Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/bc/88/bbf40bfebbce33c9aa421b6da8ea89d2771edd5142ee3f35f6b4b3efb98c/google_cloud_storage_control-1.8.0-py3-none-any.whl", hash = "sha256:1a3179438f82fc49b2ad3d4674d737164bd6a51e0a9b545a9ec7e7d118b8bee0", size = 86054, upload-time = "2025-10-20T14:54:06.198Z" }, -] - -[[package]] -name = "google-crc32c" -version = "1.8.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/03/41/4b9c02f99e4c5fb477122cd5437403b552873f014616ac1d19ac8221a58d/google_crc32c-1.8.0.tar.gz", hash = "sha256:a428e25fb7691024de47fecfbff7ff957214da51eddded0da0ae0e0f03a2cf79", size = 14192, upload-time = "2025-12-16T00:35:25.142Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/5d/ef/21ccfaab3d5078d41efe8612e0ed0bfc9ce22475de074162a91a25f7980d/google_crc32c-1.8.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:014a7e68d623e9a4222d663931febc3033c5c7c9730785727de2a81f87d5bab8", size = 31298, upload-time = "2025-12-16T00:20:32.241Z" }, - { url = "https://files.pythonhosted.org/packages/c5/b8/f8413d3f4b676136e965e764ceedec904fe38ae8de0cdc52a12d8eb1096e/google_crc32c-1.8.0-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:86cfc00fe45a0ac7359e5214a1704e51a99e757d0272554874f419f79838c5f7", size = 30872, upload-time = "2025-12-16T00:33:58.785Z" }, - { url = "https://files.pythonhosted.org/packages/f6/fd/33aa4ec62b290477181c55bb1c9302c9698c58c0ce9a6ab4874abc8b0d60/google_crc32c-1.8.0-cp311-cp311-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:19b40d637a54cb71e0829179f6cb41835f0fbd9e8eb60552152a8b52c36cbe15", size = 33243, upload-time = "2025-12-16T00:40:21.46Z" }, - { url = "https://files.pythonhosted.org/packages/71/03/4820b3bd99c9653d1a5210cb32f9ba4da9681619b4d35b6a052432df4773/google_crc32c-1.8.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:17446feb05abddc187e5441a45971b8394ea4c1b6efd88ab0af393fd9e0a156a", size = 33608, upload-time = "2025-12-16T00:40:22.204Z" }, - { url = "https://files.pythonhosted.org/packages/7c/43/acf61476a11437bf9733fb2f70599b1ced11ec7ed9ea760fdd9a77d0c619/google_crc32c-1.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:71734788a88f551fbd6a97be9668a0020698e07b2bf5b3aa26a36c10cdfb27b2", size = 34439, upload-time = "2025-12-16T00:35:20.458Z" }, - { url = "https://files.pythonhosted.org/packages/e9/5f/7307325b1198b59324c0fa9807cafb551afb65e831699f2ce211ad5c8240/google_crc32c-1.8.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:4b8286b659c1335172e39563ab0a768b8015e88e08329fa5321f774275fc3113", size = 31300, upload-time = "2025-12-16T00:21:56.723Z" }, - { url = "https://files.pythonhosted.org/packages/21/8e/58c0d5d86e2220e6a37befe7e6a94dd2f6006044b1a33edf1ff6d9f7e319/google_crc32c-1.8.0-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:2a3dc3318507de089c5384cc74d54318401410f82aa65b2d9cdde9d297aca7cb", size = 30867, upload-time = "2025-12-16T00:38:31.302Z" }, - { url = "https://files.pythonhosted.org/packages/ce/a9/a780cc66f86335a6019f557a8aaca8fbb970728f0efd2430d15ff1beae0e/google_crc32c-1.8.0-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:14f87e04d613dfa218d6135e81b78272c3b904e2a7053b841481b38a7d901411", size = 33364, upload-time = "2025-12-16T00:40:22.96Z" }, - { url = "https://files.pythonhosted.org/packages/21/3f/3457ea803db0198c9aaca2dd373750972ce28a26f00544b6b85088811939/google_crc32c-1.8.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:cb5c869c2923d56cb0c8e6bcdd73c009c36ae39b652dbe46a05eb4ef0ad01454", size = 33740, upload-time = "2025-12-16T00:40:23.96Z" }, - { url = "https://files.pythonhosted.org/packages/df/c0/87c2073e0c72515bb8733d4eef7b21548e8d189f094b5dad20b0ecaf64f6/google_crc32c-1.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:3cc0c8912038065eafa603b238abf252e204accab2a704c63b9e14837a854962", size = 34437, upload-time = "2025-12-16T00:35:21.395Z" }, - { url = "https://files.pythonhosted.org/packages/d1/db/000f15b41724589b0e7bc24bc7a8967898d8d3bc8caf64c513d91ef1f6c0/google_crc32c-1.8.0-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:3ebb04528e83b2634857f43f9bb8ef5b2bbe7f10f140daeb01b58f972d04736b", size = 31297, upload-time = "2025-12-16T00:23:20.709Z" }, - { url = "https://files.pythonhosted.org/packages/d7/0d/8ebed0c39c53a7e838e2a486da8abb0e52de135f1b376ae2f0b160eb4c1a/google_crc32c-1.8.0-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:450dc98429d3e33ed2926fc99ee81001928d63460f8538f21a5d6060912a8e27", size = 30867, upload-time = "2025-12-16T00:43:14.628Z" }, - { url = "https://files.pythonhosted.org/packages/ce/42/b468aec74a0354b34c8cbf748db20d6e350a68a2b0912e128cabee49806c/google_crc32c-1.8.0-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:3b9776774b24ba76831609ffbabce8cdf6fa2bd5e9df37b594221c7e333a81fa", size = 33344, upload-time = "2025-12-16T00:40:24.742Z" }, - { url = "https://files.pythonhosted.org/packages/1c/e8/b33784d6fc77fb5062a8a7854e43e1e618b87d5ddf610a88025e4de6226e/google_crc32c-1.8.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:89c17d53d75562edfff86679244830599ee0a48efc216200691de8b02ab6b2b8", size = 33694, upload-time = "2025-12-16T00:40:25.505Z" }, - { url = "https://files.pythonhosted.org/packages/92/b1/d3cbd4d988afb3d8e4db94ca953df429ed6db7282ed0e700d25e6c7bfc8d/google_crc32c-1.8.0-cp313-cp313-win_amd64.whl", hash = "sha256:57a50a9035b75643996fbf224d6661e386c7162d1dfdab9bc4ca790947d1007f", size = 34435, upload-time = "2025-12-16T00:35:22.107Z" }, - { url = "https://files.pythonhosted.org/packages/21/88/8ecf3c2b864a490b9e7010c84fd203ec8cf3b280651106a3a74dd1b0ca72/google_crc32c-1.8.0-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:e6584b12cb06796d285d09e33f63309a09368b9d806a551d8036a4207ea43697", size = 31301, upload-time = "2025-12-16T00:24:48.527Z" }, - { url = "https://files.pythonhosted.org/packages/36/c6/f7ff6c11f5ca215d9f43d3629163727a272eabc356e5c9b2853df2bfe965/google_crc32c-1.8.0-cp314-cp314-macosx_12_0_x86_64.whl", hash = "sha256:f4b51844ef67d6cf2e9425983274da75f18b1597bb2c998e1c0a0e8d46f8f651", size = 30868, upload-time = "2025-12-16T00:48:12.163Z" }, - { url = "https://files.pythonhosted.org/packages/56/15/c25671c7aad70f8179d858c55a6ae8404902abe0cdcf32a29d581792b491/google_crc32c-1.8.0-cp314-cp314-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b0d1a7afc6e8e4635564ba8aa5c0548e3173e41b6384d7711a9123165f582de2", size = 33381, upload-time = "2025-12-16T00:40:26.268Z" }, - { url = "https://files.pythonhosted.org/packages/42/fa/f50f51260d7b0ef5d4898af122d8a7ec5a84e2984f676f746445f783705f/google_crc32c-1.8.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8b3f68782f3cbd1bce027e48768293072813469af6a61a86f6bb4977a4380f21", size = 33734, upload-time = "2025-12-16T00:40:27.028Z" }, - { url = "https://files.pythonhosted.org/packages/08/a5/7b059810934a09fb3ccb657e0843813c1fee1183d3bc2c8041800374aa2c/google_crc32c-1.8.0-cp314-cp314-win_amd64.whl", hash = "sha256:d511b3153e7011a27ab6ee6bb3a5404a55b994dc1a7322c0b87b29606d9790e2", size = 34878, upload-time = "2025-12-16T00:35:23.142Z" }, - { url = "https://files.pythonhosted.org/packages/52/c5/c171e4d8c44fec1422d801a6d2e5d7ddabd733eeda505c79730ee9607f07/google_crc32c-1.8.0-pp311-pypy311_pp73-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:87fa445064e7db928226b2e6f0d5304ab4cd0339e664a4e9a25029f384d9bb93", size = 28615, upload-time = "2025-12-16T00:40:29.298Z" }, - { url = "https://files.pythonhosted.org/packages/9c/97/7d75fe37a7a6ed171a2cf17117177e7aab7e6e0d115858741b41e9dd4254/google_crc32c-1.8.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f639065ea2042d5c034bf258a9f085eaa7af0cd250667c0635a3118e8f92c69c", size = 28800, upload-time = "2025-12-16T00:40:30.322Z" }, -] - [[package]] name = "google-genai" version = "1.56.0" @@ -621,111 +454,48 @@ wheels = [ ] [[package]] -name = "google-resumable-media" -version = "2.8.0" +name = "griffelib" +version = "2.0.0" source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "google-crc32c" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/64/d7/520b62a35b23038ff005e334dba3ffc75fcf583bee26723f1fd8fd4b6919/google_resumable_media-2.8.0.tar.gz", hash = "sha256:f1157ed8b46994d60a1bc432544db62352043113684d4e030ee02e77ebe9a1ae", size = 2163265, upload-time = "2025-11-17T15:38:06.659Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/1f/0b/93afde9cfe012260e9fe1522f35c9b72d6ee222f316586b1f23ecf44d518/google_resumable_media-2.8.0-py3-none-any.whl", hash = "sha256:dd14a116af303845a8d932ddae161a26e86cc229645bc98b39f026f9b1717582", size = 81340, upload-time = "2025-11-17T15:38:05.594Z" }, + { url = "https://files.pythonhosted.org/packages/4d/51/c936033e16d12b627ea334aaaaf42229c37620d0f15593456ab69ab48161/griffelib-2.0.0-py3-none-any.whl", hash = "sha256:01284878c966508b6d6f1dbff9b6fa607bc062d8261c5c7253cb285b06422a7f", size = 142004, upload-time = "2026-02-09T19:09:40.561Z" }, ] [[package]] -name = "googleapis-common-protos" -version = "1.72.0" -source = { registry = "https://pypi.org/simple" } +name = "groundmark" +version = "0.1.0" +source = { editable = "." } dependencies = [ - { name = "protobuf" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/e5/7b/adfd75544c415c487b33061fe7ae526165241c1ea133f9a9125a56b39fd8/googleapis_common_protos-1.72.0.tar.gz", hash = "sha256:e55a601c1b32b52d7a3e65f43563e2aa61bcd737998ee672ac9b951cd49319f5", size = 147433, upload-time = "2025-11-06T18:29:24.087Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/c4/ab/09169d5a4612a5f92490806649ac8d41e3ec9129c636754575b3553f4ea4/googleapis_common_protos-1.72.0-py3-none-any.whl", hash = "sha256:4299c5a82d5ae1a9702ada957347726b167f9f8d1fc352477702a1e851ff4038", size = 297515, upload-time = "2025-11-06T18:29:13.14Z" }, + { name = "anchorite" }, + { name = "pdfplumber" }, + { name = "pydantic-ai-slim", extra = ["anthropic", "bedrock", "google", "openai"] }, + { name = "pypdf" }, ] -[package.optional-dependencies] -grpc = [ - { name = "grpcio" }, +[package.dev-dependencies] +dev = [ + { name = "pre-commit" }, + { name = "pytest" }, + { name = "pytest-asyncio" }, + { name = "ruff" }, + { name = "typer" }, ] -[[package]] -name = "grpc-google-iam-v1" -version = "0.14.3" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "googleapis-common-protos", extra = ["grpc"] }, - { name = "grpcio" }, - { name = "protobuf" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/76/1e/1011451679a983f2f5c6771a1682542ecb027776762ad031fd0d7129164b/grpc_google_iam_v1-0.14.3.tar.gz", hash = "sha256:879ac4ef33136c5491a6300e27575a9ec760f6cdf9a2518798c1b8977a5dc389", size = 23745, upload-time = "2025-10-15T21:14:53.318Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/4a/bd/330a1bbdb1afe0b96311249e699b6dc9cfc17916394fd4503ac5aca2514b/grpc_google_iam_v1-0.14.3-py3-none-any.whl", hash = "sha256:7a7f697e017a067206a3dfef44e4c634a34d3dee135fe7d7a4613fe3e59217e6", size = 32690, upload-time = "2025-10-15T21:14:51.72Z" }, +[package.metadata] +requires-dist = [ + { name = "anchorite", specifier = ">=0.1.1" }, + { name = "pdfplumber", specifier = ">=0.11.9" }, + { name = "pydantic-ai-slim", extras = ["anthropic", "bedrock", "google", "openai"], specifier = ">=1.67.0" }, + { name = "pypdf", specifier = ">=6.8.0" }, ] -[[package]] -name = "grpcio" -version = "1.76.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/b6/e0/318c1ce3ae5a17894d5791e87aea147587c9e702f24122cc7a5c8bbaeeb1/grpcio-1.76.0.tar.gz", hash = "sha256:7be78388d6da1a25c0d5ec506523db58b18be22d9c37d8d3a32c08be4987bd73", size = 12785182, upload-time = "2025-10-21T16:23:12.106Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a0/00/8163a1beeb6971f66b4bbe6ac9457b97948beba8dd2fc8e1281dce7f79ec/grpcio-1.76.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:2e1743fbd7f5fa713a1b0a8ac8ebabf0ec980b5d8809ec358d488e273b9cf02a", size = 5843567, upload-time = "2025-10-21T16:20:52.829Z" }, - { url = "https://files.pythonhosted.org/packages/10/c1/934202f5cf335e6d852530ce14ddb0fef21be612ba9ecbbcbd4d748ca32d/grpcio-1.76.0-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:a8c2cf1209497cf659a667d7dea88985e834c24b7c3b605e6254cbb5076d985c", size = 11848017, upload-time = "2025-10-21T16:20:56.705Z" }, - { url = "https://files.pythonhosted.org/packages/11/0b/8dec16b1863d74af6eb3543928600ec2195af49ca58b16334972f6775663/grpcio-1.76.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:08caea849a9d3c71a542827d6df9d5a69067b0a1efbea8a855633ff5d9571465", size = 6412027, upload-time = "2025-10-21T16:20:59.3Z" }, - { url = "https://files.pythonhosted.org/packages/d7/64/7b9e6e7ab910bea9d46f2c090380bab274a0b91fb0a2fe9b0cd399fffa12/grpcio-1.76.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:f0e34c2079d47ae9f6188211db9e777c619a21d4faba6977774e8fa43b085e48", size = 7075913, upload-time = "2025-10-21T16:21:01.645Z" }, - { url = "https://files.pythonhosted.org/packages/68/86/093c46e9546073cefa789bd76d44c5cb2abc824ca62af0c18be590ff13ba/grpcio-1.76.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8843114c0cfce61b40ad48df65abcfc00d4dba82eae8718fab5352390848c5da", size = 6615417, upload-time = "2025-10-21T16:21:03.844Z" }, - { url = "https://files.pythonhosted.org/packages/f7/b6/5709a3a68500a9c03da6fb71740dcdd5ef245e39266461a03f31a57036d8/grpcio-1.76.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8eddfb4d203a237da6f3cc8a540dad0517d274b5a1e9e636fd8d2c79b5c1d397", size = 7199683, upload-time = "2025-10-21T16:21:06.195Z" }, - { url = "https://files.pythonhosted.org/packages/91/d3/4b1f2bf16ed52ce0b508161df3a2d186e4935379a159a834cb4a7d687429/grpcio-1.76.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:32483fe2aab2c3794101c2a159070584e5db11d0aa091b2c0ea9c4fc43d0d749", size = 8163109, upload-time = "2025-10-21T16:21:08.498Z" }, - { url = "https://files.pythonhosted.org/packages/5c/61/d9043f95f5f4cf085ac5dd6137b469d41befb04bd80280952ffa2a4c3f12/grpcio-1.76.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:dcfe41187da8992c5f40aa8c5ec086fa3672834d2be57a32384c08d5a05b4c00", size = 7626676, upload-time = "2025-10-21T16:21:10.693Z" }, - { url = "https://files.pythonhosted.org/packages/36/95/fd9a5152ca02d8881e4dd419cdd790e11805979f499a2e5b96488b85cf27/grpcio-1.76.0-cp311-cp311-win32.whl", hash = "sha256:2107b0c024d1b35f4083f11245c0e23846ae64d02f40b2b226684840260ed054", size = 3997688, upload-time = "2025-10-21T16:21:12.746Z" }, - { url = "https://files.pythonhosted.org/packages/60/9c/5c359c8d4c9176cfa3c61ecd4efe5affe1f38d9bae81e81ac7186b4c9cc8/grpcio-1.76.0-cp311-cp311-win_amd64.whl", hash = "sha256:522175aba7af9113c48ec10cc471b9b9bd4f6ceb36aeb4544a8e2c80ed9d252d", size = 4709315, upload-time = "2025-10-21T16:21:15.26Z" }, - { url = "https://files.pythonhosted.org/packages/bf/05/8e29121994b8d959ffa0afd28996d452f291b48cfc0875619de0bde2c50c/grpcio-1.76.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:81fd9652b37b36f16138611c7e884eb82e0cec137c40d3ef7c3f9b3ed00f6ed8", size = 5799718, upload-time = "2025-10-21T16:21:17.939Z" }, - { url = "https://files.pythonhosted.org/packages/d9/75/11d0e66b3cdf998c996489581bdad8900db79ebd83513e45c19548f1cba4/grpcio-1.76.0-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:04bbe1bfe3a68bbfd4e52402ab7d4eb59d72d02647ae2042204326cf4bbad280", size = 11825627, upload-time = "2025-10-21T16:21:20.466Z" }, - { url = "https://files.pythonhosted.org/packages/28/50/2f0aa0498bc188048f5d9504dcc5c2c24f2eb1a9337cd0fa09a61a2e75f0/grpcio-1.76.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d388087771c837cdb6515539f43b9d4bf0b0f23593a24054ac16f7a960be16f4", size = 6359167, upload-time = "2025-10-21T16:21:23.122Z" }, - { url = "https://files.pythonhosted.org/packages/66/e5/bbf0bb97d29ede1d59d6588af40018cfc345b17ce979b7b45424628dc8bb/grpcio-1.76.0-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:9f8f757bebaaea112c00dba718fc0d3260052ce714e25804a03f93f5d1c6cc11", size = 7044267, upload-time = "2025-10-21T16:21:25.995Z" }, - { url = "https://files.pythonhosted.org/packages/f5/86/f6ec2164f743d9609691115ae8ece098c76b894ebe4f7c94a655c6b03e98/grpcio-1.76.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:980a846182ce88c4f2f7e2c22c56aefd515daeb36149d1c897f83cf57999e0b6", size = 6573963, upload-time = "2025-10-21T16:21:28.631Z" }, - { url = "https://files.pythonhosted.org/packages/60/bc/8d9d0d8505feccfdf38a766d262c71e73639c165b311c9457208b56d92ae/grpcio-1.76.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f92f88e6c033db65a5ae3d97905c8fea9c725b63e28d5a75cb73b49bda5024d8", size = 7164484, upload-time = "2025-10-21T16:21:30.837Z" }, - { url = "https://files.pythonhosted.org/packages/67/e6/5d6c2fc10b95edf6df9b8f19cf10a34263b7fd48493936fffd5085521292/grpcio-1.76.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4baf3cbe2f0be3289eb68ac8ae771156971848bb8aaff60bad42005539431980", size = 8127777, upload-time = "2025-10-21T16:21:33.577Z" }, - { url = "https://files.pythonhosted.org/packages/3f/c8/dce8ff21c86abe025efe304d9e31fdb0deaaa3b502b6a78141080f206da0/grpcio-1.76.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:615ba64c208aaceb5ec83bfdce7728b80bfeb8be97562944836a7a0a9647d882", size = 7594014, upload-time = "2025-10-21T16:21:41.882Z" }, - { url = "https://files.pythonhosted.org/packages/e0/42/ad28191ebf983a5d0ecef90bab66baa5a6b18f2bfdef9d0a63b1973d9f75/grpcio-1.76.0-cp312-cp312-win32.whl", hash = "sha256:45d59a649a82df5718fd9527ce775fd66d1af35e6d31abdcdc906a49c6822958", size = 3984750, upload-time = "2025-10-21T16:21:44.006Z" }, - { url = "https://files.pythonhosted.org/packages/9e/00/7bd478cbb851c04a48baccaa49b75abaa8e4122f7d86da797500cccdd771/grpcio-1.76.0-cp312-cp312-win_amd64.whl", hash = "sha256:c088e7a90b6017307f423efbb9d1ba97a22aa2170876223f9709e9d1de0b5347", size = 4704003, upload-time = "2025-10-21T16:21:46.244Z" }, - { url = "https://files.pythonhosted.org/packages/fc/ed/71467ab770effc9e8cef5f2e7388beb2be26ed642d567697bb103a790c72/grpcio-1.76.0-cp313-cp313-linux_armv7l.whl", hash = "sha256:26ef06c73eb53267c2b319f43e6634c7556ea37672029241a056629af27c10e2", size = 5807716, upload-time = "2025-10-21T16:21:48.475Z" }, - { url = "https://files.pythonhosted.org/packages/2c/85/c6ed56f9817fab03fa8a111ca91469941fb514e3e3ce6d793cb8f1e1347b/grpcio-1.76.0-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:45e0111e73f43f735d70786557dc38141185072d7ff8dc1829d6a77ac1471468", size = 11821522, upload-time = "2025-10-21T16:21:51.142Z" }, - { url = "https://files.pythonhosted.org/packages/ac/31/2b8a235ab40c39cbc141ef647f8a6eb7b0028f023015a4842933bc0d6831/grpcio-1.76.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:83d57312a58dcfe2a3a0f9d1389b299438909a02db60e2f2ea2ae2d8034909d3", size = 6362558, upload-time = "2025-10-21T16:21:54.213Z" }, - { url = "https://files.pythonhosted.org/packages/bd/64/9784eab483358e08847498ee56faf8ff6ea8e0a4592568d9f68edc97e9e9/grpcio-1.76.0-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:3e2a27c89eb9ac3d81ec8835e12414d73536c6e620355d65102503064a4ed6eb", size = 7049990, upload-time = "2025-10-21T16:21:56.476Z" }, - { url = "https://files.pythonhosted.org/packages/2b/94/8c12319a6369434e7a184b987e8e9f3b49a114c489b8315f029e24de4837/grpcio-1.76.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:61f69297cba3950a524f61c7c8ee12e55c486cb5f7db47ff9dcee33da6f0d3ae", size = 6575387, upload-time = "2025-10-21T16:21:59.051Z" }, - { url = "https://files.pythonhosted.org/packages/15/0f/f12c32b03f731f4a6242f771f63039df182c8b8e2cf8075b245b409259d4/grpcio-1.76.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6a15c17af8839b6801d554263c546c69c4d7718ad4321e3166175b37eaacca77", size = 7166668, upload-time = "2025-10-21T16:22:02.049Z" }, - { url = "https://files.pythonhosted.org/packages/ff/2d/3ec9ce0c2b1d92dd59d1c3264aaec9f0f7c817d6e8ac683b97198a36ed5a/grpcio-1.76.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:25a18e9810fbc7e7f03ec2516addc116a957f8cbb8cbc95ccc80faa072743d03", size = 8124928, upload-time = "2025-10-21T16:22:04.984Z" }, - { url = "https://files.pythonhosted.org/packages/1a/74/fd3317be5672f4856bcdd1a9e7b5e17554692d3db9a3b273879dc02d657d/grpcio-1.76.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:931091142fd8cc14edccc0845a79248bc155425eee9a98b2db2ea4f00a235a42", size = 7589983, upload-time = "2025-10-21T16:22:07.881Z" }, - { url = "https://files.pythonhosted.org/packages/45/bb/ca038cf420f405971f19821c8c15bcbc875505f6ffadafe9ffd77871dc4c/grpcio-1.76.0-cp313-cp313-win32.whl", hash = "sha256:5e8571632780e08526f118f74170ad8d50fb0a48c23a746bef2a6ebade3abd6f", size = 3984727, upload-time = "2025-10-21T16:22:10.032Z" }, - { url = "https://files.pythonhosted.org/packages/41/80/84087dc56437ced7cdd4b13d7875e7439a52a261e3ab4e06488ba6173b0a/grpcio-1.76.0-cp313-cp313-win_amd64.whl", hash = "sha256:f9f7bd5faab55f47231ad8dba7787866b69f5e93bc306e3915606779bbfb4ba8", size = 4702799, upload-time = "2025-10-21T16:22:12.709Z" }, - { url = "https://files.pythonhosted.org/packages/b4/46/39adac80de49d678e6e073b70204091e76631e03e94928b9ea4ecf0f6e0e/grpcio-1.76.0-cp314-cp314-linux_armv7l.whl", hash = "sha256:ff8a59ea85a1f2191a0ffcc61298c571bc566332f82e5f5be1b83c9d8e668a62", size = 5808417, upload-time = "2025-10-21T16:22:15.02Z" }, - { url = "https://files.pythonhosted.org/packages/9c/f5/a4531f7fb8b4e2a60b94e39d5d924469b7a6988176b3422487be61fe2998/grpcio-1.76.0-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:06c3d6b076e7b593905d04fdba6a0525711b3466f43b3400266f04ff735de0cd", size = 11828219, upload-time = "2025-10-21T16:22:17.954Z" }, - { url = "https://files.pythonhosted.org/packages/4b/1c/de55d868ed7a8bd6acc6b1d6ddc4aa36d07a9f31d33c912c804adb1b971b/grpcio-1.76.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:fd5ef5932f6475c436c4a55e4336ebbe47bd3272be04964a03d316bbf4afbcbc", size = 6367826, upload-time = "2025-10-21T16:22:20.721Z" }, - { url = "https://files.pythonhosted.org/packages/59/64/99e44c02b5adb0ad13ab3adc89cb33cb54bfa90c74770f2607eea629b86f/grpcio-1.76.0-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:b331680e46239e090f5b3cead313cc772f6caa7d0fc8de349337563125361a4a", size = 7049550, upload-time = "2025-10-21T16:22:23.637Z" }, - { url = "https://files.pythonhosted.org/packages/43/28/40a5be3f9a86949b83e7d6a2ad6011d993cbe9b6bd27bea881f61c7788b6/grpcio-1.76.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:2229ae655ec4e8999599469559e97630185fdd53ae1e8997d147b7c9b2b72cba", size = 6575564, upload-time = "2025-10-21T16:22:26.016Z" }, - { url = "https://files.pythonhosted.org/packages/4b/a9/1be18e6055b64467440208a8559afac243c66a8b904213af6f392dc2212f/grpcio-1.76.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:490fa6d203992c47c7b9e4a9d39003a0c2bcc1c9aa3c058730884bbbb0ee9f09", size = 7176236, upload-time = "2025-10-21T16:22:28.362Z" }, - { url = "https://files.pythonhosted.org/packages/0f/55/dba05d3fcc151ce6e81327541d2cc8394f442f6b350fead67401661bf041/grpcio-1.76.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:479496325ce554792dba6548fae3df31a72cef7bad71ca2e12b0e58f9b336bfc", size = 8125795, upload-time = "2025-10-21T16:22:31.075Z" }, - { url = "https://files.pythonhosted.org/packages/4a/45/122df922d05655f63930cf42c9e3f72ba20aadb26c100ee105cad4ce4257/grpcio-1.76.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:1c9b93f79f48b03ada57ea24725d83a30284a012ec27eab2cf7e50a550cbbbcc", size = 7592214, upload-time = "2025-10-21T16:22:33.831Z" }, - { url = "https://files.pythonhosted.org/packages/4a/6e/0b899b7f6b66e5af39e377055fb4a6675c9ee28431df5708139df2e93233/grpcio-1.76.0-cp314-cp314-win32.whl", hash = "sha256:747fa73efa9b8b1488a95d0ba1039c8e2dca0f741612d80415b1e1c560febf4e", size = 4062961, upload-time = "2025-10-21T16:22:36.468Z" }, - { url = "https://files.pythonhosted.org/packages/19/41/0b430b01a2eb38ee887f88c1f07644a1df8e289353b78e82b37ef988fb64/grpcio-1.76.0-cp314-cp314-win_amd64.whl", hash = "sha256:922fa70ba549fce362d2e2871ab542082d66e2aaf0c19480ea453905b01f384e", size = 4834462, upload-time = "2025-10-21T16:22:39.772Z" }, -] - -[[package]] -name = "grpcio-status" -version = "1.76.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "googleapis-common-protos" }, - { name = "grpcio" }, - { name = "protobuf" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/3f/46/e9f19d5be65e8423f886813a2a9d0056ba94757b0c5007aa59aed1a961fa/grpcio_status-1.76.0.tar.gz", hash = "sha256:25fcbfec74c15d1a1cb5da3fab8ee9672852dc16a5a9eeb5baf7d7a9952943cd", size = 13679, upload-time = "2025-10-21T16:28:52.545Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/8c/cc/27ba60ad5a5f2067963e6a858743500df408eb5855e98be778eaef8c9b02/grpcio_status-1.76.0-py3-none-any.whl", hash = "sha256:380568794055a8efbbd8871162df92012e0228a5f6dffaf57f2a00c534103b18", size = 14425, upload-time = "2025-10-21T16:28:40.853Z" }, +[package.metadata.requires-dev] +dev = [ + { name = "pre-commit", specifier = ">=4.5.1" }, + { name = "pytest" }, + { name = "pytest-asyncio" }, + { name = "ruff", specifier = ">=0.14.6" }, + { name = "typer", specifier = ">=0.24.1" }, ] [[package]] @@ -765,6 +535,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" }, ] +[[package]] +name = "identify" +version = "2.6.17" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/57/84/376a3b96e5a8d33a7aa2c5b3b31a4b3c364117184bf0b17418055f6ace66/identify-2.6.17.tar.gz", hash = "sha256:f816b0b596b204c9fdf076ded172322f2723cf958d02f9c3587504834c8ff04d", size = 99579, upload-time = "2026-03-01T20:04:12.702Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/40/66/71c1227dff78aaeb942fed29dd5651f2aec166cc7c9aeea3e8b26a539b7d/identify-2.6.17-py2.py3-none-any.whl", hash = "sha256:be5f8412d5ed4b20f2bd41a65f920990bdccaa6a4a18a08f1eefdcd0bdd885f0", size = 99382, upload-time = "2026-03-01T20:04:11.439Z" }, +] + [[package]] name = "idna" version = "3.11" @@ -774,6 +553,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", size = 71008, upload-time = "2025-10-12T14:55:18.883Z" }, ] +[[package]] +name = "importlib-metadata" +version = "8.7.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "zipp" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f3/49/3b30cad09e7771a4982d9975a8cbf64f00d4a1ececb53297f1d9a7be1b10/importlib_metadata-8.7.1.tar.gz", hash = "sha256:49fef1ae6440c182052f407c8d34a68f72efc36db9ca90dc0113398f2fdde8bb", size = 57107, upload-time = "2025-12-21T10:00:19.278Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fa/5e/f8e9a1d23b9c20a551a8a02ea3637b4642e22c2626e3a13a9a29cdea99eb/importlib_metadata-8.7.1-py3-none-any.whl", hash = "sha256:5a1f80bf1daa489495071efbb095d75a634cf28a8bc299581244063b53176151", size = 27865, upload-time = "2025-12-21T10:00:18.329Z" }, +] + [[package]] name = "iniconfig" version = "2.3.0" @@ -784,120 +575,136 @@ wheels = [ ] [[package]] -name = "multidict" -version = "6.7.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/80/1e/5492c365f222f907de1039b91f922b93fa4f764c713ee858d235495d8f50/multidict-6.7.0.tar.gz", hash = "sha256:c6e99d9a65ca282e578dfea819cfa9c0a62b2499d8677392e09feaf305e9e6f5", size = 101834, upload-time = "2025-10-06T14:52:30.657Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/34/9e/5c727587644d67b2ed479041e4b1c58e30afc011e3d45d25bbe35781217c/multidict-6.7.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4d409aa42a94c0b3fa617708ef5276dfe81012ba6753a0370fcc9d0195d0a1fc", size = 76604, upload-time = "2025-10-06T14:48:54.277Z" }, - { url = "https://files.pythonhosted.org/packages/17/e4/67b5c27bd17c085a5ea8f1ec05b8a3e5cba0ca734bfcad5560fb129e70ca/multidict-6.7.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:14c9e076eede3b54c636f8ce1c9c252b5f057c62131211f0ceeec273810c9721", size = 44715, upload-time = "2025-10-06T14:48:55.445Z" }, - { url = "https://files.pythonhosted.org/packages/4d/e1/866a5d77be6ea435711bef2a4291eed11032679b6b28b56b4776ab06ba3e/multidict-6.7.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4c09703000a9d0fa3c3404b27041e574cc7f4df4c6563873246d0e11812a94b6", size = 44332, upload-time = "2025-10-06T14:48:56.706Z" }, - { url = "https://files.pythonhosted.org/packages/31/61/0c2d50241ada71ff61a79518db85ada85fdabfcf395d5968dae1cbda04e5/multidict-6.7.0-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:a265acbb7bb33a3a2d626afbe756371dce0279e7b17f4f4eda406459c2b5ff1c", size = 245212, upload-time = "2025-10-06T14:48:58.042Z" }, - { url = "https://files.pythonhosted.org/packages/ac/e0/919666a4e4b57fff1b57f279be1c9316e6cdc5de8a8b525d76f6598fefc7/multidict-6.7.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:51cb455de290ae462593e5b1cb1118c5c22ea7f0d3620d9940bf695cea5a4bd7", size = 246671, upload-time = "2025-10-06T14:49:00.004Z" }, - { url = "https://files.pythonhosted.org/packages/a1/cc/d027d9c5a520f3321b65adea289b965e7bcbd2c34402663f482648c716ce/multidict-6.7.0-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:db99677b4457c7a5c5a949353e125ba72d62b35f74e26da141530fbb012218a7", size = 225491, upload-time = "2025-10-06T14:49:01.393Z" }, - { url = "https://files.pythonhosted.org/packages/75/c4/bbd633980ce6155a28ff04e6a6492dd3335858394d7bb752d8b108708558/multidict-6.7.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f470f68adc395e0183b92a2f4689264d1ea4b40504a24d9882c27375e6662bb9", size = 257322, upload-time = "2025-10-06T14:49:02.745Z" }, - { url = "https://files.pythonhosted.org/packages/4c/6d/d622322d344f1f053eae47e033b0b3f965af01212de21b10bcf91be991fb/multidict-6.7.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0db4956f82723cc1c270de9c6e799b4c341d327762ec78ef82bb962f79cc07d8", size = 254694, upload-time = "2025-10-06T14:49:04.15Z" }, - { url = "https://files.pythonhosted.org/packages/a8/9f/78f8761c2705d4c6d7516faed63c0ebdac569f6db1bef95e0d5218fdc146/multidict-6.7.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3e56d780c238f9e1ae66a22d2adf8d16f485381878250db8d496623cd38b22bd", size = 246715, upload-time = "2025-10-06T14:49:05.967Z" }, - { url = "https://files.pythonhosted.org/packages/78/59/950818e04f91b9c2b95aab3d923d9eabd01689d0dcd889563988e9ea0fd8/multidict-6.7.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9d14baca2ee12c1a64740d4531356ba50b82543017f3ad6de0deb943c5979abb", size = 243189, upload-time = "2025-10-06T14:49:07.37Z" }, - { url = "https://files.pythonhosted.org/packages/7a/3d/77c79e1934cad2ee74991840f8a0110966d9599b3af95964c0cd79bb905b/multidict-6.7.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:295a92a76188917c7f99cda95858c822f9e4aae5824246bba9b6b44004ddd0a6", size = 237845, upload-time = "2025-10-06T14:49:08.759Z" }, - { url = "https://files.pythonhosted.org/packages/63/1b/834ce32a0a97a3b70f86437f685f880136677ac00d8bce0027e9fd9c2db7/multidict-6.7.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:39f1719f57adbb767ef592a50ae5ebb794220d1188f9ca93de471336401c34d2", size = 246374, upload-time = "2025-10-06T14:49:10.574Z" }, - { url = "https://files.pythonhosted.org/packages/23/ef/43d1c3ba205b5dec93dc97f3fba179dfa47910fc73aaaea4f7ceb41cec2a/multidict-6.7.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:0a13fb8e748dfc94749f622de065dd5c1def7e0d2216dba72b1d8069a389c6ff", size = 253345, upload-time = "2025-10-06T14:49:12.331Z" }, - { url = "https://files.pythonhosted.org/packages/6b/03/eaf95bcc2d19ead522001f6a650ef32811aa9e3624ff0ad37c445c7a588c/multidict-6.7.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:e3aa16de190d29a0ea1b48253c57d99a68492c8dd8948638073ab9e74dc9410b", size = 246940, upload-time = "2025-10-06T14:49:13.821Z" }, - { url = "https://files.pythonhosted.org/packages/e8/df/ec8a5fd66ea6cd6f525b1fcbb23511b033c3e9bc42b81384834ffa484a62/multidict-6.7.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a048ce45dcdaaf1defb76b2e684f997fb5abf74437b6cb7b22ddad934a964e34", size = 242229, upload-time = "2025-10-06T14:49:15.603Z" }, - { url = "https://files.pythonhosted.org/packages/8a/a2/59b405d59fd39ec86d1142630e9049243015a5f5291ba49cadf3c090c541/multidict-6.7.0-cp311-cp311-win32.whl", hash = "sha256:a90af66facec4cebe4181b9e62a68be65e45ac9b52b67de9eec118701856e7ff", size = 41308, upload-time = "2025-10-06T14:49:16.871Z" }, - { url = "https://files.pythonhosted.org/packages/32/0f/13228f26f8b882c34da36efa776c3b7348455ec383bab4a66390e42963ae/multidict-6.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:95b5ffa4349df2887518bb839409bcf22caa72d82beec453216802f475b23c81", size = 46037, upload-time = "2025-10-06T14:49:18.457Z" }, - { url = "https://files.pythonhosted.org/packages/84/1f/68588e31b000535a3207fd3c909ebeec4fb36b52c442107499c18a896a2a/multidict-6.7.0-cp311-cp311-win_arm64.whl", hash = "sha256:329aa225b085b6f004a4955271a7ba9f1087e39dcb7e65f6284a988264a63912", size = 43023, upload-time = "2025-10-06T14:49:19.648Z" }, - { url = "https://files.pythonhosted.org/packages/c2/9e/9f61ac18d9c8b475889f32ccfa91c9f59363480613fc807b6e3023d6f60b/multidict-6.7.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:8a3862568a36d26e650a19bb5cbbba14b71789032aebc0423f8cc5f150730184", size = 76877, upload-time = "2025-10-06T14:49:20.884Z" }, - { url = "https://files.pythonhosted.org/packages/38/6f/614f09a04e6184f8824268fce4bc925e9849edfa654ddd59f0b64508c595/multidict-6.7.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:960c60b5849b9b4f9dcc9bea6e3626143c252c74113df2c1540aebce70209b45", size = 45467, upload-time = "2025-10-06T14:49:22.054Z" }, - { url = "https://files.pythonhosted.org/packages/b3/93/c4f67a436dd026f2e780c433277fff72be79152894d9fc36f44569cab1a6/multidict-6.7.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2049be98fb57a31b4ccf870bf377af2504d4ae35646a19037ec271e4c07998aa", size = 43834, upload-time = "2025-10-06T14:49:23.566Z" }, - { url = "https://files.pythonhosted.org/packages/7f/f5/013798161ca665e4a422afbc5e2d9e4070142a9ff8905e482139cd09e4d0/multidict-6.7.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:0934f3843a1860dd465d38895c17fce1f1cb37295149ab05cd1b9a03afacb2a7", size = 250545, upload-time = "2025-10-06T14:49:24.882Z" }, - { url = "https://files.pythonhosted.org/packages/71/2f/91dbac13e0ba94669ea5119ba267c9a832f0cb65419aca75549fcf09a3dc/multidict-6.7.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b3e34f3a1b8131ba06f1a73adab24f30934d148afcd5f5de9a73565a4404384e", size = 258305, upload-time = "2025-10-06T14:49:26.778Z" }, - { url = "https://files.pythonhosted.org/packages/ef/b0/754038b26f6e04488b48ac621f779c341338d78503fb45403755af2df477/multidict-6.7.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:efbb54e98446892590dc2458c19c10344ee9a883a79b5cec4bc34d6656e8d546", size = 242363, upload-time = "2025-10-06T14:49:28.562Z" }, - { url = "https://files.pythonhosted.org/packages/87/15/9da40b9336a7c9fa606c4cf2ed80a649dffeb42b905d4f63a1d7eb17d746/multidict-6.7.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a35c5fc61d4f51eb045061e7967cfe3123d622cd500e8868e7c0c592a09fedc4", size = 268375, upload-time = "2025-10-06T14:49:29.96Z" }, - { url = "https://files.pythonhosted.org/packages/82/72/c53fcade0cc94dfaad583105fd92b3a783af2091eddcb41a6d5a52474000/multidict-6.7.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:29fe6740ebccba4175af1b9b87bf553e9c15cd5868ee967e010efcf94e4fd0f1", size = 269346, upload-time = "2025-10-06T14:49:31.404Z" }, - { url = "https://files.pythonhosted.org/packages/0d/e2/9baffdae21a76f77ef8447f1a05a96ec4bc0a24dae08767abc0a2fe680b8/multidict-6.7.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:123e2a72e20537add2f33a79e605f6191fba2afda4cbb876e35c1a7074298a7d", size = 256107, upload-time = "2025-10-06T14:49:32.974Z" }, - { url = "https://files.pythonhosted.org/packages/3c/06/3f06f611087dc60d65ef775f1fb5aca7c6d61c6db4990e7cda0cef9b1651/multidict-6.7.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b284e319754366c1aee2267a2036248b24eeb17ecd5dc16022095e747f2f4304", size = 253592, upload-time = "2025-10-06T14:49:34.52Z" }, - { url = "https://files.pythonhosted.org/packages/20/24/54e804ec7945b6023b340c412ce9c3f81e91b3bf5fa5ce65558740141bee/multidict-6.7.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:803d685de7be4303b5a657b76e2f6d1240e7e0a8aa2968ad5811fa2285553a12", size = 251024, upload-time = "2025-10-06T14:49:35.956Z" }, - { url = "https://files.pythonhosted.org/packages/14/48/011cba467ea0b17ceb938315d219391d3e421dfd35928e5dbdc3f4ae76ef/multidict-6.7.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c04a328260dfd5db8c39538f999f02779012268f54614902d0afc775d44e0a62", size = 251484, upload-time = "2025-10-06T14:49:37.631Z" }, - { url = "https://files.pythonhosted.org/packages/0d/2f/919258b43bb35b99fa127435cfb2d91798eb3a943396631ef43e3720dcf4/multidict-6.7.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:8a19cdb57cd3df4cd865849d93ee14920fb97224300c88501f16ecfa2604b4e0", size = 263579, upload-time = "2025-10-06T14:49:39.502Z" }, - { url = "https://files.pythonhosted.org/packages/31/22/a0e884d86b5242b5a74cf08e876bdf299e413016b66e55511f7a804a366e/multidict-6.7.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9b2fd74c52accced7e75de26023b7dccee62511a600e62311b918ec5c168fc2a", size = 259654, upload-time = "2025-10-06T14:49:41.32Z" }, - { url = "https://files.pythonhosted.org/packages/b2/e5/17e10e1b5c5f5a40f2fcbb45953c9b215f8a4098003915e46a93f5fcaa8f/multidict-6.7.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3e8bfdd0e487acf992407a140d2589fe598238eaeffa3da8448d63a63cd363f8", size = 251511, upload-time = "2025-10-06T14:49:46.021Z" }, - { url = "https://files.pythonhosted.org/packages/e3/9a/201bb1e17e7af53139597069c375e7b0dcbd47594604f65c2d5359508566/multidict-6.7.0-cp312-cp312-win32.whl", hash = "sha256:dd32a49400a2c3d52088e120ee00c1e3576cbff7e10b98467962c74fdb762ed4", size = 41895, upload-time = "2025-10-06T14:49:48.718Z" }, - { url = "https://files.pythonhosted.org/packages/46/e2/348cd32faad84eaf1d20cce80e2bb0ef8d312c55bca1f7fa9865e7770aaf/multidict-6.7.0-cp312-cp312-win_amd64.whl", hash = "sha256:92abb658ef2d7ef22ac9f8bb88e8b6c3e571671534e029359b6d9e845923eb1b", size = 46073, upload-time = "2025-10-06T14:49:50.28Z" }, - { url = "https://files.pythonhosted.org/packages/25/ec/aad2613c1910dce907480e0c3aa306905830f25df2e54ccc9dea450cb5aa/multidict-6.7.0-cp312-cp312-win_arm64.whl", hash = "sha256:490dab541a6a642ce1a9d61a4781656b346a55c13038f0b1244653828e3a83ec", size = 43226, upload-time = "2025-10-06T14:49:52.304Z" }, - { url = "https://files.pythonhosted.org/packages/d2/86/33272a544eeb36d66e4d9a920602d1a2f57d4ebea4ef3cdfe5a912574c95/multidict-6.7.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:bee7c0588aa0076ce77c0ea5d19a68d76ad81fcd9fe8501003b9a24f9d4000f6", size = 76135, upload-time = "2025-10-06T14:49:54.26Z" }, - { url = "https://files.pythonhosted.org/packages/91/1c/eb97db117a1ebe46d457a3d235a7b9d2e6dcab174f42d1b67663dd9e5371/multidict-6.7.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7ef6b61cad77091056ce0e7ce69814ef72afacb150b7ac6a3e9470def2198159", size = 45117, upload-time = "2025-10-06T14:49:55.82Z" }, - { url = "https://files.pythonhosted.org/packages/f1/d8/6c3442322e41fb1dd4de8bd67bfd11cd72352ac131f6368315617de752f1/multidict-6.7.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9c0359b1ec12b1d6849c59f9d319610b7f20ef990a6d454ab151aa0e3b9f78ca", size = 43472, upload-time = "2025-10-06T14:49:57.048Z" }, - { url = "https://files.pythonhosted.org/packages/75/3f/e2639e80325af0b6c6febdf8e57cc07043ff15f57fa1ef808f4ccb5ac4cd/multidict-6.7.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:cd240939f71c64bd658f186330603aac1a9a81bf6273f523fca63673cb7378a8", size = 249342, upload-time = "2025-10-06T14:49:58.368Z" }, - { url = "https://files.pythonhosted.org/packages/5d/cc/84e0585f805cbeaa9cbdaa95f9a3d6aed745b9d25700623ac89a6ecff400/multidict-6.7.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a60a4d75718a5efa473ebd5ab685786ba0c67b8381f781d1be14da49f1a2dc60", size = 257082, upload-time = "2025-10-06T14:49:59.89Z" }, - { url = "https://files.pythonhosted.org/packages/b0/9c/ac851c107c92289acbbf5cfb485694084690c1b17e555f44952c26ddc5bd/multidict-6.7.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:53a42d364f323275126aff81fb67c5ca1b7a04fda0546245730a55c8c5f24bc4", size = 240704, upload-time = "2025-10-06T14:50:01.485Z" }, - { url = "https://files.pythonhosted.org/packages/50/cc/5f93e99427248c09da95b62d64b25748a5f5c98c7c2ab09825a1d6af0e15/multidict-6.7.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3b29b980d0ddbecb736735ee5bef69bb2ddca56eff603c86f3f29a1128299b4f", size = 266355, upload-time = "2025-10-06T14:50:02.955Z" }, - { url = "https://files.pythonhosted.org/packages/ec/0c/2ec1d883ceb79c6f7f6d7ad90c919c898f5d1c6ea96d322751420211e072/multidict-6.7.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f8a93b1c0ed2d04b97a5e9336fd2d33371b9a6e29ab7dd6503d63407c20ffbaf", size = 267259, upload-time = "2025-10-06T14:50:04.446Z" }, - { url = "https://files.pythonhosted.org/packages/c6/2d/f0b184fa88d6630aa267680bdb8623fb69cb0d024b8c6f0d23f9a0f406d3/multidict-6.7.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9ff96e8815eecacc6645da76c413eb3b3d34cfca256c70b16b286a687d013c32", size = 254903, upload-time = "2025-10-06T14:50:05.98Z" }, - { url = "https://files.pythonhosted.org/packages/06/c9/11ea263ad0df7dfabcad404feb3c0dd40b131bc7f232d5537f2fb1356951/multidict-6.7.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7516c579652f6a6be0e266aec0acd0db80829ca305c3d771ed898538804c2036", size = 252365, upload-time = "2025-10-06T14:50:07.511Z" }, - { url = "https://files.pythonhosted.org/packages/41/88/d714b86ee2c17d6e09850c70c9d310abac3d808ab49dfa16b43aba9d53fd/multidict-6.7.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:040f393368e63fb0f3330e70c26bfd336656bed925e5cbe17c9da839a6ab13ec", size = 250062, upload-time = "2025-10-06T14:50:09.074Z" }, - { url = "https://files.pythonhosted.org/packages/15/fe/ad407bb9e818c2b31383f6131ca19ea7e35ce93cf1310fce69f12e89de75/multidict-6.7.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b3bc26a951007b1057a1c543af845f1c7e3e71cc240ed1ace7bf4484aa99196e", size = 249683, upload-time = "2025-10-06T14:50:10.714Z" }, - { url = "https://files.pythonhosted.org/packages/8c/a4/a89abdb0229e533fb925e7c6e5c40201c2873efebc9abaf14046a4536ee6/multidict-6.7.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:7b022717c748dd1992a83e219587aabe45980d88969f01b316e78683e6285f64", size = 261254, upload-time = "2025-10-06T14:50:12.28Z" }, - { url = "https://files.pythonhosted.org/packages/8d/aa/0e2b27bd88b40a4fb8dc53dd74eecac70edaa4c1dd0707eb2164da3675b3/multidict-6.7.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:9600082733859f00d79dee64effc7aef1beb26adb297416a4ad2116fd61374bd", size = 257967, upload-time = "2025-10-06T14:50:14.16Z" }, - { url = "https://files.pythonhosted.org/packages/d0/8e/0c67b7120d5d5f6d874ed85a085f9dc770a7f9d8813e80f44a9fec820bb7/multidict-6.7.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:94218fcec4d72bc61df51c198d098ce2b378e0ccbac41ddbed5ef44092913288", size = 250085, upload-time = "2025-10-06T14:50:15.639Z" }, - { url = "https://files.pythonhosted.org/packages/ba/55/b73e1d624ea4b8fd4dd07a3bb70f6e4c7c6c5d9d640a41c6ffe5cdbd2a55/multidict-6.7.0-cp313-cp313-win32.whl", hash = "sha256:a37bd74c3fa9d00be2d7b8eca074dc56bd8077ddd2917a839bd989612671ed17", size = 41713, upload-time = "2025-10-06T14:50:17.066Z" }, - { url = "https://files.pythonhosted.org/packages/32/31/75c59e7d3b4205075b4c183fa4ca398a2daf2303ddf616b04ae6ef55cffe/multidict-6.7.0-cp313-cp313-win_amd64.whl", hash = "sha256:30d193c6cc6d559db42b6bcec8a5d395d34d60c9877a0b71ecd7c204fcf15390", size = 45915, upload-time = "2025-10-06T14:50:18.264Z" }, - { url = "https://files.pythonhosted.org/packages/31/2a/8987831e811f1184c22bc2e45844934385363ee61c0a2dcfa8f71b87e608/multidict-6.7.0-cp313-cp313-win_arm64.whl", hash = "sha256:ea3334cabe4d41b7ccd01e4d349828678794edbc2d3ae97fc162a3312095092e", size = 43077, upload-time = "2025-10-06T14:50:19.853Z" }, - { url = "https://files.pythonhosted.org/packages/e8/68/7b3a5170a382a340147337b300b9eb25a9ddb573bcdfff19c0fa3f31ffba/multidict-6.7.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:ad9ce259f50abd98a1ca0aa6e490b58c316a0fce0617f609723e40804add2c00", size = 83114, upload-time = "2025-10-06T14:50:21.223Z" }, - { url = "https://files.pythonhosted.org/packages/55/5c/3fa2d07c84df4e302060f555bbf539310980362236ad49f50eeb0a1c1eb9/multidict-6.7.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:07f5594ac6d084cbb5de2df218d78baf55ef150b91f0ff8a21cc7a2e3a5a58eb", size = 48442, upload-time = "2025-10-06T14:50:22.871Z" }, - { url = "https://files.pythonhosted.org/packages/fc/56/67212d33239797f9bd91962bb899d72bb0f4c35a8652dcdb8ed049bef878/multidict-6.7.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:0591b48acf279821a579282444814a2d8d0af624ae0bc600aa4d1b920b6e924b", size = 46885, upload-time = "2025-10-06T14:50:24.258Z" }, - { url = "https://files.pythonhosted.org/packages/46/d1/908f896224290350721597a61a69cd19b89ad8ee0ae1f38b3f5cd12ea2ac/multidict-6.7.0-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:749a72584761531d2b9467cfbdfd29487ee21124c304c4b6cb760d8777b27f9c", size = 242588, upload-time = "2025-10-06T14:50:25.716Z" }, - { url = "https://files.pythonhosted.org/packages/ab/67/8604288bbd68680eee0ab568fdcb56171d8b23a01bcd5cb0c8fedf6e5d99/multidict-6.7.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b4c3d199f953acd5b446bf7c0de1fe25d94e09e79086f8dc2f48a11a129cdf1", size = 249966, upload-time = "2025-10-06T14:50:28.192Z" }, - { url = "https://files.pythonhosted.org/packages/20/33/9228d76339f1ba51e3efef7da3ebd91964d3006217aae13211653193c3ff/multidict-6.7.0-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:9fb0211dfc3b51efea2f349ec92c114d7754dd62c01f81c3e32b765b70c45c9b", size = 228618, upload-time = "2025-10-06T14:50:29.82Z" }, - { url = "https://files.pythonhosted.org/packages/f8/2d/25d9b566d10cab1c42b3b9e5b11ef79c9111eaf4463b8c257a3bd89e0ead/multidict-6.7.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a027ec240fe73a8d6281872690b988eed307cd7d91b23998ff35ff577ca688b5", size = 257539, upload-time = "2025-10-06T14:50:31.731Z" }, - { url = "https://files.pythonhosted.org/packages/b6/b1/8d1a965e6637fc33de3c0d8f414485c2b7e4af00f42cab3d84e7b955c222/multidict-6.7.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d1d964afecdf3a8288789df2f5751dc0a8261138c3768d9af117ed384e538fad", size = 256345, upload-time = "2025-10-06T14:50:33.26Z" }, - { url = "https://files.pythonhosted.org/packages/ba/0c/06b5a8adbdeedada6f4fb8d8f193d44a347223b11939b42953eeb6530b6b/multidict-6.7.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:caf53b15b1b7df9fbd0709aa01409000a2b4dd03a5f6f5cc548183c7c8f8b63c", size = 247934, upload-time = "2025-10-06T14:50:34.808Z" }, - { url = "https://files.pythonhosted.org/packages/8f/31/b2491b5fe167ca044c6eb4b8f2c9f3b8a00b24c432c365358eadac5d7625/multidict-6.7.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:654030da3197d927f05a536a66186070e98765aa5142794c9904555d3a9d8fb5", size = 245243, upload-time = "2025-10-06T14:50:36.436Z" }, - { url = "https://files.pythonhosted.org/packages/61/1a/982913957cb90406c8c94f53001abd9eafc271cb3e70ff6371590bec478e/multidict-6.7.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:2090d3718829d1e484706a2f525e50c892237b2bf9b17a79b059cb98cddc2f10", size = 235878, upload-time = "2025-10-06T14:50:37.953Z" }, - { url = "https://files.pythonhosted.org/packages/be/c0/21435d804c1a1cf7a2608593f4d19bca5bcbd7a81a70b253fdd1c12af9c0/multidict-6.7.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:2d2cfeec3f6f45651b3d408c4acec0ebf3daa9bc8a112a084206f5db5d05b754", size = 243452, upload-time = "2025-10-06T14:50:39.574Z" }, - { url = "https://files.pythonhosted.org/packages/54/0a/4349d540d4a883863191be6eb9a928846d4ec0ea007d3dcd36323bb058ac/multidict-6.7.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:4ef089f985b8c194d341eb2c24ae6e7408c9a0e2e5658699c92f497437d88c3c", size = 252312, upload-time = "2025-10-06T14:50:41.612Z" }, - { url = "https://files.pythonhosted.org/packages/26/64/d5416038dbda1488daf16b676e4dbfd9674dde10a0cc8f4fc2b502d8125d/multidict-6.7.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:e93a0617cd16998784bf4414c7e40f17a35d2350e5c6f0bd900d3a8e02bd3762", size = 246935, upload-time = "2025-10-06T14:50:43.972Z" }, - { url = "https://files.pythonhosted.org/packages/9f/8c/8290c50d14e49f35e0bd4abc25e1bc7711149ca9588ab7d04f886cdf03d9/multidict-6.7.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f0feece2ef8ebc42ed9e2e8c78fc4aa3cf455733b507c09ef7406364c94376c6", size = 243385, upload-time = "2025-10-06T14:50:45.648Z" }, - { url = "https://files.pythonhosted.org/packages/ef/a0/f83ae75e42d694b3fbad3e047670e511c138be747bc713cf1b10d5096416/multidict-6.7.0-cp313-cp313t-win32.whl", hash = "sha256:19a1d55338ec1be74ef62440ca9e04a2f001a04d0cc49a4983dc320ff0f3212d", size = 47777, upload-time = "2025-10-06T14:50:47.154Z" }, - { url = "https://files.pythonhosted.org/packages/dc/80/9b174a92814a3830b7357307a792300f42c9e94664b01dee8e457551fa66/multidict-6.7.0-cp313-cp313t-win_amd64.whl", hash = "sha256:3da4fb467498df97e986af166b12d01f05d2e04f978a9c1c680ea1988e0bc4b6", size = 53104, upload-time = "2025-10-06T14:50:48.851Z" }, - { url = "https://files.pythonhosted.org/packages/cc/28/04baeaf0428d95bb7a7bea0e691ba2f31394338ba424fb0679a9ed0f4c09/multidict-6.7.0-cp313-cp313t-win_arm64.whl", hash = "sha256:b4121773c49a0776461f4a904cdf6264c88e42218aaa8407e803ca8025872792", size = 45503, upload-time = "2025-10-06T14:50:50.16Z" }, - { url = "https://files.pythonhosted.org/packages/e2/b1/3da6934455dd4b261d4c72f897e3a5728eba81db59959f3a639245891baa/multidict-6.7.0-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:3bab1e4aff7adaa34410f93b1f8e57c4b36b9af0426a76003f441ee1d3c7e842", size = 75128, upload-time = "2025-10-06T14:50:51.92Z" }, - { url = "https://files.pythonhosted.org/packages/14/2c/f069cab5b51d175a1a2cb4ccdf7a2c2dabd58aa5bd933fa036a8d15e2404/multidict-6.7.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:b8512bac933afc3e45fb2b18da8e59b78d4f408399a960339598374d4ae3b56b", size = 44410, upload-time = "2025-10-06T14:50:53.275Z" }, - { url = "https://files.pythonhosted.org/packages/42/e2/64bb41266427af6642b6b128e8774ed84c11b80a90702c13ac0a86bb10cc/multidict-6.7.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:79dcf9e477bc65414ebfea98ffd013cb39552b5ecd62908752e0e413d6d06e38", size = 43205, upload-time = "2025-10-06T14:50:54.911Z" }, - { url = "https://files.pythonhosted.org/packages/02/68/6b086fef8a3f1a8541b9236c594f0c9245617c29841f2e0395d979485cde/multidict-6.7.0-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:31bae522710064b5cbeddaf2e9f32b1abab70ac6ac91d42572502299e9953128", size = 245084, upload-time = "2025-10-06T14:50:56.369Z" }, - { url = "https://files.pythonhosted.org/packages/15/ee/f524093232007cd7a75c1d132df70f235cfd590a7c9eaccd7ff422ef4ae8/multidict-6.7.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4a0df7ff02397bb63e2fd22af2c87dfa39e8c7f12947bc524dbdc528282c7e34", size = 252667, upload-time = "2025-10-06T14:50:57.991Z" }, - { url = "https://files.pythonhosted.org/packages/02/a5/eeb3f43ab45878f1895118c3ef157a480db58ede3f248e29b5354139c2c9/multidict-6.7.0-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:7a0222514e8e4c514660e182d5156a415c13ef0aabbd71682fc714e327b95e99", size = 233590, upload-time = "2025-10-06T14:50:59.589Z" }, - { url = "https://files.pythonhosted.org/packages/6a/1e/76d02f8270b97269d7e3dbd45644b1785bda457b474315f8cf999525a193/multidict-6.7.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2397ab4daaf2698eb51a76721e98db21ce4f52339e535725de03ea962b5a3202", size = 264112, upload-time = "2025-10-06T14:51:01.183Z" }, - { url = "https://files.pythonhosted.org/packages/76/0b/c28a70ecb58963847c2a8efe334904cd254812b10e535aefb3bcce513918/multidict-6.7.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8891681594162635948a636c9fe0ff21746aeb3dd5463f6e25d9bea3a8a39ca1", size = 261194, upload-time = "2025-10-06T14:51:02.794Z" }, - { url = "https://files.pythonhosted.org/packages/b4/63/2ab26e4209773223159b83aa32721b4021ffb08102f8ac7d689c943fded1/multidict-6.7.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:18706cc31dbf402a7945916dd5cddf160251b6dab8a2c5f3d6d5a55949f676b3", size = 248510, upload-time = "2025-10-06T14:51:04.724Z" }, - { url = "https://files.pythonhosted.org/packages/93/cd/06c1fa8282af1d1c46fd55c10a7930af652afdce43999501d4d68664170c/multidict-6.7.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:f844a1bbf1d207dd311a56f383f7eda2d0e134921d45751842d8235e7778965d", size = 248395, upload-time = "2025-10-06T14:51:06.306Z" }, - { url = "https://files.pythonhosted.org/packages/99/ac/82cb419dd6b04ccf9e7e61befc00c77614fc8134362488b553402ecd55ce/multidict-6.7.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:d4393e3581e84e5645506923816b9cc81f5609a778c7e7534054091acc64d1c6", size = 239520, upload-time = "2025-10-06T14:51:08.091Z" }, - { url = "https://files.pythonhosted.org/packages/fa/f3/a0f9bf09493421bd8716a362e0cd1d244f5a6550f5beffdd6b47e885b331/multidict-6.7.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:fbd18dc82d7bf274b37aa48d664534330af744e03bccf696d6f4c6042e7d19e7", size = 245479, upload-time = "2025-10-06T14:51:10.365Z" }, - { url = "https://files.pythonhosted.org/packages/8d/01/476d38fc73a212843f43c852b0eee266b6971f0e28329c2184a8df90c376/multidict-6.7.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:b6234e14f9314731ec45c42fc4554b88133ad53a09092cc48a88e771c125dadb", size = 258903, upload-time = "2025-10-06T14:51:12.466Z" }, - { url = "https://files.pythonhosted.org/packages/49/6d/23faeb0868adba613b817d0e69c5f15531b24d462af8012c4f6de4fa8dc3/multidict-6.7.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:08d4379f9744d8f78d98c8673c06e202ffa88296f009c71bbafe8a6bf847d01f", size = 252333, upload-time = "2025-10-06T14:51:14.48Z" }, - { url = "https://files.pythonhosted.org/packages/1e/cc/48d02ac22b30fa247f7dad82866e4b1015431092f4ba6ebc7e77596e0b18/multidict-6.7.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:9fe04da3f79387f450fd0061d4dd2e45a72749d31bf634aecc9e27f24fdc4b3f", size = 243411, upload-time = "2025-10-06T14:51:16.072Z" }, - { url = "https://files.pythonhosted.org/packages/4a/03/29a8bf5a18abf1fe34535c88adbdfa88c9fb869b5a3b120692c64abe8284/multidict-6.7.0-cp314-cp314-win32.whl", hash = "sha256:fbafe31d191dfa7c4c51f7a6149c9fb7e914dcf9ffead27dcfd9f1ae382b3885", size = 40940, upload-time = "2025-10-06T14:51:17.544Z" }, - { url = "https://files.pythonhosted.org/packages/82/16/7ed27b680791b939de138f906d5cf2b4657b0d45ca6f5dd6236fdddafb1a/multidict-6.7.0-cp314-cp314-win_amd64.whl", hash = "sha256:2f67396ec0310764b9222a1728ced1ab638f61aadc6226f17a71dd9324f9a99c", size = 45087, upload-time = "2025-10-06T14:51:18.875Z" }, - { url = "https://files.pythonhosted.org/packages/cd/3c/e3e62eb35a1950292fe39315d3c89941e30a9d07d5d2df42965ab041da43/multidict-6.7.0-cp314-cp314-win_arm64.whl", hash = "sha256:ba672b26069957ee369cfa7fc180dde1fc6f176eaf1e6beaf61fbebbd3d9c000", size = 42368, upload-time = "2025-10-06T14:51:20.225Z" }, - { url = "https://files.pythonhosted.org/packages/8b/40/cd499bd0dbc5f1136726db3153042a735fffd0d77268e2ee20d5f33c010f/multidict-6.7.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:c1dcc7524066fa918c6a27d61444d4ee7900ec635779058571f70d042d86ed63", size = 82326, upload-time = "2025-10-06T14:51:21.588Z" }, - { url = "https://files.pythonhosted.org/packages/13/8a/18e031eca251c8df76daf0288e6790561806e439f5ce99a170b4af30676b/multidict-6.7.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:27e0b36c2d388dc7b6ced3406671b401e84ad7eb0656b8f3a2f46ed0ce483718", size = 48065, upload-time = "2025-10-06T14:51:22.93Z" }, - { url = "https://files.pythonhosted.org/packages/40/71/5e6701277470a87d234e433fb0a3a7deaf3bcd92566e421e7ae9776319de/multidict-6.7.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:2a7baa46a22e77f0988e3b23d4ede5513ebec1929e34ee9495be535662c0dfe2", size = 46475, upload-time = "2025-10-06T14:51:24.352Z" }, - { url = "https://files.pythonhosted.org/packages/fe/6a/bab00cbab6d9cfb57afe1663318f72ec28289ea03fd4e8236bb78429893a/multidict-6.7.0-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:7bf77f54997a9166a2f5675d1201520586439424c2511723a7312bdb4bcc034e", size = 239324, upload-time = "2025-10-06T14:51:25.822Z" }, - { url = "https://files.pythonhosted.org/packages/2a/5f/8de95f629fc22a7769ade8b41028e3e5a822c1f8904f618d175945a81ad3/multidict-6.7.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e011555abada53f1578d63389610ac8a5400fc70ce71156b0aa30d326f1a5064", size = 246877, upload-time = "2025-10-06T14:51:27.604Z" }, - { url = "https://files.pythonhosted.org/packages/23/b4/38881a960458f25b89e9f4a4fdcb02ac101cfa710190db6e5528841e67de/multidict-6.7.0-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:28b37063541b897fd6a318007373930a75ca6d6ac7c940dbe14731ffdd8d498e", size = 225824, upload-time = "2025-10-06T14:51:29.664Z" }, - { url = "https://files.pythonhosted.org/packages/1e/39/6566210c83f8a261575f18e7144736059f0c460b362e96e9cf797a24b8e7/multidict-6.7.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:05047ada7a2fde2631a0ed706f1fd68b169a681dfe5e4cf0f8e4cb6618bbc2cd", size = 253558, upload-time = "2025-10-06T14:51:31.684Z" }, - { url = "https://files.pythonhosted.org/packages/00/a3/67f18315100f64c269f46e6c0319fa87ba68f0f64f2b8e7fd7c72b913a0b/multidict-6.7.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:716133f7d1d946a4e1b91b1756b23c088881e70ff180c24e864c26192ad7534a", size = 252339, upload-time = "2025-10-06T14:51:33.699Z" }, - { url = "https://files.pythonhosted.org/packages/c8/2a/1cb77266afee2458d82f50da41beba02159b1d6b1f7973afc9a1cad1499b/multidict-6.7.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d1bed1b467ef657f2a0ae62844a607909ef1c6889562de5e1d505f74457d0b96", size = 244895, upload-time = "2025-10-06T14:51:36.189Z" }, - { url = "https://files.pythonhosted.org/packages/dd/72/09fa7dd487f119b2eb9524946ddd36e2067c08510576d43ff68469563b3b/multidict-6.7.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:ca43bdfa5d37bd6aee89d85e1d0831fb86e25541be7e9d376ead1b28974f8e5e", size = 241862, upload-time = "2025-10-06T14:51:41.291Z" }, - { url = "https://files.pythonhosted.org/packages/65/92/bc1f8bd0853d8669300f732c801974dfc3702c3eeadae2f60cef54dc69d7/multidict-6.7.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:44b546bd3eb645fd26fb949e43c02a25a2e632e2ca21a35e2e132c8105dc8599", size = 232376, upload-time = "2025-10-06T14:51:43.55Z" }, - { url = "https://files.pythonhosted.org/packages/09/86/ac39399e5cb9d0c2ac8ef6e10a768e4d3bc933ac808d49c41f9dc23337eb/multidict-6.7.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:a6ef16328011d3f468e7ebc326f24c1445f001ca1dec335b2f8e66bed3006394", size = 240272, upload-time = "2025-10-06T14:51:45.265Z" }, - { url = "https://files.pythonhosted.org/packages/3d/b6/fed5ac6b8563ec72df6cb1ea8dac6d17f0a4a1f65045f66b6d3bf1497c02/multidict-6.7.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:5aa873cbc8e593d361ae65c68f85faadd755c3295ea2c12040ee146802f23b38", size = 248774, upload-time = "2025-10-06T14:51:46.836Z" }, - { url = "https://files.pythonhosted.org/packages/6b/8d/b954d8c0dc132b68f760aefd45870978deec6818897389dace00fcde32ff/multidict-6.7.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:3d7b6ccce016e29df4b7ca819659f516f0bc7a4b3efa3bb2012ba06431b044f9", size = 242731, upload-time = "2025-10-06T14:51:48.541Z" }, - { url = "https://files.pythonhosted.org/packages/16/9d/a2dac7009125d3540c2f54e194829ea18ac53716c61b655d8ed300120b0f/multidict-6.7.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:171b73bd4ee683d307599b66793ac80981b06f069b62eea1c9e29c9241aa66b0", size = 240193, upload-time = "2025-10-06T14:51:50.355Z" }, - { url = "https://files.pythonhosted.org/packages/39/ca/c05f144128ea232ae2178b008d5011d4e2cea86e4ee8c85c2631b1b94802/multidict-6.7.0-cp314-cp314t-win32.whl", hash = "sha256:b2d7f80c4e1fd010b07cb26820aae86b7e73b681ee4889684fb8d2d4537aab13", size = 48023, upload-time = "2025-10-06T14:51:51.883Z" }, - { url = "https://files.pythonhosted.org/packages/ba/8f/0a60e501584145588be1af5cc829265701ba3c35a64aec8e07cbb71d39bb/multidict-6.7.0-cp314-cp314t-win_amd64.whl", hash = "sha256:09929cab6fcb68122776d575e03c6cc64ee0b8fca48d17e135474b042ce515cd", size = 53507, upload-time = "2025-10-06T14:51:53.672Z" }, - { url = "https://files.pythonhosted.org/packages/7f/ae/3148b988a9c6239903e786eac19c889fab607c31d6efa7fb2147e5680f23/multidict-6.7.0-cp314-cp314t-win_arm64.whl", hash = "sha256:cc41db090ed742f32bd2d2c721861725e6109681eddf835d0a82bd3a5c382827", size = 44804, upload-time = "2025-10-06T14:51:55.415Z" }, - { url = "https://files.pythonhosted.org/packages/b7/da/7d22601b625e241d4f23ef1ebff8acfc60da633c9e7e7922e24d10f592b3/multidict-6.7.0-py3-none-any.whl", hash = "sha256:394fc5c42a333c9ffc3e421a4c85e08580d990e08b99f6bf35b4132114c5dcb3", size = 12317, upload-time = "2025-10-06T14:52:29.272Z" }, +name = "jiter" +version = "0.13.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0d/5e/4ec91646aee381d01cdb9974e30882c9cd3b8c5d1079d6b5ff4af522439a/jiter-0.13.0.tar.gz", hash = "sha256:f2839f9c2c7e2dffc1bc5929a510e14ce0a946be9365fd1219e7ef342dae14f4", size = 164847, upload-time = "2026-02-02T12:37:56.441Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/71/29/499f8c9eaa8a16751b1c0e45e6f5f1761d180da873d417996cc7bddc8eef/jiter-0.13.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:ea026e70a9a28ebbdddcbcf0f1323128a8db66898a06eaad3a4e62d2f554d096", size = 311157, upload-time = "2026-02-02T12:35:37.758Z" }, + { url = "https://files.pythonhosted.org/packages/50/f6/566364c777d2ab450b92100bea11333c64c38d32caf8dc378b48e5b20c46/jiter-0.13.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:66aa3e663840152d18cc8ff1e4faad3dd181373491b9cfdc6004b92198d67911", size = 319729, upload-time = "2026-02-02T12:35:39.246Z" }, + { url = "https://files.pythonhosted.org/packages/73/dd/560f13ec5e4f116d8ad2658781646cca91b617ae3b8758d4a5076b278f70/jiter-0.13.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c3524798e70655ff19aec58c7d05adb1f074fecff62da857ea9be2b908b6d701", size = 354766, upload-time = "2026-02-02T12:35:40.662Z" }, + { url = "https://files.pythonhosted.org/packages/7c/0d/061faffcfe94608cbc28a0d42a77a74222bdf5055ccdbe5fd2292b94f510/jiter-0.13.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ec7e287d7fbd02cb6e22f9a00dd9c9cd504c40a61f2c61e7e1f9690a82726b4c", size = 362587, upload-time = "2026-02-02T12:35:42.025Z" }, + { url = "https://files.pythonhosted.org/packages/92/c9/c66a7864982fd38a9773ec6e932e0398d1262677b8c60faecd02ffb67bf3/jiter-0.13.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:47455245307e4debf2ce6c6e65a717550a0244231240dcf3b8f7d64e4c2f22f4", size = 487537, upload-time = "2026-02-02T12:35:43.459Z" }, + { url = "https://files.pythonhosted.org/packages/6c/86/84eb4352cd3668f16d1a88929b5888a3fe0418ea8c1dfc2ad4e7bf6e069a/jiter-0.13.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ee9da221dca6e0429c2704c1b3655fe7b025204a71d4d9b73390c759d776d165", size = 373717, upload-time = "2026-02-02T12:35:44.928Z" }, + { url = "https://files.pythonhosted.org/packages/6e/09/9fe4c159358176f82d4390407a03f506a8659ed13ca3ac93a843402acecf/jiter-0.13.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24ab43126d5e05f3d53a36a8e11eb2f23304c6c1117844aaaf9a0aa5e40b5018", size = 362683, upload-time = "2026-02-02T12:35:46.636Z" }, + { url = "https://files.pythonhosted.org/packages/c9/5e/85f3ab9caca0c1d0897937d378b4a515cae9e119730563572361ea0c48ae/jiter-0.13.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9da38b4fedde4fb528c740c2564628fbab737166a0e73d6d46cb4bb5463ff411", size = 392345, upload-time = "2026-02-02T12:35:48.088Z" }, + { url = "https://files.pythonhosted.org/packages/12/4c/05b8629ad546191939e6f0c2f17e29f542a398f4a52fb987bc70b6d1eb8b/jiter-0.13.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0b34c519e17658ed88d5047999a93547f8889f3c1824120c26ad6be5f27b6cf5", size = 517775, upload-time = "2026-02-02T12:35:49.482Z" }, + { url = "https://files.pythonhosted.org/packages/4d/88/367ea2eb6bc582c7052e4baf5ddf57ebe5ab924a88e0e09830dfb585c02d/jiter-0.13.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d2a6394e6af690d462310a86b53c47ad75ac8c21dc79f120714ea449979cb1d3", size = 551325, upload-time = "2026-02-02T12:35:51.104Z" }, + { url = "https://files.pythonhosted.org/packages/f3/12/fa377ffb94a2f28c41afaed093e0d70cfe512035d5ecb0cad0ae4792d35e/jiter-0.13.0-cp311-cp311-win32.whl", hash = "sha256:0f0c065695f616a27c920a56ad0d4fc46415ef8b806bf8fc1cacf25002bd24e1", size = 204709, upload-time = "2026-02-02T12:35:52.467Z" }, + { url = "https://files.pythonhosted.org/packages/cb/16/8e8203ce92f844dfcd3d9d6a5a7322c77077248dbb12da52d23193a839cd/jiter-0.13.0-cp311-cp311-win_amd64.whl", hash = "sha256:0733312953b909688ae3c2d58d043aa040f9f1a6a75693defed7bc2cc4bf2654", size = 204560, upload-time = "2026-02-02T12:35:53.925Z" }, + { url = "https://files.pythonhosted.org/packages/44/26/97cc40663deb17b9e13c3a5cf29251788c271b18ee4d262c8f94798b8336/jiter-0.13.0-cp311-cp311-win_arm64.whl", hash = "sha256:5d9b34ad56761b3bf0fbe8f7e55468704107608512350962d3317ffd7a4382d5", size = 189608, upload-time = "2026-02-02T12:35:55.304Z" }, + { url = "https://files.pythonhosted.org/packages/2e/30/7687e4f87086829955013ca12a9233523349767f69653ebc27036313def9/jiter-0.13.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:0a2bd69fc1d902e89925fc34d1da51b2128019423d7b339a45d9e99c894e0663", size = 307958, upload-time = "2026-02-02T12:35:57.165Z" }, + { url = "https://files.pythonhosted.org/packages/c3/27/e57f9a783246ed95481e6749cc5002a8a767a73177a83c63ea71f0528b90/jiter-0.13.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f917a04240ef31898182f76a332f508f2cc4b57d2b4d7ad2dbfebbfe167eb505", size = 318597, upload-time = "2026-02-02T12:35:58.591Z" }, + { url = "https://files.pythonhosted.org/packages/cf/52/e5719a60ac5d4d7c5995461a94ad5ef962a37c8bf5b088390e6fad59b2ff/jiter-0.13.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1e2b199f446d3e82246b4fd9236d7cb502dc2222b18698ba0d986d2fecc6152", size = 348821, upload-time = "2026-02-02T12:36:00.093Z" }, + { url = "https://files.pythonhosted.org/packages/61/db/c1efc32b8ba4c740ab3fc2d037d8753f67685f475e26b9d6536a4322bcdd/jiter-0.13.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:04670992b576fa65bd056dbac0c39fe8bd67681c380cb2b48efa885711d9d726", size = 364163, upload-time = "2026-02-02T12:36:01.937Z" }, + { url = "https://files.pythonhosted.org/packages/55/8a/fb75556236047c8806995671a18e4a0ad646ed255276f51a20f32dceaeec/jiter-0.13.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5a1aff1fbdb803a376d4d22a8f63f8e7ccbce0b4890c26cc7af9e501ab339ef0", size = 483709, upload-time = "2026-02-02T12:36:03.41Z" }, + { url = "https://files.pythonhosted.org/packages/7e/16/43512e6ee863875693a8e6f6d532e19d650779d6ba9a81593ae40a9088ff/jiter-0.13.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3b3fb8c2053acaef8580809ac1d1f7481a0a0bdc012fd7f5d8b18fb696a5a089", size = 370480, upload-time = "2026-02-02T12:36:04.791Z" }, + { url = "https://files.pythonhosted.org/packages/f8/4c/09b93e30e984a187bc8aaa3510e1ec8dcbdcd71ca05d2f56aac0492453aa/jiter-0.13.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bdaba7d87e66f26a2c45d8cbadcbfc4bf7884182317907baf39cfe9775bb4d93", size = 360735, upload-time = "2026-02-02T12:36:06.994Z" }, + { url = "https://files.pythonhosted.org/packages/1a/1b/46c5e349019874ec5dfa508c14c37e29864ea108d376ae26d90bee238cd7/jiter-0.13.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7b88d649135aca526da172e48083da915ec086b54e8e73a425ba50999468cc08", size = 391814, upload-time = "2026-02-02T12:36:08.368Z" }, + { url = "https://files.pythonhosted.org/packages/15/9e/26184760e85baee7162ad37b7912797d2077718476bf91517641c92b3639/jiter-0.13.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:e404ea551d35438013c64b4f357b0474c7abf9f781c06d44fcaf7a14c69ff9e2", size = 513990, upload-time = "2026-02-02T12:36:09.993Z" }, + { url = "https://files.pythonhosted.org/packages/e9/34/2c9355247d6debad57a0a15e76ab1566ab799388042743656e566b3b7de1/jiter-0.13.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:1f4748aad1b4a93c8bdd70f604d0f748cdc0e8744c5547798acfa52f10e79228", size = 548021, upload-time = "2026-02-02T12:36:11.376Z" }, + { url = "https://files.pythonhosted.org/packages/ac/4a/9f2c23255d04a834398b9c2e0e665382116911dc4d06b795710503cdad25/jiter-0.13.0-cp312-cp312-win32.whl", hash = "sha256:0bf670e3b1445fc4d31612199f1744f67f889ee1bbae703c4b54dc097e5dd394", size = 203024, upload-time = "2026-02-02T12:36:12.682Z" }, + { url = "https://files.pythonhosted.org/packages/09/ee/f0ae675a957ae5a8f160be3e87acea6b11dc7b89f6b7ab057e77b2d2b13a/jiter-0.13.0-cp312-cp312-win_amd64.whl", hash = "sha256:15db60e121e11fe186c0b15236bd5d18381b9ddacdcf4e659feb96fc6c969c92", size = 205424, upload-time = "2026-02-02T12:36:13.93Z" }, + { url = "https://files.pythonhosted.org/packages/1b/02/ae611edf913d3cbf02c97cdb90374af2082c48d7190d74c1111dde08bcdd/jiter-0.13.0-cp312-cp312-win_arm64.whl", hash = "sha256:41f92313d17989102f3cb5dd533a02787cdb99454d494344b0361355da52fcb9", size = 186818, upload-time = "2026-02-02T12:36:15.308Z" }, + { url = "https://files.pythonhosted.org/packages/91/9c/7ee5a6ff4b9991e1a45263bfc46731634c4a2bde27dfda6c8251df2d958c/jiter-0.13.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1f8a55b848cbabf97d861495cd65f1e5c590246fabca8b48e1747c4dfc8f85bf", size = 306897, upload-time = "2026-02-02T12:36:16.748Z" }, + { url = "https://files.pythonhosted.org/packages/7c/02/be5b870d1d2be5dd6a91bdfb90f248fbb7dcbd21338f092c6b89817c3dbf/jiter-0.13.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f556aa591c00f2c45eb1b89f68f52441a016034d18b65da60e2d2875bbbf344a", size = 317507, upload-time = "2026-02-02T12:36:18.351Z" }, + { url = "https://files.pythonhosted.org/packages/da/92/b25d2ec333615f5f284f3a4024f7ce68cfa0604c322c6808b2344c7f5d2b/jiter-0.13.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f7e1d61da332ec412350463891923f960c3073cf1aae93b538f0bb4c8cd46efb", size = 350560, upload-time = "2026-02-02T12:36:19.746Z" }, + { url = "https://files.pythonhosted.org/packages/be/ec/74dcb99fef0aca9fbe56b303bf79f6bd839010cb18ad41000bf6cc71eec0/jiter-0.13.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3097d665a27bc96fd9bbf7f86178037db139f319f785e4757ce7ccbf390db6c2", size = 363232, upload-time = "2026-02-02T12:36:21.243Z" }, + { url = "https://files.pythonhosted.org/packages/1b/37/f17375e0bb2f6a812d4dd92d7616e41917f740f3e71343627da9db2824ce/jiter-0.13.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d01ecc3a8cbdb6f25a37bd500510550b64ddf9f7d64a107d92f3ccb25035d0f", size = 483727, upload-time = "2026-02-02T12:36:22.688Z" }, + { url = "https://files.pythonhosted.org/packages/77/d2/a71160a5ae1a1e66c1395b37ef77da67513b0adba73b993a27fbe47eb048/jiter-0.13.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ed9bbc30f5d60a3bdf63ae76beb3f9db280d7f195dfcfa61af792d6ce912d159", size = 370799, upload-time = "2026-02-02T12:36:24.106Z" }, + { url = "https://files.pythonhosted.org/packages/01/99/ed5e478ff0eb4e8aa5fd998f9d69603c9fd3f32de3bd16c2b1194f68361c/jiter-0.13.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98fbafb6e88256f4454de33c1f40203d09fc33ed19162a68b3b257b29ca7f663", size = 359120, upload-time = "2026-02-02T12:36:25.519Z" }, + { url = "https://files.pythonhosted.org/packages/16/be/7ffd08203277a813f732ba897352797fa9493faf8dc7995b31f3d9cb9488/jiter-0.13.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5467696f6b827f1116556cb0db620440380434591e93ecee7fd14d1a491b6daa", size = 390664, upload-time = "2026-02-02T12:36:26.866Z" }, + { url = "https://files.pythonhosted.org/packages/d1/84/e0787856196d6d346264d6dcccb01f741e5f0bd014c1d9a2ebe149caf4f3/jiter-0.13.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:2d08c9475d48b92892583df9da592a0e2ac49bcd41fae1fec4f39ba6cf107820", size = 513543, upload-time = "2026-02-02T12:36:28.217Z" }, + { url = "https://files.pythonhosted.org/packages/65/50/ecbd258181c4313cf79bca6c88fb63207d04d5bf5e4f65174114d072aa55/jiter-0.13.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:aed40e099404721d7fcaf5b89bd3b4568a4666358bcac7b6b15c09fb6252ab68", size = 547262, upload-time = "2026-02-02T12:36:29.678Z" }, + { url = "https://files.pythonhosted.org/packages/27/da/68f38d12e7111d2016cd198161b36e1f042bd115c169255bcb7ec823a3bf/jiter-0.13.0-cp313-cp313-win32.whl", hash = "sha256:36ebfbcffafb146d0e6ffb3e74d51e03d9c35ce7c625c8066cdbfc7b953bdc72", size = 200630, upload-time = "2026-02-02T12:36:31.808Z" }, + { url = "https://files.pythonhosted.org/packages/25/65/3bd1a972c9a08ecd22eb3b08a95d1941ebe6938aea620c246cf426ae09c2/jiter-0.13.0-cp313-cp313-win_amd64.whl", hash = "sha256:8d76029f077379374cf0dbc78dbe45b38dec4a2eb78b08b5194ce836b2517afc", size = 202602, upload-time = "2026-02-02T12:36:33.679Z" }, + { url = "https://files.pythonhosted.org/packages/15/fe/13bd3678a311aa67686bb303654792c48206a112068f8b0b21426eb6851e/jiter-0.13.0-cp313-cp313-win_arm64.whl", hash = "sha256:bb7613e1a427cfcb6ea4544f9ac566b93d5bf67e0d48c787eca673ff9c9dff2b", size = 185939, upload-time = "2026-02-02T12:36:35.065Z" }, + { url = "https://files.pythonhosted.org/packages/49/19/a929ec002ad3228bc97ca01dbb14f7632fffdc84a95ec92ceaf4145688ae/jiter-0.13.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:fa476ab5dd49f3bf3a168e05f89358c75a17608dbabb080ef65f96b27c19ab10", size = 316616, upload-time = "2026-02-02T12:36:36.579Z" }, + { url = "https://files.pythonhosted.org/packages/52/56/d19a9a194afa37c1728831e5fb81b7722c3de18a3109e8f282bfc23e587a/jiter-0.13.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ade8cb6ff5632a62b7dbd4757d8c5573f7a2e9ae285d6b5b841707d8363205ef", size = 346850, upload-time = "2026-02-02T12:36:38.058Z" }, + { url = "https://files.pythonhosted.org/packages/36/4a/94e831c6bf287754a8a019cb966ed39ff8be6ab78cadecf08df3bb02d505/jiter-0.13.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9950290340acc1adaded363edd94baebcee7dabdfa8bee4790794cd5cfad2af6", size = 358551, upload-time = "2026-02-02T12:36:39.417Z" }, + { url = "https://files.pythonhosted.org/packages/a2/ec/a4c72c822695fa80e55d2b4142b73f0012035d9fcf90eccc56bc060db37c/jiter-0.13.0-cp313-cp313t-win_amd64.whl", hash = "sha256:2b4972c6df33731aac0742b64fd0d18e0a69bc7d6e03108ce7d40c85fd9e3e6d", size = 201950, upload-time = "2026-02-02T12:36:40.791Z" }, + { url = "https://files.pythonhosted.org/packages/b6/00/393553ec27b824fbc29047e9c7cd4a3951d7fbe4a76743f17e44034fa4e4/jiter-0.13.0-cp313-cp313t-win_arm64.whl", hash = "sha256:701a1e77d1e593c1b435315ff625fd071f0998c5f02792038a5ca98899261b7d", size = 185852, upload-time = "2026-02-02T12:36:42.077Z" }, + { url = "https://files.pythonhosted.org/packages/6e/f5/f1997e987211f6f9bd71b8083047b316208b4aca0b529bb5f8c96c89ef3e/jiter-0.13.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:cc5223ab19fe25e2f0bf2643204ad7318896fe3729bf12fde41b77bfc4fafff0", size = 308804, upload-time = "2026-02-02T12:36:43.496Z" }, + { url = "https://files.pythonhosted.org/packages/cd/8f/5482a7677731fd44881f0204981ce2d7175db271f82cba2085dd2212e095/jiter-0.13.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:9776ebe51713acf438fd9b4405fcd86893ae5d03487546dae7f34993217f8a91", size = 318787, upload-time = "2026-02-02T12:36:45.071Z" }, + { url = "https://files.pythonhosted.org/packages/f3/b9/7257ac59778f1cd025b26a23c5520a36a424f7f1b068f2442a5b499b7464/jiter-0.13.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:879e768938e7b49b5e90b7e3fecc0dbec01b8cb89595861fb39a8967c5220d09", size = 353880, upload-time = "2026-02-02T12:36:47.365Z" }, + { url = "https://files.pythonhosted.org/packages/c3/87/719eec4a3f0841dad99e3d3604ee4cba36af4419a76f3cb0b8e2e691ad67/jiter-0.13.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:682161a67adea11e3aae9038c06c8b4a9a71023228767477d683f69903ebc607", size = 366702, upload-time = "2026-02-02T12:36:48.871Z" }, + { url = "https://files.pythonhosted.org/packages/d2/65/415f0a75cf6921e43365a1bc227c565cb949caca8b7532776e430cbaa530/jiter-0.13.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a13b68cd1cd8cc9de8f244ebae18ccb3e4067ad205220ef324c39181e23bbf66", size = 486319, upload-time = "2026-02-02T12:36:53.006Z" }, + { url = "https://files.pythonhosted.org/packages/54/a2/9e12b48e82c6bbc6081fd81abf915e1443add1b13d8fc586e1d90bb02bb8/jiter-0.13.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:87ce0f14c6c08892b610686ae8be350bf368467b6acd5085a5b65441e2bf36d2", size = 372289, upload-time = "2026-02-02T12:36:54.593Z" }, + { url = "https://files.pythonhosted.org/packages/4e/c1/e4693f107a1789a239c759a432e9afc592366f04e901470c2af89cfd28e1/jiter-0.13.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c365005b05505a90d1c47856420980d0237adf82f70c4aff7aebd3c1cc143ad", size = 360165, upload-time = "2026-02-02T12:36:56.112Z" }, + { url = "https://files.pythonhosted.org/packages/17/08/91b9ea976c1c758240614bd88442681a87672eebc3d9a6dde476874e706b/jiter-0.13.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1317fdffd16f5873e46ce27d0e0f7f4f90f0cdf1d86bf6abeaea9f63ca2c401d", size = 389634, upload-time = "2026-02-02T12:36:57.495Z" }, + { url = "https://files.pythonhosted.org/packages/18/23/58325ef99390d6d40427ed6005bf1ad54f2577866594bcf13ce55675f87d/jiter-0.13.0-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:c05b450d37ba0c9e21c77fef1f205f56bcee2330bddca68d344baebfc55ae0df", size = 514933, upload-time = "2026-02-02T12:36:58.909Z" }, + { url = "https://files.pythonhosted.org/packages/5b/25/69f1120c7c395fd276c3996bb8adefa9c6b84c12bb7111e5c6ccdcd8526d/jiter-0.13.0-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:775e10de3849d0631a97c603f996f518159272db00fdda0a780f81752255ee9d", size = 548842, upload-time = "2026-02-02T12:37:00.433Z" }, + { url = "https://files.pythonhosted.org/packages/18/05/981c9669d86850c5fbb0d9e62bba144787f9fba84546ba43d624ee27ef29/jiter-0.13.0-cp314-cp314-win32.whl", hash = "sha256:632bf7c1d28421c00dd8bbb8a3bac5663e1f57d5cd5ed962bce3c73bf62608e6", size = 202108, upload-time = "2026-02-02T12:37:01.718Z" }, + { url = "https://files.pythonhosted.org/packages/8d/96/cdcf54dd0b0341db7d25413229888a346c7130bd20820530905fdb65727b/jiter-0.13.0-cp314-cp314-win_amd64.whl", hash = "sha256:f22ef501c3f87ede88f23f9b11e608581c14f04db59b6a801f354397ae13739f", size = 204027, upload-time = "2026-02-02T12:37:03.075Z" }, + { url = "https://files.pythonhosted.org/packages/fb/f9/724bcaaab7a3cd727031fe4f6995cb86c4bd344909177c186699c8dec51a/jiter-0.13.0-cp314-cp314-win_arm64.whl", hash = "sha256:07b75fe09a4ee8e0c606200622e571e44943f47254f95e2436c8bdcaceb36d7d", size = 187199, upload-time = "2026-02-02T12:37:04.414Z" }, + { url = "https://files.pythonhosted.org/packages/62/92/1661d8b9fd6a3d7a2d89831db26fe3c1509a287d83ad7838831c7b7a5c7e/jiter-0.13.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:964538479359059a35fb400e769295d4b315ae61e4105396d355a12f7fef09f0", size = 318423, upload-time = "2026-02-02T12:37:05.806Z" }, + { url = "https://files.pythonhosted.org/packages/4f/3b/f77d342a54d4ebcd128e520fc58ec2f5b30a423b0fd26acdfc0c6fef8e26/jiter-0.13.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e104da1db1c0991b3eaed391ccd650ae8d947eab1480c733e5a3fb28d4313e40", size = 351438, upload-time = "2026-02-02T12:37:07.189Z" }, + { url = "https://files.pythonhosted.org/packages/76/b3/ba9a69f0e4209bd3331470c723c2f5509e6f0482e416b612431a5061ed71/jiter-0.13.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0e3a5f0cde8ff433b8e88e41aa40131455420fb3649a3c7abdda6145f8cb7202", size = 364774, upload-time = "2026-02-02T12:37:08.579Z" }, + { url = "https://files.pythonhosted.org/packages/b3/16/6cdb31fa342932602458dbb631bfbd47f601e03d2e4950740e0b2100b570/jiter-0.13.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:57aab48f40be1db920a582b30b116fe2435d184f77f0e4226f546794cedd9cf0", size = 487238, upload-time = "2026-02-02T12:37:10.066Z" }, + { url = "https://files.pythonhosted.org/packages/ed/b1/956cc7abaca8d95c13aa8d6c9b3f3797241c246cd6e792934cc4c8b250d2/jiter-0.13.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7772115877c53f62beeb8fd853cab692dbc04374ef623b30f997959a4c0e7e95", size = 372892, upload-time = "2026-02-02T12:37:11.656Z" }, + { url = "https://files.pythonhosted.org/packages/26/c4/97ecde8b1e74f67b8598c57c6fccf6df86ea7861ed29da84629cdbba76c4/jiter-0.13.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1211427574b17b633cfceba5040de8081e5abf114f7a7602f73d2e16f9fdaa59", size = 360309, upload-time = "2026-02-02T12:37:13.244Z" }, + { url = "https://files.pythonhosted.org/packages/4b/d7/eabe3cf46715854ccc80be2cd78dd4c36aedeb30751dbf85a1d08c14373c/jiter-0.13.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7beae3a3d3b5212d3a55d2961db3c292e02e302feb43fce6a3f7a31b90ea6dfe", size = 389607, upload-time = "2026-02-02T12:37:14.881Z" }, + { url = "https://files.pythonhosted.org/packages/df/2d/03963fc0804e6109b82decfb9974eb92df3797fe7222428cae12f8ccaa0c/jiter-0.13.0-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:e5562a0f0e90a6223b704163ea28e831bd3a9faa3512a711f031611e6b06c939", size = 514986, upload-time = "2026-02-02T12:37:16.326Z" }, + { url = "https://files.pythonhosted.org/packages/f6/6c/8c83b45eb3eb1c1e18d841fe30b4b5bc5619d781267ca9bc03e005d8fd0a/jiter-0.13.0-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:6c26a424569a59140fb51160a56df13f438a2b0967365e987889186d5fc2f6f9", size = 548756, upload-time = "2026-02-02T12:37:17.736Z" }, + { url = "https://files.pythonhosted.org/packages/47/66/eea81dfff765ed66c68fd2ed8c96245109e13c896c2a5015c7839c92367e/jiter-0.13.0-cp314-cp314t-win32.whl", hash = "sha256:24dc96eca9f84da4131cdf87a95e6ce36765c3b156fc9ae33280873b1c32d5f6", size = 201196, upload-time = "2026-02-02T12:37:19.101Z" }, + { url = "https://files.pythonhosted.org/packages/ff/32/4ac9c7a76402f8f00d00842a7f6b83b284d0cf7c1e9d4227bc95aa6d17fa/jiter-0.13.0-cp314-cp314t-win_amd64.whl", hash = "sha256:0a8d76c7524087272c8ae913f5d9d608bd839154b62c4322ef65723d2e5bb0b8", size = 204215, upload-time = "2026-02-02T12:37:20.495Z" }, + { url = "https://files.pythonhosted.org/packages/f9/8e/7def204fea9f9be8b3c21a6f2dd6c020cf56c7d5ff753e0e23ed7f9ea57e/jiter-0.13.0-cp314-cp314t-win_arm64.whl", hash = "sha256:2c26cf47e2cad140fa23b6d58d435a7c0161f5c514284802f25e87fddfe11024", size = 187152, upload-time = "2026-02-02T12:37:22.124Z" }, + { url = "https://files.pythonhosted.org/packages/79/b3/3c29819a27178d0e461a8571fb63c6ae38be6dc36b78b3ec2876bbd6a910/jiter-0.13.0-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:b1cbfa133241d0e6bdab48dcdc2604e8ba81512f6bbd68ec3e8e1357dd3c316c", size = 307016, upload-time = "2026-02-02T12:37:42.755Z" }, + { url = "https://files.pythonhosted.org/packages/eb/ae/60993e4b07b1ac5ebe46da7aa99fdbb802eb986c38d26e3883ac0125c4e0/jiter-0.13.0-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:db367d8be9fad6e8ebbac4a7578b7af562e506211036cba2c06c3b998603c3d2", size = 305024, upload-time = "2026-02-02T12:37:44.774Z" }, + { url = "https://files.pythonhosted.org/packages/77/fa/2227e590e9cf98803db2811f172b2d6460a21539ab73006f251c66f44b14/jiter-0.13.0-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45f6f8efb2f3b0603092401dc2df79fa89ccbc027aaba4174d2d4133ed661434", size = 339337, upload-time = "2026-02-02T12:37:46.668Z" }, + { url = "https://files.pythonhosted.org/packages/2d/92/015173281f7eb96c0ef580c997da8ef50870d4f7f4c9e03c845a1d62ae04/jiter-0.13.0-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:597245258e6ad085d064780abfb23a284d418d3e61c57362d9449c6c7317ee2d", size = 346395, upload-time = "2026-02-02T12:37:48.09Z" }, + { url = "https://files.pythonhosted.org/packages/80/60/e50fa45dd7e2eae049f0ce964663849e897300433921198aef94b6ffa23a/jiter-0.13.0-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:3d744a6061afba08dd7ae375dcde870cffb14429b7477e10f67e9e6d68772a0a", size = 305169, upload-time = "2026-02-02T12:37:50.376Z" }, + { url = "https://files.pythonhosted.org/packages/d2/73/a009f41c5eed71c49bec53036c4b33555afcdee70682a18c6f66e396c039/jiter-0.13.0-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:ff732bd0a0e778f43d5009840f20b935e79087b4dc65bd36f1cd0f9b04b8ff7f", size = 303808, upload-time = "2026-02-02T12:37:52.092Z" }, + { url = "https://files.pythonhosted.org/packages/c4/10/528b439290763bff3d939268085d03382471b442f212dca4ff5f12802d43/jiter-0.13.0-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ab44b178f7981fcaea7e0a5df20e773c663d06ffda0198f1a524e91b2fde7e59", size = 337384, upload-time = "2026-02-02T12:37:53.582Z" }, + { url = "https://files.pythonhosted.org/packages/67/8a/a342b2f0251f3dac4ca17618265d93bf244a2a4d089126e81e4c1056ac50/jiter-0.13.0-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7bb00b6d26db67a05fe3e12c76edc75f32077fb51deed13822dc648fa373bc19", size = 343768, upload-time = "2026-02-02T12:37:55.055Z" }, +] + +[[package]] +name = "jmespath" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d3/59/322338183ecda247fb5d1763a6cbe46eff7222eaeebafd9fa65d4bf5cb11/jmespath-1.1.0.tar.gz", hash = "sha256:472c87d80f36026ae83c6ddd0f1d05d4e510134ed462851fd5f754c8c3cbb88d", size = 27377, upload-time = "2026-01-22T16:35:26.279Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/14/2f/967ba146e6d58cf6a652da73885f52fc68001525b4197effc174321d70b4/jmespath-1.1.0-py3-none-any.whl", hash = "sha256:a5663118de4908c91729bea0acadca56526eb2698e83de10cd116ae0f4e97c64", size = 20419, upload-time = "2026-01-22T16:35:24.919Z" }, +] + +[[package]] +name = "logfire-api" +version = "4.28.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f7/c9/f2deb23fd2ce59630dd42ea86cc6c3dc0b8e17692238406a19a220ddb5ed/logfire_api-4.28.0.tar.gz", hash = "sha256:03b7814aa792eb91498871b6a33bd912a0ed910d20d20d87131e56525cf4c221", size = 76410, upload-time = "2026-03-11T16:23:42.815Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/17/b0/b00af83be6fbdee98371802b23fa43f395fb973498c454dbd012e80f372d/logfire_api-4.28.0-py3-none-any.whl", hash = "sha256:d95714211673b64cf61f94b01704155033e6dc0f48b88b3cc312f94bbaaeeca6", size = 121457, upload-time = "2026-03-11T16:23:39.892Z" }, +] + +[[package]] +name = "markdown-it-py" +version = "4.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mdurl" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5b/f5/4ec618ed16cc4f8fb3b701563655a69816155e79e24a17b651541804721d/markdown_it_py-4.0.0.tar.gz", hash = "sha256:cb0a2b4aa34f932c007117b194e945bd74e0ec24133ceb5bac59009cda1cb9f3", size = 73070, upload-time = "2025-08-11T12:57:52.854Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl", hash = "sha256:87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147", size = 87321, upload-time = "2025-08-11T12:57:51.923Z" }, +] + +[[package]] +name = "mdurl" +version = "0.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" }, +] + +[[package]] +name = "nodeenv" +version = "1.10.0" +source = { registry = "https://pypi.org/simple" } +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/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]] @@ -982,12 +789,35 @@ wheels = [ ] [[package]] -name = "oauthlib" -version = "3.3.1" +name = "openai" +version = "2.26.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/0b/5f/19930f824ffeb0ad4372da4812c50edbd1434f678c90c2733e1188edfc63/oauthlib-3.3.1.tar.gz", hash = "sha256:0f0f8aa759826a193cf66c12ea1af1637f87b9b4622d46e866952bb022e538c9", size = 185918, upload-time = "2025-06-19T22:48:08.269Z" } +dependencies = [ + { name = "anyio" }, + { name = "distro" }, + { name = "httpx" }, + { name = "jiter" }, + { name = "pydantic" }, + { name = "sniffio" }, + { name = "tqdm" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d7/91/2a06c4e9597c338cac1e5e5a8dd6f29e1836fc229c4c523529dca387fda8/openai-2.26.0.tar.gz", hash = "sha256:b41f37c140ae0034a6e92b0c509376d907f3a66109935fba2c1b471a7c05a8fb", size = 666702, upload-time = "2026-03-05T23:17:35.874Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/be/9c/92789c596b8df838baa98fa71844d84283302f7604ed565dafe5a6b5041a/oauthlib-3.3.1-py3-none-any.whl", hash = "sha256:88119c938d2b8fb88561af5f6ee0eec8cc8d552b7bb1f712743136eb7523b7a1", size = 160065, upload-time = "2025-06-19T22:48:06.508Z" }, + { url = "https://files.pythonhosted.org/packages/c6/2e/3f73e8ca53718952222cacd0cf7eecc9db439d020f0c1fe7ae717e4e199a/openai-2.26.0-py3-none-any.whl", hash = "sha256:6151bf8f83802f036117f06cc8a57b3a4da60da9926826cc96747888b57f394f", size = 1136409, upload-time = "2026-03-05T23:17:34.072Z" }, +] + +[[package]] +name = "opentelemetry-api" +version = "1.40.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "importlib-metadata" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/2c/1d/4049a9e8698361cc1a1aa03a6c59e4fa4c71e0c0f94a30f988a6876a2ae6/opentelemetry_api-1.40.0.tar.gz", hash = "sha256:159be641c0b04d11e9ecd576906462773eb97ae1b657730f0ecf64d32071569f", size = 70851, upload-time = "2026-03-04T14:17:21.555Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5f/bf/93795954016c522008da367da292adceed71cca6ee1717e1d64c83089099/opentelemetry_api-1.40.0-py3-none-any.whl", hash = "sha256:82dd69331ae74b06f6a874704be0cfaa49a1650e1537d4a813b86ecef7d0ecf9", size = 68676, upload-time = "2026-03-04T14:17:01.24Z" }, ] [[package]] @@ -1000,138 +830,151 @@ wheels = [ ] [[package]] -name = "pluggy" -version = "1.6.0" +name = "pdfminer-six" +version = "20251230" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" } +dependencies = [ + { name = "charset-normalizer" }, + { name = "cryptography" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/46/9a/d79d8fa6d47a0338846bb558b39b9963b8eb2dfedec61867c138c1b17eeb/pdfminer_six-20251230.tar.gz", hash = "sha256:e8f68a14c57e00c2d7276d26519ea64be1b48f91db1cdc776faa80528ca06c1e", size = 8511285, upload-time = "2025-12-30T15:49:13.104Z" } 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" }, + { url = "https://files.pythonhosted.org/packages/65/d7/b288ea32deb752a09aab73c75e1e7572ab2a2b56c3124a5d1eb24c62ceb3/pdfminer_six-20251230-py3-none-any.whl", hash = "sha256:9ff2e3466a7dfc6de6fd779478850b6b7c2d9e9405aa2a5869376a822771f485", size = 6591909, upload-time = "2025-12-30T15:49:10.76Z" }, ] [[package]] -name = "propcache" -version = "0.4.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/9e/da/e9fc233cf63743258bff22b3dfa7ea5baef7b5bc324af47a0ad89b8ffc6f/propcache-0.4.1.tar.gz", hash = "sha256:f48107a8c637e80362555f37ecf49abe20370e557cc4ab374f04ec4423c97c3d", size = 46442, upload-time = "2025-10-08T19:49:02.291Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/8c/d4/4e2c9aaf7ac2242b9358f98dccd8f90f2605402f5afeff6c578682c2c491/propcache-0.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:60a8fda9644b7dfd5dece8c61d8a85e271cb958075bfc4e01083c148b61a7caf", size = 80208, upload-time = "2025-10-08T19:46:24.597Z" }, - { url = "https://files.pythonhosted.org/packages/c2/21/d7b68e911f9c8e18e4ae43bdbc1e1e9bbd971f8866eb81608947b6f585ff/propcache-0.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c30b53e7e6bda1d547cabb47c825f3843a0a1a42b0496087bb58d8fedf9f41b5", size = 45777, upload-time = "2025-10-08T19:46:25.733Z" }, - { url = "https://files.pythonhosted.org/packages/d3/1d/11605e99ac8ea9435651ee71ab4cb4bf03f0949586246476a25aadfec54a/propcache-0.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6918ecbd897443087a3b7cd978d56546a812517dcaaca51b49526720571fa93e", size = 47647, upload-time = "2025-10-08T19:46:27.304Z" }, - { url = "https://files.pythonhosted.org/packages/58/1a/3c62c127a8466c9c843bccb503d40a273e5cc69838805f322e2826509e0d/propcache-0.4.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3d902a36df4e5989763425a8ab9e98cd8ad5c52c823b34ee7ef307fd50582566", size = 214929, upload-time = "2025-10-08T19:46:28.62Z" }, - { url = "https://files.pythonhosted.org/packages/56/b9/8fa98f850960b367c4b8fe0592e7fc341daa7a9462e925228f10a60cf74f/propcache-0.4.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a9695397f85973bb40427dedddf70d8dc4a44b22f1650dd4af9eedf443d45165", size = 221778, upload-time = "2025-10-08T19:46:30.358Z" }, - { url = "https://files.pythonhosted.org/packages/46/a6/0ab4f660eb59649d14b3d3d65c439421cf2f87fe5dd68591cbe3c1e78a89/propcache-0.4.1-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2bb07ffd7eaad486576430c89f9b215f9e4be68c4866a96e97db9e97fead85dc", size = 228144, upload-time = "2025-10-08T19:46:32.607Z" }, - { url = "https://files.pythonhosted.org/packages/52/6a/57f43e054fb3d3a56ac9fc532bc684fc6169a26c75c353e65425b3e56eef/propcache-0.4.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fd6f30fdcf9ae2a70abd34da54f18da086160e4d7d9251f81f3da0ff84fc5a48", size = 210030, upload-time = "2025-10-08T19:46:33.969Z" }, - { url = "https://files.pythonhosted.org/packages/40/e2/27e6feebb5f6b8408fa29f5efbb765cd54c153ac77314d27e457a3e993b7/propcache-0.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:fc38cba02d1acba4e2869eef1a57a43dfbd3d49a59bf90dda7444ec2be6a5570", size = 208252, upload-time = "2025-10-08T19:46:35.309Z" }, - { url = "https://files.pythonhosted.org/packages/9e/f8/91c27b22ccda1dbc7967f921c42825564fa5336a01ecd72eb78a9f4f53c2/propcache-0.4.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:67fad6162281e80e882fb3ec355398cf72864a54069d060321f6cd0ade95fe85", size = 202064, upload-time = "2025-10-08T19:46:36.993Z" }, - { url = "https://files.pythonhosted.org/packages/f2/26/7f00bd6bd1adba5aafe5f4a66390f243acab58eab24ff1a08bebb2ef9d40/propcache-0.4.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f10207adf04d08bec185bae14d9606a1444715bc99180f9331c9c02093e1959e", size = 212429, upload-time = "2025-10-08T19:46:38.398Z" }, - { url = "https://files.pythonhosted.org/packages/84/89/fd108ba7815c1117ddca79c228f3f8a15fc82a73bca8b142eb5de13b2785/propcache-0.4.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:e9b0d8d0845bbc4cfcdcbcdbf5086886bc8157aa963c31c777ceff7846c77757", size = 216727, upload-time = "2025-10-08T19:46:39.732Z" }, - { url = "https://files.pythonhosted.org/packages/79/37/3ec3f7e3173e73f1d600495d8b545b53802cbf35506e5732dd8578db3724/propcache-0.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:981333cb2f4c1896a12f4ab92a9cc8f09ea664e9b7dbdc4eff74627af3a11c0f", size = 205097, upload-time = "2025-10-08T19:46:41.025Z" }, - { url = "https://files.pythonhosted.org/packages/61/b0/b2631c19793f869d35f47d5a3a56fb19e9160d3c119f15ac7344fc3ccae7/propcache-0.4.1-cp311-cp311-win32.whl", hash = "sha256:f1d2f90aeec838a52f1c1a32fe9a619fefd5e411721a9117fbf82aea638fe8a1", size = 38084, upload-time = "2025-10-08T19:46:42.693Z" }, - { url = "https://files.pythonhosted.org/packages/f4/78/6cce448e2098e9f3bfc91bb877f06aa24b6ccace872e39c53b2f707c4648/propcache-0.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:364426a62660f3f699949ac8c621aad6977be7126c5807ce48c0aeb8e7333ea6", size = 41637, upload-time = "2025-10-08T19:46:43.778Z" }, - { url = "https://files.pythonhosted.org/packages/9c/e9/754f180cccd7f51a39913782c74717c581b9cc8177ad0e949f4d51812383/propcache-0.4.1-cp311-cp311-win_arm64.whl", hash = "sha256:e53f3a38d3510c11953f3e6a33f205c6d1b001129f972805ca9b42fc308bc239", size = 38064, upload-time = "2025-10-08T19:46:44.872Z" }, - { url = "https://files.pythonhosted.org/packages/a2/0f/f17b1b2b221d5ca28b4b876e8bb046ac40466513960646bda8e1853cdfa2/propcache-0.4.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e153e9cd40cc8945138822807139367f256f89c6810c2634a4f6902b52d3b4e2", size = 80061, upload-time = "2025-10-08T19:46:46.075Z" }, - { url = "https://files.pythonhosted.org/packages/76/47/8ccf75935f51448ba9a16a71b783eb7ef6b9ee60f5d14c7f8a8a79fbeed7/propcache-0.4.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:cd547953428f7abb73c5ad82cbb32109566204260d98e41e5dfdc682eb7f8403", size = 46037, upload-time = "2025-10-08T19:46:47.23Z" }, - { url = "https://files.pythonhosted.org/packages/0a/b6/5c9a0e42df4d00bfb4a3cbbe5cf9f54260300c88a0e9af1f47ca5ce17ac0/propcache-0.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f048da1b4f243fc44f205dfd320933a951b8d89e0afd4c7cacc762a8b9165207", size = 47324, upload-time = "2025-10-08T19:46:48.384Z" }, - { url = "https://files.pythonhosted.org/packages/9e/d3/6c7ee328b39a81ee877c962469f1e795f9db87f925251efeb0545e0020d0/propcache-0.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ec17c65562a827bba85e3872ead335f95405ea1674860d96483a02f5c698fa72", size = 225505, upload-time = "2025-10-08T19:46:50.055Z" }, - { url = "https://files.pythonhosted.org/packages/01/5d/1c53f4563490b1d06a684742cc6076ef944bc6457df6051b7d1a877c057b/propcache-0.4.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:405aac25c6394ef275dee4c709be43745d36674b223ba4eb7144bf4d691b7367", size = 230242, upload-time = "2025-10-08T19:46:51.815Z" }, - { url = "https://files.pythonhosted.org/packages/20/e1/ce4620633b0e2422207c3cb774a0ee61cac13abc6217763a7b9e2e3f4a12/propcache-0.4.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0013cb6f8dde4b2a2f66903b8ba740bdfe378c943c4377a200551ceb27f379e4", size = 238474, upload-time = "2025-10-08T19:46:53.208Z" }, - { url = "https://files.pythonhosted.org/packages/46/4b/3aae6835b8e5f44ea6a68348ad90f78134047b503765087be2f9912140ea/propcache-0.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:15932ab57837c3368b024473a525e25d316d8353016e7cc0e5ba9eb343fbb1cf", size = 221575, upload-time = "2025-10-08T19:46:54.511Z" }, - { url = "https://files.pythonhosted.org/packages/6e/a5/8a5e8678bcc9d3a1a15b9a29165640d64762d424a16af543f00629c87338/propcache-0.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:031dce78b9dc099f4c29785d9cf5577a3faf9ebf74ecbd3c856a7b92768c3df3", size = 216736, upload-time = "2025-10-08T19:46:56.212Z" }, - { url = "https://files.pythonhosted.org/packages/f1/63/b7b215eddeac83ca1c6b934f89d09a625aa9ee4ba158338854c87210cc36/propcache-0.4.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:ab08df6c9a035bee56e31af99be621526bd237bea9f32def431c656b29e41778", size = 213019, upload-time = "2025-10-08T19:46:57.595Z" }, - { url = "https://files.pythonhosted.org/packages/57/74/f580099a58c8af587cac7ba19ee7cb418506342fbbe2d4a4401661cca886/propcache-0.4.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4d7af63f9f93fe593afbf104c21b3b15868efb2c21d07d8732c0c4287e66b6a6", size = 220376, upload-time = "2025-10-08T19:46:59.067Z" }, - { url = "https://files.pythonhosted.org/packages/c4/ee/542f1313aff7eaf19c2bb758c5d0560d2683dac001a1c96d0774af799843/propcache-0.4.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:cfc27c945f422e8b5071b6e93169679e4eb5bf73bbcbf1ba3ae3a83d2f78ebd9", size = 226988, upload-time = "2025-10-08T19:47:00.544Z" }, - { url = "https://files.pythonhosted.org/packages/8f/18/9c6b015dd9c6930f6ce2229e1f02fb35298b847f2087ea2b436a5bfa7287/propcache-0.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:35c3277624a080cc6ec6f847cbbbb5b49affa3598c4535a0a4682a697aaa5c75", size = 215615, upload-time = "2025-10-08T19:47:01.968Z" }, - { url = "https://files.pythonhosted.org/packages/80/9e/e7b85720b98c45a45e1fca6a177024934dc9bc5f4d5dd04207f216fc33ed/propcache-0.4.1-cp312-cp312-win32.whl", hash = "sha256:671538c2262dadb5ba6395e26c1731e1d52534bfe9ae56d0b5573ce539266aa8", size = 38066, upload-time = "2025-10-08T19:47:03.503Z" }, - { url = "https://files.pythonhosted.org/packages/54/09/d19cff2a5aaac632ec8fc03737b223597b1e347416934c1b3a7df079784c/propcache-0.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:cb2d222e72399fcf5890d1d5cc1060857b9b236adff2792ff48ca2dfd46c81db", size = 41655, upload-time = "2025-10-08T19:47:04.973Z" }, - { url = "https://files.pythonhosted.org/packages/68/ab/6b5c191bb5de08036a8c697b265d4ca76148efb10fa162f14af14fb5f076/propcache-0.4.1-cp312-cp312-win_arm64.whl", hash = "sha256:204483131fb222bdaaeeea9f9e6c6ed0cac32731f75dfc1d4a567fc1926477c1", size = 37789, upload-time = "2025-10-08T19:47:06.077Z" }, - { url = "https://files.pythonhosted.org/packages/bf/df/6d9c1b6ac12b003837dde8a10231a7344512186e87b36e855bef32241942/propcache-0.4.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:43eedf29202c08550aac1d14e0ee619b0430aaef78f85864c1a892294fbc28cf", size = 77750, upload-time = "2025-10-08T19:47:07.648Z" }, - { url = "https://files.pythonhosted.org/packages/8b/e8/677a0025e8a2acf07d3418a2e7ba529c9c33caf09d3c1f25513023c1db56/propcache-0.4.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:d62cdfcfd89ccb8de04e0eda998535c406bf5e060ffd56be6c586cbcc05b3311", size = 44780, upload-time = "2025-10-08T19:47:08.851Z" }, - { url = "https://files.pythonhosted.org/packages/89/a4/92380f7ca60f99ebae761936bc48a72a639e8a47b29050615eef757cb2a7/propcache-0.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cae65ad55793da34db5f54e4029b89d3b9b9490d8abe1b4c7ab5d4b8ec7ebf74", size = 46308, upload-time = "2025-10-08T19:47:09.982Z" }, - { url = "https://files.pythonhosted.org/packages/2d/48/c5ac64dee5262044348d1d78a5f85dd1a57464a60d30daee946699963eb3/propcache-0.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:333ddb9031d2704a301ee3e506dc46b1fe5f294ec198ed6435ad5b6a085facfe", size = 208182, upload-time = "2025-10-08T19:47:11.319Z" }, - { url = "https://files.pythonhosted.org/packages/c6/0c/cd762dd011a9287389a6a3eb43aa30207bde253610cca06824aeabfe9653/propcache-0.4.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:fd0858c20f078a32cf55f7e81473d96dcf3b93fd2ccdb3d40fdf54b8573df3af", size = 211215, upload-time = "2025-10-08T19:47:13.146Z" }, - { url = "https://files.pythonhosted.org/packages/30/3e/49861e90233ba36890ae0ca4c660e95df565b2cd15d4a68556ab5865974e/propcache-0.4.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:678ae89ebc632c5c204c794f8dab2837c5f159aeb59e6ed0539500400577298c", size = 218112, upload-time = "2025-10-08T19:47:14.913Z" }, - { url = "https://files.pythonhosted.org/packages/f1/8b/544bc867e24e1bd48f3118cecd3b05c694e160a168478fa28770f22fd094/propcache-0.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d472aeb4fbf9865e0c6d622d7f4d54a4e101a89715d8904282bb5f9a2f476c3f", size = 204442, upload-time = "2025-10-08T19:47:16.277Z" }, - { url = "https://files.pythonhosted.org/packages/50/a6/4282772fd016a76d3e5c0df58380a5ea64900afd836cec2c2f662d1b9bb3/propcache-0.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4d3df5fa7e36b3225954fba85589da77a0fe6a53e3976de39caf04a0db4c36f1", size = 199398, upload-time = "2025-10-08T19:47:17.962Z" }, - { url = "https://files.pythonhosted.org/packages/3e/ec/d8a7cd406ee1ddb705db2139f8a10a8a427100347bd698e7014351c7af09/propcache-0.4.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:ee17f18d2498f2673e432faaa71698032b0127ebf23ae5974eeaf806c279df24", size = 196920, upload-time = "2025-10-08T19:47:19.355Z" }, - { url = "https://files.pythonhosted.org/packages/f6/6c/f38ab64af3764f431e359f8baf9e0a21013e24329e8b85d2da32e8ed07ca/propcache-0.4.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:580e97762b950f993ae618e167e7be9256b8353c2dcd8b99ec100eb50f5286aa", size = 203748, upload-time = "2025-10-08T19:47:21.338Z" }, - { url = "https://files.pythonhosted.org/packages/d6/e3/fa846bd70f6534d647886621388f0a265254d30e3ce47e5c8e6e27dbf153/propcache-0.4.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:501d20b891688eb8e7aa903021f0b72d5a55db40ffaab27edefd1027caaafa61", size = 205877, upload-time = "2025-10-08T19:47:23.059Z" }, - { url = "https://files.pythonhosted.org/packages/e2/39/8163fc6f3133fea7b5f2827e8eba2029a0277ab2c5beee6c1db7b10fc23d/propcache-0.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9a0bd56e5b100aef69bd8562b74b46254e7c8812918d3baa700c8a8009b0af66", size = 199437, upload-time = "2025-10-08T19:47:24.445Z" }, - { url = "https://files.pythonhosted.org/packages/93/89/caa9089970ca49c7c01662bd0eeedfe85494e863e8043565aeb6472ce8fe/propcache-0.4.1-cp313-cp313-win32.whl", hash = "sha256:bcc9aaa5d80322bc2fb24bb7accb4a30f81e90ab8d6ba187aec0744bc302ad81", size = 37586, upload-time = "2025-10-08T19:47:25.736Z" }, - { url = "https://files.pythonhosted.org/packages/f5/ab/f76ec3c3627c883215b5c8080debb4394ef5a7a29be811f786415fc1e6fd/propcache-0.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:381914df18634f5494334d201e98245c0596067504b9372d8cf93f4bb23e025e", size = 40790, upload-time = "2025-10-08T19:47:26.847Z" }, - { url = "https://files.pythonhosted.org/packages/59/1b/e71ae98235f8e2ba5004d8cb19765a74877abf189bc53fc0c80d799e56c3/propcache-0.4.1-cp313-cp313-win_arm64.whl", hash = "sha256:8873eb4460fd55333ea49b7d189749ecf6e55bf85080f11b1c4530ed3034cba1", size = 37158, upload-time = "2025-10-08T19:47:27.961Z" }, - { url = "https://files.pythonhosted.org/packages/83/ce/a31bbdfc24ee0dcbba458c8175ed26089cf109a55bbe7b7640ed2470cfe9/propcache-0.4.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:92d1935ee1f8d7442da9c0c4fa7ac20d07e94064184811b685f5c4fada64553b", size = 81451, upload-time = "2025-10-08T19:47:29.445Z" }, - { url = "https://files.pythonhosted.org/packages/25/9c/442a45a470a68456e710d96cacd3573ef26a1d0a60067e6a7d5e655621ed/propcache-0.4.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:473c61b39e1460d386479b9b2f337da492042447c9b685f28be4f74d3529e566", size = 46374, upload-time = "2025-10-08T19:47:30.579Z" }, - { url = "https://files.pythonhosted.org/packages/f4/bf/b1d5e21dbc3b2e889ea4327044fb16312a736d97640fb8b6aa3f9c7b3b65/propcache-0.4.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:c0ef0aaafc66fbd87842a3fe3902fd889825646bc21149eafe47be6072725835", size = 48396, upload-time = "2025-10-08T19:47:31.79Z" }, - { url = "https://files.pythonhosted.org/packages/f4/04/5b4c54a103d480e978d3c8a76073502b18db0c4bc17ab91b3cb5092ad949/propcache-0.4.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f95393b4d66bfae908c3ca8d169d5f79cd65636ae15b5e7a4f6e67af675adb0e", size = 275950, upload-time = "2025-10-08T19:47:33.481Z" }, - { url = "https://files.pythonhosted.org/packages/b4/c1/86f846827fb969c4b78b0af79bba1d1ea2156492e1b83dea8b8a6ae27395/propcache-0.4.1-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c07fda85708bc48578467e85099645167a955ba093be0a2dcba962195676e859", size = 273856, upload-time = "2025-10-08T19:47:34.906Z" }, - { url = "https://files.pythonhosted.org/packages/36/1d/fc272a63c8d3bbad6878c336c7a7dea15e8f2d23a544bda43205dfa83ada/propcache-0.4.1-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:af223b406d6d000830c6f65f1e6431783fc3f713ba3e6cc8c024d5ee96170a4b", size = 280420, upload-time = "2025-10-08T19:47:36.338Z" }, - { url = "https://files.pythonhosted.org/packages/07/0c/01f2219d39f7e53d52e5173bcb09c976609ba30209912a0680adfb8c593a/propcache-0.4.1-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a78372c932c90ee474559c5ddfffd718238e8673c340dc21fe45c5b8b54559a0", size = 263254, upload-time = "2025-10-08T19:47:37.692Z" }, - { url = "https://files.pythonhosted.org/packages/2d/18/cd28081658ce597898f0c4d174d4d0f3c5b6d4dc27ffafeef835c95eb359/propcache-0.4.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:564d9f0d4d9509e1a870c920a89b2fec951b44bf5ba7d537a9e7c1ccec2c18af", size = 261205, upload-time = "2025-10-08T19:47:39.659Z" }, - { url = "https://files.pythonhosted.org/packages/7a/71/1f9e22eb8b8316701c2a19fa1f388c8a3185082607da8e406a803c9b954e/propcache-0.4.1-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:17612831fda0138059cc5546f4d12a2aacfb9e47068c06af35c400ba58ba7393", size = 247873, upload-time = "2025-10-08T19:47:41.084Z" }, - { url = "https://files.pythonhosted.org/packages/4a/65/3d4b61f36af2b4eddba9def857959f1016a51066b4f1ce348e0cf7881f58/propcache-0.4.1-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:41a89040cb10bd345b3c1a873b2bf36413d48da1def52f268a055f7398514874", size = 262739, upload-time = "2025-10-08T19:47:42.51Z" }, - { url = "https://files.pythonhosted.org/packages/2a/42/26746ab087faa77c1c68079b228810436ccd9a5ce9ac85e2b7307195fd06/propcache-0.4.1-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:e35b88984e7fa64aacecea39236cee32dd9bd8c55f57ba8a75cf2399553f9bd7", size = 263514, upload-time = "2025-10-08T19:47:43.927Z" }, - { url = "https://files.pythonhosted.org/packages/94/13/630690fe201f5502d2403dd3cfd451ed8858fe3c738ee88d095ad2ff407b/propcache-0.4.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6f8b465489f927b0df505cbe26ffbeed4d6d8a2bbc61ce90eb074ff129ef0ab1", size = 257781, upload-time = "2025-10-08T19:47:45.448Z" }, - { url = "https://files.pythonhosted.org/packages/92/f7/1d4ec5841505f423469efbfc381d64b7b467438cd5a4bbcbb063f3b73d27/propcache-0.4.1-cp313-cp313t-win32.whl", hash = "sha256:2ad890caa1d928c7c2965b48f3a3815c853180831d0e5503d35cf00c472f4717", size = 41396, upload-time = "2025-10-08T19:47:47.202Z" }, - { url = "https://files.pythonhosted.org/packages/48/f0/615c30622316496d2cbbc29f5985f7777d3ada70f23370608c1d3e081c1f/propcache-0.4.1-cp313-cp313t-win_amd64.whl", hash = "sha256:f7ee0e597f495cf415bcbd3da3caa3bd7e816b74d0d52b8145954c5e6fd3ff37", size = 44897, upload-time = "2025-10-08T19:47:48.336Z" }, - { url = "https://files.pythonhosted.org/packages/fd/ca/6002e46eccbe0e33dcd4069ef32f7f1c9e243736e07adca37ae8c4830ec3/propcache-0.4.1-cp313-cp313t-win_arm64.whl", hash = "sha256:929d7cbe1f01bb7baffb33dc14eb5691c95831450a26354cd210a8155170c93a", size = 39789, upload-time = "2025-10-08T19:47:49.876Z" }, - { url = "https://files.pythonhosted.org/packages/8e/5c/bca52d654a896f831b8256683457ceddd490ec18d9ec50e97dfd8fc726a8/propcache-0.4.1-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:3f7124c9d820ba5548d431afb4632301acf965db49e666aa21c305cbe8c6de12", size = 78152, upload-time = "2025-10-08T19:47:51.051Z" }, - { url = "https://files.pythonhosted.org/packages/65/9b/03b04e7d82a5f54fb16113d839f5ea1ede58a61e90edf515f6577c66fa8f/propcache-0.4.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:c0d4b719b7da33599dfe3b22d3db1ef789210a0597bc650b7cee9c77c2be8c5c", size = 44869, upload-time = "2025-10-08T19:47:52.594Z" }, - { url = "https://files.pythonhosted.org/packages/b2/fa/89a8ef0468d5833a23fff277b143d0573897cf75bd56670a6d28126c7d68/propcache-0.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:9f302f4783709a78240ebc311b793f123328716a60911d667e0c036bc5dcbded", size = 46596, upload-time = "2025-10-08T19:47:54.073Z" }, - { url = "https://files.pythonhosted.org/packages/86/bd/47816020d337f4a746edc42fe8d53669965138f39ee117414c7d7a340cfe/propcache-0.4.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c80ee5802e3fb9ea37938e7eecc307fb984837091d5fd262bb37238b1ae97641", size = 206981, upload-time = "2025-10-08T19:47:55.715Z" }, - { url = "https://files.pythonhosted.org/packages/df/f6/c5fa1357cc9748510ee55f37173eb31bfde6d94e98ccd9e6f033f2fc06e1/propcache-0.4.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ed5a841e8bb29a55fb8159ed526b26adc5bdd7e8bd7bf793ce647cb08656cdf4", size = 211490, upload-time = "2025-10-08T19:47:57.499Z" }, - { url = "https://files.pythonhosted.org/packages/80/1e/e5889652a7c4a3846683401a48f0f2e5083ce0ec1a8a5221d8058fbd1adf/propcache-0.4.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:55c72fd6ea2da4c318e74ffdf93c4fe4e926051133657459131a95c846d16d44", size = 215371, upload-time = "2025-10-08T19:47:59.317Z" }, - { url = "https://files.pythonhosted.org/packages/b2/f2/889ad4b2408f72fe1a4f6a19491177b30ea7bf1a0fd5f17050ca08cfc882/propcache-0.4.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8326e144341460402713f91df60ade3c999d601e7eb5ff8f6f7862d54de0610d", size = 201424, upload-time = "2025-10-08T19:48:00.67Z" }, - { url = "https://files.pythonhosted.org/packages/27/73/033d63069b57b0812c8bd19f311faebeceb6ba31b8f32b73432d12a0b826/propcache-0.4.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:060b16ae65bc098da7f6d25bf359f1f31f688384858204fe5d652979e0015e5b", size = 197566, upload-time = "2025-10-08T19:48:02.604Z" }, - { url = "https://files.pythonhosted.org/packages/dc/89/ce24f3dc182630b4e07aa6d15f0ff4b14ed4b9955fae95a0b54c58d66c05/propcache-0.4.1-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:89eb3fa9524f7bec9de6e83cf3faed9d79bffa560672c118a96a171a6f55831e", size = 193130, upload-time = "2025-10-08T19:48:04.499Z" }, - { url = "https://files.pythonhosted.org/packages/a9/24/ef0d5fd1a811fb5c609278d0209c9f10c35f20581fcc16f818da959fc5b4/propcache-0.4.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:dee69d7015dc235f526fe80a9c90d65eb0039103fe565776250881731f06349f", size = 202625, upload-time = "2025-10-08T19:48:06.213Z" }, - { url = "https://files.pythonhosted.org/packages/f5/02/98ec20ff5546f68d673df2f7a69e8c0d076b5abd05ca882dc7ee3a83653d/propcache-0.4.1-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:5558992a00dfd54ccbc64a32726a3357ec93825a418a401f5cc67df0ac5d9e49", size = 204209, upload-time = "2025-10-08T19:48:08.432Z" }, - { url = "https://files.pythonhosted.org/packages/a0/87/492694f76759b15f0467a2a93ab68d32859672b646aa8a04ce4864e7932d/propcache-0.4.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:c9b822a577f560fbd9554812526831712c1436d2c046cedee4c3796d3543b144", size = 197797, upload-time = "2025-10-08T19:48:09.968Z" }, - { url = "https://files.pythonhosted.org/packages/ee/36/66367de3575db1d2d3f3d177432bd14ee577a39d3f5d1b3d5df8afe3b6e2/propcache-0.4.1-cp314-cp314-win32.whl", hash = "sha256:ab4c29b49d560fe48b696cdcb127dd36e0bc2472548f3bf56cc5cb3da2b2984f", size = 38140, upload-time = "2025-10-08T19:48:11.232Z" }, - { url = "https://files.pythonhosted.org/packages/0c/2a/a758b47de253636e1b8aef181c0b4f4f204bf0dd964914fb2af90a95b49b/propcache-0.4.1-cp314-cp314-win_amd64.whl", hash = "sha256:5a103c3eb905fcea0ab98be99c3a9a5ab2de60228aa5aceedc614c0281cf6153", size = 41257, upload-time = "2025-10-08T19:48:12.707Z" }, - { url = "https://files.pythonhosted.org/packages/34/5e/63bd5896c3fec12edcbd6f12508d4890d23c265df28c74b175e1ef9f4f3b/propcache-0.4.1-cp314-cp314-win_arm64.whl", hash = "sha256:74c1fb26515153e482e00177a1ad654721bf9207da8a494a0c05e797ad27b992", size = 38097, upload-time = "2025-10-08T19:48:13.923Z" }, - { url = "https://files.pythonhosted.org/packages/99/85/9ff785d787ccf9bbb3f3106f79884a130951436f58392000231b4c737c80/propcache-0.4.1-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:824e908bce90fb2743bd6b59db36eb4f45cd350a39637c9f73b1c1ea66f5b75f", size = 81455, upload-time = "2025-10-08T19:48:15.16Z" }, - { url = "https://files.pythonhosted.org/packages/90/85/2431c10c8e7ddb1445c1f7c4b54d886e8ad20e3c6307e7218f05922cad67/propcache-0.4.1-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:c2b5e7db5328427c57c8e8831abda175421b709672f6cfc3d630c3b7e2146393", size = 46372, upload-time = "2025-10-08T19:48:16.424Z" }, - { url = "https://files.pythonhosted.org/packages/01/20/b0972d902472da9bcb683fa595099911f4d2e86e5683bcc45de60dd05dc3/propcache-0.4.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6f6ff873ed40292cd4969ef5310179afd5db59fdf055897e282485043fc80ad0", size = 48411, upload-time = "2025-10-08T19:48:17.577Z" }, - { url = "https://files.pythonhosted.org/packages/e2/e3/7dc89f4f21e8f99bad3d5ddb3a3389afcf9da4ac69e3deb2dcdc96e74169/propcache-0.4.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:49a2dc67c154db2c1463013594c458881a069fcf98940e61a0569016a583020a", size = 275712, upload-time = "2025-10-08T19:48:18.901Z" }, - { url = "https://files.pythonhosted.org/packages/20/67/89800c8352489b21a8047c773067644e3897f02ecbbd610f4d46b7f08612/propcache-0.4.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:005f08e6a0529984491e37d8dbc3dd86f84bd78a8ceb5fa9a021f4c48d4984be", size = 273557, upload-time = "2025-10-08T19:48:20.762Z" }, - { url = "https://files.pythonhosted.org/packages/e2/a1/b52b055c766a54ce6d9c16d9aca0cad8059acd9637cdf8aa0222f4a026ef/propcache-0.4.1-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5c3310452e0d31390da9035c348633b43d7e7feb2e37be252be6da45abd1abcc", size = 280015, upload-time = "2025-10-08T19:48:22.592Z" }, - { url = "https://files.pythonhosted.org/packages/48/c8/33cee30bd890672c63743049f3c9e4be087e6780906bfc3ec58528be59c1/propcache-0.4.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4c3c70630930447f9ef1caac7728c8ad1c56bc5015338b20fed0d08ea2480b3a", size = 262880, upload-time = "2025-10-08T19:48:23.947Z" }, - { url = "https://files.pythonhosted.org/packages/0c/b1/8f08a143b204b418285c88b83d00edbd61afbc2c6415ffafc8905da7038b/propcache-0.4.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8e57061305815dfc910a3634dcf584f08168a8836e6999983569f51a8544cd89", size = 260938, upload-time = "2025-10-08T19:48:25.656Z" }, - { url = "https://files.pythonhosted.org/packages/cf/12/96e4664c82ca2f31e1c8dff86afb867348979eb78d3cb8546a680287a1e9/propcache-0.4.1-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:521a463429ef54143092c11a77e04056dd00636f72e8c45b70aaa3140d639726", size = 247641, upload-time = "2025-10-08T19:48:27.207Z" }, - { url = "https://files.pythonhosted.org/packages/18/ed/e7a9cfca28133386ba52278136d42209d3125db08d0a6395f0cba0c0285c/propcache-0.4.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:120c964da3fdc75e3731aa392527136d4ad35868cc556fd09bb6d09172d9a367", size = 262510, upload-time = "2025-10-08T19:48:28.65Z" }, - { url = "https://files.pythonhosted.org/packages/f5/76/16d8bf65e8845dd62b4e2b57444ab81f07f40caa5652b8969b87ddcf2ef6/propcache-0.4.1-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:d8f353eb14ee3441ee844ade4277d560cdd68288838673273b978e3d6d2c8f36", size = 263161, upload-time = "2025-10-08T19:48:30.133Z" }, - { url = "https://files.pythonhosted.org/packages/e7/70/c99e9edb5d91d5ad8a49fa3c1e8285ba64f1476782fed10ab251ff413ba1/propcache-0.4.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ab2943be7c652f09638800905ee1bab2c544e537edb57d527997a24c13dc1455", size = 257393, upload-time = "2025-10-08T19:48:31.567Z" }, - { url = "https://files.pythonhosted.org/packages/08/02/87b25304249a35c0915d236575bc3574a323f60b47939a2262b77632a3ee/propcache-0.4.1-cp314-cp314t-win32.whl", hash = "sha256:05674a162469f31358c30bcaa8883cb7829fa3110bf9c0991fe27d7896c42d85", size = 42546, upload-time = "2025-10-08T19:48:32.872Z" }, - { url = "https://files.pythonhosted.org/packages/cb/ef/3c6ecf8b317aa982f309835e8f96987466123c6e596646d4e6a1dfcd080f/propcache-0.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:990f6b3e2a27d683cb7602ed6c86f15ee6b43b1194736f9baaeb93d0016633b1", size = 46259, upload-time = "2025-10-08T19:48:34.226Z" }, - { url = "https://files.pythonhosted.org/packages/c4/2d/346e946d4951f37eca1e4f55be0f0174c52cd70720f84029b02f296f4a38/propcache-0.4.1-cp314-cp314t-win_arm64.whl", hash = "sha256:ecef2343af4cc68e05131e45024ba34f6095821988a9d0a02aa7c73fcc448aa9", size = 40428, upload-time = "2025-10-08T19:48:35.441Z" }, - { 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 = "proto-plus" -version = "1.27.0" +name = "pdfplumber" +version = "0.11.9" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "protobuf" }, + { name = "pdfminer-six" }, + { name = "pillow" }, + { name = "pypdfium2" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/01/89/9cbe2f4bba860e149108b683bc2efec21f14d5f7ed6e25562ad86acbc373/proto_plus-1.27.0.tar.gz", hash = "sha256:873af56dd0d7e91836aee871e5799e1c6f1bda86ac9a983e0bb9f0c266a568c4", size = 56158, upload-time = "2025-12-16T13:46:25.729Z" } +sdist = { url = "https://files.pythonhosted.org/packages/38/37/9ca3519e92a8434eb93be570b131476cc0a4e840bb39c62ddb7813a39d53/pdfplumber-0.11.9.tar.gz", hash = "sha256:481224b678b2bbdbf376e2c39bf914144eef7c3d301b4a28eebf0f7f6109d6dc", size = 102768, upload-time = "2026-01-05T08:10:29.072Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8b/c8/cdbc975f5b634e249cfa6597e37c50f3078412474f21c015e508bfbfe3c3/pdfplumber-0.11.9-py3-none-any.whl", hash = "sha256:33ec5580959ba524e9100138746e090879504c42955df1b8a997604dd326c443", size = 60045, upload-time = "2026-01-05T08:10:27.512Z" }, +] + +[[package]] +name = "pillow" +version = "12.1.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1f/42/5c74462b4fd957fcd7b13b04fb3205ff8349236ea74c7c375766d6c82288/pillow-12.1.1.tar.gz", hash = "sha256:9ad8fa5937ab05218e2b6a4cff30295ad35afd2f83ac592e68c0d871bb0fdbc4", size = 46980264, upload-time = "2026-02-11T04:23:07.146Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2b/46/5da1ec4a5171ee7bf1a0efa064aba70ba3d6e0788ce3f5acd1375d23c8c0/pillow-12.1.1-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:e879bb6cd5c73848ef3b2b48b8af9ff08c5b71ecda8048b7dd22d8a33f60be32", size = 5304084, upload-time = "2026-02-11T04:20:27.501Z" }, + { url = "https://files.pythonhosted.org/packages/78/93/a29e9bc02d1cf557a834da780ceccd54e02421627200696fcf805ebdc3fb/pillow-12.1.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:365b10bb9417dd4498c0e3b128018c4a624dc11c7b97d8cc54effe3b096f4c38", size = 4657866, upload-time = "2026-02-11T04:20:29.827Z" }, + { url = "https://files.pythonhosted.org/packages/13/84/583a4558d492a179d31e4aae32eadce94b9acf49c0337c4ce0b70e0a01f2/pillow-12.1.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d4ce8e329c93845720cd2014659ca67eac35f6433fd3050393d85f3ecef0dad5", size = 6232148, upload-time = "2026-02-11T04:20:31.329Z" }, + { url = "https://files.pythonhosted.org/packages/d5/e2/53c43334bbbb2d3b938978532fbda8e62bb6e0b23a26ce8592f36bcc4987/pillow-12.1.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fc354a04072b765eccf2204f588a7a532c9511e8b9c7f900e1b64e3e33487090", size = 8038007, upload-time = "2026-02-11T04:20:34.225Z" }, + { url = "https://files.pythonhosted.org/packages/b8/a6/3d0e79c8a9d58150dd98e199d7c1c56861027f3829a3a60b3c2784190180/pillow-12.1.1-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7e7976bf1910a8116b523b9f9f58bf410f3e8aa330cd9a2bb2953f9266ab49af", size = 6345418, upload-time = "2026-02-11T04:20:35.858Z" }, + { url = "https://files.pythonhosted.org/packages/a2/c8/46dfeac5825e600579157eea177be43e2f7ff4a99da9d0d0a49533509ac5/pillow-12.1.1-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:597bd9c8419bc7c6af5604e55847789b69123bbe25d65cc6ad3012b4f3c98d8b", size = 7034590, upload-time = "2026-02-11T04:20:37.91Z" }, + { url = "https://files.pythonhosted.org/packages/af/bf/e6f65d3db8a8bbfeaf9e13cc0417813f6319863a73de934f14b2229ada18/pillow-12.1.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2c1fc0f2ca5f96a3c8407e41cca26a16e46b21060fe6d5b099d2cb01412222f5", size = 6458655, upload-time = "2026-02-11T04:20:39.496Z" }, + { url = "https://files.pythonhosted.org/packages/f9/c2/66091f3f34a25894ca129362e510b956ef26f8fb67a0e6417bc5744e56f1/pillow-12.1.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:578510d88c6229d735855e1f278aa305270438d36a05031dfaae5067cc8eb04d", size = 7159286, upload-time = "2026-02-11T04:20:41.139Z" }, + { url = "https://files.pythonhosted.org/packages/7b/5a/24bc8eb526a22f957d0cec6243146744966d40857e3d8deb68f7902ca6c1/pillow-12.1.1-cp311-cp311-win32.whl", hash = "sha256:7311c0a0dcadb89b36b7025dfd8326ecfa36964e29913074d47382706e516a7c", size = 6328663, upload-time = "2026-02-11T04:20:43.184Z" }, + { url = "https://files.pythonhosted.org/packages/31/03/bef822e4f2d8f9d7448c133d0a18185d3cce3e70472774fffefe8b0ed562/pillow-12.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:fbfa2a7c10cc2623f412753cddf391c7f971c52ca40a3f65dc5039b2939e8563", size = 7031448, upload-time = "2026-02-11T04:20:44.696Z" }, + { url = "https://files.pythonhosted.org/packages/49/70/f76296f53610bd17b2e7d31728b8b7825e3ac3b5b3688b51f52eab7c0818/pillow-12.1.1-cp311-cp311-win_arm64.whl", hash = "sha256:b81b5e3511211631b3f672a595e3221252c90af017e399056d0faabb9538aa80", size = 2453651, upload-time = "2026-02-11T04:20:46.243Z" }, + { url = "https://files.pythonhosted.org/packages/07/d3/8df65da0d4df36b094351dce696f2989bec731d4f10e743b1c5f4da4d3bf/pillow-12.1.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ab323b787d6e18b3d91a72fc99b1a2c28651e4358749842b8f8dfacd28ef2052", size = 5262803, upload-time = "2026-02-11T04:20:47.653Z" }, + { url = "https://files.pythonhosted.org/packages/d6/71/5026395b290ff404b836e636f51d7297e6c83beceaa87c592718747e670f/pillow-12.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:adebb5bee0f0af4909c30db0d890c773d1a92ffe83da908e2e9e720f8edf3984", size = 4657601, upload-time = "2026-02-11T04:20:49.328Z" }, + { url = "https://files.pythonhosted.org/packages/b1/2e/1001613d941c67442f745aff0f7cc66dd8df9a9c084eb497e6a543ee6f7e/pillow-12.1.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:bb66b7cc26f50977108790e2456b7921e773f23db5630261102233eb355a3b79", size = 6234995, upload-time = "2026-02-11T04:20:51.032Z" }, + { url = "https://files.pythonhosted.org/packages/07/26/246ab11455b2549b9233dbd44d358d033a2f780fa9007b61a913c5b2d24e/pillow-12.1.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:aee2810642b2898bb187ced9b349e95d2a7272930796e022efaf12e99dccd293", size = 8045012, upload-time = "2026-02-11T04:20:52.882Z" }, + { url = "https://files.pythonhosted.org/packages/b2/8b/07587069c27be7535ac1fe33874e32de118fbd34e2a73b7f83436a88368c/pillow-12.1.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a0b1cd6232e2b618adcc54d9882e4e662a089d5768cd188f7c245b4c8c44a397", size = 6349638, upload-time = "2026-02-11T04:20:54.444Z" }, + { url = "https://files.pythonhosted.org/packages/ff/79/6df7b2ee763d619cda2fb4fea498e5f79d984dae304d45a8999b80d6cf5c/pillow-12.1.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7aac39bcf8d4770d089588a2e1dd111cbaa42df5a94be3114222057d68336bd0", size = 7041540, upload-time = "2026-02-11T04:20:55.97Z" }, + { url = "https://files.pythonhosted.org/packages/2c/5e/2ba19e7e7236d7529f4d873bdaf317a318896bac289abebd4bb00ef247f0/pillow-12.1.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ab174cd7d29a62dd139c44bf74b698039328f45cb03b4596c43473a46656b2f3", size = 6462613, upload-time = "2026-02-11T04:20:57.542Z" }, + { url = "https://files.pythonhosted.org/packages/03/03/31216ec124bb5c3dacd74ce8efff4cc7f52643653bad4825f8f08c697743/pillow-12.1.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:339ffdcb7cbeaa08221cd401d517d4b1fe7a9ed5d400e4a8039719238620ca35", size = 7166745, upload-time = "2026-02-11T04:20:59.196Z" }, + { url = "https://files.pythonhosted.org/packages/1f/e7/7c4552d80052337eb28653b617eafdef39adfb137c49dd7e831b8dc13bc5/pillow-12.1.1-cp312-cp312-win32.whl", hash = "sha256:5d1f9575a12bed9e9eedd9a4972834b08c97a352bd17955ccdebfeca5913fa0a", size = 6328823, upload-time = "2026-02-11T04:21:01.385Z" }, + { url = "https://files.pythonhosted.org/packages/3d/17/688626d192d7261bbbf98846fc98995726bddc2c945344b65bec3a29d731/pillow-12.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:21329ec8c96c6e979cd0dfd29406c40c1d52521a90544463057d2aaa937d66a6", size = 7033367, upload-time = "2026-02-11T04:21:03.536Z" }, + { url = "https://files.pythonhosted.org/packages/ed/fe/a0ef1f73f939b0eca03ee2c108d0043a87468664770612602c63266a43c4/pillow-12.1.1-cp312-cp312-win_arm64.whl", hash = "sha256:af9a332e572978f0218686636610555ae3defd1633597be015ed50289a03c523", size = 2453811, upload-time = "2026-02-11T04:21:05.116Z" }, + { url = "https://files.pythonhosted.org/packages/d5/11/6db24d4bd7685583caeae54b7009584e38da3c3d4488ed4cd25b439de486/pillow-12.1.1-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:d242e8ac078781f1de88bf823d70c1a9b3c7950a44cdf4b7c012e22ccbcd8e4e", size = 4062689, upload-time = "2026-02-11T04:21:06.804Z" }, + { url = "https://files.pythonhosted.org/packages/33/c0/ce6d3b1fe190f0021203e0d9b5b99e57843e345f15f9ef22fcd43842fd21/pillow-12.1.1-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:02f84dfad02693676692746df05b89cf25597560db2857363a208e393429f5e9", size = 4138535, upload-time = "2026-02-11T04:21:08.452Z" }, + { url = "https://files.pythonhosted.org/packages/a0/c6/d5eb6a4fb32a3f9c21a8c7613ec706534ea1cf9f4b3663e99f0d83f6fca8/pillow-12.1.1-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:e65498daf4b583091ccbb2556c7000abf0f3349fcd57ef7adc9a84a394ed29f6", size = 3601364, upload-time = "2026-02-11T04:21:10.194Z" }, + { url = "https://files.pythonhosted.org/packages/14/a1/16c4b823838ba4c9c52c0e6bbda903a3fe5a1bdbf1b8eb4fff7156f3e318/pillow-12.1.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:6c6db3b84c87d48d0088943bf33440e0c42370b99b1c2a7989216f7b42eede60", size = 5262561, upload-time = "2026-02-11T04:21:11.742Z" }, + { url = "https://files.pythonhosted.org/packages/bb/ad/ad9dc98ff24f485008aa5cdedaf1a219876f6f6c42a4626c08bc4e80b120/pillow-12.1.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8b7e5304e34942bf62e15184219a7b5ad4ff7f3bb5cca4d984f37df1a0e1aee2", size = 4657460, upload-time = "2026-02-11T04:21:13.786Z" }, + { url = "https://files.pythonhosted.org/packages/9e/1b/f1a4ea9a895b5732152789326202a82464d5254759fbacae4deea3069334/pillow-12.1.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:18e5bddd742a44b7e6b1e773ab5db102bd7a94c32555ba656e76d319d19c3850", size = 6232698, upload-time = "2026-02-11T04:21:15.949Z" }, + { url = "https://files.pythonhosted.org/packages/95/f4/86f51b8745070daf21fd2e5b1fe0eb35d4db9ca26e6d58366562fb56a743/pillow-12.1.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fc44ef1f3de4f45b50ccf9136999d71abb99dca7706bc75d222ed350b9fd2289", size = 8041706, upload-time = "2026-02-11T04:21:17.723Z" }, + { url = "https://files.pythonhosted.org/packages/29/9b/d6ecd956bb1266dd1045e995cce9b8d77759e740953a1c9aad9502a0461e/pillow-12.1.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5a8eb7ed8d4198bccbd07058416eeec51686b498e784eda166395a23eb99138e", size = 6346621, upload-time = "2026-02-11T04:21:19.547Z" }, + { url = "https://files.pythonhosted.org/packages/71/24/538bff45bde96535d7d998c6fed1a751c75ac7c53c37c90dc2601b243893/pillow-12.1.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:47b94983da0c642de92ced1702c5b6c292a84bd3a8e1d1702ff923f183594717", size = 7038069, upload-time = "2026-02-11T04:21:21.378Z" }, + { url = "https://files.pythonhosted.org/packages/94/0e/58cb1a6bc48f746bc4cb3adb8cabff73e2742c92b3bf7a220b7cf69b9177/pillow-12.1.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:518a48c2aab7ce596d3bf79d0e275661b846e86e4d0e7dec34712c30fe07f02a", size = 6460040, upload-time = "2026-02-11T04:21:23.148Z" }, + { url = "https://files.pythonhosted.org/packages/6c/57/9045cb3ff11eeb6c1adce3b2d60d7d299d7b273a2e6c8381a524abfdc474/pillow-12.1.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a550ae29b95c6dc13cf69e2c9dc5747f814c54eeb2e32d683e5e93af56caa029", size = 7164523, upload-time = "2026-02-11T04:21:25.01Z" }, + { url = "https://files.pythonhosted.org/packages/73/f2/9be9cb99f2175f0d4dbadd6616ce1bf068ee54a28277ea1bf1fbf729c250/pillow-12.1.1-cp313-cp313-win32.whl", hash = "sha256:a003d7422449f6d1e3a34e3dd4110c22148336918ddbfc6a32581cd54b2e0b2b", size = 6332552, upload-time = "2026-02-11T04:21:27.238Z" }, + { url = "https://files.pythonhosted.org/packages/3f/eb/b0834ad8b583d7d9d42b80becff092082a1c3c156bb582590fcc973f1c7c/pillow-12.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:344cf1e3dab3be4b1fa08e449323d98a2a3f819ad20f4b22e77a0ede31f0faa1", size = 7040108, upload-time = "2026-02-11T04:21:29.462Z" }, + { url = "https://files.pythonhosted.org/packages/d5/7d/fc09634e2aabdd0feabaff4a32f4a7d97789223e7c2042fd805ea4b4d2c2/pillow-12.1.1-cp313-cp313-win_arm64.whl", hash = "sha256:5c0dd1636633e7e6a0afe7bf6a51a14992b7f8e60de5789018ebbdfae55b040a", size = 2453712, upload-time = "2026-02-11T04:21:31.072Z" }, + { url = "https://files.pythonhosted.org/packages/19/2a/b9d62794fc8a0dd14c1943df68347badbd5511103e0d04c035ffe5cf2255/pillow-12.1.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0330d233c1a0ead844fc097a7d16c0abff4c12e856c0b325f231820fee1f39da", size = 5264880, upload-time = "2026-02-11T04:21:32.865Z" }, + { url = "https://files.pythonhosted.org/packages/26/9d/e03d857d1347fa5ed9247e123fcd2a97b6220e15e9cb73ca0a8d91702c6e/pillow-12.1.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:5dae5f21afb91322f2ff791895ddd8889e5e947ff59f71b46041c8ce6db790bc", size = 4660616, upload-time = "2026-02-11T04:21:34.97Z" }, + { url = "https://files.pythonhosted.org/packages/f7/ec/8a6d22afd02570d30954e043f09c32772bfe143ba9285e2fdb11284952cd/pillow-12.1.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:2e0c664be47252947d870ac0d327fea7e63985a08794758aa8af5b6cb6ec0c9c", size = 6269008, upload-time = "2026-02-11T04:21:36.623Z" }, + { url = "https://files.pythonhosted.org/packages/3d/1d/6d875422c9f28a4a361f495a5f68d9de4a66941dc2c619103ca335fa6446/pillow-12.1.1-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:691ab2ac363b8217f7d31b3497108fb1f50faab2f75dfb03284ec2f217e87bf8", size = 8073226, upload-time = "2026-02-11T04:21:38.585Z" }, + { url = "https://files.pythonhosted.org/packages/a1/cd/134b0b6ee5eda6dc09e25e24b40fdafe11a520bc725c1d0bbaa5e00bf95b/pillow-12.1.1-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e9e8064fb1cc019296958595f6db671fba95209e3ceb0c4734c9baf97de04b20", size = 6380136, upload-time = "2026-02-11T04:21:40.562Z" }, + { url = "https://files.pythonhosted.org/packages/7a/a9/7628f013f18f001c1b98d8fffe3452f306a70dc6aba7d931019e0492f45e/pillow-12.1.1-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:472a8d7ded663e6162dafdf20015c486a7009483ca671cece7a9279b512fcb13", size = 7067129, upload-time = "2026-02-11T04:21:42.521Z" }, + { url = "https://files.pythonhosted.org/packages/1e/f8/66ab30a2193b277785601e82ee2d49f68ea575d9637e5e234faaa98efa4c/pillow-12.1.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:89b54027a766529136a06cfebeecb3a04900397a3590fd252160b888479517bf", size = 6491807, upload-time = "2026-02-11T04:21:44.22Z" }, + { url = "https://files.pythonhosted.org/packages/da/0b/a877a6627dc8318fdb84e357c5e1a758c0941ab1ddffdafd231983788579/pillow-12.1.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:86172b0831b82ce4f7877f280055892b31179e1576aa00d0df3bb1bbf8c3e524", size = 7190954, upload-time = "2026-02-11T04:21:46.114Z" }, + { url = "https://files.pythonhosted.org/packages/83/43/6f732ff85743cf746b1361b91665d9f5155e1483817f693f8d57ea93147f/pillow-12.1.1-cp313-cp313t-win32.whl", hash = "sha256:44ce27545b6efcf0fdbdceb31c9a5bdea9333e664cda58a7e674bb74608b3986", size = 6336441, upload-time = "2026-02-11T04:21:48.22Z" }, + { url = "https://files.pythonhosted.org/packages/3b/44/e865ef3986611bb75bfabdf94a590016ea327833f434558801122979cd0e/pillow-12.1.1-cp313-cp313t-win_amd64.whl", hash = "sha256:a285e3eb7a5a45a2ff504e31f4a8d1b12ef62e84e5411c6804a42197c1cf586c", size = 7045383, upload-time = "2026-02-11T04:21:50.015Z" }, + { url = "https://files.pythonhosted.org/packages/a8/c6/f4fb24268d0c6908b9f04143697ea18b0379490cb74ba9e8d41b898bd005/pillow-12.1.1-cp313-cp313t-win_arm64.whl", hash = "sha256:cc7d296b5ea4d29e6570dabeaed58d31c3fea35a633a69679fb03d7664f43fb3", size = 2456104, upload-time = "2026-02-11T04:21:51.633Z" }, + { url = "https://files.pythonhosted.org/packages/03/d0/bebb3ffbf31c5a8e97241476c4cf8b9828954693ce6744b4a2326af3e16b/pillow-12.1.1-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:417423db963cb4be8bac3fc1204fe61610f6abeed1580a7a2cbb2fbda20f12af", size = 4062652, upload-time = "2026-02-11T04:21:53.19Z" }, + { url = "https://files.pythonhosted.org/packages/2d/c0/0e16fb0addda4851445c28f8350d8c512f09de27bbb0d6d0bbf8b6709605/pillow-12.1.1-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:b957b71c6b2387610f556a7eb0828afbe40b4a98036fc0d2acfa5a44a0c2036f", size = 4138823, upload-time = "2026-02-11T04:22:03.088Z" }, + { url = "https://files.pythonhosted.org/packages/6b/fb/6170ec655d6f6bb6630a013dd7cf7bc218423d7b5fa9071bf63dc32175ae/pillow-12.1.1-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:097690ba1f2efdeb165a20469d59d8bb03c55fb6621eb2041a060ae8ea3e9642", size = 3601143, upload-time = "2026-02-11T04:22:04.909Z" }, + { url = "https://files.pythonhosted.org/packages/59/04/dc5c3f297510ba9a6837cbb318b87dd2b8f73eb41a43cc63767f65cb599c/pillow-12.1.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:2815a87ab27848db0321fb78c7f0b2c8649dee134b7f2b80c6a45c6831d75ccd", size = 5266254, upload-time = "2026-02-11T04:22:07.656Z" }, + { url = "https://files.pythonhosted.org/packages/05/30/5db1236b0d6313f03ebf97f5e17cda9ca060f524b2fcc875149a8360b21c/pillow-12.1.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:f7ed2c6543bad5a7d5530eb9e78c53132f93dfa44a28492db88b41cdab885202", size = 4657499, upload-time = "2026-02-11T04:22:09.613Z" }, + { url = "https://files.pythonhosted.org/packages/6f/18/008d2ca0eb612e81968e8be0bbae5051efba24d52debf930126d7eaacbba/pillow-12.1.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:652a2c9ccfb556235b2b501a3a7cf3742148cd22e04b5625c5fe057ea3e3191f", size = 6232137, upload-time = "2026-02-11T04:22:11.434Z" }, + { url = "https://files.pythonhosted.org/packages/70/f1/f14d5b8eeb4b2cd62b9f9f847eb6605f103df89ef619ac68f92f748614ea/pillow-12.1.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d6e4571eedf43af33d0fc233a382a76e849badbccdf1ac438841308652a08e1f", size = 8042721, upload-time = "2026-02-11T04:22:13.321Z" }, + { url = "https://files.pythonhosted.org/packages/5a/d6/17824509146e4babbdabf04d8171491fa9d776f7061ff6e727522df9bd03/pillow-12.1.1-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b574c51cf7d5d62e9be37ba446224b59a2da26dc4c1bb2ecbe936a4fb1a7cb7f", size = 6347798, upload-time = "2026-02-11T04:22:15.449Z" }, + { url = "https://files.pythonhosted.org/packages/d1/ee/c85a38a9ab92037a75615aba572c85ea51e605265036e00c5b67dfafbfe2/pillow-12.1.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a37691702ed687799de29a518d63d4682d9016932db66d4e90c345831b02fb4e", size = 7039315, upload-time = "2026-02-11T04:22:17.24Z" }, + { url = "https://files.pythonhosted.org/packages/ec/f3/bc8ccc6e08a148290d7523bde4d9a0d6c981db34631390dc6e6ec34cacf6/pillow-12.1.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:f95c00d5d6700b2b890479664a06e754974848afaae5e21beb4d83c106923fd0", size = 6462360, upload-time = "2026-02-11T04:22:19.111Z" }, + { url = "https://files.pythonhosted.org/packages/f6/ab/69a42656adb1d0665ab051eec58a41f169ad295cf81ad45406963105408f/pillow-12.1.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:559b38da23606e68681337ad74622c4dbba02254fc9cb4488a305dd5975c7eeb", size = 7165438, upload-time = "2026-02-11T04:22:21.041Z" }, + { url = "https://files.pythonhosted.org/packages/02/46/81f7aa8941873f0f01d4b55cc543b0a3d03ec2ee30d617a0448bf6bd6dec/pillow-12.1.1-cp314-cp314-win32.whl", hash = "sha256:03edcc34d688572014ff223c125a3f77fb08091e4607e7745002fc214070b35f", size = 6431503, upload-time = "2026-02-11T04:22:22.833Z" }, + { url = "https://files.pythonhosted.org/packages/40/72/4c245f7d1044b67affc7f134a09ea619d4895333d35322b775b928180044/pillow-12.1.1-cp314-cp314-win_amd64.whl", hash = "sha256:50480dcd74fa63b8e78235957d302d98d98d82ccbfac4c7e12108ba9ecbdba15", size = 7176748, upload-time = "2026-02-11T04:22:24.64Z" }, + { url = "https://files.pythonhosted.org/packages/e4/ad/8a87bdbe038c5c698736e3348af5c2194ffb872ea52f11894c95f9305435/pillow-12.1.1-cp314-cp314-win_arm64.whl", hash = "sha256:5cb1785d97b0c3d1d1a16bc1d710c4a0049daefc4935f3a8f31f827f4d3d2e7f", size = 2544314, upload-time = "2026-02-11T04:22:26.685Z" }, + { url = "https://files.pythonhosted.org/packages/6c/9d/efd18493f9de13b87ede7c47e69184b9e859e4427225ea962e32e56a49bc/pillow-12.1.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:1f90cff8aa76835cba5769f0b3121a22bd4eb9e6884cfe338216e557a9a548b8", size = 5268612, upload-time = "2026-02-11T04:22:29.884Z" }, + { url = "https://files.pythonhosted.org/packages/f8/f1/4f42eb2b388eb2ffc660dcb7f7b556c1015c53ebd5f7f754965ef997585b/pillow-12.1.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1f1be78ce9466a7ee64bfda57bdba0f7cc499d9794d518b854816c41bf0aa4e9", size = 4660567, upload-time = "2026-02-11T04:22:31.799Z" }, + { url = "https://files.pythonhosted.org/packages/01/54/df6ef130fa43e4b82e32624a7b821a2be1c5653a5fdad8469687a7db4e00/pillow-12.1.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:42fc1f4677106188ad9a55562bbade416f8b55456f522430fadab3cef7cd4e60", size = 6269951, upload-time = "2026-02-11T04:22:33.921Z" }, + { url = "https://files.pythonhosted.org/packages/a9/48/618752d06cc44bb4aae8ce0cd4e6426871929ed7b46215638088270d9b34/pillow-12.1.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:98edb152429ab62a1818039744d8fbb3ccab98a7c29fc3d5fcef158f3f1f68b7", size = 8074769, upload-time = "2026-02-11T04:22:35.877Z" }, + { url = "https://files.pythonhosted.org/packages/c3/bd/f1d71eb39a72fa088d938655afba3e00b38018d052752f435838961127d8/pillow-12.1.1-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d470ab1178551dd17fdba0fef463359c41aaa613cdcd7ff8373f54be629f9f8f", size = 6381358, upload-time = "2026-02-11T04:22:37.698Z" }, + { url = "https://files.pythonhosted.org/packages/64/ef/c784e20b96674ed36a5af839305f55616f8b4f8aa8eeccf8531a6e312243/pillow-12.1.1-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6408a7b064595afcab0a49393a413732a35788f2a5092fdc6266952ed67de586", size = 7068558, upload-time = "2026-02-11T04:22:39.597Z" }, + { url = "https://files.pythonhosted.org/packages/73/cb/8059688b74422ae61278202c4e1ad992e8a2e7375227be0a21c6b87ca8d5/pillow-12.1.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5d8c41325b382c07799a3682c1c258469ea2ff97103c53717b7893862d0c98ce", size = 6493028, upload-time = "2026-02-11T04:22:42.73Z" }, + { url = "https://files.pythonhosted.org/packages/c6/da/e3c008ed7d2dd1f905b15949325934510b9d1931e5df999bb15972756818/pillow-12.1.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:c7697918b5be27424e9ce568193efd13d925c4481dd364e43f5dff72d33e10f8", size = 7191940, upload-time = "2026-02-11T04:22:44.543Z" }, + { url = "https://files.pythonhosted.org/packages/01/4a/9202e8d11714c1fc5951f2e1ef362f2d7fbc595e1f6717971d5dd750e969/pillow-12.1.1-cp314-cp314t-win32.whl", hash = "sha256:d2912fd8114fc5545aa3a4b5576512f64c55a03f3ebcca4c10194d593d43ea36", size = 6438736, upload-time = "2026-02-11T04:22:46.347Z" }, + { url = "https://files.pythonhosted.org/packages/f3/ca/cbce2327eb9885476b3957b2e82eb12c866a8b16ad77392864ad601022ce/pillow-12.1.1-cp314-cp314t-win_amd64.whl", hash = "sha256:4ceb838d4bd9dab43e06c363cab2eebf63846d6a4aeaea283bbdfd8f1a8ed58b", size = 7182894, upload-time = "2026-02-11T04:22:48.114Z" }, + { url = "https://files.pythonhosted.org/packages/ec/d2/de599c95ba0a973b94410477f8bf0b6f0b5e67360eb89bcb1ad365258beb/pillow-12.1.1-cp314-cp314t-win_arm64.whl", hash = "sha256:7b03048319bfc6170e93bd60728a1af51d3dd7704935feb228c4d4faab35d334", size = 2546446, upload-time = "2026-02-11T04:22:50.342Z" }, + { url = "https://files.pythonhosted.org/packages/56/11/5d43209aa4cb58e0cc80127956ff1796a68b928e6324bbf06ef4db34367b/pillow-12.1.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:600fd103672b925fe62ed08e0d874ea34d692474df6f4bf7ebe148b30f89f39f", size = 5228606, upload-time = "2026-02-11T04:22:52.106Z" }, + { url = "https://files.pythonhosted.org/packages/5f/d5/3b005b4e4fda6698b371fa6c21b097d4707585d7db99e98d9b0b87ac612a/pillow-12.1.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:665e1b916b043cef294bc54d47bf02d87e13f769bc4bc5fa225a24b3a6c5aca9", size = 4622321, upload-time = "2026-02-11T04:22:53.827Z" }, + { url = "https://files.pythonhosted.org/packages/df/36/ed3ea2d594356fd8037e5a01f6156c74bc8d92dbb0fa60746cc96cabb6e8/pillow-12.1.1-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:495c302af3aad1ca67420ddd5c7bd480c8867ad173528767d906428057a11f0e", size = 5247579, upload-time = "2026-02-11T04:22:56.094Z" }, + { url = "https://files.pythonhosted.org/packages/54/9a/9cc3e029683cf6d20ae5085da0dafc63148e3252c2f13328e553aaa13cfb/pillow-12.1.1-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8fd420ef0c52c88b5a035a0886f367748c72147b2b8f384c9d12656678dfdfa9", size = 6989094, upload-time = "2026-02-11T04:22:58.288Z" }, + { url = "https://files.pythonhosted.org/packages/00/98/fc53ab36da80b88df0967896b6c4b4cd948a0dc5aa40a754266aa3ae48b3/pillow-12.1.1-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f975aa7ef9684ce7e2c18a3aa8f8e2106ce1e46b94ab713d156b2898811651d3", size = 5313850, upload-time = "2026-02-11T04:23:00.554Z" }, + { url = "https://files.pythonhosted.org/packages/30/02/00fa585abfd9fe9d73e5f6e554dc36cc2b842898cbfc46d70353dae227f8/pillow-12.1.1-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8089c852a56c2966cf18835db62d9b34fef7ba74c726ad943928d494fa7f4735", size = 5963343, upload-time = "2026-02-11T04:23:02.934Z" }, + { url = "https://files.pythonhosted.org/packages/f2/26/c56ce33ca856e358d27fda9676c055395abddb82c35ac0f593877ed4562e/pillow-12.1.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:cb9bb857b2d057c6dfc72ac5f3b44836924ba15721882ef103cecb40d002d80e", size = 7029880, upload-time = "2026-02-11T04:23:04.783Z" }, +] + +[[package]] +name = "platformdirs" +version = "4.9.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/19/56/8d4c30c8a1d07013911a8fdbd8f89440ef9f08d07a1b50ab8ca8be5a20f9/platformdirs-4.9.4.tar.gz", hash = "sha256:1ec356301b7dc906d83f371c8f487070e99d3ccf9e501686456394622a01a934", size = 28737, upload-time = "2026-03-05T18:34:13.271Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/63/d7/97f7e3a6abb67d8080dd406fd4df842c2be0efaf712d1c899c32a075027c/platformdirs-4.9.4-py3-none-any.whl", hash = "sha256:68a9a4619a666ea6439f2ff250c12a853cd1cbd5158d258bd824a7df6be2f868", size = 21216, upload-time = "2026-03-05T18:34:12.172Z" }, +] + +[[package]] +name = "pluggy" +version = "1.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/cd/24/3b7a0818484df9c28172857af32c2397b6d8fcd99d9468bd4684f98ebf0a/proto_plus-1.27.0-py3-none-any.whl", hash = "sha256:1baa7f81cf0f8acb8bc1f6d085008ba4171eaf669629d1b6d1673b21ed1c0a82", size = 50205, upload-time = "2025-12-16T13:46:24.76Z" }, + { 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 = "protobuf" -version = "6.33.2" +name = "pre-commit" +version = "4.5.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/34/44/e49ecff446afeec9d1a66d6bbf9adc21e3c7cea7803a920ca3773379d4f6/protobuf-6.33.2.tar.gz", hash = "sha256:56dc370c91fbb8ac85bc13582c9e373569668a290aa2e66a590c2a0d35ddb9e4", size = 444296, upload-time = "2025-12-06T00:17:53.311Z" } +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/bc/91/1e3a34881a88697a7354ffd177e8746e97a722e5e8db101544b47e84afb1/protobuf-6.33.2-cp310-abi3-win32.whl", hash = "sha256:87eb388bd2d0f78febd8f4c8779c79247b26a5befad525008e49a6955787ff3d", size = 425603, upload-time = "2025-12-06T00:17:41.114Z" }, - { url = "https://files.pythonhosted.org/packages/64/20/4d50191997e917ae13ad0a235c8b42d8c1ab9c3e6fd455ca16d416944355/protobuf-6.33.2-cp310-abi3-win_amd64.whl", hash = "sha256:fc2a0e8b05b180e5fc0dd1559fe8ebdae21a27e81ac77728fb6c42b12c7419b4", size = 436930, upload-time = "2025-12-06T00:17:43.278Z" }, - { url = "https://files.pythonhosted.org/packages/b2/ca/7e485da88ba45c920fb3f50ae78de29ab925d9e54ef0de678306abfbb497/protobuf-6.33.2-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:d9b19771ca75935b3a4422957bc518b0cecb978b31d1dd12037b088f6bcc0e43", size = 427621, upload-time = "2025-12-06T00:17:44.445Z" }, - { url = "https://files.pythonhosted.org/packages/7d/4f/f743761e41d3b2b2566748eb76bbff2b43e14d5fcab694f494a16458b05f/protobuf-6.33.2-cp39-abi3-manylinux2014_aarch64.whl", hash = "sha256:b5d3b5625192214066d99b2b605f5783483575656784de223f00a8d00754fc0e", size = 324460, upload-time = "2025-12-06T00:17:45.678Z" }, - { url = "https://files.pythonhosted.org/packages/b1/fa/26468d00a92824020f6f2090d827078c09c9c587e34cbfd2d0c7911221f8/protobuf-6.33.2-cp39-abi3-manylinux2014_s390x.whl", hash = "sha256:8cd7640aee0b7828b6d03ae518b5b4806fdfc1afe8de82f79c3454f8aef29872", size = 339168, upload-time = "2025-12-06T00:17:46.813Z" }, - { url = "https://files.pythonhosted.org/packages/56/13/333b8f421738f149d4fe5e49553bc2a2ab75235486259f689b4b91f96cec/protobuf-6.33.2-cp39-abi3-manylinux2014_x86_64.whl", hash = "sha256:1f8017c48c07ec5859106533b682260ba3d7c5567b1ca1f24297ce03384d1b4f", size = 323270, upload-time = "2025-12-06T00:17:48.253Z" }, - { url = "https://files.pythonhosted.org/packages/0e/15/4f02896cc3df04fc465010a4c6a0cd89810f54617a32a70ef531ed75d61c/protobuf-6.33.2-py3-none-any.whl", hash = "sha256:7636aad9bb01768870266de5dc009de2d1b936771b38a793f73cbbf279c91c5c", size = 170501, upload-time = "2025-12-06T00:17:52.211Z" }, + { 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]] @@ -1155,6 +998,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/47/8d/d529b5d697919ba8c11ad626e835d4039be708a35b0d22de83a269a6682c/pyasn1_modules-0.4.2-py3-none-any.whl", hash = "sha256:29253a9207ce32b64c3ac6600edc75368f98473906e8fd1043bd6b5b1de2c14a", size = 181259, upload-time = "2025-03-28T02:41:19.028Z" }, ] +[[package]] +name = "pycparser" +version = "3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1b/7d/92392ff7815c21062bea51aa7b87d45576f649f16458d78b7cf94b9ab2e6/pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29", size = 103492, upload-time = "2026-01-21T14:26:51.89Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992", size = 48172, upload-time = "2026-01-21T14:26:50.693Z" }, +] + [[package]] name = "pydantic" version = "2.12.5" @@ -1170,6 +1022,39 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl", hash = "sha256:e561593fccf61e8a20fc46dfc2dfe075b8be7d0188df33f221ad1f0139180f9d", size = 463580, upload-time = "2025-11-26T15:11:44.605Z" }, ] +[[package]] +name = "pydantic-ai-slim" +version = "1.67.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "genai-prices" }, + { name = "griffelib" }, + { name = "httpx" }, + { name = "opentelemetry-api" }, + { name = "pydantic" }, + { name = "pydantic-graph" }, + { name = "typing-inspection" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8c/51/c20e9aa4ee5f1d92a77dcb74741113e0d1838d63b65bb04ef16b9ba4b55f/pydantic_ai_slim-1.67.0.tar.gz", hash = "sha256:ce646e96aea775c00305d0c214080c970640cb4adf3bf58aa1296e186103e765", size = 436929, upload-time = "2026-03-06T22:40:07.061Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2f/bc/401bf11e4615a7adf8c00fb8f62313eb15ae7ee191fa77438cb9a27fa745/pydantic_ai_slim-1.67.0-py3-none-any.whl", hash = "sha256:241290e634298a38ed60c135eca2f9efbfa269811bf1e95aad33b234b6880945", size = 567858, upload-time = "2026-03-06T22:39:59.977Z" }, +] + +[package.optional-dependencies] +anthropic = [ + { name = "anthropic" }, +] +bedrock = [ + { name = "boto3" }, +] +google = [ + { name = "google-genai" }, +] +openai = [ + { name = "openai" }, + { name = "tiktoken" }, +] + [[package]] name = "pydantic-core" version = "2.41.5" @@ -1267,6 +1152,21 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/36/c7/cfc8e811f061c841d7990b0201912c3556bfeb99cdcb7ed24adc8d6f8704/pydantic_core-2.41.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:56121965f7a4dc965bff783d70b907ddf3d57f6eba29b6d2e5dabfaf07799c51", size = 2145302, upload-time = "2025-11-04T13:43:46.64Z" }, ] +[[package]] +name = "pydantic-graph" +version = "1.67.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "httpx" }, + { name = "logfire-api" }, + { name = "pydantic" }, + { name = "typing-inspection" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/17/f9/a2ce0fb0bba88701b77cc49ca249e6b143bd8b2adcbfcdff7b7b9e3f689d/pydantic_graph-1.67.0.tar.gz", hash = "sha256:d7bb6bb95aa5f3808b10d3700235aa881feebc462736cb8a5b917ffb470da36b", size = 58527, upload-time = "2026-03-06T22:40:09.271Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/22/b8/fc47a5151b274c354c8e15a7a02fe306d0c4d6e050cdf0cc0060f36d1ac2/pydantic_graph-1.67.0-py3-none-any.whl", hash = "sha256:fd3ec24dcf1f93435c6ad8b2968f66d2a20505c488e6319f1d96cfac832322d5", size = 72352, upload-time = "2026-03-06T22:40:03.04Z" }, +] + [[package]] name = "pygments" version = "2.19.2" @@ -1277,18 +1177,41 @@ wheels = [ ] [[package]] -name = "pymupdf" -version = "1.26.7" +name = "pypdf" +version = "6.8.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/48/d6/09b28f027b510838559f7748807192149c419b30cb90e6d5f0cf916dc9dc/pymupdf-1.26.7.tar.gz", hash = "sha256:71add8bdc8eb1aaa207c69a13400693f06ad9b927bea976f5d5ab9df0bb489c3", size = 84327033, upload-time = "2025-12-11T21:48:50.694Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b4/a3/e705b0805212b663a4c27b861c8a603dba0f8b4bb281f96f8e746576a50d/pypdf-6.8.0.tar.gz", hash = "sha256:cb7eaeaa4133ce76f762184069a854e03f4d9a08568f0e0623f7ea810407833b", size = 5307831, upload-time = "2026-03-09T13:37:40.591Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/94/35/cd74cea1787b2247702ef8522186bdef32e9cb30a099e6bb864627ef6045/pymupdf-1.26.7-cp310-abi3-macosx_10_9_x86_64.whl", hash = "sha256:07085718dfdae5ab83b05eb5eb397f863bcc538fe05135318a01ea353e7a1353", size = 23179369, upload-time = "2025-12-11T21:47:21.587Z" }, - { url = "https://files.pythonhosted.org/packages/72/74/448b6172927c829c6a3fba80078d7b0a016ebbe2c9ee528821f5ea21677a/pymupdf-1.26.7-cp310-abi3-macosx_11_0_arm64.whl", hash = "sha256:31aa9c8377ea1eea02934b92f4dcf79fb2abba0bf41f8a46d64c3e31546a3c02", size = 22470101, upload-time = "2025-12-11T21:47:37.105Z" }, - { url = "https://files.pythonhosted.org/packages/65/e7/47af26f3ac76be7ac3dd4d6cc7ee105948a8355d774e5ca39857bf91c11c/pymupdf-1.26.7-cp310-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:e419b609996434a14a80fa060adec72c434a1cca6a511ec54db9841bc5d51b3c", size = 23502486, upload-time = "2025-12-12T09:51:25.824Z" }, - { url = "https://files.pythonhosted.org/packages/2a/6b/3de1714d734ff949be1e90a22375d0598d3540b22ae73eb85c2d7d1f36a9/pymupdf-1.26.7-cp310-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:69dfc78f206a96e5b3ac22741263ebab945fdf51f0dbe7c5757c3511b23d9d72", size = 24115727, upload-time = "2025-12-11T21:47:51.274Z" }, - { url = "https://files.pythonhosted.org/packages/62/9b/f86224847949577a523be2207315ae0fd3155b5d909cd66c274d095349a3/pymupdf-1.26.7-cp310-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:1d5106f46e1ca0d64d46bd51892372a4f82076bdc14a9678d33d630702abca36", size = 24324386, upload-time = "2025-12-12T14:58:45.483Z" }, - { url = "https://files.pythonhosted.org/packages/85/8e/a117d39092ca645fde8b903f4a941d9aa75b370a67b4f1f435f56393dc5a/pymupdf-1.26.7-cp310-abi3-win32.whl", hash = "sha256:7c9645b6f5452629c747690190350213d3e5bbdb6b2eca227d82702b327f6eee", size = 17203888, upload-time = "2025-12-12T13:59:57.613Z" }, - { url = "https://files.pythonhosted.org/packages/dd/c3/d0047678146c294469c33bae167c8ace337deafb736b0bf97b9bc481aa65/pymupdf-1.26.7-cp310-abi3-win_amd64.whl", hash = "sha256:425b1befe40d41b72eb0fe211711c7ae334db5eb60307e9dd09066ed060cceba", size = 18405952, upload-time = "2025-12-11T21:48:02.947Z" }, + { url = "https://files.pythonhosted.org/packages/8c/ec/4ccf3bb86b1afe5d7176e1c8abcdbf22b53dd682ec2eda50e1caadcf6846/pypdf-6.8.0-py3-none-any.whl", hash = "sha256:2a025080a8dd73f48123c89c57174a5ff3806c71763ee4e49572dc90454943c7", size = 332177, upload-time = "2026-03-09T13:37:38.774Z" }, +] + +[[package]] +name = "pypdfium2" +version = "5.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/3b/01/be763b9081c7eb823196e7d13d9c145bf75ac43f3c1466de81c21c24b381/pypdfium2-5.6.0.tar.gz", hash = "sha256:bcb9368acfe3547054698abbdae68ba0cbd2d3bda8e8ee437e061deef061976d", size = 270714, upload-time = "2026-03-08T01:05:06.5Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9d/b1/129ed0177521a93a892f8a6a215dd3260093e30e77ef7035004bb8af7b6c/pypdfium2-5.6.0-py3-none-android_23_arm64_v8a.whl", hash = "sha256:fb7858c9707708555b4a719b5548a6e7f5d26bc82aef55ae4eb085d7a2190b11", size = 3346059, upload-time = "2026-03-08T01:04:21.37Z" }, + { url = "https://files.pythonhosted.org/packages/86/34/cbdece6886012180a7f2c7b2c360c415cf5e1f83f1973d2c9201dae3506a/pypdfium2-5.6.0-py3-none-android_23_armeabi_v7a.whl", hash = "sha256:6a7e1f4597317786f994bfb947eef480e53933f804a990193ab89eef8243f805", size = 2804418, upload-time = "2026-03-08T01:04:23.384Z" }, + { url = "https://files.pythonhosted.org/packages/6e/f6/9f9e190fe0e5a6b86b82f83bd8b5d3490348766062381140ca5cad8e00b1/pypdfium2-5.6.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:e468c38997573f0e86f03273c2c1fbdea999de52ba43fee96acaa2f6b2ad35f7", size = 3412541, upload-time = "2026-03-08T01:04:25.45Z" }, + { url = "https://files.pythonhosted.org/packages/ee/8d/e57492cb2228ba56ed57de1ff044c8ac114b46905f8b1445c33299ba0488/pypdfium2-5.6.0-py3-none-macosx_11_0_x86_64.whl", hash = "sha256:ad3abddc5805424f962e383253ccad6a0d1d2ebd86afa9a9e1b9ca659773cd0d", size = 3592320, upload-time = "2026-03-08T01:04:27.509Z" }, + { url = "https://files.pythonhosted.org/packages/f9/8a/8ab82e33e9c551494cbe1526ea250ca8cc4e9e98d6a4fc6b6f8d959aa1d1/pypdfium2-5.6.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f6b5eb9eae5c45076395454522ca26add72ba8bd1fe473e1e4721aa58521470c", size = 3596450, upload-time = "2026-03-08T01:04:29.183Z" }, + { url = "https://files.pythonhosted.org/packages/f5/b5/602a792282312ccb158cc63849528079d94b0a11efdc61f2a359edfb41e9/pypdfium2-5.6.0-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:258624da8ef45cdc426e11b33e9d83f9fb723c1c201c6e0f4ab5a85966c6b876", size = 3325442, upload-time = "2026-03-08T01:04:30.886Z" }, + { url = "https://files.pythonhosted.org/packages/81/1f/9e48ec05ed8d19d736c2d1f23c1bd0f20673f02ef846a2576c69e237f15d/pypdfium2-5.6.0-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e9367451c8a00931d6612db0822525a18c06f649d562cd323a719e46ac19c9bb", size = 3727434, upload-time = "2026-03-08T01:04:33.619Z" }, + { url = "https://files.pythonhosted.org/packages/33/90/0efd020928b4edbd65f4f3c2af0c84e20b43a3ada8fa6d04f999a97afe7a/pypdfium2-5.6.0-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a757869f891eac1cc1372e38a4aa01adac8abc8fe2a8a4e2ebf50595e3bf5937", size = 4139029, upload-time = "2026-03-08T01:04:36.08Z" }, + { url = "https://files.pythonhosted.org/packages/ff/49/a640b288a48dab1752281dd9b72c0679fccea107874e80a65a606b00efa9/pypdfium2-5.6.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:515be355222cc57ae9e62cd5c7c350b8e0c863efc539f80c7d75e2811ba45cb6", size = 3646387, upload-time = "2026-03-08T01:04:38.151Z" }, + { url = "https://files.pythonhosted.org/packages/b0/3b/a344c19c01021eeb5d830c102e4fc9b1602f19c04aa7d11abbe2d188fd8e/pypdfium2-5.6.0-py3-none-manylinux_2_27_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d1c4753c7caf7d004211d7f57a21f10d127f5e0e5510a14d24bc073e7220a3ea", size = 3097212, upload-time = "2026-03-08T01:04:40.776Z" }, + { url = "https://files.pythonhosted.org/packages/50/96/e48e13789ace22aeb9b7510904a1b1493ec588196e11bbacc122da330b3d/pypdfium2-5.6.0-py3-none-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c49729090281fdd85775fb8912c10bd19e99178efaa98f145ab06e7ce68554d2", size = 2965026, upload-time = "2026-03-08T01:04:42.857Z" }, + { url = "https://files.pythonhosted.org/packages/cb/06/3100e44d4935f73af8f5d633d3bd40f0d36d606027085a0ef1f0566a6320/pypdfium2-5.6.0-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:a4a1749a8d4afd62924a8d95cfa4f2e26fc32957ce34ac3b674be6f127ed252e", size = 4131431, upload-time = "2026-03-08T01:04:44.982Z" }, + { url = "https://files.pythonhosted.org/packages/64/ef/d8df63569ce9a66c8496057782eb8af78e0d28667922d62ec958434e3d4b/pypdfium2-5.6.0-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:36469ebd0fdffb7130ce45ed9c44f8232d91571c89eb851bd1633c64b6f6114f", size = 3747469, upload-time = "2026-03-08T01:04:46.702Z" }, + { url = "https://files.pythonhosted.org/packages/a6/47/fd2c6a67a49fade1acd719fbd11f7c375e7219912923ef2de0ea0ac1544e/pypdfium2-5.6.0-py3-none-musllinux_1_2_i686.whl", hash = "sha256:9da900df09be3cf546b637a127a7b6428fb22d705951d731269e25fd3adef457", size = 4337578, upload-time = "2026-03-08T01:04:49.007Z" }, + { url = "https://files.pythonhosted.org/packages/6b/f5/836c83e54b01e09478c4d6bf4912651d6053c932250fcee953f5c72d8e4a/pypdfium2-5.6.0-py3-none-musllinux_1_2_ppc64le.whl", hash = "sha256:45fccd5622233c5ec91a885770ae7dd4004d4320ac05a4ad8fa03a66dea40244", size = 4376104, upload-time = "2026-03-08T01:04:51.04Z" }, + { url = "https://files.pythonhosted.org/packages/6e/7f/b940b6a1664daf8f9bad87c6c99b84effa3611615b8708d10392dc33036c/pypdfium2-5.6.0-py3-none-musllinux_1_2_riscv64.whl", hash = "sha256:282dc030e767cd61bd0299f9d581052b91188e2b87561489057a8e7963e7e0cb", size = 3929824, upload-time = "2026-03-08T01:04:53.544Z" }, + { url = "https://files.pythonhosted.org/packages/88/79/00267d92a6a58c229e364d474f5698efe446e0c7f4f152f58d0138715e99/pypdfium2-5.6.0-py3-none-musllinux_1_2_s390x.whl", hash = "sha256:a1c1dfe950382c76a7bba1ba160ec5e40df8dd26b04a1124ae268fda55bc4cbe", size = 4270201, upload-time = "2026-03-08T01:04:55.81Z" }, + { url = "https://files.pythonhosted.org/packages/e1/ab/b127f38aba41746bdf9ace15ba08411d7ef6ecba1326d529ba414eb1ed50/pypdfium2-5.6.0-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:43b0341ca6feb6c92e4b7a9eb4813e5466f5f5e8b6baeb14df0a94d5f312c00b", size = 4180793, upload-time = "2026-03-08T01:04:57.961Z" }, + { url = "https://files.pythonhosted.org/packages/0e/8c/a01c8e4302448b614d25a85c08298b0d3e9dfbdac5bd1b2f32c9b02e83d9/pypdfium2-5.6.0-py3-none-win32.whl", hash = "sha256:9dfcd4ff49a2b9260d00e38539ab28190d59e785e83030b30ffaf7a29c42155d", size = 3596753, upload-time = "2026-03-08T01:05:00.566Z" }, + { url = "https://files.pythonhosted.org/packages/9b/5f/2d871adf46761bb002a62686545da6348afe838d19af03df65d1ece786a2/pypdfium2-5.6.0-py3-none-win_amd64.whl", hash = "sha256:c6bc8dd63d0568f4b592f3e03de756afafc0e44aa1fe8878cc4aba1b11ae7374", size = 3716526, upload-time = "2026-03-08T01:05:02.433Z" }, + { url = "https://files.pythonhosted.org/packages/3a/80/0d9b162098597fbe3ac2b269b1682c0c3e8db9ba87679603fdd9b19afaa6/pypdfium2-5.6.0-py3-none-win_arm64.whl", hash = "sha256:5538417b199bdcb3207370c88df61f2ba3dac7a3253f82e1aa2708e6376b6f90", size = 3515049, upload-time = "2026-03-08T01:05:04.587Z" }, ] [[package]] @@ -1321,12 +1244,187 @@ wheels = [ ] [[package]] -name = "python-dotenv" -version = "1.2.1" +name = "python-dateutil" +version = "2.9.0.post0" 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 = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" }, +] + +[[package]] +name = "python-discovery" +version = "1.1.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "filelock" }, + { name = "platformdirs" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d7/7e/9f3b0dd3a074a6c3e1e79f35e465b1f2ee4b262d619de00cfce523cc9b24/python_discovery-1.1.3.tar.gz", hash = "sha256:7acca36e818cd88e9b2ba03e045ad7e93e1713e29c6bbfba5d90202310b7baa5", size = 56945, upload-time = "2026-03-10T15:08:15.038Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e7/80/73211fc5bfbfc562369b4aa61dc1e4bf07dc7b34df7b317e4539316b809c/python_discovery-1.1.3-py3-none-any.whl", hash = "sha256:90e795f0121bc84572e737c9aa9966311b9fde44ffb88a5953b3ec9b31c6945e", size = 31485, upload-time = "2026-03-10T15:08:13.06Z" }, +] + +[[package]] +name = "pyyaml" +version = "6.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6d/16/a95b6757765b7b031c9374925bb718d55e0a9ba8a1b6a12d25962ea44347/pyyaml-6.0.3-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:44edc647873928551a01e7a563d7452ccdebee747728c1080d881d68af7b997e", size = 185826, upload-time = "2025-09-25T21:31:58.655Z" }, + { url = "https://files.pythonhosted.org/packages/16/19/13de8e4377ed53079ee996e1ab0a9c33ec2faf808a4647b7b4c0d46dd239/pyyaml-6.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:652cb6edd41e718550aad172851962662ff2681490a8a711af6a4d288dd96824", size = 175577, upload-time = "2025-09-25T21:32:00.088Z" }, + { url = "https://files.pythonhosted.org/packages/0c/62/d2eb46264d4b157dae1275b573017abec435397aa59cbcdab6fc978a8af4/pyyaml-6.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:10892704fc220243f5305762e276552a0395f7beb4dbf9b14ec8fd43b57f126c", size = 775556, upload-time = "2025-09-25T21:32:01.31Z" }, + { url = "https://files.pythonhosted.org/packages/10/cb/16c3f2cf3266edd25aaa00d6c4350381c8b012ed6f5276675b9eba8d9ff4/pyyaml-6.0.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:850774a7879607d3a6f50d36d04f00ee69e7fc816450e5f7e58d7f17f1ae5c00", size = 882114, upload-time = "2025-09-25T21:32:03.376Z" }, + { url = "https://files.pythonhosted.org/packages/71/60/917329f640924b18ff085ab889a11c763e0b573da888e8404ff486657602/pyyaml-6.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b8bb0864c5a28024fac8a632c443c87c5aa6f215c0b126c449ae1a150412f31d", size = 806638, upload-time = "2025-09-25T21:32:04.553Z" }, + { url = "https://files.pythonhosted.org/packages/dd/6f/529b0f316a9fd167281a6c3826b5583e6192dba792dd55e3203d3f8e655a/pyyaml-6.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d37d57ad971609cf3c53ba6a7e365e40660e3be0e5175fa9f2365a379d6095a", size = 767463, upload-time = "2025-09-25T21:32:06.152Z" }, + { url = "https://files.pythonhosted.org/packages/f2/6a/b627b4e0c1dd03718543519ffb2f1deea4a1e6d42fbab8021936a4d22589/pyyaml-6.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:37503bfbfc9d2c40b344d06b2199cf0e96e97957ab1c1b546fd4f87e53e5d3e4", size = 794986, upload-time = "2025-09-25T21:32:07.367Z" }, + { url = "https://files.pythonhosted.org/packages/45/91/47a6e1c42d9ee337c4839208f30d9f09caa9f720ec7582917b264defc875/pyyaml-6.0.3-cp311-cp311-win32.whl", hash = "sha256:8098f252adfa6c80ab48096053f512f2321f0b998f98150cea9bd23d83e1467b", size = 142543, upload-time = "2025-09-25T21:32:08.95Z" }, + { url = "https://files.pythonhosted.org/packages/da/e3/ea007450a105ae919a72393cb06f122f288ef60bba2dc64b26e2646fa315/pyyaml-6.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:9f3bfb4965eb874431221a3ff3fdcddc7e74e3b07799e0e84ca4a0f867d449bf", size = 158763, upload-time = "2025-09-25T21:32:09.96Z" }, + { url = "https://files.pythonhosted.org/packages/d1/33/422b98d2195232ca1826284a76852ad5a86fe23e31b009c9886b2d0fb8b2/pyyaml-6.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196", size = 182063, upload-time = "2025-09-25T21:32:11.445Z" }, + { url = "https://files.pythonhosted.org/packages/89/a0/6cf41a19a1f2f3feab0e9c0b74134aa2ce6849093d5517a0c550fe37a648/pyyaml-6.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0", size = 173973, upload-time = "2025-09-25T21:32:12.492Z" }, + { url = "https://files.pythonhosted.org/packages/ed/23/7a778b6bd0b9a8039df8b1b1d80e2e2ad78aa04171592c8a5c43a56a6af4/pyyaml-6.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28", size = 775116, upload-time = "2025-09-25T21:32:13.652Z" }, + { url = "https://files.pythonhosted.org/packages/65/30/d7353c338e12baef4ecc1b09e877c1970bd3382789c159b4f89d6a70dc09/pyyaml-6.0.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c", size = 844011, upload-time = "2025-09-25T21:32:15.21Z" }, + { url = "https://files.pythonhosted.org/packages/8b/9d/b3589d3877982d4f2329302ef98a8026e7f4443c765c46cfecc8858c6b4b/pyyaml-6.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc", size = 807870, upload-time = "2025-09-25T21:32:16.431Z" }, + { url = "https://files.pythonhosted.org/packages/05/c0/b3be26a015601b822b97d9149ff8cb5ead58c66f981e04fedf4e762f4bd4/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e", size = 761089, upload-time = "2025-09-25T21:32:17.56Z" }, + { url = "https://files.pythonhosted.org/packages/be/8e/98435a21d1d4b46590d5459a22d88128103f8da4c2d4cb8f14f2a96504e1/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea", size = 790181, upload-time = "2025-09-25T21:32:18.834Z" }, + { url = "https://files.pythonhosted.org/packages/74/93/7baea19427dcfbe1e5a372d81473250b379f04b1bd3c4c5ff825e2327202/pyyaml-6.0.3-cp312-cp312-win32.whl", hash = "sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5", size = 137658, upload-time = "2025-09-25T21:32:20.209Z" }, + { url = "https://files.pythonhosted.org/packages/86/bf/899e81e4cce32febab4fb42bb97dcdf66bc135272882d1987881a4b519e9/pyyaml-6.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b", size = 154003, upload-time = "2025-09-25T21:32:21.167Z" }, + { url = "https://files.pythonhosted.org/packages/1a/08/67bd04656199bbb51dbed1439b7f27601dfb576fb864099c7ef0c3e55531/pyyaml-6.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd", size = 140344, upload-time = "2025-09-25T21:32:22.617Z" }, + { url = "https://files.pythonhosted.org/packages/d1/11/0fd08f8192109f7169db964b5707a2f1e8b745d4e239b784a5a1dd80d1db/pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8", size = 181669, upload-time = "2025-09-25T21:32:23.673Z" }, + { url = "https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1", size = 173252, upload-time = "2025-09-25T21:32:25.149Z" }, + { url = "https://files.pythonhosted.org/packages/50/31/b20f376d3f810b9b2371e72ef5adb33879b25edb7a6d072cb7ca0c486398/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c", size = 767081, upload-time = "2025-09-25T21:32:26.575Z" }, + { url = "https://files.pythonhosted.org/packages/49/1e/a55ca81e949270d5d4432fbbd19dfea5321eda7c41a849d443dc92fd1ff7/pyyaml-6.0.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5", size = 841159, upload-time = "2025-09-25T21:32:27.727Z" }, + { url = "https://files.pythonhosted.org/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6", size = 801626, upload-time = "2025-09-25T21:32:28.878Z" }, + { url = "https://files.pythonhosted.org/packages/f9/11/ba845c23988798f40e52ba45f34849aa8a1f2d4af4b798588010792ebad6/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6", size = 753613, upload-time = "2025-09-25T21:32:30.178Z" }, + { url = "https://files.pythonhosted.org/packages/3d/e0/7966e1a7bfc0a45bf0a7fb6b98ea03fc9b8d84fa7f2229e9659680b69ee3/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be", size = 794115, upload-time = "2025-09-25T21:32:31.353Z" }, + { url = "https://files.pythonhosted.org/packages/de/94/980b50a6531b3019e45ddeada0626d45fa85cbe22300844a7983285bed3b/pyyaml-6.0.3-cp313-cp313-win32.whl", hash = "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26", size = 137427, upload-time = "2025-09-25T21:32:32.58Z" }, + { url = "https://files.pythonhosted.org/packages/97/c9/39d5b874e8b28845e4ec2202b5da735d0199dbe5b8fb85f91398814a9a46/pyyaml-6.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c", size = 154090, upload-time = "2025-09-25T21:32:33.659Z" }, + { url = "https://files.pythonhosted.org/packages/73/e8/2bdf3ca2090f68bb3d75b44da7bbc71843b19c9f2b9cb9b0f4ab7a5a4329/pyyaml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb", size = 140246, upload-time = "2025-09-25T21:32:34.663Z" }, + { url = "https://files.pythonhosted.org/packages/9d/8c/f4bd7f6465179953d3ac9bc44ac1a8a3e6122cf8ada906b4f96c60172d43/pyyaml-6.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac", size = 181814, upload-time = "2025-09-25T21:32:35.712Z" }, + { url = "https://files.pythonhosted.org/packages/bd/9c/4d95bb87eb2063d20db7b60faa3840c1b18025517ae857371c4dd55a6b3a/pyyaml-6.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310", size = 173809, upload-time = "2025-09-25T21:32:36.789Z" }, + { url = "https://files.pythonhosted.org/packages/92/b5/47e807c2623074914e29dabd16cbbdd4bf5e9b2db9f8090fa64411fc5382/pyyaml-6.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7", size = 766454, upload-time = "2025-09-25T21:32:37.966Z" }, + { url = "https://files.pythonhosted.org/packages/02/9e/e5e9b168be58564121efb3de6859c452fccde0ab093d8438905899a3a483/pyyaml-6.0.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788", size = 836355, upload-time = "2025-09-25T21:32:39.178Z" }, + { url = "https://files.pythonhosted.org/packages/88/f9/16491d7ed2a919954993e48aa941b200f38040928474c9e85ea9e64222c3/pyyaml-6.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5", size = 794175, upload-time = "2025-09-25T21:32:40.865Z" }, + { url = "https://files.pythonhosted.org/packages/dd/3f/5989debef34dc6397317802b527dbbafb2b4760878a53d4166579111411e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764", size = 755228, upload-time = "2025-09-25T21:32:42.084Z" }, + { url = "https://files.pythonhosted.org/packages/d7/ce/af88a49043cd2e265be63d083fc75b27b6ed062f5f9fd6cdc223ad62f03e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35", size = 789194, upload-time = "2025-09-25T21:32:43.362Z" }, + { url = "https://files.pythonhosted.org/packages/23/20/bb6982b26a40bb43951265ba29d4c246ef0ff59c9fdcdf0ed04e0687de4d/pyyaml-6.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac", size = 156429, upload-time = "2025-09-25T21:32:57.844Z" }, + { url = "https://files.pythonhosted.org/packages/f4/f4/a4541072bb9422c8a883ab55255f918fa378ecf083f5b85e87fc2b4eda1b/pyyaml-6.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3", size = 143912, upload-time = "2025-09-25T21:32:59.247Z" }, + { url = "https://files.pythonhosted.org/packages/7c/f9/07dd09ae774e4616edf6cda684ee78f97777bdd15847253637a6f052a62f/pyyaml-6.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3", size = 189108, upload-time = "2025-09-25T21:32:44.377Z" }, + { url = "https://files.pythonhosted.org/packages/4e/78/8d08c9fb7ce09ad8c38ad533c1191cf27f7ae1effe5bb9400a46d9437fcf/pyyaml-6.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba", size = 183641, upload-time = "2025-09-25T21:32:45.407Z" }, + { url = "https://files.pythonhosted.org/packages/7b/5b/3babb19104a46945cf816d047db2788bcaf8c94527a805610b0289a01c6b/pyyaml-6.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c", size = 831901, upload-time = "2025-09-25T21:32:48.83Z" }, + { url = "https://files.pythonhosted.org/packages/8b/cc/dff0684d8dc44da4d22a13f35f073d558c268780ce3c6ba1b87055bb0b87/pyyaml-6.0.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702", size = 861132, upload-time = "2025-09-25T21:32:50.149Z" }, + { url = "https://files.pythonhosted.org/packages/b1/5e/f77dc6b9036943e285ba76b49e118d9ea929885becb0a29ba8a7c75e29fe/pyyaml-6.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c", size = 839261, upload-time = "2025-09-25T21:32:51.808Z" }, + { url = "https://files.pythonhosted.org/packages/ce/88/a9db1376aa2a228197c58b37302f284b5617f56a5d959fd1763fb1675ce6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065", size = 805272, upload-time = "2025-09-25T21:32:52.941Z" }, + { url = "https://files.pythonhosted.org/packages/da/92/1446574745d74df0c92e6aa4a7b0b3130706a4142b2d1a5869f2eaa423c6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65", size = 829923, upload-time = "2025-09-25T21:32:54.537Z" }, + { url = "https://files.pythonhosted.org/packages/f0/7a/1c7270340330e575b92f397352af856a8c06f230aa3e76f86b39d01b416a/pyyaml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9", size = 174062, upload-time = "2025-09-25T21:32:55.767Z" }, + { url = "https://files.pythonhosted.org/packages/f1/12/de94a39c2ef588c7e6455cfbe7343d3b2dc9d6b6b2f40c4c6565744c873d/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b", size = 149341, upload-time = "2025-09-25T21:32:56.828Z" }, +] + +[[package]] +name = "regex" +version = "2026.2.28" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/8b/71/41455aa99a5a5ac1eaf311f5d8efd9ce6433c03ac1e0962de163350d0d97/regex-2026.2.28.tar.gz", hash = "sha256:a729e47d418ea11d03469f321aaf67cdee8954cde3ff2cf8403ab87951ad10f2", size = 415184, upload-time = "2026-02-28T02:19:42.792Z" } 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/04/db/8cbfd0ba3f302f2d09dd0019a9fcab74b63fee77a76c937d0e33161fb8c1/regex-2026.2.28-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e621fb7c8dc147419b28e1702f58a0177ff8308a76fa295c71f3e7827849f5d9", size = 488462, upload-time = "2026-02-28T02:16:22.616Z" }, + { url = "https://files.pythonhosted.org/packages/5d/10/ccc22c52802223f2368731964ddd117799e1390ffc39dbb31634a83022ee/regex-2026.2.28-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0d5bef2031cbf38757a0b0bc4298bb4824b6332d28edc16b39247228fbdbad97", size = 290774, upload-time = "2026-02-28T02:16:23.993Z" }, + { url = "https://files.pythonhosted.org/packages/62/b9/6796b3bf3101e64117201aaa3a5a030ec677ecf34b3cd6141b5d5c6c67d5/regex-2026.2.28-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bcb399ed84eabf4282587ba151f2732ad8168e66f1d3f85b1d038868fe547703", size = 288724, upload-time = "2026-02-28T02:16:25.403Z" }, + { url = "https://files.pythonhosted.org/packages/9c/02/291c0ae3f3a10cea941d0f5366da1843d8d1fa8a25b0671e20a0e454bb38/regex-2026.2.28-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7c1b34dfa72f826f535b20712afa9bb3ba580020e834f3c69866c5bddbf10098", size = 791924, upload-time = "2026-02-28T02:16:26.863Z" }, + { url = "https://files.pythonhosted.org/packages/0f/57/f0235cc520d9672742196c5c15098f8f703f2758d48d5a7465a56333e496/regex-2026.2.28-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:851fa70df44325e1e4cdb79c5e676e91a78147b1b543db2aec8734d2add30ec2", size = 860095, upload-time = "2026-02-28T02:16:28.772Z" }, + { url = "https://files.pythonhosted.org/packages/b3/7c/393c94cbedda79a0f5f2435ebd01644aba0b338d327eb24b4aa5b8d6c07f/regex-2026.2.28-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:516604edd17b1c2c3e579cf4e9b25a53bf8fa6e7cedddf1127804d3e0140ca64", size = 906583, upload-time = "2026-02-28T02:16:30.977Z" }, + { url = "https://files.pythonhosted.org/packages/2c/73/a72820f47ca5abf2b5d911d0407ba5178fc52cf9780191ed3a54f5f419a2/regex-2026.2.28-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e7ce83654d1ab701cb619285a18a8e5a889c1216d746ddc710c914ca5fd71022", size = 800234, upload-time = "2026-02-28T02:16:32.55Z" }, + { url = "https://files.pythonhosted.org/packages/34/b3/6e6a4b7b31fa998c4cf159a12cbeaf356386fbd1a8be743b1e80a3da51e4/regex-2026.2.28-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f2791948f7c70bb9335a9102df45e93d428f4b8128020d85920223925d73b9e1", size = 772803, upload-time = "2026-02-28T02:16:34.029Z" }, + { url = "https://files.pythonhosted.org/packages/10/e7/5da0280c765d5a92af5e1cd324b3fe8464303189cbaa449de9a71910e273/regex-2026.2.28-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:03a83cc26aa2acda6b8b9dfe748cf9e84cbd390c424a1de34fdcef58961a297a", size = 781117, upload-time = "2026-02-28T02:16:36.253Z" }, + { url = "https://files.pythonhosted.org/packages/76/39/0b8d7efb256ae34e1b8157acc1afd8758048a1cf0196e1aec2e71fd99f4b/regex-2026.2.28-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:ec6f5674c5dc836994f50f1186dd1fafde4be0666aae201ae2fcc3d29d8adf27", size = 854224, upload-time = "2026-02-28T02:16:38.119Z" }, + { url = "https://files.pythonhosted.org/packages/21/ff/a96d483ebe8fe6d1c67907729202313895d8de8495569ec319c6f29d0438/regex-2026.2.28-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:50c2fc924749543e0eacc93ada6aeeb3ea5f6715825624baa0dccaec771668ae", size = 761898, upload-time = "2026-02-28T02:16:40.333Z" }, + { url = "https://files.pythonhosted.org/packages/89/bd/d4f2e75cb4a54b484e796017e37c0d09d8a0a837de43d17e238adf163f4e/regex-2026.2.28-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:ba55c50f408fb5c346a3a02d2ce0ebc839784e24f7c9684fde328ff063c3cdea", size = 844832, upload-time = "2026-02-28T02:16:41.875Z" }, + { url = "https://files.pythonhosted.org/packages/8a/a7/428a135cf5e15e4e11d1e696eb2bf968362f8ea8a5f237122e96bc2ae950/regex-2026.2.28-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:edb1b1b3a5576c56f08ac46f108c40333f222ebfd5cf63afdfa3aab0791ebe5b", size = 788347, upload-time = "2026-02-28T02:16:43.472Z" }, + { url = "https://files.pythonhosted.org/packages/a9/59/68691428851cf9c9c3707217ab1d9b47cfeec9d153a49919e6c368b9e926/regex-2026.2.28-cp311-cp311-win32.whl", hash = "sha256:948c12ef30ecedb128903c2c2678b339746eb7c689c5c21957c4a23950c96d15", size = 266033, upload-time = "2026-02-28T02:16:45.094Z" }, + { url = "https://files.pythonhosted.org/packages/42/8b/1483de1c57024e89296cbcceb9cccb3f625d416ddb46e570be185c9b05a9/regex-2026.2.28-cp311-cp311-win_amd64.whl", hash = "sha256:fd63453f10d29097cc3dc62d070746523973fb5aa1c66d25f8558bebd47fed61", size = 277978, upload-time = "2026-02-28T02:16:46.75Z" }, + { url = "https://files.pythonhosted.org/packages/a4/36/abec45dc6e7252e3dbc797120496e43bb5730a7abf0d9cb69340696a2f2d/regex-2026.2.28-cp311-cp311-win_arm64.whl", hash = "sha256:00f2b8d9615aa165fdff0a13f1a92049bfad555ee91e20d246a51aa0b556c60a", size = 270340, upload-time = "2026-02-28T02:16:48.626Z" }, + { url = "https://files.pythonhosted.org/packages/07/42/9061b03cf0fc4b5fa2c3984cbbaed54324377e440a5c5a29d29a72518d62/regex-2026.2.28-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:fcf26c3c6d0da98fada8ae4ef0aa1c3405a431c0a77eb17306d38a89b02adcd7", size = 489574, upload-time = "2026-02-28T02:16:50.455Z" }, + { url = "https://files.pythonhosted.org/packages/77/83/0c8a5623a233015595e3da499c5a1c13720ac63c107897a6037bb97af248/regex-2026.2.28-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:02473c954af35dd2defeb07e44182f5705b30ea3f351a7cbffa9177beb14da5d", size = 291426, upload-time = "2026-02-28T02:16:52.52Z" }, + { url = "https://files.pythonhosted.org/packages/9e/06/3ef1ac6910dc3295ebd71b1f9bfa737e82cfead211a18b319d45f85ddd09/regex-2026.2.28-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9b65d33a17101569f86d9c5966a8b1d7fbf8afdda5a8aa219301b0a80f58cf7d", size = 289200, upload-time = "2026-02-28T02:16:54.08Z" }, + { url = "https://files.pythonhosted.org/packages/dd/c9/8cc8d850b35ab5650ff6756a1cb85286e2000b66c97520b29c1587455344/regex-2026.2.28-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e71dcecaa113eebcc96622c17692672c2d104b1d71ddf7adeda90da7ddeb26fc", size = 796765, upload-time = "2026-02-28T02:16:55.905Z" }, + { url = "https://files.pythonhosted.org/packages/e9/5d/57702597627fc23278ebf36fbb497ac91c0ce7fec89ac6c81e420ca3e38c/regex-2026.2.28-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:481df4623fa4969c8b11f3433ed7d5e3dc9cec0f008356c3212b3933fb77e3d8", size = 863093, upload-time = "2026-02-28T02:16:58.094Z" }, + { url = "https://files.pythonhosted.org/packages/02/6d/f3ecad537ca2811b4d26b54ca848cf70e04fcfc138667c146a9f3157779c/regex-2026.2.28-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:64e7c6ad614573e0640f271e811a408d79a9e1fe62a46adb602f598df42a818d", size = 909455, upload-time = "2026-02-28T02:17:00.918Z" }, + { url = "https://files.pythonhosted.org/packages/9e/40/bb226f203caa22c1043c1ca79b36340156eca0f6a6742b46c3bb222a3a57/regex-2026.2.28-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d6b08a06976ff4fb0d83077022fde3eca06c55432bb997d8c0495b9a4e9872f4", size = 802037, upload-time = "2026-02-28T02:17:02.842Z" }, + { url = "https://files.pythonhosted.org/packages/44/7c/c6d91d8911ac6803b45ca968e8e500c46934e58c0903cbc6d760ee817a0a/regex-2026.2.28-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:864cdd1a2ef5716b0ab468af40139e62ede1b3a53386b375ec0786bb6783fc05", size = 775113, upload-time = "2026-02-28T02:17:04.506Z" }, + { url = "https://files.pythonhosted.org/packages/dc/8d/4a9368d168d47abd4158580b8c848709667b1cd293ff0c0c277279543bd0/regex-2026.2.28-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:511f7419f7afab475fd4d639d4aedfc54205bcb0800066753ef68a59f0f330b5", size = 784194, upload-time = "2026-02-28T02:17:06.888Z" }, + { url = "https://files.pythonhosted.org/packages/cc/bf/2c72ab5d8b7be462cb1651b5cc333da1d0068740342f350fcca3bca31947/regex-2026.2.28-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:b42f7466e32bf15a961cf09f35fa6323cc72e64d3d2c990b10de1274a5da0a59", size = 856846, upload-time = "2026-02-28T02:17:09.11Z" }, + { url = "https://files.pythonhosted.org/packages/7c/f4/6b65c979bb6d09f51bb2d2a7bc85de73c01ec73335d7ddd202dcb8cd1c8f/regex-2026.2.28-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:8710d61737b0c0ce6836b1da7109f20d495e49b3809f30e27e9560be67a257bf", size = 763516, upload-time = "2026-02-28T02:17:11.004Z" }, + { url = "https://files.pythonhosted.org/packages/8e/32/29ea5e27400ee86d2cc2b4e80aa059df04eaf78b4f0c18576ae077aeff68/regex-2026.2.28-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:4390c365fd2d45278f45afd4673cb90f7285f5701607e3ad4274df08e36140ae", size = 849278, upload-time = "2026-02-28T02:17:12.693Z" }, + { url = "https://files.pythonhosted.org/packages/1d/91/3233d03b5f865111cd517e1c95ee8b43e8b428d61fa73764a80c9bb6f537/regex-2026.2.28-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:cb3b1db8ff6c7b8bf838ab05583ea15230cb2f678e569ab0e3a24d1e8320940b", size = 790068, upload-time = "2026-02-28T02:17:14.9Z" }, + { url = "https://files.pythonhosted.org/packages/76/92/abc706c1fb03b4580a09645b206a3fc032f5a9f457bc1a8038ac555658ab/regex-2026.2.28-cp312-cp312-win32.whl", hash = "sha256:f8ed9a5d4612df9d4de15878f0bc6aa7a268afbe5af21a3fdd97fa19516e978c", size = 266416, upload-time = "2026-02-28T02:17:17.15Z" }, + { url = "https://files.pythonhosted.org/packages/fa/06/2a6f7dff190e5fa9df9fb4acf2fdf17a1aa0f7f54596cba8de608db56b3a/regex-2026.2.28-cp312-cp312-win_amd64.whl", hash = "sha256:01d65fd24206c8e1e97e2e31b286c59009636c022eb5d003f52760b0f42155d4", size = 277297, upload-time = "2026-02-28T02:17:18.723Z" }, + { url = "https://files.pythonhosted.org/packages/b7/f0/58a2484851fadf284458fdbd728f580d55c1abac059ae9f048c63b92f427/regex-2026.2.28-cp312-cp312-win_arm64.whl", hash = "sha256:c0b5ccbb8ffb433939d248707d4a8b31993cb76ab1a0187ca886bf50e96df952", size = 270408, upload-time = "2026-02-28T02:17:20.328Z" }, + { url = "https://files.pythonhosted.org/packages/87/f6/dc9ef48c61b79c8201585bf37fa70cd781977da86e466cd94e8e95d2443b/regex-2026.2.28-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:6d63a07e5ec8ce7184452cb00c41c37b49e67dc4f73b2955b5b8e782ea970784", size = 489311, upload-time = "2026-02-28T02:17:22.591Z" }, + { url = "https://files.pythonhosted.org/packages/95/c8/c20390f2232d3f7956f420f4ef1852608ad57aa26c3dd78516cb9f3dc913/regex-2026.2.28-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e59bc8f30414d283ae8ee1617b13d8112e7135cb92830f0ec3688cb29152585a", size = 291285, upload-time = "2026-02-28T02:17:24.355Z" }, + { url = "https://files.pythonhosted.org/packages/d2/a6/ba1068a631ebd71a230e7d8013fcd284b7c89c35f46f34a7da02082141b1/regex-2026.2.28-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:de0cf053139f96219ccfabb4a8dd2d217c8c82cb206c91d9f109f3f552d6b43d", size = 289051, upload-time = "2026-02-28T02:17:26.722Z" }, + { url = "https://files.pythonhosted.org/packages/1d/1b/7cc3b7af4c244c204b7a80924bd3d85aecd9ba5bc82b485c5806ee8cda9e/regex-2026.2.28-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fb4db2f17e6484904f986c5a657cec85574c76b5c5e61c7aae9ffa1bc6224f95", size = 796842, upload-time = "2026-02-28T02:17:29.064Z" }, + { url = "https://files.pythonhosted.org/packages/24/87/26bd03efc60e0d772ac1e7b60a2e6325af98d974e2358f659c507d3c76db/regex-2026.2.28-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:52b017b35ac2214d0db5f4f90e303634dc44e4aba4bd6235a27f97ecbe5b0472", size = 863083, upload-time = "2026-02-28T02:17:31.363Z" }, + { url = "https://files.pythonhosted.org/packages/ae/54/aeaf4afb1aa0a65e40de52a61dc2ac5b00a83c6cb081c8a1d0dda74f3010/regex-2026.2.28-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:69fc560ccbf08a09dc9b52ab69cacfae51e0ed80dc5693078bdc97db2f91ae96", size = 909412, upload-time = "2026-02-28T02:17:33.248Z" }, + { url = "https://files.pythonhosted.org/packages/12/2f/049901def913954e640d199bbc6a7ca2902b6aeda0e5da9d17f114100ec2/regex-2026.2.28-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e61eea47230eba62a31f3e8a0e3164d0f37ef9f40529fb2c79361bc6b53d2a92", size = 802101, upload-time = "2026-02-28T02:17:35.053Z" }, + { url = "https://files.pythonhosted.org/packages/7d/a5/512fb9ff7f5b15ea204bb1967ebb649059446decacccb201381f9fa6aad4/regex-2026.2.28-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4f5c0b182ad4269e7381b7c27fdb0408399881f7a92a4624fd5487f2971dfc11", size = 775260, upload-time = "2026-02-28T02:17:37.692Z" }, + { url = "https://files.pythonhosted.org/packages/d1/a8/9a92935878aba19bd72706b9db5646a6f993d99b3f6ed42c02ec8beb1d61/regex-2026.2.28-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:96f6269a2882fbb0ee76967116b83679dc628e68eaea44e90884b8d53d833881", size = 784311, upload-time = "2026-02-28T02:17:39.855Z" }, + { url = "https://files.pythonhosted.org/packages/09/d3/fc51a8a738a49a6b6499626580554c9466d3ea561f2b72cfdc72e4149773/regex-2026.2.28-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:b5acd4b6a95f37c3c3828e5d053a7d4edaedb85de551db0153754924cb7c83e3", size = 856876, upload-time = "2026-02-28T02:17:42.317Z" }, + { url = "https://files.pythonhosted.org/packages/08/b7/2e641f3d084b120ca4c52e8c762a78da0b32bf03ef546330db3e2635dc5f/regex-2026.2.28-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:2234059cfe33d9813a3677ef7667999caea9eeaa83fef98eb6ce15c6cf9e0215", size = 763632, upload-time = "2026-02-28T02:17:45.073Z" }, + { url = "https://files.pythonhosted.org/packages/fe/6d/0009021d97e79ee99f3d8641f0a8d001eed23479ade4c3125a5480bf3e2d/regex-2026.2.28-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:c15af43c72a7fb0c97cbc66fa36a43546eddc5c06a662b64a0cbf30d6ac40944", size = 849320, upload-time = "2026-02-28T02:17:47.192Z" }, + { url = "https://files.pythonhosted.org/packages/05/7a/51cfbad5758f8edae430cb21961a9c8d04bce1dae4d2d18d4186eec7cfa1/regex-2026.2.28-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9185cc63359862a6e80fe97f696e04b0ad9a11c4ac0a4a927f979f611bfe3768", size = 790152, upload-time = "2026-02-28T02:17:49.067Z" }, + { url = "https://files.pythonhosted.org/packages/90/3d/a83e2b6b3daa142acb8c41d51de3876186307d5cb7490087031747662500/regex-2026.2.28-cp313-cp313-win32.whl", hash = "sha256:fb66e5245db9652abd7196ace599b04d9c0e4aa7c8f0e2803938377835780081", size = 266398, upload-time = "2026-02-28T02:17:50.744Z" }, + { url = "https://files.pythonhosted.org/packages/85/4f/16e9ebb1fe5425e11b9596c8d57bf8877dcb32391da0bfd33742e3290637/regex-2026.2.28-cp313-cp313-win_amd64.whl", hash = "sha256:71a911098be38c859ceb3f9a9ce43f4ed9f4c6720ad8684a066ea246b76ad9ff", size = 277282, upload-time = "2026-02-28T02:17:53.074Z" }, + { url = "https://files.pythonhosted.org/packages/07/b4/92851335332810c5a89723bf7a7e35c7209f90b7d4160024501717b28cc9/regex-2026.2.28-cp313-cp313-win_arm64.whl", hash = "sha256:39bb5727650b9a0275c6a6690f9bb3fe693a7e6cc5c3155b1240aedf8926423e", size = 270382, upload-time = "2026-02-28T02:17:54.888Z" }, + { url = "https://files.pythonhosted.org/packages/24/07/6c7e4cec1e585959e96cbc24299d97e4437a81173217af54f1804994e911/regex-2026.2.28-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:97054c55db06ab020342cc0d35d6f62a465fa7662871190175f1ad6c655c028f", size = 492541, upload-time = "2026-02-28T02:17:56.813Z" }, + { url = "https://files.pythonhosted.org/packages/7c/13/55eb22ada7f43d4f4bb3815b6132183ebc331c81bd496e2d1f3b8d862e0d/regex-2026.2.28-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0d25a10811de831c2baa6aef3c0be91622f44dd8d31dd12e69f6398efb15e48b", size = 292984, upload-time = "2026-02-28T02:17:58.538Z" }, + { url = "https://files.pythonhosted.org/packages/5b/11/c301f8cb29ce9644a5ef85104c59244e6e7e90994a0f458da4d39baa8e17/regex-2026.2.28-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:d6cfe798d8da41bb1862ed6e0cba14003d387c3c0c4a5d45591076ae9f0ce2f8", size = 291509, upload-time = "2026-02-28T02:18:00.208Z" }, + { url = "https://files.pythonhosted.org/packages/b5/43/aabe384ec1994b91796e903582427bc2ffaed9c4103819ed3c16d8e749f3/regex-2026.2.28-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fd0ce43e71d825b7c0661f9c54d4d74bd97c56c3fd102a8985bcfea48236bacb", size = 809429, upload-time = "2026-02-28T02:18:02.328Z" }, + { url = "https://files.pythonhosted.org/packages/04/b8/8d2d987a816720c4f3109cee7c06a4b24ad0e02d4fc74919ab619e543737/regex-2026.2.28-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:00945d007fd74a9084d2ab79b695b595c6b7ba3698972fadd43e23230c6979c1", size = 869422, upload-time = "2026-02-28T02:18:04.23Z" }, + { url = "https://files.pythonhosted.org/packages/fc/ad/2c004509e763c0c3719f97c03eca26473bffb3868d54c5f280b8cd4f9e3d/regex-2026.2.28-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:bec23c11cbbf09a4df32fe50d57cbdd777bc442269b6e39a1775654f1c95dee2", size = 915175, upload-time = "2026-02-28T02:18:06.791Z" }, + { url = "https://files.pythonhosted.org/packages/55/c2/fd429066da487ef555a9da73bf214894aec77fc8c66a261ee355a69871a8/regex-2026.2.28-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5cdcc17d935c8f9d3f4db5c2ebe2640c332e3822ad5d23c2f8e0228e6947943a", size = 812044, upload-time = "2026-02-28T02:18:08.736Z" }, + { url = "https://files.pythonhosted.org/packages/5b/ca/feedb7055c62a3f7f659971bf45f0e0a87544b6b0cf462884761453f97c5/regex-2026.2.28-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a448af01e3d8031c89c5d902040b124a5e921a25c4e5e07a861ca591ce429341", size = 782056, upload-time = "2026-02-28T02:18:10.777Z" }, + { url = "https://files.pythonhosted.org/packages/95/30/1aa959ed0d25c1dd7dd5047ea8ba482ceaef38ce363c401fd32a6b923e60/regex-2026.2.28-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:10d28e19bd4888e4abf43bd3925f3c134c52fdf7259219003588a42e24c2aa25", size = 798743, upload-time = "2026-02-28T02:18:13.025Z" }, + { url = "https://files.pythonhosted.org/packages/3b/1f/dadb9cf359004784051c897dcf4d5d79895f73a1bbb7b827abaa4814ae80/regex-2026.2.28-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:99985a2c277dcb9ccb63f937451af5d65177af1efdeb8173ac55b61095a0a05c", size = 864633, upload-time = "2026-02-28T02:18:16.84Z" }, + { url = "https://files.pythonhosted.org/packages/a7/f1/b9a25eb24e1cf79890f09e6ec971ee5b511519f1851de3453bc04f6c902b/regex-2026.2.28-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:e1e7b24cb3ae9953a560c563045d1ba56ee4749fbd05cf21ba571069bd7be81b", size = 770862, upload-time = "2026-02-28T02:18:18.892Z" }, + { url = "https://files.pythonhosted.org/packages/02/9a/c5cb10b7aa6f182f9247a30cc9527e326601f46f4df864ac6db588d11fcd/regex-2026.2.28-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:d8511a01d0e4ee1992eb3ba19e09bc1866fe03f05129c3aec3fdc4cbc77aad3f", size = 854788, upload-time = "2026-02-28T02:18:21.475Z" }, + { url = "https://files.pythonhosted.org/packages/0a/50/414ba0731c4bd40b011fa4703b2cc86879ec060c64f2a906e65a56452589/regex-2026.2.28-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:aaffaecffcd2479ce87aa1e74076c221700b7c804e48e98e62500ee748f0f550", size = 800184, upload-time = "2026-02-28T02:18:23.492Z" }, + { url = "https://files.pythonhosted.org/packages/69/50/0c7290987f97e7e6830b0d853f69dc4dc5852c934aae63e7fdcd76b4c383/regex-2026.2.28-cp313-cp313t-win32.whl", hash = "sha256:ef77bdde9c9eba3f7fa5b58084b29bbcc74bcf55fdbeaa67c102a35b5bd7e7cc", size = 269137, upload-time = "2026-02-28T02:18:25.375Z" }, + { url = "https://files.pythonhosted.org/packages/68/80/ef26ff90e74ceb4051ad6efcbbb8a4be965184a57e879ebcbdef327d18fa/regex-2026.2.28-cp313-cp313t-win_amd64.whl", hash = "sha256:98adf340100cbe6fbaf8e6dc75e28f2c191b1be50ffefe292fb0e6f6eefdb0d8", size = 280682, upload-time = "2026-02-28T02:18:27.205Z" }, + { url = "https://files.pythonhosted.org/packages/69/8b/fbad9c52e83ffe8f97e3ed1aa0516e6dff6bb633a41da9e64645bc7efdc5/regex-2026.2.28-cp313-cp313t-win_arm64.whl", hash = "sha256:2fb950ac1d88e6b6a9414381f403797b236f9fa17e1eee07683af72b1634207b", size = 271735, upload-time = "2026-02-28T02:18:29.015Z" }, + { url = "https://files.pythonhosted.org/packages/cf/03/691015f7a7cb1ed6dacb2ea5de5682e4858e05a4c5506b2839cd533bbcd6/regex-2026.2.28-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:78454178c7df31372ea737996fb7f36b3c2c92cccc641d251e072478afb4babc", size = 489497, upload-time = "2026-02-28T02:18:30.889Z" }, + { url = "https://files.pythonhosted.org/packages/c6/ba/8db8fd19afcbfa0e1036eaa70c05f20ca8405817d4ad7a38a6b4c2f031ac/regex-2026.2.28-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:5d10303dd18cedfd4d095543998404df656088240bcfd3cd20a8f95b861f74bd", size = 291295, upload-time = "2026-02-28T02:18:33.426Z" }, + { url = "https://files.pythonhosted.org/packages/5a/79/9aa0caf089e8defef9b857b52fc53801f62ff868e19e5c83d4a96612eba1/regex-2026.2.28-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:19a9c9e0a8f24f39d575a6a854d516b48ffe4cbdcb9de55cb0570a032556ecff", size = 289275, upload-time = "2026-02-28T02:18:35.247Z" }, + { url = "https://files.pythonhosted.org/packages/eb/26/ee53117066a30ef9c883bf1127eece08308ccf8ccd45c45a966e7a665385/regex-2026.2.28-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:09500be324f49b470d907b3ef8af9afe857f5cca486f853853f7945ddbf75911", size = 797176, upload-time = "2026-02-28T02:18:37.15Z" }, + { url = "https://files.pythonhosted.org/packages/05/1b/67fb0495a97259925f343ae78b5d24d4a6624356ae138b57f18bd43006e4/regex-2026.2.28-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:fb1c4ff62277d87a7335f2c1ea4e0387b8f2b3ad88a64efd9943906aafad4f33", size = 863813, upload-time = "2026-02-28T02:18:39.478Z" }, + { url = "https://files.pythonhosted.org/packages/a0/1d/93ac9bbafc53618091c685c7ed40239a90bf9f2a82c983f0baa97cb7ae07/regex-2026.2.28-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b8b3f1be1738feadc69f62daa250c933e85c6f34fa378f54a7ff43807c1b9117", size = 908678, upload-time = "2026-02-28T02:18:41.619Z" }, + { url = "https://files.pythonhosted.org/packages/c7/7a/a8f5e0561702b25239846a16349feece59712ae20598ebb205580332a471/regex-2026.2.28-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dc8ed8c3f41c27acb83f7b6a9eb727a73fc6663441890c5cb3426a5f6a91ce7d", size = 801528, upload-time = "2026-02-28T02:18:43.624Z" }, + { url = "https://files.pythonhosted.org/packages/96/5d/ed6d4cbde80309854b1b9f42d9062fee38ade15f7eb4909f6ef2440403b5/regex-2026.2.28-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fa539be029844c0ce1114762d2952ab6cfdd7c7c9bd72e0db26b94c3c36dcc5a", size = 775373, upload-time = "2026-02-28T02:18:46.102Z" }, + { url = "https://files.pythonhosted.org/packages/6a/e9/6e53c34e8068b9deec3e87210086ecb5b9efebdefca6b0d3fa43d66dcecb/regex-2026.2.28-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7900157786428a79615a8264dac1f12c9b02957c473c8110c6b1f972dcecaddf", size = 784859, upload-time = "2026-02-28T02:18:48.269Z" }, + { url = "https://files.pythonhosted.org/packages/48/3c/736e1c7ca7f0dcd2ae33819888fdc69058a349b7e5e84bc3e2f296bbf794/regex-2026.2.28-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:0b1d2b07614d95fa2bf8a63fd1e98bd8fa2b4848dc91b1efbc8ba219fdd73952", size = 857813, upload-time = "2026-02-28T02:18:50.576Z" }, + { url = "https://files.pythonhosted.org/packages/6e/7c/48c4659ad9da61f58e79dbe8c05223e0006696b603c16eb6b5cbfbb52c27/regex-2026.2.28-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:b389c61aa28a79c2e0527ac36da579869c2e235a5b208a12c5b5318cda2501d8", size = 763705, upload-time = "2026-02-28T02:18:52.59Z" }, + { url = "https://files.pythonhosted.org/packages/cf/a1/bc1c261789283128165f71b71b4b221dd1b79c77023752a6074c102f18d8/regex-2026.2.28-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:f467cb602f03fbd1ab1908f68b53c649ce393fde056628dc8c7e634dab6bfc07", size = 848734, upload-time = "2026-02-28T02:18:54.595Z" }, + { url = "https://files.pythonhosted.org/packages/10/d8/979407faf1397036e25a5ae778157366a911c0f382c62501009f4957cf86/regex-2026.2.28-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:e8c8cb2deba42f5ec1ede46374e990f8adc5e6456a57ac1a261b19be6f28e4e6", size = 789871, upload-time = "2026-02-28T02:18:57.34Z" }, + { url = "https://files.pythonhosted.org/packages/03/23/da716821277115fcb1f4e3de1e5dc5023a1e6533598c486abf5448612579/regex-2026.2.28-cp314-cp314-win32.whl", hash = "sha256:9036b400b20e4858d56d117108d7813ed07bb7803e3eed766675862131135ca6", size = 271825, upload-time = "2026-02-28T02:18:59.202Z" }, + { url = "https://files.pythonhosted.org/packages/91/ff/90696f535d978d5f16a52a419be2770a8d8a0e7e0cfecdbfc31313df7fab/regex-2026.2.28-cp314-cp314-win_amd64.whl", hash = "sha256:1d367257cd86c1cbb97ea94e77b373a0bbc2224976e247f173d19e8f18b4afa7", size = 280548, upload-time = "2026-02-28T02:19:01.049Z" }, + { url = "https://files.pythonhosted.org/packages/69/f9/5e1b5652fc0af3fcdf7677e7df3ad2a0d47d669b34ac29a63bb177bb731b/regex-2026.2.28-cp314-cp314-win_arm64.whl", hash = "sha256:5e68192bb3a1d6fb2836da24aa494e413ea65853a21505e142e5b1064a595f3d", size = 273444, upload-time = "2026-02-28T02:19:03.255Z" }, + { url = "https://files.pythonhosted.org/packages/d3/eb/8389f9e940ac89bcf58d185e230a677b4fd07c5f9b917603ad5c0f8fa8fe/regex-2026.2.28-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:a5dac14d0872eeb35260a8e30bac07ddf22adc1e3a0635b52b02e180d17c9c7e", size = 492546, upload-time = "2026-02-28T02:19:05.378Z" }, + { url = "https://files.pythonhosted.org/packages/7b/c7/09441d27ce2a6fa6a61ea3150ea4639c1dcda9b31b2ea07b80d6937b24dd/regex-2026.2.28-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:ec0c608b7a7465ffadb344ed7c987ff2f11ee03f6a130b569aa74d8a70e8333c", size = 292986, upload-time = "2026-02-28T02:19:07.24Z" }, + { url = "https://files.pythonhosted.org/packages/fb/69/4144b60ed7760a6bd235e4087041f487aa4aa62b45618ce018b0c14833ea/regex-2026.2.28-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c7815afb0ca45456613fdaf60ea9c993715511c8d53a83bc468305cbc0ee23c7", size = 291518, upload-time = "2026-02-28T02:19:09.698Z" }, + { url = "https://files.pythonhosted.org/packages/2d/be/77e5426cf5948c82f98c53582009ca9e94938c71f73a8918474f2e2990bb/regex-2026.2.28-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b059e71ec363968671693a78c5053bd9cb2fe410f9b8e4657e88377ebd603a2e", size = 809464, upload-time = "2026-02-28T02:19:12.494Z" }, + { url = "https://files.pythonhosted.org/packages/45/99/2c8c5ac90dc7d05c6e7d8e72c6a3599dc08cd577ac476898e91ca787d7f1/regex-2026.2.28-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b8cf76f1a29f0e99dcfd7aef1551a9827588aae5a737fe31442021165f1920dc", size = 869553, upload-time = "2026-02-28T02:19:15.151Z" }, + { url = "https://files.pythonhosted.org/packages/53/34/daa66a342f0271e7737003abf6c3097aa0498d58c668dbd88362ef94eb5d/regex-2026.2.28-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:180e08a435a0319e6a4821c3468da18dc7001987e1c17ae1335488dfe7518dd8", size = 915289, upload-time = "2026-02-28T02:19:17.331Z" }, + { url = "https://files.pythonhosted.org/packages/c5/c7/e22c2aaf0a12e7e22ab19b004bb78d32ca1ecc7ef245949935463c5567de/regex-2026.2.28-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1e496956106fd59ba6322a8ea17141a27c5040e5ee8f9433ae92d4e5204462a0", size = 812156, upload-time = "2026-02-28T02:19:20.011Z" }, + { url = "https://files.pythonhosted.org/packages/7f/bb/2dc18c1efd9051cf389cd0d7a3a4d90f6804b9fff3a51b5dc3c85b935f71/regex-2026.2.28-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bba2b18d70eeb7b79950f12f633beeecd923f7c9ad6f6bae28e59b4cb3ab046b", size = 782215, upload-time = "2026-02-28T02:19:22.047Z" }, + { url = "https://files.pythonhosted.org/packages/17/1e/9e4ec9b9013931faa32226ec4aa3c71fe664a6d8a2b91ac56442128b332f/regex-2026.2.28-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:6db7bfae0f8a2793ff1f7021468ea55e2699d0790eb58ee6ab36ae43aa00bc5b", size = 798925, upload-time = "2026-02-28T02:19:24.173Z" }, + { url = "https://files.pythonhosted.org/packages/71/57/a505927e449a9ccb41e2cc8d735e2abe3444b0213d1cf9cb364a8c1f2524/regex-2026.2.28-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:d0b02e8b7e5874b48ae0f077ecca61c1a6a9f9895e9c6dfb191b55b242862033", size = 864701, upload-time = "2026-02-28T02:19:26.376Z" }, + { url = "https://files.pythonhosted.org/packages/a6/ad/c62cb60cdd93e13eac5b3d9d6bd5d284225ed0e3329426f94d2552dd7cca/regex-2026.2.28-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:25b6eb660c5cf4b8c3407a1ed462abba26a926cc9965e164268a3267bcc06a43", size = 770899, upload-time = "2026-02-28T02:19:29.38Z" }, + { url = "https://files.pythonhosted.org/packages/3c/5a/874f861f5c3d5ab99633e8030dee1bc113db8e0be299d1f4b07f5b5ec349/regex-2026.2.28-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:5a932ea8ad5d0430351ff9c76c8db34db0d9f53c1d78f06022a21f4e290c5c18", size = 854727, upload-time = "2026-02-28T02:19:31.494Z" }, + { url = "https://files.pythonhosted.org/packages/6b/ca/d2c03b0efde47e13db895b975b2be6a73ed90b8ba963677927283d43bf74/regex-2026.2.28-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:1c2c95e1a2b0f89d01e821ff4de1be4b5d73d1f4b0bf679fa27c1ad8d2327f1a", size = 800366, upload-time = "2026-02-28T02:19:34.248Z" }, + { url = "https://files.pythonhosted.org/packages/14/bd/ee13b20b763b8989f7c75d592bfd5de37dc1181814a2a2747fedcf97e3ba/regex-2026.2.28-cp314-cp314t-win32.whl", hash = "sha256:bbb882061f742eb5d46f2f1bd5304055be0a66b783576de3d7eef1bed4778a6e", size = 274936, upload-time = "2026-02-28T02:19:36.313Z" }, + { url = "https://files.pythonhosted.org/packages/cb/e7/d8020e39414c93af7f0d8688eabcecece44abfd5ce314b21dfda0eebd3d8/regex-2026.2.28-cp314-cp314t-win_amd64.whl", hash = "sha256:6591f281cb44dc13de9585b552cec6fc6cf47fb2fe7a48892295ee9bc4a612f9", size = 284779, upload-time = "2026-02-28T02:19:38.625Z" }, + { url = "https://files.pythonhosted.org/packages/13/c0/ad225f4a405827486f1955283407cf758b6d2fb966712644c5f5aef33d1b/regex-2026.2.28-cp314-cp314t-win_arm64.whl", hash = "sha256:dee50f1be42222f89767b64b283283ef963189da0dda4a515aa54a5563c62dec", size = 275010, upload-time = "2026-02-28T02:19:40.65Z" }, ] [[package]] @@ -1345,16 +1443,16 @@ wheels = [ ] [[package]] -name = "requests-oauthlib" -version = "2.0.0" +name = "rich" +version = "14.3.3" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "oauthlib" }, - { name = "requests" }, + { name = "markdown-it-py" }, + { name = "pygments" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/42/f2/05f29bc3913aea15eb670be136045bf5c5bbf4b99ecb839da9b422bb2c85/requests-oauthlib-2.0.0.tar.gz", hash = "sha256:b3dffaebd884d8cd778494369603a9e7b58d29111bf6b41bdc2dcd87203af4e9", size = 55650, upload-time = "2024-03-22T20:32:29.939Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b3/c6/f3b320c27991c46f43ee9d856302c70dc2d0fb2dba4842ff739d5f46b393/rich-14.3.3.tar.gz", hash = "sha256:b8daa0b9e4eef54dd8cf7c86c03713f53241884e814f4e2f5fb342fe520f639b", size = 230582, upload-time = "2026-02-19T17:23:12.474Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/3b/5d/63d4ae3b9daea098d5d6f5da83984853c1bbacd5dc826764b249fe119d24/requests_oauthlib-2.0.0-py2.py3-none-any.whl", hash = "sha256:7dd8a5c40426b779b0868c404bdef9768deccf22749cde15852df527e6269b36", size = 24179, upload-time = "2024-03-22T20:32:28.055Z" }, + { url = "https://files.pythonhosted.org/packages/14/25/b208c5683343959b670dc001595f2f3737e051da617f66c31f7c4fa93abc/rich-14.3.3-py3-none-any.whl", hash = "sha256:793431c1f8619afa7d3b52b2cdec859562b950ea0d4b6b505397612db8d5362d", size = 310458, upload-time = "2026-02-19T17:23:13.732Z" }, ] [[package]] @@ -1395,6 +1493,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/74/31/b0e29d572670dca3674eeee78e418f20bdf97fa8aa9ea71380885e175ca0/ruff-0.14.10-py3-none-win_arm64.whl", hash = "sha256:e51d046cf6dda98a4633b8a8a771451107413b0f07183b2bef03f075599e44e6", size = 13729839, upload-time = "2025-12-18T19:28:48.636Z" }, ] +[[package]] +name = "s3transfer" +version = "0.16.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "botocore" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/05/04/74127fc843314818edfa81b5540e26dd537353b123a4edc563109d8f17dd/s3transfer-0.16.0.tar.gz", hash = "sha256:8e990f13268025792229cd52fa10cb7163744bf56e719e0b9cb925ab79abf920", size = 153827, upload-time = "2025-12-01T02:30:59.114Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fc/51/727abb13f44c1fcf6d145979e1535a35794db0f6e450a0cb46aa24732fe2/s3transfer-0.16.0-py3-none-any.whl", hash = "sha256:18e25d66fed509e3868dc1572b3f427ff947dd2c56f844a5bf09481ad3f3b2fe", size = 86830, upload-time = "2025-12-01T02:30:57.729Z" }, +] + [[package]] name = "seq-smith" version = "0.5.1" @@ -1421,6 +1531,24 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/5a/be/54aac5e794a5389a26e79e4231f7b10bfe3c4ff6470eecf05dff59ce7d96/seq_smith-0.5.1-cp313-cp313-win_amd64.whl", hash = "sha256:f22243a3d03e06a761d452716ab9810b058703538250b5626219f3f77952aded", size = 262778, upload-time = "2025-12-28T04:58:38.407Z" }, ] +[[package]] +name = "shellingham" +version = "1.5.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/58/15/8b3609fd3830ef7b27b655beb4b4e9c62313a4e8da8c676e142cc210d58e/shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de", size = 10310, upload-time = "2023-10-24T04:13:40.426Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755, upload-time = "2023-10-24T04:13:38.866Z" }, +] + +[[package]] +name = "six" +version = "1.17.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" } +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 = "sniffio" version = "1.3.1" @@ -1439,6 +1567,87 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e5/30/643397144bfbfec6f6ef821f36f33e57d35946c44a2352d3c9f0ae847619/tenacity-9.1.2-py3-none-any.whl", hash = "sha256:f77bf36710d8b73a50b2dd155c97b870017ad21afe6ab300326b0371b3b05138", size = 28248, upload-time = "2025-04-02T08:25:07.678Z" }, ] +[[package]] +name = "tiktoken" +version = "0.12.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "regex" }, + { name = "requests" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7d/ab/4d017d0f76ec3171d469d80fc03dfbb4e48a4bcaddaa831b31d526f05edc/tiktoken-0.12.0.tar.gz", hash = "sha256:b18ba7ee2b093863978fcb14f74b3707cdc8d4d4d3836853ce7ec60772139931", size = 37806, upload-time = "2025-10-06T20:22:45.419Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/de/46/21ea696b21f1d6d1efec8639c204bdf20fde8bafb351e1355c72c5d7de52/tiktoken-0.12.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:6e227c7f96925003487c33b1b32265fad2fbcec2b7cf4817afb76d416f40f6bb", size = 1051565, upload-time = "2025-10-06T20:21:44.566Z" }, + { url = "https://files.pythonhosted.org/packages/c9/d9/35c5d2d9e22bb2a5f74ba48266fb56c63d76ae6f66e02feb628671c0283e/tiktoken-0.12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c06cf0fcc24c2cb2adb5e185c7082a82cba29c17575e828518c2f11a01f445aa", size = 995284, upload-time = "2025-10-06T20:21:45.622Z" }, + { url = "https://files.pythonhosted.org/packages/01/84/961106c37b8e49b9fdcf33fe007bb3a8fdcc380c528b20cc7fbba80578b8/tiktoken-0.12.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:f18f249b041851954217e9fd8e5c00b024ab2315ffda5ed77665a05fa91f42dc", size = 1129201, upload-time = "2025-10-06T20:21:47.074Z" }, + { url = "https://files.pythonhosted.org/packages/6a/d0/3d9275198e067f8b65076a68894bb52fd253875f3644f0a321a720277b8a/tiktoken-0.12.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:47a5bc270b8c3db00bb46ece01ef34ad050e364b51d406b6f9730b64ac28eded", size = 1152444, upload-time = "2025-10-06T20:21:48.139Z" }, + { url = "https://files.pythonhosted.org/packages/78/db/a58e09687c1698a7c592e1038e01c206569b86a0377828d51635561f8ebf/tiktoken-0.12.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:508fa71810c0efdcd1b898fda574889ee62852989f7c1667414736bcb2b9a4bd", size = 1195080, upload-time = "2025-10-06T20:21:49.246Z" }, + { url = "https://files.pythonhosted.org/packages/9e/1b/a9e4d2bf91d515c0f74afc526fd773a812232dd6cda33ebea7f531202325/tiktoken-0.12.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a1af81a6c44f008cba48494089dd98cccb8b313f55e961a52f5b222d1e507967", size = 1255240, upload-time = "2025-10-06T20:21:50.274Z" }, + { url = "https://files.pythonhosted.org/packages/9d/15/963819345f1b1fb0809070a79e9dd96938d4ca41297367d471733e79c76c/tiktoken-0.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:3e68e3e593637b53e56f7237be560f7a394451cb8c11079755e80ae64b9e6def", size = 879422, upload-time = "2025-10-06T20:21:51.734Z" }, + { url = "https://files.pythonhosted.org/packages/a4/85/be65d39d6b647c79800fd9d29241d081d4eeb06271f383bb87200d74cf76/tiktoken-0.12.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b97f74aca0d78a1ff21b8cd9e9925714c15a9236d6ceacf5c7327c117e6e21e8", size = 1050728, upload-time = "2025-10-06T20:21:52.756Z" }, + { url = "https://files.pythonhosted.org/packages/4a/42/6573e9129bc55c9bf7300b3a35bef2c6b9117018acca0dc760ac2d93dffe/tiktoken-0.12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2b90f5ad190a4bb7c3eb30c5fa32e1e182ca1ca79f05e49b448438c3e225a49b", size = 994049, upload-time = "2025-10-06T20:21:53.782Z" }, + { url = "https://files.pythonhosted.org/packages/66/c5/ed88504d2f4a5fd6856990b230b56d85a777feab84e6129af0822f5d0f70/tiktoken-0.12.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:65b26c7a780e2139e73acc193e5c63ac754021f160df919add909c1492c0fb37", size = 1129008, upload-time = "2025-10-06T20:21:54.832Z" }, + { url = "https://files.pythonhosted.org/packages/f4/90/3dae6cc5436137ebd38944d396b5849e167896fc2073da643a49f372dc4f/tiktoken-0.12.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:edde1ec917dfd21c1f2f8046b86348b0f54a2c0547f68149d8600859598769ad", size = 1152665, upload-time = "2025-10-06T20:21:56.129Z" }, + { url = "https://files.pythonhosted.org/packages/a3/fe/26df24ce53ffde419a42f5f53d755b995c9318908288c17ec3f3448313a3/tiktoken-0.12.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:35a2f8ddd3824608b3d650a000c1ef71f730d0c56486845705a8248da00f9fe5", size = 1194230, upload-time = "2025-10-06T20:21:57.546Z" }, + { url = "https://files.pythonhosted.org/packages/20/cc/b064cae1a0e9fac84b0d2c46b89f4e57051a5f41324e385d10225a984c24/tiktoken-0.12.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:83d16643edb7fa2c99eff2ab7733508aae1eebb03d5dfc46f5565862810f24e3", size = 1254688, upload-time = "2025-10-06T20:21:58.619Z" }, + { url = "https://files.pythonhosted.org/packages/81/10/b8523105c590c5b8349f2587e2fdfe51a69544bd5a76295fc20f2374f470/tiktoken-0.12.0-cp312-cp312-win_amd64.whl", hash = "sha256:ffc5288f34a8bc02e1ea7047b8d041104791d2ddbf42d1e5fa07822cbffe16bd", size = 878694, upload-time = "2025-10-06T20:21:59.876Z" }, + { url = "https://files.pythonhosted.org/packages/00/61/441588ee21e6b5cdf59d6870f86beb9789e532ee9718c251b391b70c68d6/tiktoken-0.12.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:775c2c55de2310cc1bc9a3ad8826761cbdc87770e586fd7b6da7d4589e13dab3", size = 1050802, upload-time = "2025-10-06T20:22:00.96Z" }, + { url = "https://files.pythonhosted.org/packages/1f/05/dcf94486d5c5c8d34496abe271ac76c5b785507c8eae71b3708f1ad9b45a/tiktoken-0.12.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a01b12f69052fbe4b080a2cfb867c4de12c704b56178edf1d1d7b273561db160", size = 993995, upload-time = "2025-10-06T20:22:02.788Z" }, + { url = "https://files.pythonhosted.org/packages/a0/70/5163fe5359b943f8db9946b62f19be2305de8c3d78a16f629d4165e2f40e/tiktoken-0.12.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:01d99484dc93b129cd0964f9d34eee953f2737301f18b3c7257bf368d7615baa", size = 1128948, upload-time = "2025-10-06T20:22:03.814Z" }, + { url = "https://files.pythonhosted.org/packages/0c/da/c028aa0babf77315e1cef357d4d768800c5f8a6de04d0eac0f377cb619fa/tiktoken-0.12.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:4a1a4fcd021f022bfc81904a911d3df0f6543b9e7627b51411da75ff2fe7a1be", size = 1151986, upload-time = "2025-10-06T20:22:05.173Z" }, + { url = "https://files.pythonhosted.org/packages/a0/5a/886b108b766aa53e295f7216b509be95eb7d60b166049ce2c58416b25f2a/tiktoken-0.12.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:981a81e39812d57031efdc9ec59fa32b2a5a5524d20d4776574c4b4bd2e9014a", size = 1194222, upload-time = "2025-10-06T20:22:06.265Z" }, + { url = "https://files.pythonhosted.org/packages/f4/f8/4db272048397636ac7a078d22773dd2795b1becee7bc4922fe6207288d57/tiktoken-0.12.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9baf52f84a3f42eef3ff4e754a0db79a13a27921b457ca9832cf944c6be4f8f3", size = 1255097, upload-time = "2025-10-06T20:22:07.403Z" }, + { url = "https://files.pythonhosted.org/packages/8e/32/45d02e2e0ea2be3a9ed22afc47d93741247e75018aac967b713b2941f8ea/tiktoken-0.12.0-cp313-cp313-win_amd64.whl", hash = "sha256:b8a0cd0c789a61f31bf44851defbd609e8dd1e2c8589c614cc1060940ef1f697", size = 879117, upload-time = "2025-10-06T20:22:08.418Z" }, + { url = "https://files.pythonhosted.org/packages/ce/76/994fc868f88e016e6d05b0da5ac24582a14c47893f4474c3e9744283f1d5/tiktoken-0.12.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:d5f89ea5680066b68bcb797ae85219c72916c922ef0fcdd3480c7d2315ffff16", size = 1050309, upload-time = "2025-10-06T20:22:10.939Z" }, + { url = "https://files.pythonhosted.org/packages/f6/b8/57ef1456504c43a849821920d582a738a461b76a047f352f18c0b26c6516/tiktoken-0.12.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:b4e7ed1c6a7a8a60a3230965bdedba8cc58f68926b835e519341413370e0399a", size = 993712, upload-time = "2025-10-06T20:22:12.115Z" }, + { url = "https://files.pythonhosted.org/packages/72/90/13da56f664286ffbae9dbcfadcc625439142675845baa62715e49b87b68b/tiktoken-0.12.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:fc530a28591a2d74bce821d10b418b26a094bf33839e69042a6e86ddb7a7fb27", size = 1128725, upload-time = "2025-10-06T20:22:13.541Z" }, + { url = "https://files.pythonhosted.org/packages/05/df/4f80030d44682235bdaecd7346c90f67ae87ec8f3df4a3442cb53834f7e4/tiktoken-0.12.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:06a9f4f49884139013b138920a4c393aa6556b2f8f536345f11819389c703ebb", size = 1151875, upload-time = "2025-10-06T20:22:14.559Z" }, + { url = "https://files.pythonhosted.org/packages/22/1f/ae535223a8c4ef4c0c1192e3f9b82da660be9eb66b9279e95c99288e9dab/tiktoken-0.12.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:04f0e6a985d95913cabc96a741c5ffec525a2c72e9df086ff17ebe35985c800e", size = 1194451, upload-time = "2025-10-06T20:22:15.545Z" }, + { url = "https://files.pythonhosted.org/packages/78/a7/f8ead382fce0243cb625c4f266e66c27f65ae65ee9e77f59ea1653b6d730/tiktoken-0.12.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:0ee8f9ae00c41770b5f9b0bb1235474768884ae157de3beb5439ca0fd70f3e25", size = 1253794, upload-time = "2025-10-06T20:22:16.624Z" }, + { url = "https://files.pythonhosted.org/packages/93/e0/6cc82a562bc6365785a3ff0af27a2a092d57c47d7a81d9e2295d8c36f011/tiktoken-0.12.0-cp313-cp313t-win_amd64.whl", hash = "sha256:dc2dd125a62cb2b3d858484d6c614d136b5b848976794edfb63688d539b8b93f", size = 878777, upload-time = "2025-10-06T20:22:18.036Z" }, + { url = "https://files.pythonhosted.org/packages/72/05/3abc1db5d2c9aadc4d2c76fa5640134e475e58d9fbb82b5c535dc0de9b01/tiktoken-0.12.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:a90388128df3b3abeb2bfd1895b0681412a8d7dc644142519e6f0a97c2111646", size = 1050188, upload-time = "2025-10-06T20:22:19.563Z" }, + { url = "https://files.pythonhosted.org/packages/e3/7b/50c2f060412202d6c95f32b20755c7a6273543b125c0985d6fa9465105af/tiktoken-0.12.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:da900aa0ad52247d8794e307d6446bd3cdea8e192769b56276695d34d2c9aa88", size = 993978, upload-time = "2025-10-06T20:22:20.702Z" }, + { url = "https://files.pythonhosted.org/packages/14/27/bf795595a2b897e271771cd31cb847d479073497344c637966bdf2853da1/tiktoken-0.12.0-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:285ba9d73ea0d6171e7f9407039a290ca77efcdb026be7769dccc01d2c8d7fff", size = 1129271, upload-time = "2025-10-06T20:22:22.06Z" }, + { url = "https://files.pythonhosted.org/packages/f5/de/9341a6d7a8f1b448573bbf3425fa57669ac58258a667eb48a25dfe916d70/tiktoken-0.12.0-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:d186a5c60c6a0213f04a7a802264083dea1bbde92a2d4c7069e1a56630aef830", size = 1151216, upload-time = "2025-10-06T20:22:23.085Z" }, + { url = "https://files.pythonhosted.org/packages/75/0d/881866647b8d1be4d67cb24e50d0c26f9f807f994aa1510cb9ba2fe5f612/tiktoken-0.12.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:604831189bd05480f2b885ecd2d1986dc7686f609de48208ebbbddeea071fc0b", size = 1194860, upload-time = "2025-10-06T20:22:24.602Z" }, + { url = "https://files.pythonhosted.org/packages/b3/1e/b651ec3059474dab649b8d5b69f5c65cd8fcd8918568c1935bd4136c9392/tiktoken-0.12.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:8f317e8530bb3a222547b85a58583238c8f74fd7a7408305f9f63246d1a0958b", size = 1254567, upload-time = "2025-10-06T20:22:25.671Z" }, + { url = "https://files.pythonhosted.org/packages/80/57/ce64fd16ac390fafde001268c364d559447ba09b509181b2808622420eec/tiktoken-0.12.0-cp314-cp314-win_amd64.whl", hash = "sha256:399c3dd672a6406719d84442299a490420b458c44d3ae65516302a99675888f3", size = 921067, upload-time = "2025-10-06T20:22:26.753Z" }, + { url = "https://files.pythonhosted.org/packages/ac/a4/72eed53e8976a099539cdd5eb36f241987212c29629d0a52c305173e0a68/tiktoken-0.12.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:c2c714c72bc00a38ca969dae79e8266ddec999c7ceccd603cc4f0d04ccd76365", size = 1050473, upload-time = "2025-10-06T20:22:27.775Z" }, + { url = "https://files.pythonhosted.org/packages/e6/d7/0110b8f54c008466b19672c615f2168896b83706a6611ba6e47313dbc6e9/tiktoken-0.12.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:cbb9a3ba275165a2cb0f9a83f5d7025afe6b9d0ab01a22b50f0e74fee2ad253e", size = 993855, upload-time = "2025-10-06T20:22:28.799Z" }, + { url = "https://files.pythonhosted.org/packages/5f/77/4f268c41a3957c418b084dd576ea2fad2e95da0d8e1ab705372892c2ca22/tiktoken-0.12.0-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:dfdfaa5ffff8993a3af94d1125870b1d27aed7cb97aa7eb8c1cefdbc87dbee63", size = 1129022, upload-time = "2025-10-06T20:22:29.981Z" }, + { url = "https://files.pythonhosted.org/packages/4e/2b/fc46c90fe5028bd094cd6ee25a7db321cb91d45dc87531e2bdbb26b4867a/tiktoken-0.12.0-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:584c3ad3d0c74f5269906eb8a659c8bfc6144a52895d9261cdaf90a0ae5f4de0", size = 1150736, upload-time = "2025-10-06T20:22:30.996Z" }, + { url = "https://files.pythonhosted.org/packages/28/c0/3c7a39ff68022ddfd7d93f3337ad90389a342f761c4d71de99a3ccc57857/tiktoken-0.12.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:54c891b416a0e36b8e2045b12b33dd66fb34a4fe7965565f1b482da50da3e86a", size = 1194908, upload-time = "2025-10-06T20:22:32.073Z" }, + { url = "https://files.pythonhosted.org/packages/ab/0d/c1ad6f4016a3968c048545f5d9b8ffebf577774b2ede3e2e352553b685fe/tiktoken-0.12.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5edb8743b88d5be814b1a8a8854494719080c28faaa1ccbef02e87354fe71ef0", size = 1253706, upload-time = "2025-10-06T20:22:33.385Z" }, + { url = "https://files.pythonhosted.org/packages/af/df/c7891ef9d2712ad774777271d39fdef63941ffba0a9d59b7ad1fd2765e57/tiktoken-0.12.0-cp314-cp314t-win_amd64.whl", hash = "sha256:f61c0aea5565ac82e2ec50a05e02a6c44734e91b51c10510b084ea1b8e633a71", size = 920667, upload-time = "2025-10-06T20:22:34.444Z" }, +] + +[[package]] +name = "tqdm" +version = "4.67.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/09/a9/6ba95a270c6f1fbcd8dac228323f2777d886cb206987444e4bce66338dd4/tqdm-4.67.3.tar.gz", hash = "sha256:7d825f03f89244ef73f1d4ce193cb1774a8179fd96f31d7e1dcde62092b960bb", size = 169598, upload-time = "2026-02-03T17:35:53.048Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/16/e1/3079a9ff9b8e11b846c6ac5c8b5bfb7ff225eee721825310c91b3b50304f/tqdm-4.67.3-py3-none-any.whl", hash = "sha256:ee1e4c0e59148062281c49d80b25b67771a127c85fc9676d3be5f243206826bf", size = 78374, upload-time = "2026-02-03T17:35:50.982Z" }, +] + +[[package]] +name = "typer" +version = "0.24.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "annotated-doc" }, + { name = "click" }, + { name = "rich" }, + { name = "shellingham" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f5/24/cb09efec5cc954f7f9b930bf8279447d24618bb6758d4f6adf2574c41780/typer-0.24.1.tar.gz", hash = "sha256:e39b4732d65fbdcde189ae76cf7cd48aeae72919dea1fdfc16593be016256b45", size = 118613, upload-time = "2026-02-21T16:54:40.609Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4a/91/48db081e7a63bb37284f9fbcefda7c44c277b18b0e13fbc36ea2335b71e6/typer-0.24.1-py3-none-any.whl", hash = "sha256:112c1f0ce578bfb4cab9ffdabc68f031416ebcc216536611ba21f04e9aa84c9e", size = 56085, upload-time = "2026-02-21T16:54:41.616Z" }, +] + [[package]] name = "typing-extensions" version = "4.15.0" @@ -1469,6 +1678,21 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/6d/b9/4095b668ea3678bf6a0af005527f39de12fb026516fb3df17495a733b7f8/urllib3-2.6.2-py3-none-any.whl", hash = "sha256:ec21cddfe7724fc7cb4ba4bea7aa8e2ef36f607a4bab81aa6ce42a13dc3f03dd", size = 131182, upload-time = "2025-12-11T15:56:38.584Z" }, ] +[[package]] +name = "virtualenv" +version = "21.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "distlib" }, + { name = "filelock" }, + { name = "platformdirs" }, + { name = "python-discovery" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/aa/92/58199fe10049f9703c2666e809c4f686c54ef0a68b0f6afccf518c0b1eb9/virtualenv-21.2.0.tar.gz", hash = "sha256:1720dc3a62ef5b443092e3f499228599045d7fea4c79199770499df8becf9098", size = 5840618, upload-time = "2026-03-09T17:24:38.013Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c6/59/7d02447a55b2e55755011a647479041bc92a82e143f96a8195cb33bd0a1c/virtualenv-21.2.0-py3-none-any.whl", hash = "sha256:1bd755b504931164a5a496d217c014d098426cddc79363ad66ac78125f9d908f", size = 5825084, upload-time = "2026-03-09T17:24:35.378Z" }, +] + [[package]] name = "websockets" version = "15.0.1" @@ -1512,111 +1736,10 @@ wheels = [ ] [[package]] -name = "yarl" -version = "1.22.0" +name = "zipp" +version = "3.23.0" source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "idna" }, - { name = "multidict" }, - { name = "propcache" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/57/63/0c6ebca57330cd313f6102b16dd57ffaf3ec4c83403dcb45dbd15c6f3ea1/yarl-1.22.0.tar.gz", hash = "sha256:bebf8557577d4401ba8bd9ff33906f1376c877aa78d1fe216ad01b4d6745af71", size = 187169, upload-time = "2025-10-06T14:12:55.963Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/4d/27/5ab13fc84c76a0250afd3d26d5936349a35be56ce5785447d6c423b26d92/yarl-1.22.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1ab72135b1f2db3fed3997d7e7dc1b80573c67138023852b6efb336a5eae6511", size = 141607, upload-time = "2025-10-06T14:09:16.298Z" }, - { url = "https://files.pythonhosted.org/packages/6a/a1/d065d51d02dc02ce81501d476b9ed2229d9a990818332242a882d5d60340/yarl-1.22.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:669930400e375570189492dc8d8341301578e8493aec04aebc20d4717f899dd6", size = 94027, upload-time = "2025-10-06T14:09:17.786Z" }, - { url = "https://files.pythonhosted.org/packages/c1/da/8da9f6a53f67b5106ffe902c6fa0164e10398d4e150d85838b82f424072a/yarl-1.22.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:792a2af6d58177ef7c19cbf0097aba92ca1b9cb3ffdd9c7470e156c8f9b5e028", size = 94963, upload-time = "2025-10-06T14:09:19.662Z" }, - { url = "https://files.pythonhosted.org/packages/68/fe/2c1f674960c376e29cb0bec1249b117d11738db92a6ccc4a530b972648db/yarl-1.22.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3ea66b1c11c9150f1372f69afb6b8116f2dd7286f38e14ea71a44eee9ec51b9d", size = 368406, upload-time = "2025-10-06T14:09:21.402Z" }, - { url = "https://files.pythonhosted.org/packages/95/26/812a540e1c3c6418fec60e9bbd38e871eaba9545e94fa5eff8f4a8e28e1e/yarl-1.22.0-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3e2daa88dc91870215961e96a039ec73e4937da13cf77ce17f9cad0c18df3503", size = 336581, upload-time = "2025-10-06T14:09:22.98Z" }, - { url = "https://files.pythonhosted.org/packages/0b/f5/5777b19e26fdf98563985e481f8be3d8a39f8734147a6ebf459d0dab5a6b/yarl-1.22.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ba440ae430c00eee41509353628600212112cd5018d5def7e9b05ea7ac34eb65", size = 388924, upload-time = "2025-10-06T14:09:24.655Z" }, - { url = "https://files.pythonhosted.org/packages/86/08/24bd2477bd59c0bbd994fe1d93b126e0472e4e3df5a96a277b0a55309e89/yarl-1.22.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e6438cc8f23a9c1478633d216b16104a586b9761db62bfacb6425bac0a36679e", size = 392890, upload-time = "2025-10-06T14:09:26.617Z" }, - { url = "https://files.pythonhosted.org/packages/46/00/71b90ed48e895667ecfb1eaab27c1523ee2fa217433ed77a73b13205ca4b/yarl-1.22.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4c52a6e78aef5cf47a98ef8e934755abf53953379b7d53e68b15ff4420e6683d", size = 365819, upload-time = "2025-10-06T14:09:28.544Z" }, - { url = "https://files.pythonhosted.org/packages/30/2d/f715501cae832651d3282387c6a9236cd26bd00d0ff1e404b3dc52447884/yarl-1.22.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3b06bcadaac49c70f4c88af4ffcfbe3dc155aab3163e75777818092478bcbbe7", size = 363601, upload-time = "2025-10-06T14:09:30.568Z" }, - { url = "https://files.pythonhosted.org/packages/f8/f9/a678c992d78e394e7126ee0b0e4e71bd2775e4334d00a9278c06a6cce96a/yarl-1.22.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:6944b2dc72c4d7f7052683487e3677456050ff77fcf5e6204e98caf785ad1967", size = 358072, upload-time = "2025-10-06T14:09:32.528Z" }, - { url = "https://files.pythonhosted.org/packages/2c/d1/b49454411a60edb6fefdcad4f8e6dbba7d8019e3a508a1c5836cba6d0781/yarl-1.22.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:d5372ca1df0f91a86b047d1277c2aaf1edb32d78bbcefffc81b40ffd18f027ed", size = 385311, upload-time = "2025-10-06T14:09:34.634Z" }, - { url = "https://files.pythonhosted.org/packages/87/e5/40d7a94debb8448c7771a916d1861d6609dddf7958dc381117e7ba36d9e8/yarl-1.22.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:51af598701f5299012b8416486b40fceef8c26fc87dc6d7d1f6fc30609ea0aa6", size = 381094, upload-time = "2025-10-06T14:09:36.268Z" }, - { url = "https://files.pythonhosted.org/packages/35/d8/611cc282502381ad855448643e1ad0538957fc82ae83dfe7762c14069e14/yarl-1.22.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b266bd01fedeffeeac01a79ae181719ff848a5a13ce10075adbefc8f1daee70e", size = 370944, upload-time = "2025-10-06T14:09:37.872Z" }, - { url = "https://files.pythonhosted.org/packages/2d/df/fadd00fb1c90e1a5a8bd731fa3d3de2e165e5a3666a095b04e31b04d9cb6/yarl-1.22.0-cp311-cp311-win32.whl", hash = "sha256:a9b1ba5610a4e20f655258d5a1fdc7ebe3d837bb0e45b581398b99eb98b1f5ca", size = 81804, upload-time = "2025-10-06T14:09:39.359Z" }, - { url = "https://files.pythonhosted.org/packages/b5/f7/149bb6f45f267cb5c074ac40c01c6b3ea6d8a620d34b337f6321928a1b4d/yarl-1.22.0-cp311-cp311-win_amd64.whl", hash = "sha256:078278b9b0b11568937d9509b589ee83ef98ed6d561dfe2020e24a9fd08eaa2b", size = 86858, upload-time = "2025-10-06T14:09:41.068Z" }, - { url = "https://files.pythonhosted.org/packages/2b/13/88b78b93ad3f2f0b78e13bfaaa24d11cbc746e93fe76d8c06bf139615646/yarl-1.22.0-cp311-cp311-win_arm64.whl", hash = "sha256:b6a6f620cfe13ccec221fa312139135166e47ae169f8253f72a0abc0dae94376", size = 81637, upload-time = "2025-10-06T14:09:42.712Z" }, - { url = "https://files.pythonhosted.org/packages/75/ff/46736024fee3429b80a165a732e38e5d5a238721e634ab41b040d49f8738/yarl-1.22.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e340382d1afa5d32b892b3ff062436d592ec3d692aeea3bef3a5cfe11bbf8c6f", size = 142000, upload-time = "2025-10-06T14:09:44.631Z" }, - { url = "https://files.pythonhosted.org/packages/5a/9a/b312ed670df903145598914770eb12de1bac44599549b3360acc96878df8/yarl-1.22.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f1e09112a2c31ffe8d80be1b0988fa6a18c5d5cad92a9ffbb1c04c91bfe52ad2", size = 94338, upload-time = "2025-10-06T14:09:46.372Z" }, - { url = "https://files.pythonhosted.org/packages/ba/f5/0601483296f09c3c65e303d60c070a5c19fcdbc72daa061e96170785bc7d/yarl-1.22.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:939fe60db294c786f6b7c2d2e121576628468f65453d86b0fe36cb52f987bd74", size = 94909, upload-time = "2025-10-06T14:09:48.648Z" }, - { url = "https://files.pythonhosted.org/packages/60/41/9a1fe0b73dbcefce72e46cf149b0e0a67612d60bfc90fb59c2b2efdfbd86/yarl-1.22.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e1651bf8e0398574646744c1885a41198eba53dc8a9312b954073f845c90a8df", size = 372940, upload-time = "2025-10-06T14:09:50.089Z" }, - { url = "https://files.pythonhosted.org/packages/17/7a/795cb6dfee561961c30b800f0ed616b923a2ec6258b5def2a00bf8231334/yarl-1.22.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b8a0588521a26bf92a57a1705b77b8b59044cdceccac7151bd8d229e66b8dedb", size = 345825, upload-time = "2025-10-06T14:09:52.142Z" }, - { url = "https://files.pythonhosted.org/packages/d7/93/a58f4d596d2be2ae7bab1a5846c4d270b894958845753b2c606d666744d3/yarl-1.22.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:42188e6a615c1a75bcaa6e150c3fe8f3e8680471a6b10150c5f7e83f47cc34d2", size = 386705, upload-time = "2025-10-06T14:09:54.128Z" }, - { url = "https://files.pythonhosted.org/packages/61/92/682279d0e099d0e14d7fd2e176bd04f48de1484f56546a3e1313cd6c8e7c/yarl-1.22.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f6d2cb59377d99718913ad9a151030d6f83ef420a2b8f521d94609ecc106ee82", size = 396518, upload-time = "2025-10-06T14:09:55.762Z" }, - { url = "https://files.pythonhosted.org/packages/db/0f/0d52c98b8a885aeda831224b78f3be7ec2e1aa4a62091f9f9188c3c65b56/yarl-1.22.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:50678a3b71c751d58d7908edc96d332af328839eea883bb554a43f539101277a", size = 377267, upload-time = "2025-10-06T14:09:57.958Z" }, - { url = "https://files.pythonhosted.org/packages/22/42/d2685e35908cbeaa6532c1fc73e89e7f2efb5d8a7df3959ea8e37177c5a3/yarl-1.22.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1e8fbaa7cec507aa24ea27a01456e8dd4b6fab829059b69844bd348f2d467124", size = 365797, upload-time = "2025-10-06T14:09:59.527Z" }, - { url = "https://files.pythonhosted.org/packages/a2/83/cf8c7bcc6355631762f7d8bdab920ad09b82efa6b722999dfb05afa6cfac/yarl-1.22.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:433885ab5431bc3d3d4f2f9bd15bfa1614c522b0f1405d62c4f926ccd69d04fa", size = 365535, upload-time = "2025-10-06T14:10:01.139Z" }, - { url = "https://files.pythonhosted.org/packages/25/e1/5302ff9b28f0c59cac913b91fe3f16c59a033887e57ce9ca5d41a3a94737/yarl-1.22.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:b790b39c7e9a4192dc2e201a282109ed2985a1ddbd5ac08dc56d0e121400a8f7", size = 382324, upload-time = "2025-10-06T14:10:02.756Z" }, - { url = "https://files.pythonhosted.org/packages/bf/cd/4617eb60f032f19ae3a688dc990d8f0d89ee0ea378b61cac81ede3e52fae/yarl-1.22.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:31f0b53913220599446872d757257be5898019c85e7971599065bc55065dc99d", size = 383803, upload-time = "2025-10-06T14:10:04.552Z" }, - { url = "https://files.pythonhosted.org/packages/59/65/afc6e62bb506a319ea67b694551dab4a7e6fb7bf604e9bd9f3e11d575fec/yarl-1.22.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a49370e8f711daec68d09b821a34e1167792ee2d24d405cbc2387be4f158b520", size = 374220, upload-time = "2025-10-06T14:10:06.489Z" }, - { url = "https://files.pythonhosted.org/packages/e7/3d/68bf18d50dc674b942daec86a9ba922d3113d8399b0e52b9897530442da2/yarl-1.22.0-cp312-cp312-win32.whl", hash = "sha256:70dfd4f241c04bd9239d53b17f11e6ab672b9f1420364af63e8531198e3f5fe8", size = 81589, upload-time = "2025-10-06T14:10:09.254Z" }, - { url = "https://files.pythonhosted.org/packages/c8/9a/6ad1a9b37c2f72874f93e691b2e7ecb6137fb2b899983125db4204e47575/yarl-1.22.0-cp312-cp312-win_amd64.whl", hash = "sha256:8884d8b332a5e9b88e23f60bb166890009429391864c685e17bd73a9eda9105c", size = 87213, upload-time = "2025-10-06T14:10:11.369Z" }, - { url = "https://files.pythonhosted.org/packages/44/c5/c21b562d1680a77634d748e30c653c3ca918beb35555cff24986fff54598/yarl-1.22.0-cp312-cp312-win_arm64.whl", hash = "sha256:ea70f61a47f3cc93bdf8b2f368ed359ef02a01ca6393916bc8ff877427181e74", size = 81330, upload-time = "2025-10-06T14:10:13.112Z" }, - { url = "https://files.pythonhosted.org/packages/ea/f3/d67de7260456ee105dc1d162d43a019ecad6b91e2f51809d6cddaa56690e/yarl-1.22.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8dee9c25c74997f6a750cd317b8ca63545169c098faee42c84aa5e506c819b53", size = 139980, upload-time = "2025-10-06T14:10:14.601Z" }, - { url = "https://files.pythonhosted.org/packages/01/88/04d98af0b47e0ef42597b9b28863b9060bb515524da0a65d5f4db160b2d5/yarl-1.22.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:01e73b85a5434f89fc4fe27dcda2aff08ddf35e4d47bbbea3bdcd25321af538a", size = 93424, upload-time = "2025-10-06T14:10:16.115Z" }, - { url = "https://files.pythonhosted.org/packages/18/91/3274b215fd8442a03975ce6bee5fe6aa57a8326b29b9d3d56234a1dca244/yarl-1.22.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:22965c2af250d20c873cdbee8ff958fb809940aeb2e74ba5f20aaf6b7ac8c70c", size = 93821, upload-time = "2025-10-06T14:10:17.993Z" }, - { url = "https://files.pythonhosted.org/packages/61/3a/caf4e25036db0f2da4ca22a353dfeb3c9d3c95d2761ebe9b14df8fc16eb0/yarl-1.22.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b4f15793aa49793ec8d1c708ab7f9eded1aa72edc5174cae703651555ed1b601", size = 373243, upload-time = "2025-10-06T14:10:19.44Z" }, - { url = "https://files.pythonhosted.org/packages/6e/9e/51a77ac7516e8e7803b06e01f74e78649c24ee1021eca3d6a739cb6ea49c/yarl-1.22.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e5542339dcf2747135c5c85f68680353d5cb9ffd741c0f2e8d832d054d41f35a", size = 342361, upload-time = "2025-10-06T14:10:21.124Z" }, - { url = "https://files.pythonhosted.org/packages/d4/f8/33b92454789dde8407f156c00303e9a891f1f51a0330b0fad7c909f87692/yarl-1.22.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5c401e05ad47a75869c3ab3e35137f8468b846770587e70d71e11de797d113df", size = 387036, upload-time = "2025-10-06T14:10:22.902Z" }, - { url = "https://files.pythonhosted.org/packages/d9/9a/c5db84ea024f76838220280f732970aa4ee154015d7f5c1bfb60a267af6f/yarl-1.22.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:243dda95d901c733f5b59214d28b0120893d91777cb8aa043e6ef059d3cddfe2", size = 397671, upload-time = "2025-10-06T14:10:24.523Z" }, - { url = "https://files.pythonhosted.org/packages/11/c9/cd8538dc2e7727095e0c1d867bad1e40c98f37763e6d995c1939f5fdc7b1/yarl-1.22.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bec03d0d388060058f5d291a813f21c011041938a441c593374da6077fe21b1b", size = 377059, upload-time = "2025-10-06T14:10:26.406Z" }, - { url = "https://files.pythonhosted.org/packages/a1/b9/ab437b261702ced75122ed78a876a6dec0a1b0f5e17a4ac7a9a2482d8abe/yarl-1.22.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b0748275abb8c1e1e09301ee3cf90c8a99678a4e92e4373705f2a2570d581273", size = 365356, upload-time = "2025-10-06T14:10:28.461Z" }, - { url = "https://files.pythonhosted.org/packages/b2/9d/8e1ae6d1d008a9567877b08f0ce4077a29974c04c062dabdb923ed98e6fe/yarl-1.22.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:47fdb18187e2a4e18fda2c25c05d8251a9e4a521edaed757fef033e7d8498d9a", size = 361331, upload-time = "2025-10-06T14:10:30.541Z" }, - { url = "https://files.pythonhosted.org/packages/ca/5a/09b7be3905962f145b73beb468cdd53db8aa171cf18c80400a54c5b82846/yarl-1.22.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c7044802eec4524fde550afc28edda0dd5784c4c45f0be151a2d3ba017daca7d", size = 382590, upload-time = "2025-10-06T14:10:33.352Z" }, - { url = "https://files.pythonhosted.org/packages/aa/7f/59ec509abf90eda5048b0bc3e2d7b5099dffdb3e6b127019895ab9d5ef44/yarl-1.22.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:139718f35149ff544caba20fce6e8a2f71f1e39b92c700d8438a0b1d2a631a02", size = 385316, upload-time = "2025-10-06T14:10:35.034Z" }, - { url = "https://files.pythonhosted.org/packages/e5/84/891158426bc8036bfdfd862fabd0e0fa25df4176ec793e447f4b85cf1be4/yarl-1.22.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e1b51bebd221006d3d2f95fbe124b22b247136647ae5dcc8c7acafba66e5ee67", size = 374431, upload-time = "2025-10-06T14:10:37.76Z" }, - { url = "https://files.pythonhosted.org/packages/bb/49/03da1580665baa8bef5e8ed34c6df2c2aca0a2f28bf397ed238cc1bbc6f2/yarl-1.22.0-cp313-cp313-win32.whl", hash = "sha256:d3e32536234a95f513bd374e93d717cf6b2231a791758de6c509e3653f234c95", size = 81555, upload-time = "2025-10-06T14:10:39.649Z" }, - { url = "https://files.pythonhosted.org/packages/9a/ee/450914ae11b419eadd067c6183ae08381cfdfcb9798b90b2b713bbebddda/yarl-1.22.0-cp313-cp313-win_amd64.whl", hash = "sha256:47743b82b76d89a1d20b83e60d5c20314cbd5ba2befc9cda8f28300c4a08ed4d", size = 86965, upload-time = "2025-10-06T14:10:41.313Z" }, - { url = "https://files.pythonhosted.org/packages/98/4d/264a01eae03b6cf629ad69bae94e3b0e5344741e929073678e84bf7a3e3b/yarl-1.22.0-cp313-cp313-win_arm64.whl", hash = "sha256:5d0fcda9608875f7d052eff120c7a5da474a6796fe4d83e152e0e4d42f6d1a9b", size = 81205, upload-time = "2025-10-06T14:10:43.167Z" }, - { url = "https://files.pythonhosted.org/packages/88/fc/6908f062a2f77b5f9f6d69cecb1747260831ff206adcbc5b510aff88df91/yarl-1.22.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:719ae08b6972befcba4310e49edb1161a88cdd331e3a694b84466bd938a6ab10", size = 146209, upload-time = "2025-10-06T14:10:44.643Z" }, - { url = "https://files.pythonhosted.org/packages/65/47/76594ae8eab26210b4867be6f49129861ad33da1f1ebdf7051e98492bf62/yarl-1.22.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:47d8a5c446df1c4db9d21b49619ffdba90e77c89ec6e283f453856c74b50b9e3", size = 95966, upload-time = "2025-10-06T14:10:46.554Z" }, - { url = "https://files.pythonhosted.org/packages/ab/ce/05e9828a49271ba6b5b038b15b3934e996980dd78abdfeb52a04cfb9467e/yarl-1.22.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:cfebc0ac8333520d2d0423cbbe43ae43c8838862ddb898f5ca68565e395516e9", size = 97312, upload-time = "2025-10-06T14:10:48.007Z" }, - { url = "https://files.pythonhosted.org/packages/d1/c5/7dffad5e4f2265b29c9d7ec869c369e4223166e4f9206fc2243ee9eea727/yarl-1.22.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4398557cbf484207df000309235979c79c4356518fd5c99158c7d38203c4da4f", size = 361967, upload-time = "2025-10-06T14:10:49.997Z" }, - { url = "https://files.pythonhosted.org/packages/50/b2/375b933c93a54bff7fc041e1a6ad2c0f6f733ffb0c6e642ce56ee3b39970/yarl-1.22.0-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:2ca6fd72a8cd803be290d42f2dec5cdcd5299eeb93c2d929bf060ad9efaf5de0", size = 323949, upload-time = "2025-10-06T14:10:52.004Z" }, - { url = "https://files.pythonhosted.org/packages/66/50/bfc2a29a1d78644c5a7220ce2f304f38248dc94124a326794e677634b6cf/yarl-1.22.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ca1f59c4e1ab6e72f0a23c13fca5430f889634166be85dbf1013683e49e3278e", size = 361818, upload-time = "2025-10-06T14:10:54.078Z" }, - { url = "https://files.pythonhosted.org/packages/46/96/f3941a46af7d5d0f0498f86d71275696800ddcdd20426298e572b19b91ff/yarl-1.22.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6c5010a52015e7c70f86eb967db0f37f3c8bd503a695a49f8d45700144667708", size = 372626, upload-time = "2025-10-06T14:10:55.767Z" }, - { url = "https://files.pythonhosted.org/packages/c1/42/8b27c83bb875cd89448e42cd627e0fb971fa1675c9ec546393d18826cb50/yarl-1.22.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d7672ecf7557476642c88497c2f8d8542f8e36596e928e9bcba0e42e1e7d71f", size = 341129, upload-time = "2025-10-06T14:10:57.985Z" }, - { url = "https://files.pythonhosted.org/packages/49/36/99ca3122201b382a3cf7cc937b95235b0ac944f7e9f2d5331d50821ed352/yarl-1.22.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:3b7c88eeef021579d600e50363e0b6ee4f7f6f728cd3486b9d0f3ee7b946398d", size = 346776, upload-time = "2025-10-06T14:10:59.633Z" }, - { url = "https://files.pythonhosted.org/packages/85/b4/47328bf996acd01a4c16ef9dcd2f59c969f495073616586f78cd5f2efb99/yarl-1.22.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:f4afb5c34f2c6fecdcc182dfcfc6af6cccf1aa923eed4d6a12e9d96904e1a0d8", size = 334879, upload-time = "2025-10-06T14:11:01.454Z" }, - { url = "https://files.pythonhosted.org/packages/c2/ad/b77d7b3f14a4283bffb8e92c6026496f6de49751c2f97d4352242bba3990/yarl-1.22.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:59c189e3e99a59cf8d83cbb31d4db02d66cda5a1a4374e8a012b51255341abf5", size = 350996, upload-time = "2025-10-06T14:11:03.452Z" }, - { url = "https://files.pythonhosted.org/packages/81/c8/06e1d69295792ba54d556f06686cbd6a7ce39c22307100e3fb4a2c0b0a1d/yarl-1.22.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:5a3bf7f62a289fa90f1990422dc8dff5a458469ea71d1624585ec3a4c8d6960f", size = 356047, upload-time = "2025-10-06T14:11:05.115Z" }, - { url = "https://files.pythonhosted.org/packages/4b/b8/4c0e9e9f597074b208d18cef227d83aac36184bfbc6eab204ea55783dbc5/yarl-1.22.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:de6b9a04c606978fdfe72666fa216ffcf2d1a9f6a381058d4378f8d7b1e5de62", size = 342947, upload-time = "2025-10-06T14:11:08.137Z" }, - { url = "https://files.pythonhosted.org/packages/e0/e5/11f140a58bf4c6ad7aca69a892bff0ee638c31bea4206748fc0df4ebcb3a/yarl-1.22.0-cp313-cp313t-win32.whl", hash = "sha256:1834bb90991cc2999f10f97f5f01317f99b143284766d197e43cd5b45eb18d03", size = 86943, upload-time = "2025-10-06T14:11:10.284Z" }, - { url = "https://files.pythonhosted.org/packages/31/74/8b74bae38ed7fe6793d0c15a0c8207bbb819cf287788459e5ed230996cdd/yarl-1.22.0-cp313-cp313t-win_amd64.whl", hash = "sha256:ff86011bd159a9d2dfc89c34cfd8aff12875980e3bd6a39ff097887520e60249", size = 93715, upload-time = "2025-10-06T14:11:11.739Z" }, - { url = "https://files.pythonhosted.org/packages/69/66/991858aa4b5892d57aef7ee1ba6b4d01ec3b7eb3060795d34090a3ca3278/yarl-1.22.0-cp313-cp313t-win_arm64.whl", hash = "sha256:7861058d0582b847bc4e3a4a4c46828a410bca738673f35a29ba3ca5db0b473b", size = 83857, upload-time = "2025-10-06T14:11:13.586Z" }, - { url = "https://files.pythonhosted.org/packages/46/b3/e20ef504049f1a1c54a814b4b9bed96d1ac0e0610c3b4da178f87209db05/yarl-1.22.0-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:34b36c2c57124530884d89d50ed2c1478697ad7473efd59cfd479945c95650e4", size = 140520, upload-time = "2025-10-06T14:11:15.465Z" }, - { url = "https://files.pythonhosted.org/packages/e4/04/3532d990fdbab02e5ede063676b5c4260e7f3abea2151099c2aa745acc4c/yarl-1.22.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:0dd9a702591ca2e543631c2a017e4a547e38a5c0f29eece37d9097e04a7ac683", size = 93504, upload-time = "2025-10-06T14:11:17.106Z" }, - { url = "https://files.pythonhosted.org/packages/11/63/ff458113c5c2dac9a9719ac68ee7c947cb621432bcf28c9972b1c0e83938/yarl-1.22.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:594fcab1032e2d2cc3321bb2e51271e7cd2b516c7d9aee780ece81b07ff8244b", size = 94282, upload-time = "2025-10-06T14:11:19.064Z" }, - { url = "https://files.pythonhosted.org/packages/a7/bc/315a56aca762d44a6aaaf7ad253f04d996cb6b27bad34410f82d76ea8038/yarl-1.22.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f3d7a87a78d46a2e3d5b72587ac14b4c16952dd0887dbb051451eceac774411e", size = 372080, upload-time = "2025-10-06T14:11:20.996Z" }, - { url = "https://files.pythonhosted.org/packages/3f/3f/08e9b826ec2e099ea6e7c69a61272f4f6da62cb5b1b63590bb80ca2e4a40/yarl-1.22.0-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:852863707010316c973162e703bddabec35e8757e67fcb8ad58829de1ebc8590", size = 338696, upload-time = "2025-10-06T14:11:22.847Z" }, - { url = "https://files.pythonhosted.org/packages/e3/9f/90360108e3b32bd76789088e99538febfea24a102380ae73827f62073543/yarl-1.22.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:131a085a53bfe839a477c0845acf21efc77457ba2bcf5899618136d64f3303a2", size = 387121, upload-time = "2025-10-06T14:11:24.889Z" }, - { url = "https://files.pythonhosted.org/packages/98/92/ab8d4657bd5b46a38094cfaea498f18bb70ce6b63508fd7e909bd1f93066/yarl-1.22.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:078a8aefd263f4d4f923a9677b942b445a2be970ca24548a8102689a3a8ab8da", size = 394080, upload-time = "2025-10-06T14:11:27.307Z" }, - { url = "https://files.pythonhosted.org/packages/f5/e7/d8c5a7752fef68205296201f8ec2bf718f5c805a7a7e9880576c67600658/yarl-1.22.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bca03b91c323036913993ff5c738d0842fc9c60c4648e5c8d98331526df89784", size = 372661, upload-time = "2025-10-06T14:11:29.387Z" }, - { url = "https://files.pythonhosted.org/packages/b6/2e/f4d26183c8db0bb82d491b072f3127fb8c381a6206a3a56332714b79b751/yarl-1.22.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:68986a61557d37bb90d3051a45b91fa3d5c516d177dfc6dd6f2f436a07ff2b6b", size = 364645, upload-time = "2025-10-06T14:11:31.423Z" }, - { url = "https://files.pythonhosted.org/packages/80/7c/428e5812e6b87cd00ee8e898328a62c95825bf37c7fa87f0b6bb2ad31304/yarl-1.22.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:4792b262d585ff0dff6bcb787f8492e40698443ec982a3568c2096433660c694", size = 355361, upload-time = "2025-10-06T14:11:33.055Z" }, - { url = "https://files.pythonhosted.org/packages/ec/2a/249405fd26776f8b13c067378ef4d7dd49c9098d1b6457cdd152a99e96a9/yarl-1.22.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:ebd4549b108d732dba1d4ace67614b9545b21ece30937a63a65dd34efa19732d", size = 381451, upload-time = "2025-10-06T14:11:35.136Z" }, - { url = "https://files.pythonhosted.org/packages/67/a8/fb6b1adbe98cf1e2dd9fad71003d3a63a1bc22459c6e15f5714eb9323b93/yarl-1.22.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:f87ac53513d22240c7d59203f25cc3beac1e574c6cd681bbfd321987b69f95fd", size = 383814, upload-time = "2025-10-06T14:11:37.094Z" }, - { url = "https://files.pythonhosted.org/packages/d9/f9/3aa2c0e480fb73e872ae2814c43bc1e734740bb0d54e8cb2a95925f98131/yarl-1.22.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:22b029f2881599e2f1b06f8f1db2ee63bd309e2293ba2d566e008ba12778b8da", size = 370799, upload-time = "2025-10-06T14:11:38.83Z" }, - { url = "https://files.pythonhosted.org/packages/50/3c/af9dba3b8b5eeb302f36f16f92791f3ea62e3f47763406abf6d5a4a3333b/yarl-1.22.0-cp314-cp314-win32.whl", hash = "sha256:6a635ea45ba4ea8238463b4f7d0e721bad669f80878b7bfd1f89266e2ae63da2", size = 82990, upload-time = "2025-10-06T14:11:40.624Z" }, - { url = "https://files.pythonhosted.org/packages/ac/30/ac3a0c5bdc1d6efd1b41fa24d4897a4329b3b1e98de9449679dd327af4f0/yarl-1.22.0-cp314-cp314-win_amd64.whl", hash = "sha256:0d6e6885777af0f110b0e5d7e5dda8b704efed3894da26220b7f3d887b839a79", size = 88292, upload-time = "2025-10-06T14:11:42.578Z" }, - { url = "https://files.pythonhosted.org/packages/df/0a/227ab4ff5b998a1b7410abc7b46c9b7a26b0ca9e86c34ba4b8d8bc7c63d5/yarl-1.22.0-cp314-cp314-win_arm64.whl", hash = "sha256:8218f4e98d3c10d683584cb40f0424f4b9fd6e95610232dd75e13743b070ee33", size = 82888, upload-time = "2025-10-06T14:11:44.863Z" }, - { url = "https://files.pythonhosted.org/packages/06/5e/a15eb13db90abd87dfbefb9760c0f3f257ac42a5cac7e75dbc23bed97a9f/yarl-1.22.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:45c2842ff0e0d1b35a6bf1cd6c690939dacb617a70827f715232b2e0494d55d1", size = 146223, upload-time = "2025-10-06T14:11:46.796Z" }, - { url = "https://files.pythonhosted.org/packages/18/82/9665c61910d4d84f41a5bf6837597c89e665fa88aa4941080704645932a9/yarl-1.22.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:d947071e6ebcf2e2bee8fce76e10faca8f7a14808ca36a910263acaacef08eca", size = 95981, upload-time = "2025-10-06T14:11:48.845Z" }, - { url = "https://files.pythonhosted.org/packages/5d/9a/2f65743589809af4d0a6d3aa749343c4b5f4c380cc24a8e94a3c6625a808/yarl-1.22.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:334b8721303e61b00019474cc103bdac3d7b1f65e91f0bfedeec2d56dfe74b53", size = 97303, upload-time = "2025-10-06T14:11:50.897Z" }, - { url = "https://files.pythonhosted.org/packages/b0/ab/5b13d3e157505c43c3b43b5a776cbf7b24a02bc4cccc40314771197e3508/yarl-1.22.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1e7ce67c34138a058fd092f67d07a72b8e31ff0c9236e751957465a24b28910c", size = 361820, upload-time = "2025-10-06T14:11:52.549Z" }, - { url = "https://files.pythonhosted.org/packages/fb/76/242a5ef4677615cf95330cfc1b4610e78184400699bdda0acb897ef5e49a/yarl-1.22.0-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:d77e1b2c6d04711478cb1c4ab90db07f1609ccf06a287d5607fcd90dc9863acf", size = 323203, upload-time = "2025-10-06T14:11:54.225Z" }, - { url = "https://files.pythonhosted.org/packages/8c/96/475509110d3f0153b43d06164cf4195c64d16999e0c7e2d8a099adcd6907/yarl-1.22.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c4647674b6150d2cae088fc07de2738a84b8bcedebef29802cf0b0a82ab6face", size = 363173, upload-time = "2025-10-06T14:11:56.069Z" }, - { url = "https://files.pythonhosted.org/packages/c9/66/59db471aecfbd559a1fd48aedd954435558cd98c7d0da8b03cc6c140a32c/yarl-1.22.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:efb07073be061c8f79d03d04139a80ba33cbd390ca8f0297aae9cce6411e4c6b", size = 373562, upload-time = "2025-10-06T14:11:58.783Z" }, - { url = "https://files.pythonhosted.org/packages/03/1f/c5d94abc91557384719da10ff166b916107c1b45e4d0423a88457071dd88/yarl-1.22.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e51ac5435758ba97ad69617e13233da53908beccc6cfcd6c34bbed8dcbede486", size = 339828, upload-time = "2025-10-06T14:12:00.686Z" }, - { url = "https://files.pythonhosted.org/packages/5f/97/aa6a143d3afba17b6465733681c70cf175af89f76ec8d9286e08437a7454/yarl-1.22.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:33e32a0dd0c8205efa8e83d04fc9f19313772b78522d1bdc7d9aed706bfd6138", size = 347551, upload-time = "2025-10-06T14:12:02.628Z" }, - { url = "https://files.pythonhosted.org/packages/43/3c/45a2b6d80195959239a7b2a8810506d4eea5487dce61c2a3393e7fc3c52e/yarl-1.22.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:bf4a21e58b9cde0e401e683ebd00f6ed30a06d14e93f7c8fd059f8b6e8f87b6a", size = 334512, upload-time = "2025-10-06T14:12:04.871Z" }, - { url = "https://files.pythonhosted.org/packages/86/a0/c2ab48d74599c7c84cb104ebd799c5813de252bea0f360ffc29d270c2caa/yarl-1.22.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:e4b582bab49ac33c8deb97e058cd67c2c50dac0dd134874106d9c774fd272529", size = 352400, upload-time = "2025-10-06T14:12:06.624Z" }, - { url = "https://files.pythonhosted.org/packages/32/75/f8919b2eafc929567d3d8411f72bdb1a2109c01caaab4ebfa5f8ffadc15b/yarl-1.22.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:0b5bcc1a9c4839e7e30b7b30dd47fe5e7e44fb7054ec29b5bb8d526aa1041093", size = 357140, upload-time = "2025-10-06T14:12:08.362Z" }, - { url = "https://files.pythonhosted.org/packages/cf/72/6a85bba382f22cf78add705d8c3731748397d986e197e53ecc7835e76de7/yarl-1.22.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:c0232bce2170103ec23c454e54a57008a9a72b5d1c3105dc2496750da8cfa47c", size = 341473, upload-time = "2025-10-06T14:12:10.994Z" }, - { url = "https://files.pythonhosted.org/packages/35/18/55e6011f7c044dc80b98893060773cefcfdbf60dfefb8cb2f58b9bacbd83/yarl-1.22.0-cp314-cp314t-win32.whl", hash = "sha256:8009b3173bcd637be650922ac455946197d858b3630b6d8787aa9e5c4564533e", size = 89056, upload-time = "2025-10-06T14:12:13.317Z" }, - { url = "https://files.pythonhosted.org/packages/f9/86/0f0dccb6e59a9e7f122c5afd43568b1d31b8ab7dda5f1b01fb5c7025c9a9/yarl-1.22.0-cp314-cp314t-win_amd64.whl", hash = "sha256:9fb17ea16e972c63d25d4a97f016d235c78dd2344820eb35bc034bc32012ee27", size = 96292, upload-time = "2025-10-06T14:12:15.398Z" }, - { url = "https://files.pythonhosted.org/packages/48/b7/503c98092fb3b344a179579f55814b613c1fbb1c23b3ec14a7b008a66a6e/yarl-1.22.0-cp314-cp314t-win_arm64.whl", hash = "sha256:9f6d73c1436b934e3f01df1e1b21ff765cd1d28c77dfb9ace207f746d4610ee1", size = 85171, upload-time = "2025-10-06T14:12:16.935Z" }, - { url = "https://files.pythonhosted.org/packages/73/ae/b48f95715333080afb75a4504487cbe142cae1268afc482d06692d605ae6/yarl-1.22.0-py3-none-any.whl", hash = "sha256:1380560bdba02b6b6c90de54133c81c9f2a453dee9912fe58c1dcced1edb7cff", size = 46814, upload-time = "2025-10-06T14:12:53.872Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/e3/02/0f2892c661036d50ede074e376733dca2ae7c6eb617489437771209d4180/zipp-3.23.0.tar.gz", hash = "sha256:a07157588a12518c9d4034df3fbbee09c814741a33ff63c05fa29d26a2404166", size = 25547, upload-time = "2025-06-08T17:06:39.4Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2e/54/647ade08bf0db230bfea292f893923872fd20be6ac6f53b2b936ba839d75/zipp-3.23.0-py3-none-any.whl", hash = "sha256:071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e", size = 10276, upload-time = "2025-06-08T17:06:38.034Z" }, ] diff --git a/visualize_example.jpg b/visualize_example.jpg new file mode 100644 index 0000000..37917d1 Binary files /dev/null and b/visualize_example.jpg differ