├── tests ├── __init__.py └── unit │ ├── __init__.py │ └── test_version.py ├── src └── exchange │ ├── common │ ├── __init__.py │ ├── logging.py │ ├── telemetry.py │ └── config.py │ ├── order_service │ ├── __init__.py │ ├── models.py │ ├── handlers.py │ └── main.py │ ├── trade_service │ ├── __init__.py │ ├── models.py │ ├── handlers.py │ └── main.py │ ├── notification_service │ ├── __init__.py │ ├── handlers.py │ └── main.py │ └── __init__.py ├── .env ├── config └── config.toml ├── grafana ├── provisioning │ ├── dashboards │ │ └── dashboards.yaml │ └── datasources │ │ └── datasource.yaml └── dashboards │ └── faststream.json ├── justfile ├── prometheus └── prometheus.yaml ├── .github ├── dependabot.yml └── workflows │ └── ci.yaml ├── tempo └── tempo.yaml ├── .gitignore ├── .pre-commit-config.yaml ├── Dockerfile ├── README.md ├── pyproject.toml ├── docker-compose.yaml └── pdm.lock /tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/unit/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/exchange/common/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/exchange/order_service/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/exchange/trade_service/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/exchange/notification_service/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/exchange/__init__.py: -------------------------------------------------------------------------------- 1 | __version__ = "0.1.0" 2 | -------------------------------------------------------------------------------- /tests/unit/test_version.py: -------------------------------------------------------------------------------- 1 | from exchange import __version__ 2 | 3 | 4 | def test_version() -> None: 5 | assert __version__ == "0.1.0" 6 | -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | # App config 2 | export CONFIG_PATH=./config/config.toml 3 | 4 | # RabbitMQ 5 | export RABBITMQ_USER=admin 6 | export RABBITMQ_PASSWORD=admin 7 | -------------------------------------------------------------------------------- /config/config.toml: -------------------------------------------------------------------------------- 1 | [rabbit] 2 | user = "admin" 3 | password = "admin" 4 | port = 5672 5 | host = "example.rabbit" 6 | 7 | [trace] 8 | otlp_endpoint = "http://example.tempo:4317" 9 | -------------------------------------------------------------------------------- /src/exchange/common/logging.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | 4 | def configure_logging() -> None: 5 | fmt_str = "[%(asctime)s] - %(levelname)s - [%(module)s:%(lineno)s:%(funcName)s] - %(message)s" 6 | logging.basicConfig(level=logging.INFO, format=fmt_str) 7 | -------------------------------------------------------------------------------- /grafana/provisioning/dashboards/dashboards.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | 3 | providers: 4 | - name: "FastStream" 5 | orgId: 1 6 | type: "file" 7 | disableDeletion: true 8 | editable: true 9 | options: 10 | path: "/etc/grafana/dashboards/faststream.json" 11 | -------------------------------------------------------------------------------- /src/exchange/order_service/models.py: -------------------------------------------------------------------------------- 1 | from enum import Enum 2 | 3 | from pydantic import BaseModel 4 | 5 | 6 | class Direction(Enum): 7 | BUY = "BUY" 8 | SELL = "SELL" 9 | 10 | 11 | class Order(BaseModel): 12 | symbol: str 13 | quantity: int 14 | type: Direction 15 | -------------------------------------------------------------------------------- /src/exchange/trade_service/models.py: -------------------------------------------------------------------------------- 1 | from decimal import Decimal 2 | from enum import Enum 3 | 4 | from pydantic import BaseModel 5 | 6 | from exchange.order_service.models import Order 7 | 8 | 9 | class Status(Enum): 10 | PENDING = "PENDING" 11 | SUBMITTED = "SUBMITTED" 12 | 13 | 14 | class Trade(BaseModel): 15 | order: Order 16 | status: Status 17 | price: Decimal | None = None 18 | -------------------------------------------------------------------------------- /justfile: -------------------------------------------------------------------------------- 1 | # Show help message 2 | [private] 3 | @default: 4 | just --list 5 | 6 | # Install all depends for developing 7 | @install: 8 | pdm install -G:all 9 | pre-commit install 10 | 11 | # Run tests 12 | @test: 13 | pytest tests --cov=pyproject --cov-append --cov-report term-missing -v 14 | 15 | # Run pre-commit 16 | @lint: 17 | pre-commit run --all-files 18 | 19 | # Run app in docker container 20 | @up: 21 | docker compose --profile exchange --profile grafana up --build -d 22 | 23 | # Stop docker containers 24 | @down: 25 | docker compose --profile exchange --profile grafana down 26 | -------------------------------------------------------------------------------- /prometheus/prometheus.yaml: -------------------------------------------------------------------------------- 1 | global: 2 | scrape_interval: 15s 3 | evaluation_interval: 15s 4 | 5 | scrape_configs: 6 | - job_name: "prometheus" 7 | static_configs: 8 | - targets: [ "localhost:9090" ] 9 | - job_name: "tempo" 10 | static_configs: 11 | - targets: [ "example.tempo:3200" ] 12 | - job_name: "order" 13 | static_configs: 14 | - targets: [ "example.order:8080" ] 15 | - job_name: "trade" 16 | static_configs: 17 | - targets: [ "example.trade:8080" ] 18 | - job_name: "notification" 19 | static_configs: 20 | - targets: [ "example.notification:8080" ] 21 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "pip" 4 | directory: "/" 5 | schedule: 6 | interval: "weekly" 7 | open-pull-requests-limit: 10 8 | labels: 9 | - "dependencies" 10 | - "python" 11 | 12 | - package-ecosystem: "github-actions" 13 | directory: "/" 14 | schedule: 15 | interval: "weekly" 16 | open-pull-requests-limit: 10 17 | labels: 18 | - "dependencies" 19 | - "github-actions" 20 | 21 | - package-ecosystem: "docker" 22 | directory: "/" 23 | schedule: 24 | interval: "weekly" 25 | open-pull-requests-limit: 10 26 | labels: 27 | - "dependencies" 28 | - "docker" 29 | -------------------------------------------------------------------------------- /src/exchange/notification_service/handlers.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import logging 3 | import random 4 | 5 | from faststream.rabbit import RabbitRouter 6 | from opentelemetry import trace 7 | 8 | logger = logging.getLogger(__name__) 9 | tracer = trace.get_tracer(__name__) 10 | router = RabbitRouter() 11 | 12 | 13 | async def send_notification(text: str) -> None: 14 | with tracer.start_as_current_span("send notification", attributes={"text": text}): 15 | await asyncio.sleep(random.randint(1, 50) / 10) 16 | 17 | logger.info("Notification sent successfully") 18 | 19 | 20 | @router.subscriber("notifications") 21 | async def notifications_handler(message: str) -> None: 22 | logger.info("Received message [%s]", message) 23 | await send_notification(message) 24 | -------------------------------------------------------------------------------- /src/exchange/common/telemetry.py: -------------------------------------------------------------------------------- 1 | from opentelemetry import trace 2 | from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter 3 | from opentelemetry.sdk.resources import Resource 4 | from opentelemetry.sdk.trace import TracerProvider 5 | from opentelemetry.sdk.trace.export import BatchSpanProcessor 6 | 7 | 8 | def setup_telemetry(service_name: str, otlp_endpoint: str) -> TracerProvider: 9 | resource = Resource.create(attributes={"service.name": service_name}) 10 | tracer_provider = TracerProvider(resource=resource) 11 | exporter = OTLPSpanExporter(endpoint=otlp_endpoint) 12 | processor = BatchSpanProcessor(exporter) 13 | tracer_provider.add_span_processor(processor) 14 | trace.set_tracer_provider(tracer_provider) 15 | return tracer_provider 16 | -------------------------------------------------------------------------------- /grafana/provisioning/datasources/datasource.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | 3 | datasources: 4 | - uid: tempo 5 | orgId: 1 6 | name: Tempo 7 | type: tempo 8 | typeName: Tempo 9 | access: proxy 10 | url: http://example.tempo:3200 11 | password: "" 12 | user: "" 13 | database: "" 14 | basicAuth: false 15 | isDefault: false 16 | readOnly: false 17 | editable: true 18 | jsonData: 19 | httpMethod: GET 20 | serviceMap: 21 | datasourceUid: prometheus 22 | - name: Prometheus 23 | type: prometheus 24 | uid: prometheus 25 | access: proxy 26 | orgId: 1 27 | url: http://example.prometheus:9090 28 | basicAuth: false 29 | isDefault: false 30 | version: 1 31 | editable: false 32 | jsonData: 33 | httpMethod: GET 34 | -------------------------------------------------------------------------------- /src/exchange/order_service/handlers.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import logging 3 | import random 4 | 5 | from faststream.rabbit import RabbitRouter 6 | from opentelemetry import trace 7 | 8 | from exchange.order_service.models import Order 9 | from exchange.trade_service.models import Status, Trade 10 | 11 | logger = logging.getLogger(__name__) 12 | tracer = trace.get_tracer(__name__) 13 | router = RabbitRouter() 14 | 15 | 16 | @router.publisher("trades") 17 | @router.subscriber("orders") 18 | async def orders_handler(order: Order) -> Trade: 19 | logger.info("Received order [%s]", order) 20 | 21 | with tracer.start_as_current_span("validate order", attributes={"quantity": order.quantity}): 22 | await asyncio.sleep(random.randint(1, 50) / 10) 23 | if order.quantity <= 0: 24 | raise ValueError("Order quantity must be greater than zero") 25 | 26 | return Trade(order=order, status=Status.PENDING) 27 | -------------------------------------------------------------------------------- /src/exchange/trade_service/handlers.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import logging 3 | import random 4 | from decimal import Decimal 5 | 6 | from faststream.rabbit import RabbitRouter 7 | from opentelemetry import trace 8 | 9 | from exchange.trade_service.models import Status, Trade 10 | 11 | logger = logging.getLogger(__name__) 12 | tracer = trace.get_tracer(__name__) 13 | router = RabbitRouter() 14 | 15 | 16 | @router.publisher("notifications") 17 | @router.subscriber("trades") 18 | async def trades_handler(trade: Trade) -> str: 19 | logger.info("Received trade [%s]", trade) 20 | 21 | with tracer.start_as_current_span("process trade"): 22 | price = Decimal(random.randint(1000, 1500)) 23 | trade.price = price 24 | trade.status = Status.SUBMITTED 25 | await asyncio.sleep(random.randint(1, 50) / 10) 26 | 27 | message = f"Order [{trade.order}] was executed at the asset price {trade.price}$" 28 | logger.info(message) 29 | 30 | return message 31 | -------------------------------------------------------------------------------- /src/exchange/common/config.py: -------------------------------------------------------------------------------- 1 | import os 2 | import tomllib 3 | from dataclasses import dataclass 4 | from typing import Any 5 | 6 | from adaptix import Retort 7 | 8 | DEFAULT_CONFIG_PATH = "./config/config.toml" 9 | 10 | 11 | @dataclass 12 | class RabbitConfig: 13 | user: str 14 | password: str 15 | port: int = 5672 16 | host: str = "localhost" 17 | 18 | @property 19 | def url(self) -> str: 20 | return f"amqp://{self.user}:{self.password}@{self.host}:{self.port}/" 21 | 22 | 23 | @dataclass 24 | class TraceConfig: 25 | otlp_endpoint: str 26 | 27 | 28 | @dataclass 29 | class Config: 30 | rabbit: RabbitConfig 31 | trace: TraceConfig 32 | 33 | 34 | def read_toml(path: str) -> dict[str, Any]: 35 | with open(path, "rb") as f: 36 | return tomllib.load(f) 37 | 38 | 39 | def load_config() -> Config: 40 | path = os.getenv("CONFIG_PATH", DEFAULT_CONFIG_PATH) 41 | data = read_toml(path) 42 | mapper = Retort() 43 | return mapper.load(data, Config) 44 | -------------------------------------------------------------------------------- /tempo/tempo.yaml: -------------------------------------------------------------------------------- 1 | stream_over_http_enabled: true 2 | server: 3 | http_listen_port: 3200 4 | log_level: info 5 | 6 | query_frontend: 7 | search: 8 | duration_slo: 5s 9 | throughput_bytes_slo: 1.073741824e+09 10 | trace_by_id: 11 | duration_slo: 5s 12 | 13 | distributor: 14 | receivers: 15 | otlp: 16 | protocols: 17 | grpc: 18 | endpoint: 0.0.0.0:4317 19 | 20 | ingester: 21 | max_block_duration: 5m 22 | 23 | compactor: 24 | compaction: 25 | block_retention: 1h 26 | 27 | metrics_generator: 28 | registry: 29 | external_labels: 30 | source: tempo 31 | cluster: docker-compose 32 | storage: 33 | path: /var/tempo/generator/wal 34 | remote_write: 35 | - url: http://example.prometheus:9090/api/v1/write 36 | send_exemplars: true 37 | traces_storage: 38 | path: /var/tempo/generator/traces 39 | 40 | storage: 41 | trace: 42 | backend: local 43 | wal: 44 | path: /var/tempo/wal 45 | local: 46 | path: /var/tempo/blocks 47 | 48 | overrides: 49 | defaults: 50 | metrics_generator: 51 | processors: [service-graphs, span-metrics, local-blocks] 52 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | share/python-wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | MANIFEST 28 | 29 | # Unit test / coverage reports 30 | htmlcov/ 31 | .tox/ 32 | .nox/ 33 | .coverage 34 | .coverage.* 35 | .cache 36 | nosetests.xml 37 | coverage.xml 38 | junitxml.xml 39 | *.cover 40 | *.py,cover 41 | .hypothesis/ 42 | .pytest_cache/ 43 | cover/ 44 | 45 | # Sphinx documentation 46 | docs/_build/ 47 | /docs/build/ 48 | /docs-build/ 49 | 50 | # pdm 51 | .pdm.toml 52 | .pdm-python 53 | .pdm-build/ 54 | 55 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 56 | __pypackages__/ 57 | 58 | # Environments 59 | .venv 60 | env/ 61 | venv/ 62 | ENV/ 63 | env.bak/ 64 | venv.bak/ 65 | 66 | # mypy 67 | .mypy_cache/ 68 | .dmypy.json 69 | dmypy.json 70 | 71 | # ruff 72 | /.ruff_cache/ 73 | 74 | # IDE 75 | .idea/ 76 | .vscode/ 77 | tempo-data/ 78 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | default_language_version: 2 | python: python3.12 3 | 4 | repos: 5 | - repo: https://github.com/compilerla/conventional-pre-commit 6 | rev: v4.2.0 7 | hooks: 8 | - id: conventional-pre-commit 9 | stages: [commit-msg] 10 | 11 | - repo: https://github.com/pre-commit/pre-commit-hooks 12 | rev: v5.0.0 13 | hooks: 14 | - id: check-ast 15 | - id: check-added-large-files 16 | - id: check-case-conflict 17 | - id: check-merge-conflict 18 | - id: detect-private-key 19 | - id: check-toml 20 | - id: check-yaml 21 | - id: debug-statements 22 | - id: end-of-file-fixer 23 | - id: mixed-line-ending 24 | - id: trailing-whitespace 25 | 26 | - repo: https://github.com/astral-sh/ruff-pre-commit 27 | rev: v0.12.7 28 | hooks: 29 | - id: ruff 30 | args: ["--fix"] 31 | - id: ruff-format 32 | 33 | - repo: local 34 | hooks: 35 | - id: mypy 36 | name: mypy 37 | entry: mypy src tests --config-file ./pyproject.toml 38 | language: python 39 | types: [python] 40 | require_serial: true 41 | pass_filenames: false 42 | -------------------------------------------------------------------------------- /src/exchange/trade_service/main.py: -------------------------------------------------------------------------------- 1 | import uvicorn 2 | from faststream.asgi import AsgiFastStream 3 | from faststream.rabbit import RabbitBroker 4 | from faststream.rabbit.opentelemetry import RabbitTelemetryMiddleware 5 | from faststream.rabbit.prometheus import RabbitPrometheusMiddleware 6 | from prometheus_client import CollectorRegistry, make_asgi_app 7 | 8 | from exchange.common.config import load_config 9 | from exchange.common.logging import configure_logging 10 | from exchange.common.telemetry import setup_telemetry 11 | from exchange.trade_service.handlers import router 12 | 13 | 14 | def main() -> AsgiFastStream: 15 | configure_logging() 16 | config = load_config() 17 | service_name = "trade" 18 | tracer_provider = setup_telemetry( 19 | service_name=service_name, 20 | otlp_endpoint=config.trace.otlp_endpoint, 21 | ) 22 | registry = CollectorRegistry() 23 | 24 | telemetry_middleware = RabbitTelemetryMiddleware(tracer_provider=tracer_provider) 25 | prometheus_middleware = RabbitPrometheusMiddleware( 26 | registry=registry, app_name=service_name, metrics_prefix="faststream" 27 | ) 28 | broker = RabbitBroker(url=config.rabbit.url, middlewares=(prometheus_middleware, telemetry_middleware)) 29 | broker.include_router(router) 30 | return AsgiFastStream(broker, [("/metrics", make_asgi_app(registry))]) 31 | 32 | 33 | if __name__ == "__main__": 34 | uvicorn.run(main(), host="0.0.0.0", port=8080) 35 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Use the official Python image as the base image 2 | FROM python:3.12.3-slim-bookworm as python-base 3 | 4 | # Set environment variables to non-interactive 5 | ENV PYTHONUNBUFFERED=1 \ 6 | PYTHONDONTWRITEBYTECODE=1 \ 7 | PIP_NO_CACHE_DIR=off \ 8 | PIP_DISABLE_PIP_VERSION_CHECK=on \ 9 | PIP_DEFAULT_TIMEOUT=100 \ 10 | PDM_HOME="/opt/pdm" \ 11 | PDM_PEP582="1" \ 12 | PYSETUP_PATH="/opt/pysetup" \ 13 | VENV_PATH="/opt/pysetup/.venv" \ 14 | PYTHONPATH="/app" 15 | 16 | # Update PATH to include PDM and the virtual environment binaries 17 | ENV PATH="$PDM_HOME/bin:$VENV_PATH/bin:$PATH" 18 | 19 | # Setup the builder base with system dependencies 20 | FROM python-base as builder-base 21 | RUN apt-get update && apt-get install -y git curl 22 | 23 | # Setup work directory and copy pyproject.toml (PDM uses the same pyproject.toml as Poetry) 24 | WORKDIR $PYSETUP_PATH 25 | 26 | # Copy dependencies 27 | COPY ./pyproject.toml . 28 | COPY ./pdm.lock . 29 | 30 | RUN pip install --no-cache-dir --upgrade pip \ 31 | && pip install --no-cache-dir setuptools wheel \ 32 | && pip install --no-cache-dir pdm 33 | 34 | # Install dependencies using PDM 35 | RUN pdm install --check --prod --no-editable 36 | 37 | # Setup the production environment 38 | FROM python-base as production 39 | COPY --from=builder-base $PYSETUP_PATH $PYSETUP_PATH 40 | RUN apt-get update 41 | 42 | # Set the working directory and copy your application code 43 | WORKDIR app/ 44 | COPY ./src /app 45 | -------------------------------------------------------------------------------- /src/exchange/notification_service/main.py: -------------------------------------------------------------------------------- 1 | import uvicorn 2 | from faststream.asgi import AsgiFastStream 3 | from faststream.rabbit import RabbitBroker 4 | from faststream.rabbit.opentelemetry import RabbitTelemetryMiddleware 5 | from faststream.rabbit.prometheus import RabbitPrometheusMiddleware 6 | from prometheus_client import CollectorRegistry, make_asgi_app 7 | 8 | from exchange.common.config import load_config 9 | from exchange.common.logging import configure_logging 10 | from exchange.common.telemetry import setup_telemetry 11 | from exchange.notification_service.handlers import router 12 | 13 | 14 | def main() -> AsgiFastStream: 15 | configure_logging() 16 | config = load_config() 17 | service_name = "notification" 18 | tracer_provider = setup_telemetry( 19 | service_name=service_name, 20 | otlp_endpoint=config.trace.otlp_endpoint, 21 | ) 22 | registry = CollectorRegistry() 23 | 24 | telemetry_middleware = RabbitTelemetryMiddleware(tracer_provider=tracer_provider) 25 | prometheus_middleware = RabbitPrometheusMiddleware( 26 | registry=registry, 27 | app_name=service_name, 28 | metrics_prefix="faststream", 29 | ) 30 | broker = RabbitBroker(url=config.rabbit.url, middlewares=(telemetry_middleware, prometheus_middleware)) 31 | broker.include_router(router) 32 | return AsgiFastStream(broker, [("/metrics", make_asgi_app(registry))]) 33 | 34 | 35 | if __name__ == "__main__": 36 | uvicorn.run(main(), host="0.0.0.0", port=8080) 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # [FastStream](https://github.com/ag2ai/faststream) Monitoring Example 4 | 5 | [![python](https://img.shields.io/badge/python-3.12-blue)](https://www.python.org/) 6 | [![pdm-managed](https://img.shields.io/badge/pdm-managed-blueviolet)](https://pdm-project.org) 7 | [![Checked with mypy](https://www.mypy-lang.org/static/mypy_badge.svg)](https://mypy-lang.org/) 8 | [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff) 9 | [![Test](https://github.com/draincoder/pyproject/actions/workflows/ci.yaml/badge.svg)](https://github.com/draincoder/pyproject/actions/workflows/ci.yaml) 10 | 11 |
12 | 13 | ## Example of monitoring settings for FastStream 14 | 15 | [FastStream OpenTelemetry documentation](https://faststream.ag2.ai/latest/getting-started/observability/opentelemetry/)\ 16 | [FastStream Prometheus documentation](https://faststream.ag2.ai/latest/getting-started/observability/prometheus/) 17 | 18 | * Three [**FastStream**](https://github.com/ag2ai/faststream) services 19 | * Exporting traces to **Grafana Tempo** via **gRPC** 20 | * Visualization of traces via **Grafana** 21 | * Collecting metrics and exporting using **Prometheus** 22 | * [**Grafana dashboard**](https://grafana.com/grafana/dashboards/22130-faststream-metrics/) for metrics 23 | * Examples with custom spans 24 | * Configured **docker-compose** with the entire infrastructure 25 | 26 | ## How to run the example 27 | 28 | 1. Clone project 29 | ```shell 30 | git clone https://github.com/draincoder/faststream-monitoring.git 31 | ``` 32 | 2. Start application 33 | ```shell 34 | docker compose --profile exchange --profile grafana up --build -d 35 | ``` 36 | 3. Open **Grafana** on `http://127.0.0.1:3000` with login `admin` and password `admin` 37 | 4. Go to **Explore** - **Tempo** 38 | 5. Enter TraceQL query `{}` 39 | 6. Go to **Dashboards** - **FastStream Metrics** 40 | 41 | ![Trace example](https://imgur.com/EziQgpy.png) 42 | ![Metrics example](https://imgur.com/J0aGEFB.png) 43 | -------------------------------------------------------------------------------- /src/exchange/order_service/main.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import random 3 | 4 | import uvicorn 5 | from faststream.asgi import AsgiFastStream 6 | from faststream.rabbit import RabbitBroker 7 | from faststream.rabbit.opentelemetry import RabbitTelemetryMiddleware 8 | from faststream.rabbit.prometheus import RabbitPrometheusMiddleware 9 | from prometheus_client import CollectorRegistry, make_asgi_app 10 | 11 | from exchange.common.config import load_config 12 | from exchange.common.logging import configure_logging 13 | from exchange.common.telemetry import setup_telemetry 14 | from exchange.order_service.handlers import router 15 | from exchange.order_service.models import Direction, Order 16 | 17 | 18 | def main() -> AsgiFastStream: 19 | configure_logging() 20 | config = load_config() 21 | service_name = "order" 22 | tracer_provider = setup_telemetry( 23 | service_name=service_name, 24 | otlp_endpoint=config.trace.otlp_endpoint, 25 | ) 26 | registry = CollectorRegistry() 27 | 28 | telemetry_middleware = RabbitTelemetryMiddleware(tracer_provider=tracer_provider) 29 | prometheus_middleware = RabbitPrometheusMiddleware( 30 | registry=registry, app_name=service_name, metrics_prefix="faststream" 31 | ) 32 | broker = RabbitBroker(url=config.rabbit.url, middlewares=(telemetry_middleware, prometheus_middleware)) 33 | broker.include_router(router) 34 | app = AsgiFastStream(broker, [("/metrics", make_asgi_app(registry))]) 35 | 36 | @app.after_startup 37 | async def after_startup() -> None: 38 | while True: 39 | await broker.publish(Order(symbol="AAPL", quantity=10, type=Direction.BUY), "orders") 40 | await broker.publish(Order(symbol="AAPL" * 100, quantity=5, type=Direction.BUY), "orders") 41 | await broker.publish(Order(symbol="AAPL" * 300, quantity=1, type=Direction.BUY), "orders") 42 | await broker.publish(Order(symbol="AAPL", quantity=-1, type=Direction.BUY), "orders") 43 | await asyncio.sleep(random.randint(1, 50) / 10) 44 | 45 | return app 46 | 47 | 48 | if __name__ == "__main__": 49 | uvicorn.run(main(), host="0.0.0.0", port=8080) 50 | -------------------------------------------------------------------------------- /.github/workflows/ci.yaml: -------------------------------------------------------------------------------- 1 | name: ci 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | - develop 8 | pull_request: 9 | branches: 10 | - master 11 | - develop 12 | 13 | jobs: 14 | lint: 15 | runs-on: ubuntu-latest 16 | steps: 17 | - name: Checkout 18 | uses: actions/checkout@v4 19 | 20 | - name: Setup Python 21 | uses: actions/setup-python@v5 22 | with: 23 | python-version: 3.12 24 | 25 | - name: Load cached Pre-Commit Dependencies 26 | id: cached-pre-commit-dependencies 27 | uses: actions/cache@v4 28 | with: 29 | path: ~/.cache/pre-commit/ 30 | key: pre-commit-4|${{ env.pythonLocation }}|${{ hashFiles('.pre-commit-config.yaml') }} 31 | 32 | - name: Set up PDM 33 | uses: pdm-project/setup-pdm@v4 34 | with: 35 | python-version: 3.12 36 | allow-python-prereleases: false 37 | cache: true 38 | cache-dependency-path: | 39 | ./pdm.lock 40 | 41 | - name: Install dependencies 42 | run: pdm install -G:all 43 | 44 | - name: Set PYTHONPATH 45 | run: echo "PYTHONPATH=$PWD" >> $GITHUB_ENV 46 | 47 | - name: Execute Pre-Commit 48 | run: pdm run pre-commit run --show-diff-on-failure --color=always --all-files 49 | 50 | test: 51 | runs-on: ubuntu-latest 52 | steps: 53 | - name: Checkout 54 | uses: actions/checkout@v4 55 | 56 | - name: Setup Python 57 | uses: actions/setup-python@v5 58 | with: 59 | python-version: 3.12 60 | 61 | - name: Set up PDM 62 | uses: pdm-project/setup-pdm@v4 63 | with: 64 | python-version: 3.12 65 | allow-python-prereleases: false 66 | cache: true 67 | cache-dependency-path: | 68 | ./pdm.lock 69 | 70 | - name: Install dependencies 71 | run: pdm install -G:all 72 | 73 | - name: Set PYTHONPATH 74 | run: echo "PYTHONPATH=$PWD" >> $GITHUB_ENV 75 | 76 | - name: Run tests 77 | run: pdm run pytest tests --cov=exchange --junitxml=junitxml.xml --cov-report "xml:coverage.xml"; exit ${PIPESTATUS[0]} 78 | 79 | - name: Test coverage comment 80 | uses: MishaKav/pytest-coverage-comment@main 81 | with: 82 | pytest-xml-coverage-path: ./coverage.xml 83 | junitxml-path: ./junitxml.xml 84 | report-only-changed-files: true 85 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "faststream-monitoring" 3 | version = "0.1.0" 4 | description = "Example of monitoring settings for FastStream." 5 | requires-python = ">=3.12" 6 | readme = "README.md" 7 | authors = [ 8 | {name = "treaditup", email = "treaditup@gmail.com"}, 9 | ] 10 | classifiers = [ 11 | "Programming Language :: Python :: 3.12", 12 | "Operating System :: OS Independent", 13 | ] 14 | dependencies = [ 15 | "opentelemetry-exporter-otlp>=1.24.0", 16 | "adaptix>=3.0.0b5", 17 | "uvicorn>=0.32.0", 18 | "faststream[otel,prometheus,rabbit]==0.6.0rc0", 19 | ] 20 | 21 | [project.urls] 22 | "Source" = "https://github.com/draincoder/faststream-monitoring" 23 | "Homepage" = "https://github.com/draincoder/faststream-monitoring" 24 | 25 | [build-system] 26 | requires = ["setuptools>=61", "wheel"] 27 | build-backend = "setuptools.build_meta" 28 | 29 | [tool.pdm.dev-dependencies] 30 | lint = [ 31 | "ruff>=0.3.4", 32 | "mypy>=1.9.0", 33 | "pre-commit>=3.7.0", 34 | ] 35 | test = [ 36 | "pytest>=8.1.1", 37 | "pytest-asyncio>=0.23.6", 38 | "pytest-cov>=5.0.0", 39 | ] 40 | 41 | [tool.ruff] 42 | line-length = 120 43 | target-version="py312" 44 | src = ["src"] 45 | include = ["src/**.py", "tests/**.py"] 46 | 47 | lint.select = [ 48 | "ALL", 49 | ] 50 | 51 | lint.ignore = [ 52 | "ARG", 53 | "ANN", 54 | "D", 55 | "EM101", 56 | "EM102", 57 | "PT001", 58 | "PT023", 59 | "SIM108", 60 | "SIM114", 61 | "TRY003", 62 | "PLW2901", 63 | "RET505", 64 | "ISC001", 65 | "UP035", 66 | "COM812", 67 | "PTH123", 68 | "S311", 69 | "S104", 70 | ] 71 | 72 | [tool.ruff.lint.per-file-ignores] 73 | "tests/**" = ["TID252", "PLR2004", "S101", "T201", "SLF001", "PERF203", "S603", "S607"] 74 | 75 | [tool.ruff.lint.mccabe] 76 | max-complexity = 12 77 | 78 | [tool.ruff.lint.isort] 79 | known-first-party = ["src", "tests"] 80 | no-lines-before = ["local-folder"] 81 | 82 | [tool.ruff.lint.flake8-tidy-imports] 83 | ban-relative-imports = "parents" 84 | 85 | [tool.ruff.format] 86 | docstring-code-format = true 87 | docstring-code-line-length = 88 88 | 89 | [tool.mypy] 90 | packages = ["src", "tests"] 91 | python_version = "3.12" 92 | 93 | strict = true 94 | pretty = true 95 | allow_redefinition = true 96 | allow_untyped_calls = true 97 | disallow_any_explicit = false 98 | disallow_any_generics = false 99 | disallow_subclassing_any = false 100 | disallow_untyped_decorators = false 101 | ignore_missing_imports = true 102 | show_column_numbers = true 103 | show_error_context = true 104 | warn_unreachable = true 105 | 106 | [tool.pytest.ini_options] 107 | asyncio_mode = "auto" 108 | filterwarnings = "ignore::DeprecationWarning" 109 | -------------------------------------------------------------------------------- /docker-compose.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | order: 3 | profiles: [ "exchange" ] 4 | container_name: example.order 5 | hostname: example.order 6 | build: 7 | context: . 8 | restart: unless-stopped 9 | depends_on: 10 | rabbit: 11 | condition: service_healthy 12 | tempo: 13 | condition: service_started 14 | networks: 15 | - example.grafana.network 16 | - example.rabbit.network 17 | volumes: 18 | - ./config:/app/config:ro 19 | environment: 20 | - CONFIG_PATH=$CONFIG_PATH 21 | command: [ "python", "-m", "exchange.order_service.main" ] 22 | 23 | trade: 24 | profiles: [ "exchange" ] 25 | container_name: example.trade 26 | hostname: example.trade 27 | build: 28 | context: . 29 | restart: unless-stopped 30 | depends_on: 31 | rabbit: 32 | condition: service_healthy 33 | tempo: 34 | condition: service_started 35 | networks: 36 | - example.grafana.network 37 | - example.rabbit.network 38 | volumes: 39 | - ./config:/app/config:ro 40 | environment: 41 | - CONFIG_PATH=$CONFIG_PATH 42 | command: [ "python", "-m", "exchange.trade_service.main" ] 43 | 44 | notification: 45 | profiles: [ "exchange" ] 46 | container_name: example.notification 47 | hostname: example.notification 48 | build: 49 | context: . 50 | restart: unless-stopped 51 | depends_on: 52 | rabbit: 53 | condition: service_healthy 54 | tempo: 55 | condition: service_started 56 | networks: 57 | - example.grafana.network 58 | - example.rabbit.network 59 | volumes: 60 | - ./config:/app/config:ro 61 | environment: 62 | - CONFIG_PATH=$CONFIG_PATH 63 | command: [ "python", "-m", "exchange.notification_service.main" ] 64 | 65 | rabbit: 66 | profiles: [ "exchange" ] 67 | image: rabbitmq:3.11-management-alpine 68 | container_name: example.rabbit 69 | hostname: example.rabbit 70 | restart: unless-stopped 71 | ports: 72 | - "5671:5671" 73 | - "5672:5672" 74 | - "15672:15672" 75 | networks: 76 | - example.rabbit.network 77 | volumes: 78 | - example.rabbit.data:/var/lib/rabbitmq/:rw 79 | environment: 80 | - RABBITMQ_DEFAULT_USER=${RABBITMQ_USER:-admin} 81 | - RABBITMQ_DEFAULT_PASS=${RABBITMQ_PASSWORD:-admin} 82 | healthcheck: 83 | test: [ "CMD-SHELL", "rabbitmq-diagnostics check_running -q" ] 84 | interval: 10s 85 | timeout: 60s 86 | retries: 5 87 | start_period: 10s 88 | 89 | grafana: 90 | profiles: [ "grafana" ] 91 | image: grafana/grafana:12.0.0 92 | container_name: example.grafana 93 | hostname: example.grafana 94 | restart: unless-stopped 95 | ports: 96 | - "3000:3000" 97 | networks: 98 | - example.grafana.network 99 | volumes: 100 | - example.grafana.data:/var/lib/grafana:rw 101 | - ./grafana/provisioning:/etc/grafana/provisioning:rw 102 | - ./grafana/dashboards:/etc/grafana/dashboards 103 | environment: 104 | - GF_SECURITY_ADMIN_USER=${GRAFANA_USER:-admin} 105 | - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD:-admin} 106 | - GF_USERS_ALLOW_SIGN_UP=false 107 | - GF_DATABASE_WAL=true 108 | - VIRTUAL_HOST=example.grafana 109 | - NETWORK_ACCESS=internal 110 | - VIRTUAL_PORT=3000 111 | 112 | tempo: 113 | profiles: [ "grafana" ] 114 | image: grafana/tempo:2.8.1 115 | container_name: example.tempo 116 | hostname: example.tempo 117 | command: [ "-config.file=/etc/tempo.yaml" ] 118 | volumes: 119 | - example.tempo.data:/var/tempo 120 | - ./tempo/tempo.yaml:/etc/tempo.yaml 121 | restart: unless-stopped 122 | ports: 123 | - "14250:14250" 124 | - "4317:4317" 125 | - "3200:3200" 126 | networks: 127 | - example.grafana.network 128 | 129 | prometheus: 130 | image: prom/prometheus:v3.3.1 131 | container_name: example.prometheus 132 | hostname: example.prometheus 133 | command: 134 | - --config.file=/etc/prometheus.yaml 135 | - --web.enable-remote-write-receiver 136 | - --enable-feature=exemplar-storage 137 | volumes: 138 | - ./prometheus/prometheus.yaml:/etc/prometheus.yaml 139 | ports: 140 | - "9090:9090" 141 | networks: 142 | - example.grafana.network 143 | 144 | volumes: 145 | example.grafana.data: {} 146 | example.rabbit.data: {} 147 | example.tempo.data: {} 148 | 149 | networks: 150 | example.grafana.network: {} 151 | example.rabbit.network: {} 152 | -------------------------------------------------------------------------------- /grafana/dashboards/faststream.json: -------------------------------------------------------------------------------- 1 | { 2 | "__inputs": [ 3 | { 4 | "name": "DS_PROMETHEUS", 5 | "label": "prometheus", 6 | "description": "Prometheus", 7 | "type": "datasource", 8 | "pluginId": "prometheus", 9 | "pluginName": "Prometheus" 10 | } 11 | ], 12 | "__requires": [ 13 | { 14 | "type": "panel", 15 | "id": "bargauge", 16 | "name": "Bar gauge", 17 | "version": "" 18 | }, 19 | { 20 | "type": "panel", 21 | "id": "gauge", 22 | "name": "Gauge", 23 | "version": "" 24 | }, 25 | { 26 | "type": "grafana", 27 | "id": "grafana", 28 | "name": "Grafana", 29 | "version": "7.0.1" 30 | }, 31 | { 32 | "type": "panel", 33 | "id": "graph", 34 | "name": "Graph", 35 | "version": "" 36 | }, 37 | { 38 | "type": "datasource", 39 | "id": "prometheus", 40 | "name": "Prometheus", 41 | "version": "1.0.0" 42 | }, 43 | { 44 | "type": "panel", 45 | "id": "stat", 46 | "name": "Stat", 47 | "version": "" 48 | }, 49 | { 50 | "type": "panel", 51 | "id": "table", 52 | "name": "Table", 53 | "version": "" 54 | } 55 | ], 56 | "annotations": { 57 | "list": [ 58 | { 59 | "builtIn": 1, 60 | "datasource": { 61 | "type": "datasource", 62 | "uid": "grafana" 63 | }, 64 | "enable": true, 65 | "hide": true, 66 | "iconColor": "rgba(0, 211, 255, 1)", 67 | "name": "Annotations & Alerts", 68 | "target": { 69 | "limit": 100, 70 | "matchAny": false, 71 | "tags": [], 72 | "type": "dashboard" 73 | }, 74 | "type": "dashboard" 75 | } 76 | ] 77 | }, 78 | "description": "FastStream is a powerful and easy-to-use Python framework for building asynchronous services interacting with event streams such as Apache Kafka, RabbitMQ, NATS and Redis", 79 | "editable": true, 80 | "fiscalYearStartMonth": 0, 81 | "graphTooltip": 0, 82 | "links": [ 83 | { 84 | "asDropdown": false, 85 | "icon": "external link", 86 | "includeVars": false, 87 | "keepTime": false, 88 | "tags": [], 89 | "targetBlank": true, 90 | "title": "FastStream", 91 | "tooltip": "", 92 | "type": "link", 93 | "url": "https://github.com/airtai/faststream" 94 | } 95 | ], 96 | "liveNow": false, 97 | "panels": [ 98 | { 99 | "datasource": { 100 | "type": "prometheus", 101 | "uid": "$datasource" 102 | }, 103 | "description": "All published messages of all statuses for the interval", 104 | "fieldConfig": { 105 | "defaults": { 106 | "mappings": [], 107 | "noValue": "N/A", 108 | "thresholds": { 109 | "mode": "absolute", 110 | "steps": [ 111 | { 112 | "color": "green", 113 | "value": null 114 | } 115 | ] 116 | }, 117 | "unit": "short", 118 | "unitScale": true 119 | }, 120 | "overrides": [] 121 | }, 122 | "gridPos": { 123 | "h": 5, 124 | "w": 3, 125 | "x": 0, 126 | "y": 0 127 | }, 128 | "id": 1, 129 | "options": { 130 | "colorMode": "value", 131 | "graphMode": "area", 132 | "justifyMode": "auto", 133 | "orientation": "auto", 134 | "reduceOptions": { 135 | "calcs": [ 136 | "lastNotNull" 137 | ], 138 | "fields": "", 139 | "values": false 140 | }, 141 | "showPercentChange": false, 142 | "textMode": "auto", 143 | "wideLayout": true 144 | }, 145 | "pluginVersion": "10.3.3", 146 | "targets": [ 147 | { 148 | "datasource": { 149 | "type": "prometheus", 150 | "uid": "$datasource" 151 | }, 152 | "exemplar": true, 153 | "expr": "sum(increase({app_name=~\"$app_name\", __name__=~\"${metrics_prefix}_published_messages_total\", destination=~\"$destination\"} [$__range]))", 154 | "interval": "", 155 | "legendFormat": "", 156 | "refId": "A" 157 | } 158 | ], 159 | "title": "Total messages published", 160 | "type": "stat" 161 | }, 162 | { 163 | "datasource": { 164 | "type": "prometheus", 165 | "uid": "$datasource" 166 | }, 167 | "description": "The number of successfully published messages per destination in the interval", 168 | "fieldConfig": { 169 | "defaults": { 170 | "fieldMinMax": false, 171 | "mappings": [], 172 | "noValue": "N/A", 173 | "thresholds": { 174 | "mode": "absolute", 175 | "steps": [ 176 | { 177 | "color": "green", 178 | "value": null 179 | } 180 | ] 181 | }, 182 | "unit": "short", 183 | "unitScale": true 184 | }, 185 | "overrides": [] 186 | }, 187 | "gridPos": { 188 | "h": 5, 189 | "w": 7, 190 | "x": 3, 191 | "y": 0 192 | }, 193 | "id": 7, 194 | "options": { 195 | "colorMode": "value", 196 | "graphMode": "area", 197 | "justifyMode": "auto", 198 | "orientation": "auto", 199 | "reduceOptions": { 200 | "calcs": [ 201 | "lastNotNull" 202 | ], 203 | "fields": "", 204 | "values": false 205 | }, 206 | "showPercentChange": false, 207 | "textMode": "value_and_name", 208 | "wideLayout": true 209 | }, 210 | "pluginVersion": "10.3.3", 211 | "targets": [ 212 | { 213 | "datasource": { 214 | "type": "prometheus", 215 | "uid": "$datasource" 216 | }, 217 | "editorMode": "code", 218 | "exemplar": true, 219 | "expr": "increase({app_name=~\"$app_name\", __name__=~\"${metrics_prefix}_published_messages_total\", status=\"success\", destination=~\"$destination\"} [$__range])", 220 | "interval": "", 221 | "legendFormat": "{{destination}}", 222 | "range": true, 223 | "refId": "A" 224 | } 225 | ], 226 | "title": "Messages published", 227 | "type": "stat" 228 | }, 229 | { 230 | "datasource": { 231 | "type": "prometheus", 232 | "uid": "$datasource" 233 | }, 234 | "description": "All received messages of all statuses for the interval", 235 | "fieldConfig": { 236 | "defaults": { 237 | "mappings": [], 238 | "noValue": "N/A", 239 | "thresholds": { 240 | "mode": "absolute", 241 | "steps": [ 242 | { 243 | "color": "green", 244 | "value": null 245 | } 246 | ] 247 | }, 248 | "unit": "short", 249 | "unitScale": true 250 | }, 251 | "overrides": [] 252 | }, 253 | "gridPos": { 254 | "h": 5, 255 | "w": 3, 256 | "x": 10, 257 | "y": 0 258 | }, 259 | "id": 2, 260 | "options": { 261 | "colorMode": "value", 262 | "graphMode": "area", 263 | "justifyMode": "auto", 264 | "orientation": "auto", 265 | "reduceOptions": { 266 | "calcs": [ 267 | "lastNotNull" 268 | ], 269 | "fields": "", 270 | "values": false 271 | }, 272 | "showPercentChange": false, 273 | "textMode": "auto", 274 | "wideLayout": true 275 | }, 276 | "pluginVersion": "10.3.3", 277 | "targets": [ 278 | { 279 | "datasource": { 280 | "type": "prometheus", 281 | "uid": "$datasource" 282 | }, 283 | "exemplar": true, 284 | "expr": "sum(increase({app_name=~\"$app_name\", __name__=~\"${metrics_prefix}_received_messages_total\", handler=~\"$handler\"} [$__range]))", 285 | "interval": "", 286 | "legendFormat": "", 287 | "refId": "A" 288 | } 289 | ], 290 | "title": "Total messages received", 291 | "type": "stat" 292 | }, 293 | { 294 | "datasource": { 295 | "type": "prometheus", 296 | "uid": "$datasource" 297 | }, 298 | "description": "All processed messages of all statuses for the interval", 299 | "fieldConfig": { 300 | "defaults": { 301 | "mappings": [], 302 | "noValue": "N/A", 303 | "thresholds": { 304 | "mode": "absolute", 305 | "steps": [ 306 | { 307 | "color": "green", 308 | "value": null 309 | } 310 | ] 311 | }, 312 | "unit": "short", 313 | "unitScale": true 314 | }, 315 | "overrides": [] 316 | }, 317 | "gridPos": { 318 | "h": 5, 319 | "w": 3, 320 | "x": 13, 321 | "y": 0 322 | }, 323 | "id": 3, 324 | "options": { 325 | "colorMode": "value", 326 | "graphMode": "area", 327 | "justifyMode": "auto", 328 | "orientation": "auto", 329 | "reduceOptions": { 330 | "calcs": [ 331 | "lastNotNull" 332 | ], 333 | "fields": "", 334 | "values": false 335 | }, 336 | "showPercentChange": false, 337 | "textMode": "auto", 338 | "wideLayout": true 339 | }, 340 | "pluginVersion": "10.3.3", 341 | "targets": [ 342 | { 343 | "datasource": { 344 | "type": "prometheus", 345 | "uid": "$datasource" 346 | }, 347 | "exemplar": true, 348 | "expr": "sum(increase({app_name=~\"$app_name\", __name__=~\"${metrics_prefix}_received_processed_messages_total\", handler=~\"$handler\"} [$__range]))", 349 | "interval": "", 350 | "legendFormat": "", 351 | "refId": "A" 352 | } 353 | ], 354 | "title": "Total messages processed", 355 | "type": "stat" 356 | }, 357 | { 358 | "datasource": { 359 | "type": "prometheus", 360 | "uid": "$datasource" 361 | }, 362 | "description": "The number of acked messages per handler in the interval", 363 | "fieldConfig": { 364 | "defaults": { 365 | "mappings": [], 366 | "noValue": "N/A", 367 | "thresholds": { 368 | "mode": "absolute", 369 | "steps": [ 370 | { 371 | "color": "green", 372 | "value": null 373 | } 374 | ] 375 | }, 376 | "unit": "short", 377 | "unitScale": true 378 | }, 379 | "overrides": [] 380 | }, 381 | "gridPos": { 382 | "h": 5, 383 | "w": 8, 384 | "x": 16, 385 | "y": 0 386 | }, 387 | "id": 8, 388 | "options": { 389 | "colorMode": "value", 390 | "graphMode": "area", 391 | "justifyMode": "auto", 392 | "orientation": "auto", 393 | "reduceOptions": { 394 | "calcs": [ 395 | "lastNotNull" 396 | ], 397 | "fields": "", 398 | "values": false 399 | }, 400 | "showPercentChange": false, 401 | "textMode": "value_and_name", 402 | "wideLayout": true 403 | }, 404 | "pluginVersion": "10.3.3", 405 | "targets": [ 406 | { 407 | "datasource": { 408 | "type": "prometheus", 409 | "uid": "$datasource" 410 | }, 411 | "exemplar": true, 412 | "expr": "increase({app_name=~\"$app_name\", __name__=~\"${metrics_prefix}_received_processed_messages_total\", status=\"acked\", handler=~\"$handler\"} [$__range])", 413 | "interval": "", 414 | "legendFormat": "{{handler}}", 415 | "refId": "A" 416 | } 417 | ], 418 | "title": "Messages processed", 419 | "type": "stat" 420 | }, 421 | { 422 | "datasource": { 423 | "type": "prometheus", 424 | "uid": "$datasource" 425 | }, 426 | "description": "All publication errors in the interval", 427 | "fieldConfig": { 428 | "defaults": { 429 | "color": { 430 | "mode": "thresholds" 431 | }, 432 | "mappings": [], 433 | "noValue": "N/A", 434 | "thresholds": { 435 | "mode": "absolute", 436 | "steps": [ 437 | { 438 | "color": "green", 439 | "value": null 440 | }, 441 | { 442 | "color": "red", 443 | "value": 1 444 | } 445 | ] 446 | }, 447 | "unitScale": true 448 | }, 449 | "overrides": [] 450 | }, 451 | "gridPos": { 452 | "h": 5, 453 | "w": 3, 454 | "x": 0, 455 | "y": 5 456 | }, 457 | "id": 5, 458 | "options": { 459 | "colorMode": "value", 460 | "graphMode": "area", 461 | "justifyMode": "auto", 462 | "orientation": "auto", 463 | "reduceOptions": { 464 | "calcs": [ 465 | "lastNotNull" 466 | ], 467 | "fields": "", 468 | "values": false 469 | }, 470 | "showPercentChange": false, 471 | "textMode": "auto", 472 | "wideLayout": true 473 | }, 474 | "pluginVersion": "10.3.3", 475 | "targets": [ 476 | { 477 | "datasource": { 478 | "type": "prometheus", 479 | "uid": "$datasource" 480 | }, 481 | "exemplar": true, 482 | "expr": "sum(increase({app_name=~\"$app_name\", __name__=~\"${metrics_prefix}_published_messages_exceptions_total\", destination=~\"$destination\"} [$__range]))", 483 | "interval": "", 484 | "legendFormat": "", 485 | "refId": "A" 486 | } 487 | ], 488 | "title": "Publish exceptions", 489 | "type": "stat" 490 | }, 491 | { 492 | "datasource": { 493 | "type": "prometheus", 494 | "uid": "$datasource" 495 | }, 496 | "description": "The average time of the publication duration for all messages per interval", 497 | "fieldConfig": { 498 | "defaults": { 499 | "color": { 500 | "mode": "continuous-GrYlRd" 501 | }, 502 | "mappings": [], 503 | "noValue": "N/A", 504 | "thresholds": { 505 | "mode": "absolute", 506 | "steps": [ 507 | { 508 | "color": "green", 509 | "value": null 510 | } 511 | ] 512 | }, 513 | "unit": "s", 514 | "unitScale": true 515 | }, 516 | "overrides": [] 517 | }, 518 | "gridPos": { 519 | "h": 5, 520 | "w": 7, 521 | "x": 3, 522 | "y": 5 523 | }, 524 | "id": 9, 525 | "options": { 526 | "displayMode": "lcd", 527 | "maxVizHeight": 300, 528 | "minVizHeight": 16, 529 | "minVizWidth": 8, 530 | "namePlacement": "auto", 531 | "orientation": "horizontal", 532 | "reduceOptions": { 533 | "calcs": [ 534 | "lastNotNull" 535 | ], 536 | "fields": "", 537 | "values": false 538 | }, 539 | "showUnfilled": true, 540 | "sizing": "auto", 541 | "valueMode": "color" 542 | }, 543 | "pluginVersion": "10.3.3", 544 | "targets": [ 545 | { 546 | "datasource": { 547 | "type": "prometheus", 548 | "uid": "$datasource" 549 | }, 550 | "exemplar": true, 551 | "expr": "{app_name=~\"$app_name\", __name__=~\"${metrics_prefix}_published_messages_duration_seconds_sum\", destination=~\"$destination\"} / {app_name=~\"$app_name\", __name__=~\"${metrics_prefix}_published_messages_duration_seconds_count\", destination=~\"$destination\"}", 552 | "interval": "", 553 | "legendFormat": "{{destination}}", 554 | "refId": "A" 555 | } 556 | ], 557 | "title": "Publish average duration", 558 | "type": "bargauge" 559 | }, 560 | { 561 | "datasource": { 562 | "type": "prometheus", 563 | "uid": "$datasource" 564 | }, 565 | "description": "All process errors in the interval", 566 | "fieldConfig": { 567 | "defaults": { 568 | "color": { 569 | "mode": "thresholds" 570 | }, 571 | "mappings": [], 572 | "noValue": "N/A", 573 | "thresholds": { 574 | "mode": "absolute", 575 | "steps": [ 576 | { 577 | "color": "green", 578 | "value": null 579 | }, 580 | { 581 | "color": "red", 582 | "value": 1 583 | } 584 | ] 585 | }, 586 | "unit": "none", 587 | "unitScale": true 588 | }, 589 | "overrides": [] 590 | }, 591 | "gridPos": { 592 | "h": 5, 593 | "w": 3, 594 | "x": 10, 595 | "y": 5 596 | }, 597 | "id": 6, 598 | "options": { 599 | "colorMode": "value", 600 | "graphMode": "area", 601 | "justifyMode": "auto", 602 | "orientation": "auto", 603 | "reduceOptions": { 604 | "calcs": [ 605 | "lastNotNull" 606 | ], 607 | "fields": "", 608 | "values": false 609 | }, 610 | "showPercentChange": false, 611 | "textMode": "auto", 612 | "wideLayout": true 613 | }, 614 | "pluginVersion": "10.3.3", 615 | "targets": [ 616 | { 617 | "datasource": { 618 | "type": "prometheus", 619 | "uid": "$datasource" 620 | }, 621 | "exemplar": true, 622 | "expr": "sum(increase({app_name=~\"$app_name\", __name__=~\"${metrics_prefix}_received_processed_messages_exceptions_total\", handler=~\"$handler\"} [$__range]))", 623 | "interval": "", 624 | "legendFormat": "", 625 | "refId": "A" 626 | } 627 | ], 628 | "title": "Process exceptions", 629 | "type": "stat" 630 | }, 631 | { 632 | "datasource": { 633 | "type": "prometheus", 634 | "uid": "$datasource" 635 | }, 636 | "description": "The number of messages in the process", 637 | "fieldConfig": { 638 | "defaults": { 639 | "mappings": [], 640 | "noValue": "N/A", 641 | "thresholds": { 642 | "mode": "absolute", 643 | "steps": [ 644 | { 645 | "color": "green", 646 | "value": null 647 | }, 648 | { 649 | "color": "yellow", 650 | "value": 10 651 | }, 652 | { 653 | "color": "red", 654 | "value": 100 655 | } 656 | ] 657 | }, 658 | "unit": "none", 659 | "unitScale": true 660 | }, 661 | "overrides": [] 662 | }, 663 | "gridPos": { 664 | "h": 5, 665 | "w": 3, 666 | "x": 13, 667 | "y": 5 668 | }, 669 | "id": 4, 670 | "options": { 671 | "colorMode": "value", 672 | "graphMode": "area", 673 | "justifyMode": "auto", 674 | "orientation": "auto", 675 | "reduceOptions": { 676 | "calcs": [ 677 | "lastNotNull" 678 | ], 679 | "fields": "", 680 | "values": false 681 | }, 682 | "showPercentChange": false, 683 | "textMode": "auto", 684 | "wideLayout": true 685 | }, 686 | "pluginVersion": "10.3.3", 687 | "targets": [ 688 | { 689 | "datasource": { 690 | "type": "prometheus", 691 | "uid": "$datasource" 692 | }, 693 | "exemplar": true, 694 | "expr": "sum({app_name=~\"$app_name\", __name__=~\"${metrics_prefix}_received_messages_in_process\", handler=~\"$handler\"})", 695 | "interval": "", 696 | "legendFormat": "", 697 | "refId": "A" 698 | } 699 | ], 700 | "title": "Messages in progress", 701 | "type": "stat" 702 | }, 703 | { 704 | "datasource": { 705 | "type": "prometheus", 706 | "uid": "$datasource" 707 | }, 708 | "description": "The average processing time for all messages per interval", 709 | "fieldConfig": { 710 | "defaults": { 711 | "color": { 712 | "mode": "continuous-GrYlRd" 713 | }, 714 | "mappings": [], 715 | "noValue": "N/A", 716 | "thresholds": { 717 | "mode": "absolute", 718 | "steps": [ 719 | { 720 | "color": "green", 721 | "value": null 722 | } 723 | ] 724 | }, 725 | "unit": "s", 726 | "unitScale": true 727 | }, 728 | "overrides": [] 729 | }, 730 | "gridPos": { 731 | "h": 5, 732 | "w": 8, 733 | "x": 16, 734 | "y": 5 735 | }, 736 | "id": 10, 737 | "options": { 738 | "displayMode": "lcd", 739 | "maxVizHeight": 300, 740 | "minVizHeight": 16, 741 | "minVizWidth": 8, 742 | "namePlacement": "auto", 743 | "orientation": "horizontal", 744 | "reduceOptions": { 745 | "calcs": [ 746 | "lastNotNull" 747 | ], 748 | "fields": "", 749 | "values": false 750 | }, 751 | "showUnfilled": true, 752 | "sizing": "auto", 753 | "valueMode": "color" 754 | }, 755 | "pluginVersion": "10.3.3", 756 | "targets": [ 757 | { 758 | "datasource": { 759 | "type": "prometheus", 760 | "uid": "$datasource" 761 | }, 762 | "exemplar": true, 763 | "expr": "{app_name=~\"$app_name\", __name__=~\"${metrics_prefix}_received_processed_messages_duration_seconds_sum\", handler=~\"$handler\"} / {app_name=~\"$app_name\", __name__=~\"${metrics_prefix}_received_processed_messages_duration_seconds_count\", handler=~\"$handler\"}", 764 | "interval": "", 765 | "legendFormat": "{{handler}}", 766 | "refId": "A" 767 | } 768 | ], 769 | "title": "Process average duration", 770 | "type": "bargauge" 771 | }, 772 | { 773 | "datasource": { 774 | "type": "prometheus", 775 | "uid": "$datasource" 776 | }, 777 | "description": "Publishing messages per second with the status", 778 | "fieldConfig": { 779 | "defaults": { 780 | "color": { 781 | "mode": "palette-classic" 782 | }, 783 | "custom": { 784 | "axisBorderShow": false, 785 | "axisCenteredZero": false, 786 | "axisColorMode": "text", 787 | "axisLabel": "", 788 | "axisPlacement": "auto", 789 | "barAlignment": 0, 790 | "drawStyle": "line", 791 | "fillOpacity": 0, 792 | "gradientMode": "none", 793 | "hideFrom": { 794 | "legend": false, 795 | "tooltip": false, 796 | "viz": false 797 | }, 798 | "insertNulls": false, 799 | "lineInterpolation": "linear", 800 | "lineStyle": { 801 | "fill": "solid" 802 | }, 803 | "lineWidth": 1, 804 | "pointSize": 5, 805 | "scaleDistribution": { 806 | "type": "linear" 807 | }, 808 | "showPoints": "auto", 809 | "spanNulls": false, 810 | "stacking": { 811 | "group": "A", 812 | "mode": "none" 813 | }, 814 | "thresholdsStyle": { 815 | "mode": "off" 816 | } 817 | }, 818 | "mappings": [], 819 | "noValue": "N/A", 820 | "thresholds": { 821 | "mode": "absolute", 822 | "steps": [ 823 | { 824 | "color": "green", 825 | "value": null 826 | } 827 | ] 828 | }, 829 | "unit": "mps", 830 | "unitScale": true 831 | }, 832 | "overrides": [] 833 | }, 834 | "gridPos": { 835 | "h": 8, 836 | "w": 8, 837 | "x": 0, 838 | "y": 10 839 | }, 840 | "id": 11, 841 | "options": { 842 | "legend": { 843 | "calcs": [], 844 | "displayMode": "list", 845 | "placement": "bottom", 846 | "showLegend": true 847 | }, 848 | "tooltip": { 849 | "mode": "single", 850 | "sort": "none" 851 | } 852 | }, 853 | "targets": [ 854 | { 855 | "datasource": { 856 | "type": "prometheus", 857 | "uid": "$datasource" 858 | }, 859 | "exemplar": true, 860 | "expr": "rate({app_name=~\"$app_name\", __name__=~\"${metrics_prefix}_published_messages_total\", destination=~\"$destination\"} [1m])", 861 | "interval": "", 862 | "legendFormat": "{{destination}} [{{status}}]", 863 | "refId": "A" 864 | } 865 | ], 866 | "title": "Publish per sec", 867 | "type": "timeseries" 868 | }, 869 | { 870 | "datasource": { 871 | "type": "prometheus", 872 | "uid": "$datasource" 873 | }, 874 | "description": "Processing messages per second with the status", 875 | "fieldConfig": { 876 | "defaults": { 877 | "color": { 878 | "mode": "palette-classic" 879 | }, 880 | "custom": { 881 | "axisBorderShow": false, 882 | "axisCenteredZero": false, 883 | "axisColorMode": "text", 884 | "axisLabel": "", 885 | "axisPlacement": "auto", 886 | "barAlignment": 0, 887 | "drawStyle": "line", 888 | "fillOpacity": 0, 889 | "gradientMode": "none", 890 | "hideFrom": { 891 | "legend": false, 892 | "tooltip": false, 893 | "viz": false 894 | }, 895 | "insertNulls": false, 896 | "lineInterpolation": "linear", 897 | "lineWidth": 1, 898 | "pointSize": 5, 899 | "scaleDistribution": { 900 | "type": "linear" 901 | }, 902 | "showPoints": "auto", 903 | "spanNulls": false, 904 | "stacking": { 905 | "group": "A", 906 | "mode": "none" 907 | }, 908 | "thresholdsStyle": { 909 | "mode": "off" 910 | } 911 | }, 912 | "mappings": [], 913 | "noValue": "N/A", 914 | "thresholds": { 915 | "mode": "absolute", 916 | "steps": [ 917 | { 918 | "color": "green", 919 | "value": null 920 | } 921 | ] 922 | }, 923 | "unit": "mps", 924 | "unitScale": true 925 | }, 926 | "overrides": [] 927 | }, 928 | "gridPos": { 929 | "h": 8, 930 | "w": 8, 931 | "x": 8, 932 | "y": 10 933 | }, 934 | "id": 12, 935 | "options": { 936 | "legend": { 937 | "calcs": [], 938 | "displayMode": "list", 939 | "placement": "bottom", 940 | "showLegend": true 941 | }, 942 | "tooltip": { 943 | "mode": "single", 944 | "sort": "none" 945 | } 946 | }, 947 | "targets": [ 948 | { 949 | "datasource": { 950 | "type": "prometheus", 951 | "uid": "$datasource" 952 | }, 953 | "exemplar": true, 954 | "expr": "rate({app_name=~\"$app_name\", __name__=~\"${metrics_prefix}_received_processed_messages_total\", handler=~\"$handler\"} [1m])", 955 | "interval": "", 956 | "legendFormat": "{{handler}} [{{status}}]", 957 | "refId": "A" 958 | } 959 | ], 960 | "title": "Process per sec", 961 | "type": "timeseries" 962 | }, 963 | { 964 | "datasource": { 965 | "type": "prometheus", 966 | "uid": "$datasource" 967 | }, 968 | "description": "Messages in process", 969 | "fieldConfig": { 970 | "defaults": { 971 | "color": { 972 | "mode": "palette-classic" 973 | }, 974 | "custom": { 975 | "axisBorderShow": false, 976 | "axisCenteredZero": false, 977 | "axisColorMode": "text", 978 | "axisLabel": "", 979 | "axisPlacement": "auto", 980 | "barAlignment": 0, 981 | "drawStyle": "line", 982 | "fillOpacity": 0, 983 | "gradientMode": "none", 984 | "hideFrom": { 985 | "legend": false, 986 | "tooltip": false, 987 | "viz": false 988 | }, 989 | "insertNulls": false, 990 | "lineInterpolation": "linear", 991 | "lineWidth": 1, 992 | "pointSize": 5, 993 | "scaleDistribution": { 994 | "type": "linear" 995 | }, 996 | "showPoints": "auto", 997 | "spanNulls": false, 998 | "stacking": { 999 | "group": "A", 1000 | "mode": "none" 1001 | }, 1002 | "thresholdsStyle": { 1003 | "mode": "off" 1004 | } 1005 | }, 1006 | "mappings": [], 1007 | "noValue": "N/A", 1008 | "thresholds": { 1009 | "mode": "absolute", 1010 | "steps": [ 1011 | { 1012 | "color": "green", 1013 | "value": null 1014 | } 1015 | ] 1016 | }, 1017 | "unitScale": true 1018 | }, 1019 | "overrides": [] 1020 | }, 1021 | "gridPos": { 1022 | "h": 8, 1023 | "w": 8, 1024 | "x": 16, 1025 | "y": 10 1026 | }, 1027 | "id": 14, 1028 | "options": { 1029 | "legend": { 1030 | "calcs": [], 1031 | "displayMode": "list", 1032 | "placement": "bottom", 1033 | "showLegend": true 1034 | }, 1035 | "tooltip": { 1036 | "mode": "single", 1037 | "sort": "none" 1038 | } 1039 | }, 1040 | "targets": [ 1041 | { 1042 | "datasource": { 1043 | "type": "prometheus", 1044 | "uid": "$datasource" 1045 | }, 1046 | "exemplar": true, 1047 | "expr": "{app_name=~\"$app_name\", __name__=~\"${metrics_prefix}_received_messages_in_process\", handler=~\"$handler\"}", 1048 | "interval": "", 1049 | "legendFormat": "{{handler}}", 1050 | "refId": "A" 1051 | } 1052 | ], 1053 | "title": "Messages in process", 1054 | "type": "timeseries" 1055 | }, 1056 | { 1057 | "datasource": { 1058 | "type": "prometheus", 1059 | "uid": "$datasource" 1060 | }, 1061 | "description": "The longest message publishing", 1062 | "fieldConfig": { 1063 | "defaults": { 1064 | "color": { 1065 | "mode": "palette-classic" 1066 | }, 1067 | "custom": { 1068 | "axisBorderShow": false, 1069 | "axisCenteredZero": false, 1070 | "axisColorMode": "text", 1071 | "axisLabel": "", 1072 | "axisPlacement": "auto", 1073 | "barAlignment": 0, 1074 | "drawStyle": "line", 1075 | "fillOpacity": 0, 1076 | "gradientMode": "none", 1077 | "hideFrom": { 1078 | "legend": false, 1079 | "tooltip": false, 1080 | "viz": false 1081 | }, 1082 | "insertNulls": false, 1083 | "lineInterpolation": "linear", 1084 | "lineWidth": 1, 1085 | "pointSize": 5, 1086 | "scaleDistribution": { 1087 | "type": "linear" 1088 | }, 1089 | "showPoints": "auto", 1090 | "spanNulls": false, 1091 | "stacking": { 1092 | "group": "A", 1093 | "mode": "none" 1094 | }, 1095 | "thresholdsStyle": { 1096 | "mode": "off" 1097 | } 1098 | }, 1099 | "mappings": [], 1100 | "noValue": "N/A", 1101 | "thresholds": { 1102 | "mode": "absolute", 1103 | "steps": [ 1104 | { 1105 | "color": "green", 1106 | "value": null 1107 | } 1108 | ] 1109 | }, 1110 | "unit": "s", 1111 | "unitScale": true 1112 | }, 1113 | "overrides": [] 1114 | }, 1115 | "gridPos": { 1116 | "h": 8, 1117 | "w": 8, 1118 | "x": 0, 1119 | "y": 18 1120 | }, 1121 | "id": 16, 1122 | "options": { 1123 | "legend": { 1124 | "calcs": [], 1125 | "displayMode": "list", 1126 | "placement": "bottom", 1127 | "showLegend": true 1128 | }, 1129 | "tooltip": { 1130 | "mode": "single", 1131 | "sort": "none" 1132 | } 1133 | }, 1134 | "targets": [ 1135 | { 1136 | "datasource": { 1137 | "type": "prometheus", 1138 | "uid": "$datasource" 1139 | }, 1140 | "exemplar": true, 1141 | "expr": "histogram_quantile(.99,sum(rate({app_name=~\"$app_name\", __name__=~\"${metrics_prefix}_published_messages_duration_seconds_bucket\", destination=~\"$destination\"} [1m])) by(destination, le))", 1142 | "interval": "", 1143 | "legendFormat": "{{destination}}", 1144 | "refId": "A" 1145 | } 1146 | ], 1147 | "title": "Publish duration [PR 99]", 1148 | "type": "timeseries" 1149 | }, 1150 | { 1151 | "datasource": { 1152 | "type": "prometheus", 1153 | "uid": "$datasource" 1154 | }, 1155 | "description": "The longest message processing", 1156 | "fieldConfig": { 1157 | "defaults": { 1158 | "color": { 1159 | "mode": "palette-classic" 1160 | }, 1161 | "custom": { 1162 | "axisBorderShow": false, 1163 | "axisCenteredZero": false, 1164 | "axisColorMode": "text", 1165 | "axisLabel": "", 1166 | "axisPlacement": "auto", 1167 | "barAlignment": 0, 1168 | "drawStyle": "line", 1169 | "fillOpacity": 0, 1170 | "gradientMode": "none", 1171 | "hideFrom": { 1172 | "legend": false, 1173 | "tooltip": false, 1174 | "viz": false 1175 | }, 1176 | "insertNulls": false, 1177 | "lineInterpolation": "linear", 1178 | "lineWidth": 1, 1179 | "pointSize": 5, 1180 | "scaleDistribution": { 1181 | "type": "linear" 1182 | }, 1183 | "showPoints": "auto", 1184 | "spanNulls": false, 1185 | "stacking": { 1186 | "group": "A", 1187 | "mode": "none" 1188 | }, 1189 | "thresholdsStyle": { 1190 | "mode": "off" 1191 | } 1192 | }, 1193 | "mappings": [], 1194 | "noValue": "N/A", 1195 | "thresholds": { 1196 | "mode": "absolute", 1197 | "steps": [ 1198 | { 1199 | "color": "green", 1200 | "value": null 1201 | }, 1202 | { 1203 | "color": "red", 1204 | "value": 80 1205 | } 1206 | ] 1207 | }, 1208 | "unit": "s", 1209 | "unitScale": true 1210 | }, 1211 | "overrides": [] 1212 | }, 1213 | "gridPos": { 1214 | "h": 8, 1215 | "w": 8, 1216 | "x": 8, 1217 | "y": 18 1218 | }, 1219 | "id": 13, 1220 | "options": { 1221 | "legend": { 1222 | "calcs": [], 1223 | "displayMode": "list", 1224 | "placement": "bottom", 1225 | "showLegend": true 1226 | }, 1227 | "tooltip": { 1228 | "mode": "single", 1229 | "sort": "none" 1230 | } 1231 | }, 1232 | "targets": [ 1233 | { 1234 | "datasource": { 1235 | "type": "prometheus", 1236 | "uid": "$datasource" 1237 | }, 1238 | "exemplar": true, 1239 | "expr": "histogram_quantile(.99,sum(rate({app_name=~\"$app_name\", __name__=~\"${metrics_prefix}_received_processed_messages_duration_seconds_bucket\", handler=~\"$handler\"} [1m])) by(handler, le))", 1240 | "interval": "", 1241 | "legendFormat": "{{handler}}", 1242 | "refId": "A" 1243 | } 1244 | ], 1245 | "title": "Process duration [PR 99]", 1246 | "type": "timeseries" 1247 | }, 1248 | { 1249 | "datasource": { 1250 | "type": "prometheus", 1251 | "uid": "$datasource" 1252 | }, 1253 | "description": "The largest received messages in size", 1254 | "fieldConfig": { 1255 | "defaults": { 1256 | "color": { 1257 | "mode": "palette-classic" 1258 | }, 1259 | "custom": { 1260 | "axisBorderShow": false, 1261 | "axisCenteredZero": false, 1262 | "axisColorMode": "text", 1263 | "axisLabel": "", 1264 | "axisPlacement": "auto", 1265 | "barAlignment": 0, 1266 | "drawStyle": "line", 1267 | "fillOpacity": 0, 1268 | "gradientMode": "none", 1269 | "hideFrom": { 1270 | "legend": false, 1271 | "tooltip": false, 1272 | "viz": false 1273 | }, 1274 | "insertNulls": false, 1275 | "lineInterpolation": "linear", 1276 | "lineWidth": 1, 1277 | "pointSize": 5, 1278 | "scaleDistribution": { 1279 | "type": "linear" 1280 | }, 1281 | "showPoints": "auto", 1282 | "spanNulls": false, 1283 | "stacking": { 1284 | "group": "A", 1285 | "mode": "none" 1286 | }, 1287 | "thresholdsStyle": { 1288 | "mode": "off" 1289 | } 1290 | }, 1291 | "mappings": [], 1292 | "noValue": "N/A", 1293 | "thresholds": { 1294 | "mode": "absolute", 1295 | "steps": [ 1296 | { 1297 | "color": "green", 1298 | "value": null 1299 | } 1300 | ] 1301 | }, 1302 | "unit": "bytes", 1303 | "unitScale": false 1304 | }, 1305 | "overrides": [] 1306 | }, 1307 | "gridPos": { 1308 | "h": 8, 1309 | "w": 8, 1310 | "x": 16, 1311 | "y": 18 1312 | }, 1313 | "id": 15, 1314 | "options": { 1315 | "legend": { 1316 | "calcs": [], 1317 | "displayMode": "list", 1318 | "placement": "bottom", 1319 | "showLegend": true 1320 | }, 1321 | "tooltip": { 1322 | "mode": "single", 1323 | "sort": "none" 1324 | } 1325 | }, 1326 | "targets": [ 1327 | { 1328 | "datasource": { 1329 | "type": "prometheus", 1330 | "uid": "$datasource" 1331 | }, 1332 | "exemplar": true, 1333 | "expr": "histogram_quantile(.99,sum(rate({app_name=~\"$app_name\", __name__=~\"${metrics_prefix}_received_messages_size_bytes_bucket\", handler=~\"$handler\"} [1m])) by(handler, le))", 1334 | "interval": "", 1335 | "legendFormat": "{{handler}}", 1336 | "refId": "A" 1337 | } 1338 | ], 1339 | "title": "Received message size [PR 99]", 1340 | "type": "timeseries" 1341 | }, 1342 | { 1343 | "collapsed": true, 1344 | "datasource": { 1345 | "type": "$datasource", 1346 | "uid": "prometheus" 1347 | }, 1348 | "gridPos": { 1349 | "h": 1, 1350 | "w": 24, 1351 | "x": 0, 1352 | "y": 26 1353 | }, 1354 | "id": 22, 1355 | "panels": [ 1356 | { 1357 | "datasource": { 1358 | "type": "prometheus", 1359 | "uid": "$datasource" 1360 | }, 1361 | "description": "Percentage of acked messages relative to all messages", 1362 | "fieldConfig": { 1363 | "defaults": { 1364 | "color": { 1365 | "mode": "palette-classic" 1366 | }, 1367 | "custom": { 1368 | "axisBorderShow": false, 1369 | "axisCenteredZero": false, 1370 | "axisColorMode": "text", 1371 | "axisLabel": "", 1372 | "axisPlacement": "auto", 1373 | "axisSoftMax": 1, 1374 | "barAlignment": 0, 1375 | "drawStyle": "line", 1376 | "fillOpacity": 0, 1377 | "gradientMode": "none", 1378 | "hideFrom": { 1379 | "legend": false, 1380 | "tooltip": false, 1381 | "viz": false 1382 | }, 1383 | "insertNulls": false, 1384 | "lineInterpolation": "linear", 1385 | "lineWidth": 1, 1386 | "pointSize": 5, 1387 | "scaleDistribution": { 1388 | "type": "linear" 1389 | }, 1390 | "showPoints": "auto", 1391 | "spanNulls": false, 1392 | "stacking": { 1393 | "group": "A", 1394 | "mode": "none" 1395 | }, 1396 | "thresholdsStyle": { 1397 | "mode": "area" 1398 | } 1399 | }, 1400 | "mappings": [], 1401 | "noValue": "N/A", 1402 | "thresholds": { 1403 | "mode": "absolute", 1404 | "steps": [ 1405 | { 1406 | "color": "red" 1407 | }, 1408 | { 1409 | "color": "green", 1410 | "value": 0.8 1411 | } 1412 | ] 1413 | }, 1414 | "unit": "percentunit", 1415 | "unitScale": true 1416 | }, 1417 | "overrides": [] 1418 | }, 1419 | "gridPos": { 1420 | "h": 8, 1421 | "w": 8, 1422 | "x": 0, 1423 | "y": 27 1424 | }, 1425 | "id": 18, 1426 | "options": { 1427 | "legend": { 1428 | "calcs": [], 1429 | "displayMode": "list", 1430 | "placement": "bottom", 1431 | "showLegend": true 1432 | }, 1433 | "tooltip": { 1434 | "mode": "single", 1435 | "sort": "none" 1436 | } 1437 | }, 1438 | "targets": [ 1439 | { 1440 | "datasource": { 1441 | "type": "prometheus", 1442 | "uid": "$datasource" 1443 | }, 1444 | "exemplar": true, 1445 | "expr": "sum by(handler) ({app_name=~\"$app_name\", __name__=~\"${metrics_prefix}_received_processed_messages_total\", status=\"acked\", handler=~\"$handler\"}) / sum by(handler) ({app_name=~\"$app_name\", __name__=~\"${metrics_prefix}_received_processed_messages_total\", handler=~\"$handler\"})", 1446 | "interval": "", 1447 | "legendFormat": "{{handler}}", 1448 | "refId": "A" 1449 | } 1450 | ], 1451 | "title": "Percent of acked messages", 1452 | "type": "timeseries" 1453 | }, 1454 | { 1455 | "datasource": { 1456 | "type": "prometheus", 1457 | "uid": "$datasource" 1458 | }, 1459 | "description": "Percentage of error messages relative to all messages", 1460 | "fieldConfig": { 1461 | "defaults": { 1462 | "color": { 1463 | "mode": "palette-classic" 1464 | }, 1465 | "custom": { 1466 | "axisBorderShow": false, 1467 | "axisCenteredZero": false, 1468 | "axisColorMode": "text", 1469 | "axisLabel": "", 1470 | "axisPlacement": "auto", 1471 | "axisSoftMax": 1, 1472 | "barAlignment": 0, 1473 | "drawStyle": "line", 1474 | "fillOpacity": 0, 1475 | "gradientMode": "none", 1476 | "hideFrom": { 1477 | "legend": false, 1478 | "tooltip": false, 1479 | "viz": false 1480 | }, 1481 | "insertNulls": false, 1482 | "lineInterpolation": "linear", 1483 | "lineWidth": 1, 1484 | "pointSize": 5, 1485 | "scaleDistribution": { 1486 | "type": "linear" 1487 | }, 1488 | "showPoints": "auto", 1489 | "spanNulls": false, 1490 | "stacking": { 1491 | "group": "A", 1492 | "mode": "none" 1493 | }, 1494 | "thresholdsStyle": { 1495 | "mode": "area" 1496 | } 1497 | }, 1498 | "mappings": [], 1499 | "noValue": "N/A", 1500 | "thresholds": { 1501 | "mode": "absolute", 1502 | "steps": [ 1503 | { 1504 | "color": "red" 1505 | } 1506 | ] 1507 | }, 1508 | "unit": "percentunit", 1509 | "unitScale": true 1510 | }, 1511 | "overrides": [] 1512 | }, 1513 | "gridPos": { 1514 | "h": 8, 1515 | "w": 8, 1516 | "x": 8, 1517 | "y": 27 1518 | }, 1519 | "id": 20, 1520 | "options": { 1521 | "legend": { 1522 | "calcs": [], 1523 | "displayMode": "list", 1524 | "placement": "bottom", 1525 | "showLegend": true 1526 | }, 1527 | "tooltip": { 1528 | "mode": "single", 1529 | "sort": "none" 1530 | } 1531 | }, 1532 | "targets": [ 1533 | { 1534 | "datasource": { 1535 | "type": "prometheus", 1536 | "uid": "$datasource" 1537 | }, 1538 | "exemplar": true, 1539 | "expr": "sum by(handler) ({app_name=~\"$app_name\", __name__=~\"${metrics_prefix}_received_processed_messages_total\", status=\"error\", handler=~\"$handler\"}) / sum by(handler) ({app_name=~\"$app_name\", __name__=~\"${metrics_prefix}_received_processed_messages_total\", handler=~\"$handler\"})", 1540 | "interval": "", 1541 | "legendFormat": "{{handler}}", 1542 | "refId": "A" 1543 | } 1544 | ], 1545 | "title": "Percent of error messages", 1546 | "type": "timeseries" 1547 | }, 1548 | { 1549 | "datasource": { 1550 | "type": "prometheus", 1551 | "uid": "$datasource" 1552 | }, 1553 | "description": "Percentage of nacked, rejected, skipped messages relative to all messages", 1554 | "fieldConfig": { 1555 | "defaults": { 1556 | "color": { 1557 | "mode": "palette-classic" 1558 | }, 1559 | "custom": { 1560 | "axisBorderShow": false, 1561 | "axisCenteredZero": false, 1562 | "axisColorMode": "text", 1563 | "axisLabel": "", 1564 | "axisPlacement": "auto", 1565 | "axisSoftMax": 1, 1566 | "barAlignment": 0, 1567 | "drawStyle": "line", 1568 | "fillOpacity": 0, 1569 | "gradientMode": "none", 1570 | "hideFrom": { 1571 | "legend": false, 1572 | "tooltip": false, 1573 | "viz": false 1574 | }, 1575 | "insertNulls": false, 1576 | "lineInterpolation": "linear", 1577 | "lineWidth": 1, 1578 | "pointSize": 5, 1579 | "scaleDistribution": { 1580 | "type": "linear" 1581 | }, 1582 | "showPoints": "auto", 1583 | "spanNulls": false, 1584 | "stacking": { 1585 | "group": "A", 1586 | "mode": "none" 1587 | }, 1588 | "thresholdsStyle": { 1589 | "mode": "area" 1590 | } 1591 | }, 1592 | "mappings": [], 1593 | "noValue": "N/A", 1594 | "thresholds": { 1595 | "mode": "absolute", 1596 | "steps": [ 1597 | { 1598 | "color": "red" 1599 | } 1600 | ] 1601 | }, 1602 | "unit": "percentunit", 1603 | "unitScale": true 1604 | }, 1605 | "overrides": [] 1606 | }, 1607 | "gridPos": { 1608 | "h": 8, 1609 | "w": 8, 1610 | "x": 16, 1611 | "y": 27 1612 | }, 1613 | "id": 21, 1614 | "options": { 1615 | "legend": { 1616 | "calcs": [], 1617 | "displayMode": "list", 1618 | "placement": "bottom", 1619 | "showLegend": true 1620 | }, 1621 | "tooltip": { 1622 | "mode": "single", 1623 | "sort": "none" 1624 | } 1625 | }, 1626 | "targets": [ 1627 | { 1628 | "datasource": { 1629 | "type": "prometheus", 1630 | "uid": "$datasource" 1631 | }, 1632 | "exemplar": true, 1633 | "expr": "sum by(handler) ({app_name=~\"$app_name\", __name__=~\"${metrics_prefix}_received_processed_messages_total\", status=~\"nacked|rejected|skipped\", handler=~\"$handler\"}) / sum by(handler) ({app_name=~\"$app_name\", __name__=~\"${metrics_prefix}_received_processed_messages_total\", handler=~\"$handler\"})", 1634 | "interval": "", 1635 | "legendFormat": "{{handler}}", 1636 | "refId": "A" 1637 | } 1638 | ], 1639 | "title": "Percent of nacked, rejected, skipped messages", 1640 | "type": "timeseries" 1641 | } 1642 | ], 1643 | "title": "Percentages of processed message statuses", 1644 | "type": "row" 1645 | } 1646 | ], 1647 | "refresh": "10s", 1648 | "schemaVersion": 39, 1649 | "tags": [ 1650 | "faststream" 1651 | ], 1652 | "templating": { 1653 | "list": [ 1654 | { 1655 | "current": { 1656 | "selected": false, 1657 | "text": "Prometheus", 1658 | "value": "prometheus" 1659 | }, 1660 | "description": "Prometheus data source", 1661 | "hide": 0, 1662 | "includeAll": false, 1663 | "label": "Data Source", 1664 | "multi": false, 1665 | "name": "datasource", 1666 | "options": [], 1667 | "query": "prometheus", 1668 | "refresh": 1, 1669 | "regex": "", 1670 | "skipUrlSync": false, 1671 | "type": "datasource" 1672 | }, 1673 | { 1674 | "current": { 1675 | "selected": false, 1676 | "text": "faststream", 1677 | "value": "faststream" 1678 | }, 1679 | "description": "The prefix of metrics that is specified in PrometheusMiddleware", 1680 | "hide": 0, 1681 | "label": "Metrics Prefix", 1682 | "name": "metrics_prefix", 1683 | "options": [ 1684 | { 1685 | "selected": true, 1686 | "text": "faststream", 1687 | "value": "faststream" 1688 | } 1689 | ], 1690 | "query": "faststream", 1691 | "skipUrlSync": false, 1692 | "type": "textbox" 1693 | }, 1694 | { 1695 | "allValue": ".+", 1696 | "current": { 1697 | "selected": false, 1698 | "text": "All", 1699 | "value": ".+" 1700 | }, 1701 | "datasource": { 1702 | "type": "prometheus", 1703 | "uid": "$datasource" 1704 | }, 1705 | "definition": "label_values({__name__=~\"${metrics_prefix}_published_messages_total|${metrics_prefix}_received_messages_total\"},app_name)", 1706 | "description": "The name of the application that is specified in PrometheusMiddleware", 1707 | "hide": 0, 1708 | "includeAll": true, 1709 | "label": "App Name", 1710 | "multi": true, 1711 | "name": "app_name", 1712 | "options": [], 1713 | "query": { 1714 | "qryType": 1, 1715 | "query": "label_values(app_name)", 1716 | "refId": "PrometheusVariableQueryEditor-VariableQuery" 1717 | }, 1718 | "refresh": 1, 1719 | "regex": "", 1720 | "skipUrlSync": false, 1721 | "sort": 1, 1722 | "type": "query" 1723 | }, 1724 | { 1725 | "allValue": ".+", 1726 | "current": { 1727 | "selected": false, 1728 | "text": "All", 1729 | "value": ".+" 1730 | }, 1731 | "datasource": { 1732 | "type": "prometheus", 1733 | "uid": "${datasource}" 1734 | }, 1735 | "definition": "label_values({__name__=~\"${metrics_prefix}_published_messages_total\", app_name=~\"$app_name\"},destination)", 1736 | "description": "Destination", 1737 | "hide": 0, 1738 | "includeAll": true, 1739 | "label": "Destination", 1740 | "multi": true, 1741 | "name": "destination", 1742 | "options": [], 1743 | "query": { 1744 | "qryType": 1, 1745 | "query": "label_values({__name__=~\"${metrics_prefix}_published_messages_total\", app_name=~\"$app_name\"},destination)", 1746 | "refId": "PrometheusVariableQueryEditor-VariableQuery" 1747 | }, 1748 | "refresh": 1, 1749 | "regex": "", 1750 | "skipUrlSync": false, 1751 | "sort": 1, 1752 | "type": "query" 1753 | }, 1754 | { 1755 | "allValue": ".+", 1756 | "current": { 1757 | "selected": false, 1758 | "text": "All", 1759 | "value": ".+" 1760 | }, 1761 | "datasource": { 1762 | "type": "prometheus", 1763 | "uid": "${datasource}" 1764 | }, 1765 | "definition": "label_values({__name__=~\"${metrics_prefix}_received_messages_total\", app_name=~\"$app_name\"},handler)", 1766 | "description": "Handler", 1767 | "hide": 0, 1768 | "includeAll": true, 1769 | "label": "Handler", 1770 | "multi": true, 1771 | "name": "handler", 1772 | "options": [], 1773 | "query": { 1774 | "qryType": 1, 1775 | "query": "label_values({__name__=~\"${metrics_prefix}_received_messages_total\", app_name=~\"$app_name\"},handler)", 1776 | "refId": "PrometheusVariableQueryEditor-VariableQuery" 1777 | }, 1778 | "refresh": 1, 1779 | "regex": "", 1780 | "skipUrlSync": false, 1781 | "sort": 1, 1782 | "type": "query" 1783 | } 1784 | ] 1785 | }, 1786 | "time": { 1787 | "from": "now-15m", 1788 | "to": "now" 1789 | }, 1790 | "timepicker": { 1791 | "refresh_intervals": [ 1792 | "5s", 1793 | "10s", 1794 | "30s", 1795 | "1m", 1796 | "5m", 1797 | "15m", 1798 | "30m", 1799 | "1h", 1800 | "2h", 1801 | "1d" 1802 | ], 1803 | "time_options": [ 1804 | "5m", 1805 | "15m", 1806 | "1h", 1807 | "6h", 1808 | "12h", 1809 | "24h", 1810 | "2d", 1811 | "7d", 1812 | "30d" 1813 | ] 1814 | }, 1815 | "timezone": "", 1816 | "title": "FastStream Metrics", 1817 | "uid": "faststream", 1818 | "version": 3, 1819 | "weekStart": "" 1820 | } 1821 | -------------------------------------------------------------------------------- /pdm.lock: -------------------------------------------------------------------------------- 1 | # This file is @generated by PDM. 2 | # It is not intended for manual editing. 3 | 4 | [metadata] 5 | groups = ["default", "lint", "test"] 6 | strategy = ["cross_platform", "inherit_metadata"] 7 | lock_version = "4.5.0" 8 | content_hash = "sha256:47ddaeac10e26a9c541dbfc00673ea972f40e15058564273415836dcde359e1e" 9 | 10 | [[metadata.targets]] 11 | requires_python = ">=3.12" 12 | 13 | [[package]] 14 | name = "adaptix" 15 | version = "3.0.0b11" 16 | requires_python = ">=3.9" 17 | summary = "An extremely flexible and configurable data model conversion library" 18 | groups = ["default"] 19 | dependencies = [ 20 | "exceptiongroup>=1.1.3; python_version < \"3.11\"", 21 | ] 22 | files = [ 23 | {file = "adaptix-3.0.0b11-py3-none-any.whl", hash = "sha256:5afa7197d1a084fc93da852bf58194de4a1c506caa3f5889c9953a27ce515bda"}, 24 | {file = "adaptix-3.0.0b11.tar.gz", hash = "sha256:3d3d660d97d9e1a85d133b181fdac8a200ff3185422fdf686601bc9ed0017162"}, 25 | ] 26 | 27 | [[package]] 28 | name = "aio-pika" 29 | version = "9.5.5" 30 | requires_python = "<4.0,>=3.9" 31 | summary = "Wrapper around the aiormq for asyncio and humans" 32 | groups = ["default"] 33 | dependencies = [ 34 | "aiormq<6.9,>=6.8", 35 | "exceptiongroup<2,>=1", 36 | "typing-extensions; python_version < \"3.10\"", 37 | "yarl", 38 | ] 39 | files = [ 40 | {file = "aio_pika-9.5.5-py3-none-any.whl", hash = "sha256:94e0ac3666398d6a28b0c3b530c1febf4c6d4ececb345620727cfd7bfe1c02e0"}, 41 | {file = "aio_pika-9.5.5.tar.gz", hash = "sha256:3d2f25838860fa7e209e21fc95555f558401f9b49a832897419489f1c9e1d6a4"}, 42 | ] 43 | 44 | [[package]] 45 | name = "aiormq" 46 | version = "6.8.1" 47 | requires_python = "<4.0,>=3.8" 48 | summary = "Pure python AMQP asynchronous client library" 49 | groups = ["default"] 50 | dependencies = [ 51 | "pamqp==3.3.0", 52 | "setuptools; python_version < \"3.8\"", 53 | "yarl", 54 | ] 55 | files = [ 56 | {file = "aiormq-6.8.1-py3-none-any.whl", hash = "sha256:5da896c8624193708f9409ffad0b20395010e2747f22aa4150593837f40aa017"}, 57 | {file = "aiormq-6.8.1.tar.gz", hash = "sha256:a964ab09634be1da1f9298ce225b310859763d5cf83ef3a7eae1a6dc6bd1da1a"}, 58 | ] 59 | 60 | [[package]] 61 | name = "annotated-types" 62 | version = "0.7.0" 63 | requires_python = ">=3.8" 64 | summary = "Reusable constraint types to use with typing.Annotated" 65 | groups = ["default"] 66 | dependencies = [ 67 | "typing-extensions>=4.0.0; python_version < \"3.9\"", 68 | ] 69 | files = [ 70 | {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, 71 | {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, 72 | ] 73 | 74 | [[package]] 75 | name = "anyio" 76 | version = "4.6.2.post1" 77 | requires_python = ">=3.9" 78 | summary = "High level compatibility layer for multiple asynchronous event loop implementations" 79 | groups = ["default"] 80 | dependencies = [ 81 | "exceptiongroup>=1.0.2; python_version < \"3.11\"", 82 | "idna>=2.8", 83 | "sniffio>=1.1", 84 | "typing-extensions>=4.1; python_version < \"3.11\"", 85 | ] 86 | files = [ 87 | {file = "anyio-4.6.2.post1-py3-none-any.whl", hash = "sha256:6d170c36fba3bdd840c73d3868c1e777e33676a69c3a72cf0a0d5d6d8009b61d"}, 88 | {file = "anyio-4.6.2.post1.tar.gz", hash = "sha256:4c8bc31ccdb51c7f7bd251f51c609e038d63e34219b44aa86e47576389880b4c"}, 89 | ] 90 | 91 | [[package]] 92 | name = "certifi" 93 | version = "2024.8.30" 94 | requires_python = ">=3.6" 95 | summary = "Python package for providing Mozilla's CA Bundle." 96 | groups = ["default"] 97 | files = [ 98 | {file = "certifi-2024.8.30-py3-none-any.whl", hash = "sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8"}, 99 | {file = "certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9"}, 100 | ] 101 | 102 | [[package]] 103 | name = "cfgv" 104 | version = "3.4.0" 105 | requires_python = ">=3.8" 106 | summary = "Validate configuration and produce human readable error messages." 107 | groups = ["lint"] 108 | files = [ 109 | {file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"}, 110 | {file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"}, 111 | ] 112 | 113 | [[package]] 114 | name = "charset-normalizer" 115 | version = "3.4.0" 116 | requires_python = ">=3.7.0" 117 | summary = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." 118 | groups = ["default"] 119 | files = [ 120 | {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0713f3adb9d03d49d365b70b84775d0a0d18e4ab08d12bc46baa6132ba78aaf6"}, 121 | {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:de7376c29d95d6719048c194a9cf1a1b0393fbe8488a22008610b0361d834ecf"}, 122 | {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4a51b48f42d9358460b78725283f04bddaf44a9358197b889657deba38f329db"}, 123 | {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b295729485b06c1a0683af02a9e42d2caa9db04a373dc38a6a58cdd1e8abddf1"}, 124 | {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ee803480535c44e7f5ad00788526da7d85525cfefaf8acf8ab9a310000be4b03"}, 125 | {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d59d125ffbd6d552765510e3f31ed75ebac2c7470c7274195b9161a32350284"}, 126 | {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cda06946eac330cbe6598f77bb54e690b4ca93f593dee1568ad22b04f347c15"}, 127 | {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07afec21bbbbf8a5cc3651aa96b980afe2526e7f048fdfb7f1014d84acc8b6d8"}, 128 | {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6b40e8d38afe634559e398cc32b1472f376a4099c75fe6299ae607e404c033b2"}, 129 | {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b8dcd239c743aa2f9c22ce674a145e0a25cb1566c495928440a181ca1ccf6719"}, 130 | {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:84450ba661fb96e9fd67629b93d2941c871ca86fc38d835d19d4225ff946a631"}, 131 | {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:44aeb140295a2f0659e113b31cfe92c9061622cadbc9e2a2f7b8ef6b1e29ef4b"}, 132 | {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1db4e7fefefd0f548d73e2e2e041f9df5c59e178b4c72fbac4cc6f535cfb1565"}, 133 | {file = "charset_normalizer-3.4.0-cp312-cp312-win32.whl", hash = "sha256:5726cf76c982532c1863fb64d8c6dd0e4c90b6ece9feb06c9f202417a31f7dd7"}, 134 | {file = "charset_normalizer-3.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:b197e7094f232959f8f20541ead1d9862ac5ebea1d58e9849c1bf979255dfac9"}, 135 | {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:dd4eda173a9fcccb5f2e2bd2a9f423d180194b1bf17cf59e3269899235b2a114"}, 136 | {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e9e3c4c9e1ed40ea53acf11e2a386383c3304212c965773704e4603d589343ed"}, 137 | {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92a7e36b000bf022ef3dbb9c46bfe2d52c047d5e3f3343f43204263c5addc250"}, 138 | {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54b6a92d009cbe2fb11054ba694bc9e284dad30a26757b1e372a1fdddaf21920"}, 139 | {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ffd9493de4c922f2a38c2bf62b831dcec90ac673ed1ca182fe11b4d8e9f2a64"}, 140 | {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:35c404d74c2926d0287fbd63ed5d27eb911eb9e4a3bb2c6d294f3cfd4a9e0c23"}, 141 | {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4796efc4faf6b53a18e3d46343535caed491776a22af773f366534056c4e1fbc"}, 142 | {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7fdd52961feb4c96507aa649550ec2a0d527c086d284749b2f582f2d40a2e0d"}, 143 | {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:92db3c28b5b2a273346bebb24857fda45601aef6ae1c011c0a997106581e8a88"}, 144 | {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ab973df98fc99ab39080bfb0eb3a925181454d7c3ac8a1e695fddfae696d9e90"}, 145 | {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4b67fdab07fdd3c10bb21edab3cbfe8cf5696f453afce75d815d9d7223fbe88b"}, 146 | {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:aa41e526a5d4a9dfcfbab0716c7e8a1b215abd3f3df5a45cf18a12721d31cb5d"}, 147 | {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ffc519621dce0c767e96b9c53f09c5d215578e10b02c285809f76509a3931482"}, 148 | {file = "charset_normalizer-3.4.0-cp313-cp313-win32.whl", hash = "sha256:f19c1585933c82098c2a520f8ec1227f20e339e33aca8fa6f956f6691b784e67"}, 149 | {file = "charset_normalizer-3.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:707b82d19e65c9bd28b81dde95249b07bf9f5b90ebe1ef17d9b57473f8a64b7b"}, 150 | {file = "charset_normalizer-3.4.0-py3-none-any.whl", hash = "sha256:fe9f97feb71aa9896b81973a7bbada8c49501dc73e58a10fcef6663af95e5079"}, 151 | {file = "charset_normalizer-3.4.0.tar.gz", hash = "sha256:223217c3d4f82c3ac5e29032b3f1c2eb0fb591b72161f86d93f5719079dae93e"}, 152 | ] 153 | 154 | [[package]] 155 | name = "click" 156 | version = "8.1.7" 157 | requires_python = ">=3.7" 158 | summary = "Composable command line interface toolkit" 159 | groups = ["default"] 160 | dependencies = [ 161 | "colorama; platform_system == \"Windows\"", 162 | "importlib-metadata; python_version < \"3.8\"", 163 | ] 164 | files = [ 165 | {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, 166 | {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, 167 | ] 168 | 169 | [[package]] 170 | name = "colorama" 171 | version = "0.4.6" 172 | requires_python = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" 173 | summary = "Cross-platform colored terminal text." 174 | groups = ["default", "test"] 175 | marker = "sys_platform == \"win32\" or platform_system == \"Windows\"" 176 | files = [ 177 | {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, 178 | {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, 179 | ] 180 | 181 | [[package]] 182 | name = "coverage" 183 | version = "7.6.4" 184 | requires_python = ">=3.9" 185 | summary = "Code coverage measurement for Python" 186 | groups = ["test"] 187 | files = [ 188 | {file = "coverage-7.6.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:12394842a3a8affa3ba62b0d4ab7e9e210c5e366fbac3e8b2a68636fb19892c2"}, 189 | {file = "coverage-7.6.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2b6b4c83d8e8ea79f27ab80778c19bc037759aea298da4b56621f4474ffeb117"}, 190 | {file = "coverage-7.6.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d5b8007f81b88696d06f7df0cb9af0d3b835fe0c8dbf489bad70b45f0e45613"}, 191 | {file = "coverage-7.6.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b57b768feb866f44eeed9f46975f3d6406380275c5ddfe22f531a2bf187eda27"}, 192 | {file = "coverage-7.6.4-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5915fcdec0e54ee229926868e9b08586376cae1f5faa9bbaf8faf3561b393d52"}, 193 | {file = "coverage-7.6.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0b58c672d14f16ed92a48db984612f5ce3836ae7d72cdd161001cc54512571f2"}, 194 | {file = "coverage-7.6.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:2fdef0d83a2d08d69b1f2210a93c416d54e14d9eb398f6ab2f0a209433db19e1"}, 195 | {file = "coverage-7.6.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8cf717ee42012be8c0cb205dbbf18ffa9003c4cbf4ad078db47b95e10748eec5"}, 196 | {file = "coverage-7.6.4-cp312-cp312-win32.whl", hash = "sha256:7bb92c539a624cf86296dd0c68cd5cc286c9eef2d0c3b8b192b604ce9de20a17"}, 197 | {file = "coverage-7.6.4-cp312-cp312-win_amd64.whl", hash = "sha256:1032e178b76a4e2b5b32e19d0fd0abbce4b58e77a1ca695820d10e491fa32b08"}, 198 | {file = "coverage-7.6.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:023bf8ee3ec6d35af9c1c6ccc1d18fa69afa1cb29eaac57cb064dbb262a517f9"}, 199 | {file = "coverage-7.6.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b0ac3d42cb51c4b12df9c5f0dd2f13a4f24f01943627120ec4d293c9181219ba"}, 200 | {file = "coverage-7.6.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8fe4984b431f8621ca53d9380901f62bfb54ff759a1348cd140490ada7b693c"}, 201 | {file = "coverage-7.6.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5fbd612f8a091954a0c8dd4c0b571b973487277d26476f8480bfa4b2a65b5d06"}, 202 | {file = "coverage-7.6.4-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dacbc52de979f2823a819571f2e3a350a7e36b8cb7484cdb1e289bceaf35305f"}, 203 | {file = "coverage-7.6.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:dab4d16dfef34b185032580e2f2f89253d302facba093d5fa9dbe04f569c4f4b"}, 204 | {file = "coverage-7.6.4-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:862264b12ebb65ad8d863d51f17758b1684560b66ab02770d4f0baf2ff75da21"}, 205 | {file = "coverage-7.6.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5beb1ee382ad32afe424097de57134175fea3faf847b9af002cc7895be4e2a5a"}, 206 | {file = "coverage-7.6.4-cp313-cp313-win32.whl", hash = "sha256:bf20494da9653f6410213424f5f8ad0ed885e01f7e8e59811f572bdb20b8972e"}, 207 | {file = "coverage-7.6.4-cp313-cp313-win_amd64.whl", hash = "sha256:182e6cd5c040cec0a1c8d415a87b67ed01193ed9ad458ee427741c7d8513d963"}, 208 | {file = "coverage-7.6.4-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:a181e99301a0ae128493a24cfe5cfb5b488c4e0bf2f8702091473d033494d04f"}, 209 | {file = "coverage-7.6.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:df57bdbeffe694e7842092c5e2e0bc80fff7f43379d465f932ef36f027179806"}, 210 | {file = "coverage-7.6.4-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0bcd1069e710600e8e4cf27f65c90c7843fa8edfb4520fb0ccb88894cad08b11"}, 211 | {file = "coverage-7.6.4-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:99b41d18e6b2a48ba949418db48159d7a2e81c5cc290fc934b7d2380515bd0e3"}, 212 | {file = "coverage-7.6.4-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6b1e54712ba3474f34b7ef7a41e65bd9037ad47916ccb1cc78769bae324c01a"}, 213 | {file = "coverage-7.6.4-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:53d202fd109416ce011578f321460795abfe10bb901b883cafd9b3ef851bacfc"}, 214 | {file = "coverage-7.6.4-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:c48167910a8f644671de9f2083a23630fbf7a1cb70ce939440cd3328e0919f70"}, 215 | {file = "coverage-7.6.4-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:cc8ff50b50ce532de2fa7a7daae9dd12f0a699bfcd47f20945364e5c31799fef"}, 216 | {file = "coverage-7.6.4-cp313-cp313t-win32.whl", hash = "sha256:b8d3a03d9bfcaf5b0141d07a88456bb6a4c3ce55c080712fec8418ef3610230e"}, 217 | {file = "coverage-7.6.4-cp313-cp313t-win_amd64.whl", hash = "sha256:f3ddf056d3ebcf6ce47bdaf56142af51bb7fad09e4af310241e9db7a3a8022e1"}, 218 | {file = "coverage-7.6.4.tar.gz", hash = "sha256:29fc0f17b1d3fea332f8001d4558f8214af7f1d87a345f3a133c901d60347c73"}, 219 | ] 220 | 221 | [[package]] 222 | name = "coverage" 223 | version = "7.6.4" 224 | extras = ["toml"] 225 | requires_python = ">=3.9" 226 | summary = "Code coverage measurement for Python" 227 | groups = ["test"] 228 | dependencies = [ 229 | "coverage==7.6.4", 230 | "tomli; python_full_version <= \"3.11.0a6\"", 231 | ] 232 | files = [ 233 | {file = "coverage-7.6.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:12394842a3a8affa3ba62b0d4ab7e9e210c5e366fbac3e8b2a68636fb19892c2"}, 234 | {file = "coverage-7.6.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2b6b4c83d8e8ea79f27ab80778c19bc037759aea298da4b56621f4474ffeb117"}, 235 | {file = "coverage-7.6.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d5b8007f81b88696d06f7df0cb9af0d3b835fe0c8dbf489bad70b45f0e45613"}, 236 | {file = "coverage-7.6.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b57b768feb866f44eeed9f46975f3d6406380275c5ddfe22f531a2bf187eda27"}, 237 | {file = "coverage-7.6.4-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5915fcdec0e54ee229926868e9b08586376cae1f5faa9bbaf8faf3561b393d52"}, 238 | {file = "coverage-7.6.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0b58c672d14f16ed92a48db984612f5ce3836ae7d72cdd161001cc54512571f2"}, 239 | {file = "coverage-7.6.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:2fdef0d83a2d08d69b1f2210a93c416d54e14d9eb398f6ab2f0a209433db19e1"}, 240 | {file = "coverage-7.6.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8cf717ee42012be8c0cb205dbbf18ffa9003c4cbf4ad078db47b95e10748eec5"}, 241 | {file = "coverage-7.6.4-cp312-cp312-win32.whl", hash = "sha256:7bb92c539a624cf86296dd0c68cd5cc286c9eef2d0c3b8b192b604ce9de20a17"}, 242 | {file = "coverage-7.6.4-cp312-cp312-win_amd64.whl", hash = "sha256:1032e178b76a4e2b5b32e19d0fd0abbce4b58e77a1ca695820d10e491fa32b08"}, 243 | {file = "coverage-7.6.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:023bf8ee3ec6d35af9c1c6ccc1d18fa69afa1cb29eaac57cb064dbb262a517f9"}, 244 | {file = "coverage-7.6.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b0ac3d42cb51c4b12df9c5f0dd2f13a4f24f01943627120ec4d293c9181219ba"}, 245 | {file = "coverage-7.6.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8fe4984b431f8621ca53d9380901f62bfb54ff759a1348cd140490ada7b693c"}, 246 | {file = "coverage-7.6.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5fbd612f8a091954a0c8dd4c0b571b973487277d26476f8480bfa4b2a65b5d06"}, 247 | {file = "coverage-7.6.4-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dacbc52de979f2823a819571f2e3a350a7e36b8cb7484cdb1e289bceaf35305f"}, 248 | {file = "coverage-7.6.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:dab4d16dfef34b185032580e2f2f89253d302facba093d5fa9dbe04f569c4f4b"}, 249 | {file = "coverage-7.6.4-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:862264b12ebb65ad8d863d51f17758b1684560b66ab02770d4f0baf2ff75da21"}, 250 | {file = "coverage-7.6.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5beb1ee382ad32afe424097de57134175fea3faf847b9af002cc7895be4e2a5a"}, 251 | {file = "coverage-7.6.4-cp313-cp313-win32.whl", hash = "sha256:bf20494da9653f6410213424f5f8ad0ed885e01f7e8e59811f572bdb20b8972e"}, 252 | {file = "coverage-7.6.4-cp313-cp313-win_amd64.whl", hash = "sha256:182e6cd5c040cec0a1c8d415a87b67ed01193ed9ad458ee427741c7d8513d963"}, 253 | {file = "coverage-7.6.4-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:a181e99301a0ae128493a24cfe5cfb5b488c4e0bf2f8702091473d033494d04f"}, 254 | {file = "coverage-7.6.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:df57bdbeffe694e7842092c5e2e0bc80fff7f43379d465f932ef36f027179806"}, 255 | {file = "coverage-7.6.4-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0bcd1069e710600e8e4cf27f65c90c7843fa8edfb4520fb0ccb88894cad08b11"}, 256 | {file = "coverage-7.6.4-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:99b41d18e6b2a48ba949418db48159d7a2e81c5cc290fc934b7d2380515bd0e3"}, 257 | {file = "coverage-7.6.4-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6b1e54712ba3474f34b7ef7a41e65bd9037ad47916ccb1cc78769bae324c01a"}, 258 | {file = "coverage-7.6.4-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:53d202fd109416ce011578f321460795abfe10bb901b883cafd9b3ef851bacfc"}, 259 | {file = "coverage-7.6.4-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:c48167910a8f644671de9f2083a23630fbf7a1cb70ce939440cd3328e0919f70"}, 260 | {file = "coverage-7.6.4-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:cc8ff50b50ce532de2fa7a7daae9dd12f0a699bfcd47f20945364e5c31799fef"}, 261 | {file = "coverage-7.6.4-cp313-cp313t-win32.whl", hash = "sha256:b8d3a03d9bfcaf5b0141d07a88456bb6a4c3ce55c080712fec8418ef3610230e"}, 262 | {file = "coverage-7.6.4-cp313-cp313t-win_amd64.whl", hash = "sha256:f3ddf056d3ebcf6ce47bdaf56142af51bb7fad09e4af310241e9db7a3a8022e1"}, 263 | {file = "coverage-7.6.4.tar.gz", hash = "sha256:29fc0f17b1d3fea332f8001d4558f8214af7f1d87a345f3a133c901d60347c73"}, 264 | ] 265 | 266 | [[package]] 267 | name = "distlib" 268 | version = "0.3.9" 269 | summary = "Distribution utilities" 270 | groups = ["lint"] 271 | files = [ 272 | {file = "distlib-0.3.9-py2.py3-none-any.whl", hash = "sha256:47f8c22fd27c27e25a65601af709b38e4f0a45ea4fc2e710f65755fa8caaaf87"}, 273 | {file = "distlib-0.3.9.tar.gz", hash = "sha256:a60f20dea646b8a33f3e7772f74dc0b2d0772d2837ee1342a00645c81edf9403"}, 274 | ] 275 | 276 | [[package]] 277 | name = "exceptiongroup" 278 | version = "1.3.0" 279 | requires_python = ">=3.7" 280 | summary = "Backport of PEP 654 (exception groups)" 281 | groups = ["default"] 282 | dependencies = [ 283 | "typing-extensions>=4.6.0; python_version < \"3.13\"", 284 | ] 285 | files = [ 286 | {file = "exceptiongroup-1.3.0-py3-none-any.whl", hash = "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10"}, 287 | {file = "exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88"}, 288 | ] 289 | 290 | [[package]] 291 | name = "fast-depends" 292 | version = "3.0.0a12" 293 | requires_python = ">=3.9" 294 | summary = "FastDepends - extracted and cleared from HTTP domain logic FastAPI Dependency Injection System. Async and sync are both supported." 295 | groups = ["default"] 296 | dependencies = [ 297 | "anyio<5.0.0,>=3.0.0", 298 | "typing-extensions!=4.12.1", 299 | ] 300 | files = [ 301 | {file = "fast_depends-3.0.0a12-py3-none-any.whl", hash = "sha256:8e16ad4c0666d031a26013c45f3f1c93bbf12ebe6e126ee5b816106137818b12"}, 302 | {file = "fast_depends-3.0.0a12.tar.gz", hash = "sha256:782fd4d4e78893dc1e39e7373aff34d3a1ccdc5b50f53ba4e8df70d3a69b139a"}, 303 | ] 304 | 305 | [[package]] 306 | name = "fast-depends" 307 | version = "3.0.0a12" 308 | extras = ["pydantic"] 309 | requires_python = ">=3.9" 310 | summary = "FastDepends - extracted and cleared from HTTP domain logic FastAPI Dependency Injection System. Async and sync are both supported." 311 | groups = ["default"] 312 | dependencies = [ 313 | "fast-depends==3.0.0a12", 314 | "pydantic!=1.8,!=1.8.1,<3.0.0,>=1.7.4", 315 | ] 316 | files = [ 317 | {file = "fast_depends-3.0.0a12-py3-none-any.whl", hash = "sha256:8e16ad4c0666d031a26013c45f3f1c93bbf12ebe6e126ee5b816106137818b12"}, 318 | {file = "fast_depends-3.0.0a12.tar.gz", hash = "sha256:782fd4d4e78893dc1e39e7373aff34d3a1ccdc5b50f53ba4e8df70d3a69b139a"}, 319 | ] 320 | 321 | [[package]] 322 | name = "faststream" 323 | version = "0.6.0rc0" 324 | requires_python = ">=3.10" 325 | summary = "FastStream: the simplest way to work with a messaging queues" 326 | groups = ["default"] 327 | dependencies = [ 328 | "anyio<5,>=3.7.1", 329 | "fast-depends[pydantic]<4.0.0,>=3.0.0a12", 330 | "typing-extensions>=4.8.0", 331 | ] 332 | files = [ 333 | {file = "faststream-0.6.0rc0-py3-none-any.whl", hash = "sha256:6f2a054e82a173d41ffc60f43ca40e828b28894f76639f69797ecfed44fcca9b"}, 334 | {file = "faststream-0.6.0rc0.tar.gz", hash = "sha256:94d461dfc8cb5ad7f87030c99e23041dc67b2f41075d5f59a6cd60d7d83d9dc9"}, 335 | ] 336 | 337 | [[package]] 338 | name = "faststream" 339 | version = "0.6.0rc0" 340 | extras = ["otel", "prometheus", "rabbit"] 341 | requires_python = ">=3.10" 342 | summary = "FastStream: the simplest way to work with a messaging queues" 343 | groups = ["default"] 344 | dependencies = [ 345 | "aio-pika<10,>=9", 346 | "faststream==0.6.0rc0", 347 | "opentelemetry-sdk<2.0.0,>=1.24.0", 348 | "prometheus-client<0.30.0,>=0.20.0", 349 | ] 350 | files = [ 351 | {file = "faststream-0.6.0rc0-py3-none-any.whl", hash = "sha256:6f2a054e82a173d41ffc60f43ca40e828b28894f76639f69797ecfed44fcca9b"}, 352 | {file = "faststream-0.6.0rc0.tar.gz", hash = "sha256:94d461dfc8cb5ad7f87030c99e23041dc67b2f41075d5f59a6cd60d7d83d9dc9"}, 353 | ] 354 | 355 | [[package]] 356 | name = "filelock" 357 | version = "3.16.1" 358 | requires_python = ">=3.8" 359 | summary = "A platform independent file lock." 360 | groups = ["lint"] 361 | files = [ 362 | {file = "filelock-3.16.1-py3-none-any.whl", hash = "sha256:2082e5703d51fbf98ea75855d9d5527e33d8ff23099bec374a134febee6946b0"}, 363 | {file = "filelock-3.16.1.tar.gz", hash = "sha256:c249fbfcd5db47e5e2d6d62198e565475ee65e4831e2561c8e313fa7eb961435"}, 364 | ] 365 | 366 | [[package]] 367 | name = "googleapis-common-protos" 368 | version = "1.65.0" 369 | requires_python = ">=3.7" 370 | summary = "Common protobufs used in Google APIs" 371 | groups = ["default"] 372 | dependencies = [ 373 | "protobuf!=3.20.0,!=3.20.1,!=4.21.1,!=4.21.2,!=4.21.3,!=4.21.4,!=4.21.5,<6.0.0.dev0,>=3.20.2", 374 | ] 375 | files = [ 376 | {file = "googleapis_common_protos-1.65.0-py2.py3-none-any.whl", hash = "sha256:2972e6c496f435b92590fd54045060867f3fe9be2c82ab148fc8885035479a63"}, 377 | {file = "googleapis_common_protos-1.65.0.tar.gz", hash = "sha256:334a29d07cddc3aa01dee4988f9afd9b2916ee2ff49d6b757155dc0d197852c0"}, 378 | ] 379 | 380 | [[package]] 381 | name = "grpcio" 382 | version = "1.67.0" 383 | requires_python = ">=3.8" 384 | summary = "HTTP/2-based RPC framework" 385 | groups = ["default"] 386 | files = [ 387 | {file = "grpcio-1.67.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:227316b5631260e0bef8a3ce04fa7db4cc81756fea1258b007950b6efc90c05d"}, 388 | {file = "grpcio-1.67.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:d90cfdafcf4b45a7a076e3e2a58e7bc3d59c698c4f6470b0bb13a4d869cf2273"}, 389 | {file = "grpcio-1.67.0-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:77196216d5dd6f99af1c51e235af2dd339159f657280e65ce7e12c1a8feffd1d"}, 390 | {file = "grpcio-1.67.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:15c05a26a0f7047f720da41dc49406b395c1470eef44ff7e2c506a47ac2c0591"}, 391 | {file = "grpcio-1.67.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3840994689cc8cbb73d60485c594424ad8adb56c71a30d8948d6453083624b52"}, 392 | {file = "grpcio-1.67.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:5a1e03c3102b6451028d5dc9f8591131d6ab3c8a0e023d94c28cb930ed4b5f81"}, 393 | {file = "grpcio-1.67.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:682968427a63d898759474e3b3178d42546e878fdce034fd7474ef75143b64e3"}, 394 | {file = "grpcio-1.67.0-cp312-cp312-win32.whl", hash = "sha256:d01793653248f49cf47e5695e0a79805b1d9d4eacef85b310118ba1dfcd1b955"}, 395 | {file = "grpcio-1.67.0-cp312-cp312-win_amd64.whl", hash = "sha256:985b2686f786f3e20326c4367eebdaed3e7aa65848260ff0c6644f817042cb15"}, 396 | {file = "grpcio-1.67.0-cp313-cp313-linux_armv7l.whl", hash = "sha256:8c9a35b8bc50db35ab8e3e02a4f2a35cfba46c8705c3911c34ce343bd777813a"}, 397 | {file = "grpcio-1.67.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:42199e704095b62688998c2d84c89e59a26a7d5d32eed86d43dc90e7a3bd04aa"}, 398 | {file = "grpcio-1.67.0-cp313-cp313-manylinux_2_17_aarch64.whl", hash = "sha256:c4c425f440fb81f8d0237c07b9322fc0fb6ee2b29fbef5f62a322ff8fcce240d"}, 399 | {file = "grpcio-1.67.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:323741b6699cd2b04a71cb38f502db98f90532e8a40cb675393d248126a268af"}, 400 | {file = "grpcio-1.67.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:662c8e105c5e5cee0317d500eb186ed7a93229586e431c1bf0c9236c2407352c"}, 401 | {file = "grpcio-1.67.0-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:f6bd2ab135c64a4d1e9e44679a616c9bc944547357c830fafea5c3caa3de5153"}, 402 | {file = "grpcio-1.67.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:2f55c1e0e2ae9bdd23b3c63459ee4c06d223b68aeb1961d83c48fb63dc29bc03"}, 403 | {file = "grpcio-1.67.0-cp313-cp313-win32.whl", hash = "sha256:fd6bc27861e460fe28e94226e3673d46e294ca4673d46b224428d197c5935e69"}, 404 | {file = "grpcio-1.67.0-cp313-cp313-win_amd64.whl", hash = "sha256:cf51d28063338608cd8d3cd64677e922134837902b70ce00dad7f116e3998210"}, 405 | {file = "grpcio-1.67.0.tar.gz", hash = "sha256:e090b2553e0da1c875449c8e75073dd4415dd71c9bde6a406240fdf4c0ee467c"}, 406 | ] 407 | 408 | [[package]] 409 | name = "h11" 410 | version = "0.14.0" 411 | requires_python = ">=3.7" 412 | summary = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" 413 | groups = ["default"] 414 | dependencies = [ 415 | "typing-extensions; python_version < \"3.8\"", 416 | ] 417 | files = [ 418 | {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, 419 | {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, 420 | ] 421 | 422 | [[package]] 423 | name = "identify" 424 | version = "2.6.1" 425 | requires_python = ">=3.8" 426 | summary = "File identification library for Python" 427 | groups = ["lint"] 428 | files = [ 429 | {file = "identify-2.6.1-py2.py3-none-any.whl", hash = "sha256:53863bcac7caf8d2ed85bd20312ea5dcfc22226800f6d6881f232d861db5a8f0"}, 430 | {file = "identify-2.6.1.tar.gz", hash = "sha256:91478c5fb7c3aac5ff7bf9b4344f803843dc586832d5f110d672b19aa1984c98"}, 431 | ] 432 | 433 | [[package]] 434 | name = "idna" 435 | version = "3.10" 436 | requires_python = ">=3.6" 437 | summary = "Internationalized Domain Names in Applications (IDNA)" 438 | groups = ["default"] 439 | files = [ 440 | {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, 441 | {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, 442 | ] 443 | 444 | [[package]] 445 | name = "importlib-metadata" 446 | version = "7.0.0" 447 | requires_python = ">=3.8" 448 | summary = "Read metadata from Python packages" 449 | groups = ["default"] 450 | dependencies = [ 451 | "typing-extensions>=3.6.4; python_version < \"3.8\"", 452 | "zipp>=0.5", 453 | ] 454 | files = [ 455 | {file = "importlib_metadata-7.0.0-py3-none-any.whl", hash = "sha256:d97503976bb81f40a193d41ee6570868479c69d5068651eb039c40d850c59d67"}, 456 | {file = "importlib_metadata-7.0.0.tar.gz", hash = "sha256:7fc841f8b8332803464e5dc1c63a2e59121f46ca186c0e2e182e80bf8c1319f7"}, 457 | ] 458 | 459 | [[package]] 460 | name = "iniconfig" 461 | version = "2.0.0" 462 | requires_python = ">=3.7" 463 | summary = "brain-dead simple config-ini parsing" 464 | groups = ["test"] 465 | files = [ 466 | {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, 467 | {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, 468 | ] 469 | 470 | [[package]] 471 | name = "multidict" 472 | version = "6.6.3" 473 | requires_python = ">=3.9" 474 | summary = "multidict implementation" 475 | groups = ["default"] 476 | dependencies = [ 477 | "typing-extensions>=4.1.0; python_version < \"3.11\"", 478 | ] 479 | files = [ 480 | {file = "multidict-6.6.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:056bebbeda16b2e38642d75e9e5310c484b7c24e3841dc0fb943206a72ec89d6"}, 481 | {file = "multidict-6.6.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e5f481cccb3c5c5e5de5d00b5141dc589c1047e60d07e85bbd7dea3d4580d63f"}, 482 | {file = "multidict-6.6.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:10bea2ee839a759ee368b5a6e47787f399b41e70cf0c20d90dfaf4158dfb4e55"}, 483 | {file = "multidict-6.6.3-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:2334cfb0fa9549d6ce2c21af2bfbcd3ac4ec3646b1b1581c88e3e2b1779ec92b"}, 484 | {file = "multidict-6.6.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b8fee016722550a2276ca2cb5bb624480e0ed2bd49125b2b73b7010b9090e888"}, 485 | {file = "multidict-6.6.3-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e5511cb35f5c50a2db21047c875eb42f308c5583edf96bd8ebf7d770a9d68f6d"}, 486 | {file = "multidict-6.6.3-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:712b348f7f449948e0a6c4564a21c7db965af900973a67db432d724619b3c680"}, 487 | {file = "multidict-6.6.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e4e15d2138ee2694e038e33b7c3da70e6b0ad8868b9f8094a72e1414aeda9c1a"}, 488 | {file = "multidict-6.6.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8df25594989aebff8a130f7899fa03cbfcc5d2b5f4a461cf2518236fe6f15961"}, 489 | {file = "multidict-6.6.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:159ca68bfd284a8860f8d8112cf0521113bffd9c17568579e4d13d1f1dc76b65"}, 490 | {file = "multidict-6.6.3-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:e098c17856a8c9ade81b4810888c5ad1914099657226283cab3062c0540b0643"}, 491 | {file = "multidict-6.6.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:67c92ed673049dec52d7ed39f8cf9ebbadf5032c774058b4406d18c8f8fe7063"}, 492 | {file = "multidict-6.6.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:bd0578596e3a835ef451784053cfd327d607fc39ea1a14812139339a18a0dbc3"}, 493 | {file = "multidict-6.6.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:346055630a2df2115cd23ae271910b4cae40f4e336773550dca4889b12916e75"}, 494 | {file = "multidict-6.6.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:555ff55a359302b79de97e0468e9ee80637b0de1fce77721639f7cd9440b3a10"}, 495 | {file = "multidict-6.6.3-cp312-cp312-win32.whl", hash = "sha256:73ab034fb8d58ff85c2bcbadc470efc3fafeea8affcf8722855fb94557f14cc5"}, 496 | {file = "multidict-6.6.3-cp312-cp312-win_amd64.whl", hash = "sha256:04cbcce84f63b9af41bad04a54d4cc4e60e90c35b9e6ccb130be2d75b71f8c17"}, 497 | {file = "multidict-6.6.3-cp312-cp312-win_arm64.whl", hash = "sha256:0f1130b896ecb52d2a1e615260f3ea2af55fa7dc3d7c3003ba0c3121a759b18b"}, 498 | {file = "multidict-6.6.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:540d3c06d48507357a7d57721e5094b4f7093399a0106c211f33540fdc374d55"}, 499 | {file = "multidict-6.6.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9c19cea2a690f04247d43f366d03e4eb110a0dc4cd1bbeee4d445435428ed35b"}, 500 | {file = "multidict-6.6.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7af039820cfd00effec86bda5d8debef711a3e86a1d3772e85bea0f243a4bd65"}, 501 | {file = "multidict-6.6.3-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:500b84f51654fdc3944e936f2922114349bf8fdcac77c3092b03449f0e5bc2b3"}, 502 | {file = "multidict-6.6.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f3fc723ab8a5c5ed6c50418e9bfcd8e6dceba6c271cee6728a10a4ed8561520c"}, 503 | {file = "multidict-6.6.3-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:94c47ea3ade005b5976789baaed66d4de4480d0a0bf31cef6edaa41c1e7b56a6"}, 504 | {file = "multidict-6.6.3-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:dbc7cf464cc6d67e83e136c9f55726da3a30176f020a36ead246eceed87f1cd8"}, 505 | {file = "multidict-6.6.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:900eb9f9da25ada070f8ee4a23f884e0ee66fe4e1a38c3af644256a508ad81ca"}, 506 | {file = "multidict-6.6.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7c6df517cf177da5d47ab15407143a89cd1a23f8b335f3a28d57e8b0a3dbb884"}, 507 | {file = "multidict-6.6.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4ef421045f13879e21c994b36e728d8e7d126c91a64b9185810ab51d474f27e7"}, 508 | {file = "multidict-6.6.3-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:6c1e61bb4f80895c081790b6b09fa49e13566df8fbff817da3f85b3a8192e36b"}, 509 | {file = "multidict-6.6.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:e5e8523bb12d7623cd8300dbd91b9e439a46a028cd078ca695eb66ba31adee3c"}, 510 | {file = "multidict-6.6.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:ef58340cc896219e4e653dade08fea5c55c6df41bcc68122e3be3e9d873d9a7b"}, 511 | {file = "multidict-6.6.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:fc9dc435ec8699e7b602b94fe0cd4703e69273a01cbc34409af29e7820f777f1"}, 512 | {file = "multidict-6.6.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9e864486ef4ab07db5e9cb997bad2b681514158d6954dd1958dfb163b83d53e6"}, 513 | {file = "multidict-6.6.3-cp313-cp313-win32.whl", hash = "sha256:5633a82fba8e841bc5c5c06b16e21529573cd654f67fd833650a215520a6210e"}, 514 | {file = "multidict-6.6.3-cp313-cp313-win_amd64.whl", hash = "sha256:e93089c1570a4ad54c3714a12c2cef549dc9d58e97bcded193d928649cab78e9"}, 515 | {file = "multidict-6.6.3-cp313-cp313-win_arm64.whl", hash = "sha256:c60b401f192e79caec61f166da9c924e9f8bc65548d4246842df91651e83d600"}, 516 | {file = "multidict-6.6.3-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:02fd8f32d403a6ff13864b0851f1f523d4c988051eea0471d4f1fd8010f11134"}, 517 | {file = "multidict-6.6.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:f3aa090106b1543f3f87b2041eef3c156c8da2aed90c63a2fbed62d875c49c37"}, 518 | {file = "multidict-6.6.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e924fb978615a5e33ff644cc42e6aa241effcf4f3322c09d4f8cebde95aff5f8"}, 519 | {file = "multidict-6.6.3-cp313-cp313t-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:b9fe5a0e57c6dbd0e2ce81ca66272282c32cd11d31658ee9553849d91289e1c1"}, 520 | {file = "multidict-6.6.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b24576f208793ebae00280c59927c3b7c2a3b1655e443a25f753c4611bc1c373"}, 521 | {file = "multidict-6.6.3-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:135631cb6c58eac37d7ac0df380294fecdc026b28837fa07c02e459c7fb9c54e"}, 522 | {file = "multidict-6.6.3-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:274d416b0df887aef98f19f21578653982cfb8a05b4e187d4a17103322eeaf8f"}, 523 | {file = "multidict-6.6.3-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e252017a817fad7ce05cafbe5711ed40faeb580e63b16755a3a24e66fa1d87c0"}, 524 | {file = "multidict-6.6.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2e4cc8d848cd4fe1cdee28c13ea79ab0ed37fc2e89dd77bac86a2e7959a8c3bc"}, 525 | {file = "multidict-6.6.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9e236a7094b9c4c1b7585f6b9cca34b9d833cf079f7e4c49e6a4a6ec9bfdc68f"}, 526 | {file = "multidict-6.6.3-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:e0cb0ab69915c55627c933f0b555a943d98ba71b4d1c57bc0d0a66e2567c7471"}, 527 | {file = "multidict-6.6.3-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:81ef2f64593aba09c5212a3d0f8c906a0d38d710a011f2f42759704d4557d3f2"}, 528 | {file = "multidict-6.6.3-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:b9cbc60010de3562545fa198bfc6d3825df430ea96d2cc509c39bd71e2e7d648"}, 529 | {file = "multidict-6.6.3-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:70d974eaaa37211390cd02ef93b7e938de564bbffa866f0b08d07e5e65da783d"}, 530 | {file = "multidict-6.6.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:3713303e4a6663c6d01d648a68f2848701001f3390a030edaaf3fc949c90bf7c"}, 531 | {file = "multidict-6.6.3-cp313-cp313t-win32.whl", hash = "sha256:639ecc9fe7cd73f2495f62c213e964843826f44505a3e5d82805aa85cac6f89e"}, 532 | {file = "multidict-6.6.3-cp313-cp313t-win_amd64.whl", hash = "sha256:9f97e181f344a0ef3881b573d31de8542cc0dbc559ec68c8f8b5ce2c2e91646d"}, 533 | {file = "multidict-6.6.3-cp313-cp313t-win_arm64.whl", hash = "sha256:ce8b7693da41a3c4fde5871c738a81490cea5496c671d74374c8ab889e1834fb"}, 534 | {file = "multidict-6.6.3-py3-none-any.whl", hash = "sha256:8db10f29c7541fc5da4defd8cd697e1ca429db743fa716325f236079b96f775a"}, 535 | {file = "multidict-6.6.3.tar.gz", hash = "sha256:798a9eb12dab0a6c2e29c1de6f3468af5cb2da6053a20dfa3344907eed0937cc"}, 536 | ] 537 | 538 | [[package]] 539 | name = "mypy" 540 | version = "1.17.1" 541 | requires_python = ">=3.9" 542 | summary = "Optional static typing for Python" 543 | groups = ["lint"] 544 | dependencies = [ 545 | "mypy-extensions>=1.0.0", 546 | "pathspec>=0.9.0", 547 | "tomli>=1.1.0; python_version < \"3.11\"", 548 | "typing-extensions>=4.6.0", 549 | ] 550 | files = [ 551 | {file = "mypy-1.17.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:69e83ea6553a3ba79c08c6e15dbd9bfa912ec1e493bf75489ef93beb65209aeb"}, 552 | {file = "mypy-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1b16708a66d38abb1e6b5702f5c2c87e133289da36f6a1d15f6a5221085c6403"}, 553 | {file = "mypy-1.17.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:89e972c0035e9e05823907ad5398c5a73b9f47a002b22359b177d40bdaee7056"}, 554 | {file = "mypy-1.17.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:03b6d0ed2b188e35ee6d5c36b5580cffd6da23319991c49ab5556c023ccf1341"}, 555 | {file = "mypy-1.17.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c837b896b37cd103570d776bda106eabb8737aa6dd4f248451aecf53030cdbeb"}, 556 | {file = "mypy-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:665afab0963a4b39dff7c1fa563cc8b11ecff7910206db4b2e64dd1ba25aed19"}, 557 | {file = "mypy-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:93378d3203a5c0800c6b6d850ad2f19f7a3cdf1a3701d3416dbf128805c6a6a7"}, 558 | {file = "mypy-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:15d54056f7fe7a826d897789f53dd6377ec2ea8ba6f776dc83c2902b899fee81"}, 559 | {file = "mypy-1.17.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:209a58fed9987eccc20f2ca94afe7257a8f46eb5df1fb69958650973230f91e6"}, 560 | {file = "mypy-1.17.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:099b9a5da47de9e2cb5165e581f158e854d9e19d2e96b6698c0d64de911dd849"}, 561 | {file = "mypy-1.17.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fa6ffadfbe6994d724c5a1bb6123a7d27dd68fc9c059561cd33b664a79578e14"}, 562 | {file = "mypy-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:9a2b7d9180aed171f033c9f2fc6c204c1245cf60b0cb61cf2e7acc24eea78e0a"}, 563 | {file = "mypy-1.17.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:15a83369400454c41ed3a118e0cc58bd8123921a602f385cb6d6ea5df050c733"}, 564 | {file = "mypy-1.17.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:55b918670f692fc9fba55c3298d8a3beae295c5cded0a55dccdc5bbead814acd"}, 565 | {file = "mypy-1.17.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:62761474061feef6f720149d7ba876122007ddc64adff5ba6f374fda35a018a0"}, 566 | {file = "mypy-1.17.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c49562d3d908fd49ed0938e5423daed8d407774a479b595b143a3d7f87cdae6a"}, 567 | {file = "mypy-1.17.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:397fba5d7616a5bc60b45c7ed204717eaddc38f826e3645402c426057ead9a91"}, 568 | {file = "mypy-1.17.1-cp314-cp314-win_amd64.whl", hash = "sha256:9d6b20b97d373f41617bd0708fd46aa656059af57f2ef72aa8c7d6a2b73b74ed"}, 569 | {file = "mypy-1.17.1-py3-none-any.whl", hash = "sha256:a9f52c0351c21fe24c21d8c0eb1f62967b262d6729393397b6f443c3b773c3b9"}, 570 | {file = "mypy-1.17.1.tar.gz", hash = "sha256:25e01ec741ab5bb3eec8ba9cdb0f769230368a22c959c4937360efb89b7e9f01"}, 571 | ] 572 | 573 | [[package]] 574 | name = "mypy-extensions" 575 | version = "1.0.0" 576 | requires_python = ">=3.5" 577 | summary = "Type system extensions for programs checked with the mypy type checker." 578 | groups = ["lint"] 579 | files = [ 580 | {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, 581 | {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, 582 | ] 583 | 584 | [[package]] 585 | name = "nodeenv" 586 | version = "1.9.1" 587 | requires_python = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" 588 | summary = "Node.js virtual environment builder" 589 | groups = ["lint"] 590 | files = [ 591 | {file = "nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9"}, 592 | {file = "nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f"}, 593 | ] 594 | 595 | [[package]] 596 | name = "opentelemetry-api" 597 | version = "1.36.0" 598 | requires_python = ">=3.9" 599 | summary = "OpenTelemetry Python API" 600 | groups = ["default"] 601 | dependencies = [ 602 | "importlib-metadata<8.8.0,>=6.0", 603 | "typing-extensions>=4.5.0", 604 | ] 605 | files = [ 606 | {file = "opentelemetry_api-1.36.0-py3-none-any.whl", hash = "sha256:02f20bcacf666e1333b6b1f04e647dc1d5111f86b8e510238fcc56d7762cda8c"}, 607 | {file = "opentelemetry_api-1.36.0.tar.gz", hash = "sha256:9a72572b9c416d004d492cbc6e61962c0501eaf945ece9b5a0f56597d8348aa0"}, 608 | ] 609 | 610 | [[package]] 611 | name = "opentelemetry-exporter-otlp" 612 | version = "1.36.0" 613 | requires_python = ">=3.9" 614 | summary = "OpenTelemetry Collector Exporters" 615 | groups = ["default"] 616 | dependencies = [ 617 | "opentelemetry-exporter-otlp-proto-grpc==1.36.0", 618 | "opentelemetry-exporter-otlp-proto-http==1.36.0", 619 | ] 620 | files = [ 621 | {file = "opentelemetry_exporter_otlp-1.36.0-py3-none-any.whl", hash = "sha256:de93b7c45bcc78296998775d52add7c63729e83ef2cd6560730a6b336d7f6494"}, 622 | {file = "opentelemetry_exporter_otlp-1.36.0.tar.gz", hash = "sha256:72f166ea5a8923ac42889337f903e93af57db8893de200369b07401e98e4e06b"}, 623 | ] 624 | 625 | [[package]] 626 | name = "opentelemetry-exporter-otlp-proto-common" 627 | version = "1.36.0" 628 | requires_python = ">=3.9" 629 | summary = "OpenTelemetry Protobuf encoding" 630 | groups = ["default"] 631 | dependencies = [ 632 | "opentelemetry-proto==1.36.0", 633 | ] 634 | files = [ 635 | {file = "opentelemetry_exporter_otlp_proto_common-1.36.0-py3-none-any.whl", hash = "sha256:0fc002a6ed63eac235ada9aa7056e5492e9a71728214a61745f6ad04b923f840"}, 636 | {file = "opentelemetry_exporter_otlp_proto_common-1.36.0.tar.gz", hash = "sha256:6c496ccbcbe26b04653cecadd92f73659b814c6e3579af157d8716e5f9f25cbf"}, 637 | ] 638 | 639 | [[package]] 640 | name = "opentelemetry-exporter-otlp-proto-grpc" 641 | version = "1.36.0" 642 | requires_python = ">=3.9" 643 | summary = "OpenTelemetry Collector Protobuf over gRPC Exporter" 644 | groups = ["default"] 645 | dependencies = [ 646 | "googleapis-common-protos~=1.57", 647 | "grpcio<2.0.0,>=1.63.2; python_version < \"3.13\"", 648 | "grpcio<2.0.0,>=1.66.2; python_version >= \"3.13\"", 649 | "opentelemetry-api~=1.15", 650 | "opentelemetry-exporter-otlp-proto-common==1.36.0", 651 | "opentelemetry-proto==1.36.0", 652 | "opentelemetry-sdk~=1.36.0", 653 | "typing-extensions>=4.6.0", 654 | ] 655 | files = [ 656 | {file = "opentelemetry_exporter_otlp_proto_grpc-1.36.0-py3-none-any.whl", hash = "sha256:734e841fc6a5d6f30e7be4d8053adb703c70ca80c562ae24e8083a28fadef211"}, 657 | {file = "opentelemetry_exporter_otlp_proto_grpc-1.36.0.tar.gz", hash = "sha256:b281afbf7036b325b3588b5b6c8bb175069e3978d1bd24071f4a59d04c1e5bbf"}, 658 | ] 659 | 660 | [[package]] 661 | name = "opentelemetry-exporter-otlp-proto-http" 662 | version = "1.36.0" 663 | requires_python = ">=3.9" 664 | summary = "OpenTelemetry Collector Protobuf over HTTP Exporter" 665 | groups = ["default"] 666 | dependencies = [ 667 | "googleapis-common-protos~=1.52", 668 | "opentelemetry-api~=1.15", 669 | "opentelemetry-exporter-otlp-proto-common==1.36.0", 670 | "opentelemetry-proto==1.36.0", 671 | "opentelemetry-sdk~=1.36.0", 672 | "requests~=2.7", 673 | "typing-extensions>=4.5.0", 674 | ] 675 | files = [ 676 | {file = "opentelemetry_exporter_otlp_proto_http-1.36.0-py3-none-any.whl", hash = "sha256:3d769f68e2267e7abe4527f70deb6f598f40be3ea34c6adc35789bea94a32902"}, 677 | {file = "opentelemetry_exporter_otlp_proto_http-1.36.0.tar.gz", hash = "sha256:dd3637f72f774b9fc9608ab1ac479f8b44d09b6fb5b2f3df68a24ad1da7d356e"}, 678 | ] 679 | 680 | [[package]] 681 | name = "opentelemetry-proto" 682 | version = "1.36.0" 683 | requires_python = ">=3.9" 684 | summary = "OpenTelemetry Python Proto" 685 | groups = ["default"] 686 | dependencies = [ 687 | "protobuf<7.0,>=5.0", 688 | ] 689 | files = [ 690 | {file = "opentelemetry_proto-1.36.0-py3-none-any.whl", hash = "sha256:151b3bf73a09f94afc658497cf77d45a565606f62ce0c17acb08cd9937ca206e"}, 691 | {file = "opentelemetry_proto-1.36.0.tar.gz", hash = "sha256:0f10b3c72f74c91e0764a5ec88fd8f1c368ea5d9c64639fb455e2854ef87dd2f"}, 692 | ] 693 | 694 | [[package]] 695 | name = "opentelemetry-sdk" 696 | version = "1.36.0" 697 | requires_python = ">=3.9" 698 | summary = "OpenTelemetry Python SDK" 699 | groups = ["default"] 700 | dependencies = [ 701 | "opentelemetry-api==1.36.0", 702 | "opentelemetry-semantic-conventions==0.57b0", 703 | "typing-extensions>=4.5.0", 704 | ] 705 | files = [ 706 | {file = "opentelemetry_sdk-1.36.0-py3-none-any.whl", hash = "sha256:19fe048b42e98c5c1ffe85b569b7073576ad4ce0bcb6e9b4c6a39e890a6c45fb"}, 707 | {file = "opentelemetry_sdk-1.36.0.tar.gz", hash = "sha256:19c8c81599f51b71670661ff7495c905d8fdf6976e41622d5245b791b06fa581"}, 708 | ] 709 | 710 | [[package]] 711 | name = "opentelemetry-semantic-conventions" 712 | version = "0.57b0" 713 | requires_python = ">=3.9" 714 | summary = "OpenTelemetry Semantic Conventions" 715 | groups = ["default"] 716 | dependencies = [ 717 | "opentelemetry-api==1.36.0", 718 | "typing-extensions>=4.5.0", 719 | ] 720 | files = [ 721 | {file = "opentelemetry_semantic_conventions-0.57b0-py3-none-any.whl", hash = "sha256:757f7e76293294f124c827e514c2a3144f191ef175b069ce8d1211e1e38e9e78"}, 722 | {file = "opentelemetry_semantic_conventions-0.57b0.tar.gz", hash = "sha256:609a4a79c7891b4620d64c7aac6898f872d790d75f22019913a660756f27ff32"}, 723 | ] 724 | 725 | [[package]] 726 | name = "packaging" 727 | version = "24.1" 728 | requires_python = ">=3.8" 729 | summary = "Core utilities for Python packages" 730 | groups = ["test"] 731 | files = [ 732 | {file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"}, 733 | {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"}, 734 | ] 735 | 736 | [[package]] 737 | name = "pamqp" 738 | version = "3.3.0" 739 | requires_python = ">=3.7" 740 | summary = "RabbitMQ Focused AMQP low-level library" 741 | groups = ["default"] 742 | files = [ 743 | {file = "pamqp-3.3.0-py2.py3-none-any.whl", hash = "sha256:c901a684794157ae39b52cbf700db8c9aae7a470f13528b9d7b4e5f7202f8eb0"}, 744 | {file = "pamqp-3.3.0.tar.gz", hash = "sha256:40b8795bd4efcf2b0f8821c1de83d12ca16d5760f4507836267fd7a02b06763b"}, 745 | ] 746 | 747 | [[package]] 748 | name = "pathspec" 749 | version = "0.12.1" 750 | requires_python = ">=3.8" 751 | summary = "Utility library for gitignore style pattern matching of file paths." 752 | groups = ["lint"] 753 | files = [ 754 | {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, 755 | {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, 756 | ] 757 | 758 | [[package]] 759 | name = "platformdirs" 760 | version = "4.3.6" 761 | requires_python = ">=3.8" 762 | summary = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." 763 | groups = ["lint"] 764 | files = [ 765 | {file = "platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb"}, 766 | {file = "platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907"}, 767 | ] 768 | 769 | [[package]] 770 | name = "pluggy" 771 | version = "1.5.0" 772 | requires_python = ">=3.8" 773 | summary = "plugin and hook calling mechanisms for python" 774 | groups = ["test"] 775 | files = [ 776 | {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, 777 | {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, 778 | ] 779 | 780 | [[package]] 781 | name = "pre-commit" 782 | version = "4.2.0" 783 | requires_python = ">=3.9" 784 | summary = "A framework for managing and maintaining multi-language pre-commit hooks." 785 | groups = ["lint"] 786 | dependencies = [ 787 | "cfgv>=2.0.0", 788 | "identify>=1.0.0", 789 | "nodeenv>=0.11.1", 790 | "pyyaml>=5.1", 791 | "virtualenv>=20.10.0", 792 | ] 793 | files = [ 794 | {file = "pre_commit-4.2.0-py2.py3-none-any.whl", hash = "sha256:a009ca7205f1eb497d10b845e52c838a98b6cdd2102a6c8e4540e94ee75c58bd"}, 795 | {file = "pre_commit-4.2.0.tar.gz", hash = "sha256:601283b9757afd87d40c4c4a9b2b5de9637a8ea02eaff7adc2d0fb4e04841146"}, 796 | ] 797 | 798 | [[package]] 799 | name = "prometheus-client" 800 | version = "0.22.1" 801 | requires_python = ">=3.9" 802 | summary = "Python client for the Prometheus monitoring system." 803 | groups = ["default"] 804 | files = [ 805 | {file = "prometheus_client-0.22.1-py3-none-any.whl", hash = "sha256:cca895342e308174341b2cbf99a56bef291fbc0ef7b9e5412a0f26d653ba7094"}, 806 | {file = "prometheus_client-0.22.1.tar.gz", hash = "sha256:190f1331e783cf21eb60bca559354e0a4d4378facecf78f5428c39b675d20d28"}, 807 | ] 808 | 809 | [[package]] 810 | name = "propcache" 811 | version = "0.3.2" 812 | requires_python = ">=3.9" 813 | summary = "Accelerated property cache" 814 | groups = ["default"] 815 | files = [ 816 | {file = "propcache-0.3.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:8de106b6c84506b31c27168582cd3cb3000a6412c16df14a8628e5871ff83c10"}, 817 | {file = "propcache-0.3.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:28710b0d3975117239c76600ea351934ac7b5ff56e60953474342608dbbb6154"}, 818 | {file = "propcache-0.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce26862344bdf836650ed2487c3d724b00fbfec4233a1013f597b78c1cb73615"}, 819 | {file = "propcache-0.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bca54bd347a253af2cf4544bbec232ab982f4868de0dd684246b67a51bc6b1db"}, 820 | {file = "propcache-0.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:55780d5e9a2ddc59711d727226bb1ba83a22dd32f64ee15594b9392b1f544eb1"}, 821 | {file = "propcache-0.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:035e631be25d6975ed87ab23153db6a73426a48db688070d925aa27e996fe93c"}, 822 | {file = "propcache-0.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ee6f22b6eaa39297c751d0e80c0d3a454f112f5c6481214fcf4c092074cecd67"}, 823 | {file = "propcache-0.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7ca3aee1aa955438c4dba34fc20a9f390e4c79967257d830f137bd5a8a32ed3b"}, 824 | {file = "propcache-0.3.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7a4f30862869fa2b68380d677cc1c5fcf1e0f2b9ea0cf665812895c75d0ca3b8"}, 825 | {file = "propcache-0.3.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:b77ec3c257d7816d9f3700013639db7491a434644c906a2578a11daf13176251"}, 826 | {file = "propcache-0.3.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:cab90ac9d3f14b2d5050928483d3d3b8fb6b4018893fc75710e6aa361ecb2474"}, 827 | {file = "propcache-0.3.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:0b504d29f3c47cf6b9e936c1852246c83d450e8e063d50562115a6be6d3a2535"}, 828 | {file = "propcache-0.3.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:ce2ac2675a6aa41ddb2a0c9cbff53780a617ac3d43e620f8fd77ba1c84dcfc06"}, 829 | {file = "propcache-0.3.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:62b4239611205294cc433845b914131b2a1f03500ff3c1ed093ed216b82621e1"}, 830 | {file = "propcache-0.3.2-cp312-cp312-win32.whl", hash = "sha256:df4a81b9b53449ebc90cc4deefb052c1dd934ba85012aa912c7ea7b7e38b60c1"}, 831 | {file = "propcache-0.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:7046e79b989d7fe457bb755844019e10f693752d169076138abf17f31380800c"}, 832 | {file = "propcache-0.3.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ca592ed634a73ca002967458187109265e980422116c0a107cf93d81f95af945"}, 833 | {file = "propcache-0.3.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9ecb0aad4020e275652ba3975740f241bd12a61f1a784df044cf7477a02bc252"}, 834 | {file = "propcache-0.3.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7f08f1cc28bd2eade7a8a3d2954ccc673bb02062e3e7da09bc75d843386b342f"}, 835 | {file = "propcache-0.3.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1a342c834734edb4be5ecb1e9fb48cb64b1e2320fccbd8c54bf8da8f2a84c33"}, 836 | {file = "propcache-0.3.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8a544caaae1ac73f1fecfae70ded3e93728831affebd017d53449e3ac052ac1e"}, 837 | {file = "propcache-0.3.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:310d11aa44635298397db47a3ebce7db99a4cc4b9bbdfcf6c98a60c8d5261cf1"}, 838 | {file = "propcache-0.3.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c1396592321ac83157ac03a2023aa6cc4a3cc3cfdecb71090054c09e5a7cce3"}, 839 | {file = "propcache-0.3.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8cabf5b5902272565e78197edb682017d21cf3b550ba0460ee473753f28d23c1"}, 840 | {file = "propcache-0.3.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0a2f2235ac46a7aa25bdeb03a9e7060f6ecbd213b1f9101c43b3090ffb971ef6"}, 841 | {file = "propcache-0.3.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:92b69e12e34869a6970fd2f3da91669899994b47c98f5d430b781c26f1d9f387"}, 842 | {file = "propcache-0.3.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:54e02207c79968ebbdffc169591009f4474dde3b4679e16634d34c9363ff56b4"}, 843 | {file = "propcache-0.3.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4adfb44cb588001f68c5466579d3f1157ca07f7504fc91ec87862e2b8e556b88"}, 844 | {file = "propcache-0.3.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:fd3e6019dc1261cd0291ee8919dd91fbab7b169bb76aeef6c716833a3f65d206"}, 845 | {file = "propcache-0.3.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4c181cad81158d71c41a2bce88edce078458e2dd5ffee7eddd6b05da85079f43"}, 846 | {file = "propcache-0.3.2-cp313-cp313-win32.whl", hash = "sha256:8a08154613f2249519e549de2330cf8e2071c2887309a7b07fb56098f5170a02"}, 847 | {file = "propcache-0.3.2-cp313-cp313-win_amd64.whl", hash = "sha256:e41671f1594fc4ab0a6dec1351864713cb3a279910ae8b58f884a88a0a632c05"}, 848 | {file = "propcache-0.3.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:9a3cf035bbaf035f109987d9d55dc90e4b0e36e04bbbb95af3055ef17194057b"}, 849 | {file = "propcache-0.3.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:156c03d07dc1323d8dacaa221fbe028c5c70d16709cdd63502778e6c3ccca1b0"}, 850 | {file = "propcache-0.3.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:74413c0ba02ba86f55cf60d18daab219f7e531620c15f1e23d95563f505efe7e"}, 851 | {file = "propcache-0.3.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f066b437bb3fa39c58ff97ab2ca351db465157d68ed0440abecb21715eb24b28"}, 852 | {file = "propcache-0.3.2-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f1304b085c83067914721e7e9d9917d41ad87696bf70f0bc7dee450e9c71ad0a"}, 853 | {file = "propcache-0.3.2-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ab50cef01b372763a13333b4e54021bdcb291fc9a8e2ccb9c2df98be51bcde6c"}, 854 | {file = "propcache-0.3.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fad3b2a085ec259ad2c2842666b2a0a49dea8463579c606426128925af1ed725"}, 855 | {file = "propcache-0.3.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:261fa020c1c14deafd54c76b014956e2f86991af198c51139faf41c4d5e83892"}, 856 | {file = "propcache-0.3.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:46d7f8aa79c927e5f987ee3a80205c987717d3659f035c85cf0c3680526bdb44"}, 857 | {file = "propcache-0.3.2-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:6d8f3f0eebf73e3c0ff0e7853f68be638b4043c65a70517bb575eff54edd8dbe"}, 858 | {file = "propcache-0.3.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:03c89c1b14a5452cf15403e291c0ccd7751d5b9736ecb2c5bab977ad6c5bcd81"}, 859 | {file = "propcache-0.3.2-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:0cc17efde71e12bbaad086d679ce575268d70bc123a5a71ea7ad76f70ba30bba"}, 860 | {file = "propcache-0.3.2-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:acdf05d00696bc0447e278bb53cb04ca72354e562cf88ea6f9107df8e7fd9770"}, 861 | {file = "propcache-0.3.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4445542398bd0b5d32df908031cb1b30d43ac848e20470a878b770ec2dcc6330"}, 862 | {file = "propcache-0.3.2-cp313-cp313t-win32.whl", hash = "sha256:f86e5d7cd03afb3a1db8e9f9f6eff15794e79e791350ac48a8c924e6f439f394"}, 863 | {file = "propcache-0.3.2-cp313-cp313t-win_amd64.whl", hash = "sha256:9704bedf6e7cbe3c65eca4379a9b53ee6a83749f047808cbb5044d40d7d72198"}, 864 | {file = "propcache-0.3.2-py3-none-any.whl", hash = "sha256:98f1ec44fb675f5052cccc8e609c46ed23a35a1cfd18545ad4e29002d858a43f"}, 865 | {file = "propcache-0.3.2.tar.gz", hash = "sha256:20d7d62e4e7ef05f221e0db2856b979540686342e7dd9973b815599c7057e168"}, 866 | ] 867 | 868 | [[package]] 869 | name = "protobuf" 870 | version = "5.29.5" 871 | requires_python = ">=3.8" 872 | summary = "" 873 | groups = ["default"] 874 | files = [ 875 | {file = "protobuf-5.29.5-cp310-abi3-win32.whl", hash = "sha256:3f1c6468a2cfd102ff4703976138844f78ebd1fb45f49011afc5139e9e283079"}, 876 | {file = "protobuf-5.29.5-cp310-abi3-win_amd64.whl", hash = "sha256:3f76e3a3675b4a4d867b52e4a5f5b78a2ef9565549d4037e06cf7b0942b1d3fc"}, 877 | {file = "protobuf-5.29.5-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:e38c5add5a311f2a6eb0340716ef9b039c1dfa428b28f25a7838ac329204a671"}, 878 | {file = "protobuf-5.29.5-cp38-abi3-manylinux2014_aarch64.whl", hash = "sha256:fa18533a299d7ab6c55a238bf8629311439995f2e7eca5caaff08663606e9015"}, 879 | {file = "protobuf-5.29.5-cp38-abi3-manylinux2014_x86_64.whl", hash = "sha256:63848923da3325e1bf7e9003d680ce6e14b07e55d0473253a690c3a8b8fd6e61"}, 880 | {file = "protobuf-5.29.5-py3-none-any.whl", hash = "sha256:6cf42630262c59b2d8de33954443d94b746c952b01434fc58a417fdbd2e84bd5"}, 881 | {file = "protobuf-5.29.5.tar.gz", hash = "sha256:bc1463bafd4b0929216c35f437a8e28731a2b7fe3d98bb77a600efced5a15c84"}, 882 | ] 883 | 884 | [[package]] 885 | name = "pydantic" 886 | version = "2.9.2" 887 | requires_python = ">=3.8" 888 | summary = "Data validation using Python type hints" 889 | groups = ["default"] 890 | dependencies = [ 891 | "annotated-types>=0.6.0", 892 | "pydantic-core==2.23.4", 893 | "typing-extensions>=4.12.2; python_version >= \"3.13\"", 894 | "typing-extensions>=4.6.1; python_version < \"3.13\"", 895 | ] 896 | files = [ 897 | {file = "pydantic-2.9.2-py3-none-any.whl", hash = "sha256:f048cec7b26778210e28a0459867920654d48e5e62db0958433636cde4254f12"}, 898 | {file = "pydantic-2.9.2.tar.gz", hash = "sha256:d155cef71265d1e9807ed1c32b4c8deec042a44a50a4188b25ac67ecd81a9c0f"}, 899 | ] 900 | 901 | [[package]] 902 | name = "pydantic-core" 903 | version = "2.23.4" 904 | requires_python = ">=3.8" 905 | summary = "Core functionality for Pydantic validation and serialization" 906 | groups = ["default"] 907 | dependencies = [ 908 | "typing-extensions!=4.7.0,>=4.6.0", 909 | ] 910 | files = [ 911 | {file = "pydantic_core-2.23.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f3e0da4ebaef65158d4dfd7d3678aad692f7666877df0002b8a522cdf088f231"}, 912 | {file = "pydantic_core-2.23.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f69a8e0b033b747bb3e36a44e7732f0c99f7edd5cea723d45bc0d6e95377ffee"}, 913 | {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:723314c1d51722ab28bfcd5240d858512ffd3116449c557a1336cbe3919beb87"}, 914 | {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bb2802e667b7051a1bebbfe93684841cc9351004e2badbd6411bf357ab8d5ac8"}, 915 | {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d18ca8148bebe1b0a382a27a8ee60350091a6ddaf475fa05ef50dc35b5df6327"}, 916 | {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33e3d65a85a2a4a0dc3b092b938a4062b1a05f3a9abde65ea93b233bca0e03f2"}, 917 | {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:128585782e5bfa515c590ccee4b727fb76925dd04a98864182b22e89a4e6ed36"}, 918 | {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:68665f4c17edcceecc112dfed5dbe6f92261fb9d6054b47d01bf6371a6196126"}, 919 | {file = "pydantic_core-2.23.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:20152074317d9bed6b7a95ade3b7d6054845d70584216160860425f4fbd5ee9e"}, 920 | {file = "pydantic_core-2.23.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:9261d3ce84fa1d38ed649c3638feefeae23d32ba9182963e465d58d62203bd24"}, 921 | {file = "pydantic_core-2.23.4-cp312-none-win32.whl", hash = "sha256:4ba762ed58e8d68657fc1281e9bb72e1c3e79cc5d464be146e260c541ec12d84"}, 922 | {file = "pydantic_core-2.23.4-cp312-none-win_amd64.whl", hash = "sha256:97df63000f4fea395b2824da80e169731088656d1818a11b95f3b173747b6cd9"}, 923 | {file = "pydantic_core-2.23.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7530e201d10d7d14abce4fb54cfe5b94a0aefc87da539d0346a484ead376c3cc"}, 924 | {file = "pydantic_core-2.23.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:df933278128ea1cd77772673c73954e53a1c95a4fdf41eef97c2b779271bd0bd"}, 925 | {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cb3da3fd1b6a5d0279a01877713dbda118a2a4fc6f0d821a57da2e464793f05"}, 926 | {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:42c6dcb030aefb668a2b7009c85b27f90e51e6a3b4d5c9bc4c57631292015b0d"}, 927 | {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:696dd8d674d6ce621ab9d45b205df149399e4bb9aa34102c970b721554828510"}, 928 | {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2971bb5ffe72cc0f555c13e19b23c85b654dd2a8f7ab493c262071377bfce9f6"}, 929 | {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8394d940e5d400d04cad4f75c0598665cbb81aecefaca82ca85bd28264af7f9b"}, 930 | {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0dff76e0602ca7d4cdaacc1ac4c005e0ce0dcfe095d5b5259163a80d3a10d327"}, 931 | {file = "pydantic_core-2.23.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7d32706badfe136888bdea71c0def994644e09fff0bfe47441deaed8e96fdbc6"}, 932 | {file = "pydantic_core-2.23.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ed541d70698978a20eb63d8c5d72f2cc6d7079d9d90f6b50bad07826f1320f5f"}, 933 | {file = "pydantic_core-2.23.4-cp313-none-win32.whl", hash = "sha256:3d5639516376dce1940ea36edf408c554475369f5da2abd45d44621cb616f769"}, 934 | {file = "pydantic_core-2.23.4-cp313-none-win_amd64.whl", hash = "sha256:5a1504ad17ba4210df3a045132a7baeeba5a200e930f57512ee02909fc5c4cb5"}, 935 | {file = "pydantic_core-2.23.4.tar.gz", hash = "sha256:2584f7cf844ac4d970fba483a717dbe10c1c1c96a969bf65d61ffe94df1b2863"}, 936 | ] 937 | 938 | [[package]] 939 | name = "pygments" 940 | version = "2.19.2" 941 | requires_python = ">=3.8" 942 | summary = "Pygments is a syntax highlighting package written in Python." 943 | groups = ["test"] 944 | files = [ 945 | {file = "pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b"}, 946 | {file = "pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887"}, 947 | ] 948 | 949 | [[package]] 950 | name = "pytest" 951 | version = "8.4.1" 952 | requires_python = ">=3.9" 953 | summary = "pytest: simple powerful testing with Python" 954 | groups = ["test"] 955 | dependencies = [ 956 | "colorama>=0.4; sys_platform == \"win32\"", 957 | "exceptiongroup>=1; python_version < \"3.11\"", 958 | "iniconfig>=1", 959 | "packaging>=20", 960 | "pluggy<2,>=1.5", 961 | "pygments>=2.7.2", 962 | "tomli>=1; python_version < \"3.11\"", 963 | ] 964 | files = [ 965 | {file = "pytest-8.4.1-py3-none-any.whl", hash = "sha256:539c70ba6fcead8e78eebbf1115e8b589e7565830d7d006a8723f19ac8a0afb7"}, 966 | {file = "pytest-8.4.1.tar.gz", hash = "sha256:7c67fd69174877359ed9371ec3af8a3d2b04741818c51e5e99cc1742251fa93c"}, 967 | ] 968 | 969 | [[package]] 970 | name = "pytest-asyncio" 971 | version = "1.1.0" 972 | requires_python = ">=3.9" 973 | summary = "Pytest support for asyncio" 974 | groups = ["test"] 975 | dependencies = [ 976 | "backports-asyncio-runner<2,>=1.1; python_version < \"3.11\"", 977 | "pytest<9,>=8.2", 978 | "typing-extensions>=4.12; python_version < \"3.10\"", 979 | ] 980 | files = [ 981 | {file = "pytest_asyncio-1.1.0-py3-none-any.whl", hash = "sha256:5fe2d69607b0bd75c656d1211f969cadba035030156745ee09e7d71740e58ecf"}, 982 | {file = "pytest_asyncio-1.1.0.tar.gz", hash = "sha256:796aa822981e01b68c12e4827b8697108f7205020f24b5793b3c41555dab68ea"}, 983 | ] 984 | 985 | [[package]] 986 | name = "pytest-cov" 987 | version = "6.2.1" 988 | requires_python = ">=3.9" 989 | summary = "Pytest plugin for measuring coverage." 990 | groups = ["test"] 991 | dependencies = [ 992 | "coverage[toml]>=7.5", 993 | "pluggy>=1.2", 994 | "pytest>=6.2.5", 995 | ] 996 | files = [ 997 | {file = "pytest_cov-6.2.1-py3-none-any.whl", hash = "sha256:f5bc4c23f42f1cdd23c70b1dab1bbaef4fc505ba950d53e0081d0730dd7e86d5"}, 998 | {file = "pytest_cov-6.2.1.tar.gz", hash = "sha256:25cc6cc0a5358204b8108ecedc51a9b57b34cc6b8c967cc2c01a4e00d8a67da2"}, 999 | ] 1000 | 1001 | [[package]] 1002 | name = "pyyaml" 1003 | version = "6.0.2" 1004 | requires_python = ">=3.8" 1005 | summary = "YAML parser and emitter for Python" 1006 | groups = ["lint"] 1007 | files = [ 1008 | {file = "PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab"}, 1009 | {file = "PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725"}, 1010 | {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5"}, 1011 | {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425"}, 1012 | {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476"}, 1013 | {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48"}, 1014 | {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b"}, 1015 | {file = "PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4"}, 1016 | {file = "PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8"}, 1017 | {file = "PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba"}, 1018 | {file = "PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1"}, 1019 | {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133"}, 1020 | {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484"}, 1021 | {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5"}, 1022 | {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc"}, 1023 | {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652"}, 1024 | {file = "PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183"}, 1025 | {file = "PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563"}, 1026 | {file = "pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e"}, 1027 | ] 1028 | 1029 | [[package]] 1030 | name = "requests" 1031 | version = "2.32.3" 1032 | requires_python = ">=3.8" 1033 | summary = "Python HTTP for Humans." 1034 | groups = ["default"] 1035 | dependencies = [ 1036 | "certifi>=2017.4.17", 1037 | "charset-normalizer<4,>=2", 1038 | "idna<4,>=2.5", 1039 | "urllib3<3,>=1.21.1", 1040 | ] 1041 | files = [ 1042 | {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, 1043 | {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, 1044 | ] 1045 | 1046 | [[package]] 1047 | name = "ruff" 1048 | version = "0.12.7" 1049 | requires_python = ">=3.7" 1050 | summary = "An extremely fast Python linter and code formatter, written in Rust." 1051 | groups = ["lint"] 1052 | files = [ 1053 | {file = "ruff-0.12.7-py3-none-linux_armv6l.whl", hash = "sha256:76e4f31529899b8c434c3c1dede98c4483b89590e15fb49f2d46183801565303"}, 1054 | {file = "ruff-0.12.7-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:789b7a03e72507c54fb3ba6209e4bb36517b90f1a3569ea17084e3fd295500fb"}, 1055 | {file = "ruff-0.12.7-py3-none-macosx_11_0_arm64.whl", hash = "sha256:2e1c2a3b8626339bb6369116e7030a4cf194ea48f49b64bb505732a7fce4f4e3"}, 1056 | {file = "ruff-0.12.7-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:32dec41817623d388e645612ec70d5757a6d9c035f3744a52c7b195a57e03860"}, 1057 | {file = "ruff-0.12.7-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:47ef751f722053a5df5fa48d412dbb54d41ab9b17875c6840a58ec63ff0c247c"}, 1058 | {file = "ruff-0.12.7-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a828a5fc25a3efd3e1ff7b241fd392686c9386f20e5ac90aa9234a5faa12c423"}, 1059 | {file = "ruff-0.12.7-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:5726f59b171111fa6a69d82aef48f00b56598b03a22f0f4170664ff4d8298efb"}, 1060 | {file = "ruff-0.12.7-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:74e6f5c04c4dd4aba223f4fe6e7104f79e0eebf7d307e4f9b18c18362124bccd"}, 1061 | {file = "ruff-0.12.7-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5d0bfe4e77fba61bf2ccadf8cf005d6133e3ce08793bbe870dd1c734f2699a3e"}, 1062 | {file = "ruff-0.12.7-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06bfb01e1623bf7f59ea749a841da56f8f653d641bfd046edee32ede7ff6c606"}, 1063 | {file = "ruff-0.12.7-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:e41df94a957d50083fd09b916d6e89e497246698c3f3d5c681c8b3e7b9bb4ac8"}, 1064 | {file = "ruff-0.12.7-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:4000623300563c709458d0ce170c3d0d788c23a058912f28bbadc6f905d67afa"}, 1065 | {file = "ruff-0.12.7-py3-none-musllinux_1_2_i686.whl", hash = "sha256:69ffe0e5f9b2cf2b8e289a3f8945b402a1b19eff24ec389f45f23c42a3dd6fb5"}, 1066 | {file = "ruff-0.12.7-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:a07a5c8ffa2611a52732bdc67bf88e243abd84fe2d7f6daef3826b59abbfeda4"}, 1067 | {file = "ruff-0.12.7-py3-none-win32.whl", hash = "sha256:c928f1b2ec59fb77dfdf70e0419408898b63998789cc98197e15f560b9e77f77"}, 1068 | {file = "ruff-0.12.7-py3-none-win_amd64.whl", hash = "sha256:9c18f3d707ee9edf89da76131956aba1270c6348bfee8f6c647de841eac7194f"}, 1069 | {file = "ruff-0.12.7-py3-none-win_arm64.whl", hash = "sha256:dfce05101dbd11833a0776716d5d1578641b7fddb537fe7fa956ab85d1769b69"}, 1070 | {file = "ruff-0.12.7.tar.gz", hash = "sha256:1fc3193f238bc2d7968772c82831a4ff69252f673be371fb49663f0068b7ec71"}, 1071 | ] 1072 | 1073 | [[package]] 1074 | name = "sniffio" 1075 | version = "1.3.1" 1076 | requires_python = ">=3.7" 1077 | summary = "Sniff out which async library your code is running under" 1078 | groups = ["default"] 1079 | files = [ 1080 | {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, 1081 | {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, 1082 | ] 1083 | 1084 | [[package]] 1085 | name = "typing-extensions" 1086 | version = "4.12.2" 1087 | requires_python = ">=3.8" 1088 | summary = "Backported and Experimental Type Hints for Python 3.8+" 1089 | groups = ["default", "lint"] 1090 | files = [ 1091 | {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, 1092 | {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, 1093 | ] 1094 | 1095 | [[package]] 1096 | name = "urllib3" 1097 | version = "2.2.3" 1098 | requires_python = ">=3.8" 1099 | summary = "HTTP library with thread-safe connection pooling, file post, and more." 1100 | groups = ["default"] 1101 | files = [ 1102 | {file = "urllib3-2.2.3-py3-none-any.whl", hash = "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac"}, 1103 | {file = "urllib3-2.2.3.tar.gz", hash = "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9"}, 1104 | ] 1105 | 1106 | [[package]] 1107 | name = "uvicorn" 1108 | version = "0.35.0" 1109 | requires_python = ">=3.9" 1110 | summary = "The lightning-fast ASGI server." 1111 | groups = ["default"] 1112 | dependencies = [ 1113 | "click>=7.0", 1114 | "h11>=0.8", 1115 | "typing-extensions>=4.0; python_version < \"3.11\"", 1116 | ] 1117 | files = [ 1118 | {file = "uvicorn-0.35.0-py3-none-any.whl", hash = "sha256:197535216b25ff9b785e29a0b79199f55222193d47f820816e7da751e9bc8d4a"}, 1119 | {file = "uvicorn-0.35.0.tar.gz", hash = "sha256:bc662f087f7cf2ce11a1d7fd70b90c9f98ef2e2831556dd078d131b96cc94a01"}, 1120 | ] 1121 | 1122 | [[package]] 1123 | name = "virtualenv" 1124 | version = "20.27.0" 1125 | requires_python = ">=3.8" 1126 | summary = "Virtual Python Environment builder" 1127 | groups = ["lint"] 1128 | dependencies = [ 1129 | "distlib<1,>=0.3.7", 1130 | "filelock<4,>=3.12.2", 1131 | "importlib-metadata>=6.6; python_version < \"3.8\"", 1132 | "platformdirs<5,>=3.9.1", 1133 | ] 1134 | files = [ 1135 | {file = "virtualenv-20.27.0-py3-none-any.whl", hash = "sha256:44a72c29cceb0ee08f300b314848c86e57bf8d1f13107a5e671fb9274138d655"}, 1136 | {file = "virtualenv-20.27.0.tar.gz", hash = "sha256:2ca56a68ed615b8fe4326d11a0dca5dfbe8fd68510fb6c6349163bed3c15f2b2"}, 1137 | ] 1138 | 1139 | [[package]] 1140 | name = "yarl" 1141 | version = "1.20.1" 1142 | requires_python = ">=3.9" 1143 | summary = "Yet another URL library" 1144 | groups = ["default"] 1145 | dependencies = [ 1146 | "idna>=2.0", 1147 | "multidict>=4.0", 1148 | "propcache>=0.2.1", 1149 | ] 1150 | files = [ 1151 | {file = "yarl-1.20.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:bdcc4cd244e58593a4379fe60fdee5ac0331f8eb70320a24d591a3be197b94a9"}, 1152 | {file = "yarl-1.20.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b29a2c385a5f5b9c7d9347e5812b6f7ab267193c62d282a540b4fc528c8a9d2a"}, 1153 | {file = "yarl-1.20.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1112ae8154186dfe2de4732197f59c05a83dc814849a5ced892b708033f40dc2"}, 1154 | {file = "yarl-1.20.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:90bbd29c4fe234233f7fa2b9b121fb63c321830e5d05b45153a2ca68f7d310ee"}, 1155 | {file = "yarl-1.20.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:680e19c7ce3710ac4cd964e90dad99bf9b5029372ba0c7cbfcd55e54d90ea819"}, 1156 | {file = "yarl-1.20.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4a979218c1fdb4246a05efc2cc23859d47c89af463a90b99b7c56094daf25a16"}, 1157 | {file = "yarl-1.20.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:255b468adf57b4a7b65d8aad5b5138dce6a0752c139965711bdcb81bc370e1b6"}, 1158 | {file = "yarl-1.20.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a97d67108e79cfe22e2b430d80d7571ae57d19f17cda8bb967057ca8a7bf5bfd"}, 1159 | {file = "yarl-1.20.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8570d998db4ddbfb9a590b185a0a33dbf8aafb831d07a5257b4ec9948df9cb0a"}, 1160 | {file = "yarl-1.20.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:97c75596019baae7c71ccf1d8cc4738bc08134060d0adfcbe5642f778d1dca38"}, 1161 | {file = "yarl-1.20.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:1c48912653e63aef91ff988c5432832692ac5a1d8f0fb8a33091520b5bbe19ef"}, 1162 | {file = "yarl-1.20.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4c3ae28f3ae1563c50f3d37f064ddb1511ecc1d5584e88c6b7c63cf7702a6d5f"}, 1163 | {file = "yarl-1.20.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c5e9642f27036283550f5f57dc6156c51084b458570b9d0d96100c8bebb186a8"}, 1164 | {file = "yarl-1.20.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:2c26b0c49220d5799f7b22c6838409ee9bc58ee5c95361a4d7831f03cc225b5a"}, 1165 | {file = "yarl-1.20.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:564ab3d517e3d01c408c67f2e5247aad4019dcf1969982aba3974b4093279004"}, 1166 | {file = "yarl-1.20.1-cp312-cp312-win32.whl", hash = "sha256:daea0d313868da1cf2fac6b2d3a25c6e3a9e879483244be38c8e6a41f1d876a5"}, 1167 | {file = "yarl-1.20.1-cp312-cp312-win_amd64.whl", hash = "sha256:48ea7d7f9be0487339828a4de0360d7ce0efc06524a48e1810f945c45b813698"}, 1168 | {file = "yarl-1.20.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:0b5ff0fbb7c9f1b1b5ab53330acbfc5247893069e7716840c8e7d5bb7355038a"}, 1169 | {file = "yarl-1.20.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:14f326acd845c2b2e2eb38fb1346c94f7f3b01a4f5c788f8144f9b630bfff9a3"}, 1170 | {file = "yarl-1.20.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f60e4ad5db23f0b96e49c018596707c3ae89f5d0bd97f0ad3684bcbad899f1e7"}, 1171 | {file = "yarl-1.20.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:49bdd1b8e00ce57e68ba51916e4bb04461746e794e7c4d4bbc42ba2f18297691"}, 1172 | {file = "yarl-1.20.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:66252d780b45189975abfed839616e8fd2dbacbdc262105ad7742c6ae58f3e31"}, 1173 | {file = "yarl-1.20.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:59174e7332f5d153d8f7452a102b103e2e74035ad085f404df2e40e663a22b28"}, 1174 | {file = "yarl-1.20.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e3968ec7d92a0c0f9ac34d5ecfd03869ec0cab0697c91a45db3fbbd95fe1b653"}, 1175 | {file = "yarl-1.20.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d1a4fbb50e14396ba3d375f68bfe02215d8e7bc3ec49da8341fe3157f59d2ff5"}, 1176 | {file = "yarl-1.20.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11a62c839c3a8eac2410e951301309426f368388ff2f33799052787035793b02"}, 1177 | {file = "yarl-1.20.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:041eaa14f73ff5a8986b4388ac6bb43a77f2ea09bf1913df7a35d4646db69e53"}, 1178 | {file = "yarl-1.20.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:377fae2fef158e8fd9d60b4c8751387b8d1fb121d3d0b8e9b0be07d1b41e83dc"}, 1179 | {file = "yarl-1.20.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:1c92f4390e407513f619d49319023664643d3339bd5e5a56a3bebe01bc67ec04"}, 1180 | {file = "yarl-1.20.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:d25ddcf954df1754ab0f86bb696af765c5bfaba39b74095f27eececa049ef9a4"}, 1181 | {file = "yarl-1.20.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:909313577e9619dcff8c31a0ea2aa0a2a828341d92673015456b3ae492e7317b"}, 1182 | {file = "yarl-1.20.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:793fd0580cb9664548c6b83c63b43c477212c0260891ddf86809e1c06c8b08f1"}, 1183 | {file = "yarl-1.20.1-cp313-cp313-win32.whl", hash = "sha256:468f6e40285de5a5b3c44981ca3a319a4b208ccc07d526b20b12aeedcfa654b7"}, 1184 | {file = "yarl-1.20.1-cp313-cp313-win_amd64.whl", hash = "sha256:495b4ef2fea40596bfc0affe3837411d6aa3371abcf31aac0ccc4bdd64d4ef5c"}, 1185 | {file = "yarl-1.20.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:f60233b98423aab21d249a30eb27c389c14929f47be8430efa7dbd91493a729d"}, 1186 | {file = "yarl-1.20.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:6f3eff4cc3f03d650d8755c6eefc844edde99d641d0dcf4da3ab27141a5f8ddf"}, 1187 | {file = "yarl-1.20.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:69ff8439d8ba832d6bed88af2c2b3445977eba9a4588b787b32945871c2444e3"}, 1188 | {file = "yarl-1.20.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3cf34efa60eb81dd2645a2e13e00bb98b76c35ab5061a3989c7a70f78c85006d"}, 1189 | {file = "yarl-1.20.1-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:8e0fe9364ad0fddab2688ce72cb7a8e61ea42eff3c7caeeb83874a5d479c896c"}, 1190 | {file = "yarl-1.20.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8f64fbf81878ba914562c672024089e3401974a39767747691c65080a67b18c1"}, 1191 | {file = "yarl-1.20.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f6342d643bf9a1de97e512e45e4b9560a043347e779a173250824f8b254bd5ce"}, 1192 | {file = "yarl-1.20.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56dac5f452ed25eef0f6e3c6a066c6ab68971d96a9fb441791cad0efba6140d3"}, 1193 | {file = "yarl-1.20.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7d7f497126d65e2cad8dc5f97d34c27b19199b6414a40cb36b52f41b79014be"}, 1194 | {file = "yarl-1.20.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:67e708dfb8e78d8a19169818eeb5c7a80717562de9051bf2413aca8e3696bf16"}, 1195 | {file = "yarl-1.20.1-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:595c07bc79af2494365cc96ddeb772f76272364ef7c80fb892ef9d0649586513"}, 1196 | {file = "yarl-1.20.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:7bdd2f80f4a7df852ab9ab49484a4dee8030023aa536df41f2d922fd57bf023f"}, 1197 | {file = "yarl-1.20.1-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:c03bfebc4ae8d862f853a9757199677ab74ec25424d0ebd68a0027e9c639a390"}, 1198 | {file = "yarl-1.20.1-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:344d1103e9c1523f32a5ed704d576172d2cabed3122ea90b1d4e11fe17c66458"}, 1199 | {file = "yarl-1.20.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:88cab98aa4e13e1ade8c141daeedd300a4603b7132819c484841bb7af3edce9e"}, 1200 | {file = "yarl-1.20.1-cp313-cp313t-win32.whl", hash = "sha256:b121ff6a7cbd4abc28985b6028235491941b9fe8fe226e6fdc539c977ea1739d"}, 1201 | {file = "yarl-1.20.1-cp313-cp313t-win_amd64.whl", hash = "sha256:541d050a355bbbc27e55d906bc91cb6fe42f96c01413dd0f4ed5a5240513874f"}, 1202 | {file = "yarl-1.20.1-py3-none-any.whl", hash = "sha256:83b8eb083fe4683c6115795d9fc1cfaf2cbbefb19b3a1cb68f6527460f483a77"}, 1203 | {file = "yarl-1.20.1.tar.gz", hash = "sha256:d017a4997ee50c91fd5466cef416231bb82177b93b029906cefc542ce14c35ac"}, 1204 | ] 1205 | 1206 | [[package]] 1207 | name = "zipp" 1208 | version = "3.20.2" 1209 | requires_python = ">=3.8" 1210 | summary = "Backport of pathlib-compatible object wrapper for zip files" 1211 | groups = ["default"] 1212 | files = [ 1213 | {file = "zipp-3.20.2-py3-none-any.whl", hash = "sha256:a817ac80d6cf4b23bf7f2828b7cabf326f15a001bea8b1f9b49631780ba28350"}, 1214 | {file = "zipp-3.20.2.tar.gz", hash = "sha256:bc9eb26f4506fda01b81bcde0ca78103b6e62f991b381fec825435c836edbc29"}, 1215 | ] 1216 | --------------------------------------------------------------------------------