From 0ba860b89250adf6983ab3372c41d4b25c90086e Mon Sep 17 00:00:00 2001 From: Brian Bjarke Jensen Date: Thu, 18 Sep 2025 12:13:39 +0200 Subject: [PATCH 1/4] added infrastructure code --- .gitea/workflows/code-quality.yml | 43 + .gitea/workflows/test.yml | 47 + .pre-commit-config.yaml | 40 + .python-version | 1 + README.md | 1 - data_store/__init__.py | 0 data_store/dto/__init__.py | 20 + data_store/dto/angle_enum.py | 11 + data_store/dto/annotation.py | 16 + data_store/dto/contact_enum.py | 10 + data_store/dto/distance_enum.py | 11 + data_store/dto/job.py | 21 + data_store/dto/point_of_view_enum.py | 10 + data_store/dto/type_checking_base_model.py | 12 + data_store/interfaces/__init__.py | 14 + .../annotation_repository_interface.py | 29 + .../interfaces/image_repository_interface.py | 29 + .../interfaces/job_repository_interface.py | 30 + data_store/repositories/__init__.py | 14 + .../repositories/annotation_repository.py | 106 ++ data_store/repositories/image_repository.py | 82 + data_store/repositories/job_repository.py | 78 + pyproject.toml | 84 + .../annotation_repository_interface_test.py | 110 ++ .../integration/annotation_repository_test.py | 86 + tests/integration/conftest.py | 340 ++++ .../image_repository_interface_test.py | 110 ++ tests/integration/image_repository_test.py | 95 ++ .../job_repository_interface_test.py | 109 ++ tests/integration/job_repository_test.py | 116 ++ tests/unit/test_annotation_repository.py | 128 ++ tests/unit/test_image_repository.py | 98 ++ tests/unit/test_job_repository.py | 85 + uv.lock | 1405 +++++++++++++++++ 34 files changed, 3390 insertions(+), 1 deletion(-) create mode 100644 .gitea/workflows/code-quality.yml create mode 100644 .gitea/workflows/test.yml create mode 100644 .pre-commit-config.yaml create mode 100644 .python-version create mode 100644 data_store/__init__.py create mode 100644 data_store/dto/__init__.py create mode 100644 data_store/dto/angle_enum.py create mode 100644 data_store/dto/annotation.py create mode 100644 data_store/dto/contact_enum.py create mode 100644 data_store/dto/distance_enum.py create mode 100644 data_store/dto/job.py create mode 100644 data_store/dto/point_of_view_enum.py create mode 100644 data_store/dto/type_checking_base_model.py create mode 100644 data_store/interfaces/__init__.py create mode 100644 data_store/interfaces/annotation_repository_interface.py create mode 100644 data_store/interfaces/image_repository_interface.py create mode 100644 data_store/interfaces/job_repository_interface.py create mode 100644 data_store/repositories/__init__.py create mode 100644 data_store/repositories/annotation_repository.py create mode 100644 data_store/repositories/image_repository.py create mode 100644 data_store/repositories/job_repository.py create mode 100644 pyproject.toml create mode 100644 tests/integration/annotation_repository_interface_test.py create mode 100644 tests/integration/annotation_repository_test.py create mode 100644 tests/integration/conftest.py create mode 100644 tests/integration/image_repository_interface_test.py create mode 100644 tests/integration/image_repository_test.py create mode 100644 tests/integration/job_repository_interface_test.py create mode 100644 tests/integration/job_repository_test.py create mode 100644 tests/unit/test_annotation_repository.py create mode 100644 tests/unit/test_image_repository.py create mode 100644 tests/unit/test_job_repository.py create mode 100644 uv.lock diff --git a/.gitea/workflows/code-quality.yml b/.gitea/workflows/code-quality.yml new file mode 100644 index 0000000..e0bf4fd --- /dev/null +++ b/.gitea/workflows/code-quality.yml @@ -0,0 +1,43 @@ +name: Code Quality Pipeline + +on: + push: + branches: + - main + pull_request: + +jobs: + code-quality: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: ${{ inputs.python-version }} + + - name: Install uv + run: pip install uv + + - name: Install dependencies + env: + UV_LINK_MODE: copy + run: uv sync --all-extras + + - name: Type check with mypy + run: uv run mypy . + + - name: Ruff lint + run: uv run ruff check . + + - name: Ruff format + run: uv run ruff format --check . + + - name: Pyupgrade check + run: uv run pyupgrade --py312-plus $(git ls-files '*.py') && git diff --exit-code + + - name: Prettier format + run: | + uv run prettier --check . diff --git a/.gitea/workflows/test.yml b/.gitea/workflows/test.yml new file mode 100644 index 0000000..a75c48c --- /dev/null +++ b/.gitea/workflows/test.yml @@ -0,0 +1,47 @@ +name: Test Python Package + +on: + push: + branches: + - main + pull_request: + +jobs: + test: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: ${{ inputs.python-version }} + + - name: Install uv + run: pip install uv + + - name: Install dependencies + env: + UV_LINK_MODE: copy + run: uv sync --all-extras + + - name: Run pytest + env: + PYTHONPATH: . + run: uv run pytest --cov=python_repositories --cov-report=term-missing > coverage.txt + + - name: Post coverage summary to PR + env: + API_URL: ${{ vars.API_URL }} + REPO_OWNER: ${{ github.repository_owner }} + REPO_NAME: ${{ github.event.repository.name }} + PR_NUMBER: ${{ github.event.pull_request.number }} + CI_RUNNER_TOKEN: ${{ secrets.CI_RUNNER_TOKEN }} + run: | + COVERAGE=$(cat coverage.txt) + COMMENT_BODY="**Test Coverage Report:**\n\`\`\`\n$COVERAGE\n\`\`\`" + curl -s -X POST "$API_URL/repos/$REPO_OWNER/$REPO_NAME/issues/$PR_NUMBER/comments" \ + -H "Authorization: token $CI_RUNNER_TOKEN" \ + -H "Content-Type: application/json" \ + -d "{\"body\": \"$COMMENT_BODY\"}" diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..abc1189 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,40 @@ +repos: + # General repository hygiene hooks + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.5.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-yaml + - id: check-added-large-files + - id: debug-statements + - id: name-tests-test + - id: check-merge-conflict + + # Python linting and formatting with Ruff + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.12.8 + hooks: + - id: ruff-check + args: [--fix] + - id: ruff-format + + # Static type checking with mypy + - repo: https://github.com/pre-commit/mirrors-mypy + rev: v1.8.0 + hooks: + - id: mypy + + # Python syntax modernization with pyupgrade + - repo: https://github.com/asottile/pyupgrade + rev: v3.20.0 + hooks: + - id: pyupgrade + args: ["--py311-plus"] + + # Formatting for Markdown, JSON, and YAML with Prettier + - repo: https://github.com/pre-commit/mirrors-prettier + rev: v3.1.0 + hooks: + - id: prettier + files: "\\.(md|json|yaml|yml)$" diff --git a/.python-version b/.python-version new file mode 100644 index 0000000..e4fba21 --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.12 diff --git a/README.md b/README.md index 8c57634..b2fb4c3 100644 --- a/README.md +++ b/README.md @@ -1,2 +1 @@ # visual-semiotic-ai-analysis - diff --git a/data_store/__init__.py b/data_store/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/data_store/dto/__init__.py b/data_store/dto/__init__.py new file mode 100644 index 0000000..6fbe0de --- /dev/null +++ b/data_store/dto/__init__.py @@ -0,0 +1,20 @@ +""" +DTO package for visual-semiotic-ai-analysis. +Exposes core data transfer objects and enums for use throughout the project. +""" + +from .angle_enum import AngleEnum +from .annotation import Annotation +from .contact_enum import ContactEnum +from .distance_enum import DistanceEnum +from .job import Job +from .point_of_view_enum import PointOfViewEnum + +__all__ = [ + "AngleEnum", + "Annotation", + "ContactEnum", + "DistanceEnum", + "Job", + "PointOfViewEnum", +] diff --git a/data_store/dto/angle_enum.py b/data_store/dto/angle_enum.py new file mode 100644 index 0000000..96a6735 --- /dev/null +++ b/data_store/dto/angle_enum.py @@ -0,0 +1,11 @@ +"""Definition of AngleEnum DTO.""" + +from enum import StrEnum + + +class AngleEnum(StrEnum): + """Enumeration for Angle values.""" + + HIGH = "high" + EYE_LEVEL = "eye-level" + LOW = "low" diff --git a/data_store/dto/annotation.py b/data_store/dto/annotation.py new file mode 100644 index 0000000..97a4427 --- /dev/null +++ b/data_store/dto/annotation.py @@ -0,0 +1,16 @@ +"""Definition of Annotation DTO.""" + +from .type_checking_base_model import TypeCheckingBaseModel +from .distance_enum import DistanceEnum +from .angle_enum import AngleEnum +from .point_of_view_enum import PointOfViewEnum +from .contact_enum import ContactEnum + + +class Annotation(TypeCheckingBaseModel): + """Data Transfer Object representing an Annotation.""" + + distance: DistanceEnum + angle: AngleEnum + point_of_view: PointOfViewEnum + contact: ContactEnum diff --git a/data_store/dto/contact_enum.py b/data_store/dto/contact_enum.py new file mode 100644 index 0000000..2f0c312 --- /dev/null +++ b/data_store/dto/contact_enum.py @@ -0,0 +1,10 @@ +"""Definition of ContactEnum DTO.""" + +from enum import StrEnum + + +class ContactEnum(StrEnum): + """Enumeration for Contact.""" + + OFFER = "offer" + DEMAND = "demand" diff --git a/data_store/dto/distance_enum.py b/data_store/dto/distance_enum.py new file mode 100644 index 0000000..16a53e0 --- /dev/null +++ b/data_store/dto/distance_enum.py @@ -0,0 +1,11 @@ +"""Definition of DistanceEnum DTO.""" + +from enum import StrEnum + + +class DistanceEnum(StrEnum): + """Enumeration for Distance values.""" + + CLOSE = "close" + MEDIUM = "medium" + LONG = "long" diff --git a/data_store/dto/job.py b/data_store/dto/job.py new file mode 100644 index 0000000..889dd5b --- /dev/null +++ b/data_store/dto/job.py @@ -0,0 +1,21 @@ +"""Definition of Job DTO.""" + +from uuid import uuid4, UUID +from pydantic import Field +from PIL import Image + +from .type_checking_base_model import TypeCheckingBaseModel +from .annotation import Annotation + + +class Job(TypeCheckingBaseModel): + """Data Transfer Object representing a Job.""" + + class Config: + """Pydantic configuration for Job DTO.""" + + arbitrary_types_allowed = True + + job_id: UUID = Field(default_factory=uuid4) + image: Image.Image + annotation: Annotation diff --git a/data_store/dto/point_of_view_enum.py b/data_store/dto/point_of_view_enum.py new file mode 100644 index 0000000..ea555e7 --- /dev/null +++ b/data_store/dto/point_of_view_enum.py @@ -0,0 +1,10 @@ +"""Definition of PointOfViewEnum DTO.""" + +from enum import StrEnum + + +class PointOfViewEnum(StrEnum): + """Enumeration for Point of View.""" + + FRONTAL = "frontal" + OBLIQUE = "oblique" diff --git a/data_store/dto/type_checking_base_model.py b/data_store/dto/type_checking_base_model.py new file mode 100644 index 0000000..74da292 --- /dev/null +++ b/data_store/dto/type_checking_base_model.py @@ -0,0 +1,12 @@ +"""Definition of class_base class.""" + +from pydantic import BaseModel, ConfigDict + + +class TypeCheckingBaseModel(BaseModel): + """BaseModel with added type checking on input types.""" + + model_config = ConfigDict( + validate_assignment=True, # ensure that dynamic validations adhere to defined types + frozen=True, # ensure data immutability + ) diff --git a/data_store/interfaces/__init__.py b/data_store/interfaces/__init__.py new file mode 100644 index 0000000..7087854 --- /dev/null +++ b/data_store/interfaces/__init__.py @@ -0,0 +1,14 @@ +""" +Interfaces package for visual-semiotic-ai-analysis. +Exposes repository interfaces for use throughout the project. +""" + +from .annotation_repository_interface import AnnotationRepositoryInterface +from .job_repository_interface import JobRepositoryInterface +from .image_repository_interface import ImageRepositoryInterface + +__all__ = [ + "JobRepositoryInterface", + "ImageRepositoryInterface", + "AnnotationRepositoryInterface", +] diff --git a/data_store/interfaces/annotation_repository_interface.py b/data_store/interfaces/annotation_repository_interface.py new file mode 100644 index 0000000..ca5f0ab --- /dev/null +++ b/data_store/interfaces/annotation_repository_interface.py @@ -0,0 +1,29 @@ +"""Definition of AnnotationRepositoryInterface.""" + +from uuid import UUID +from abc import ABC, abstractmethod +from data_store.dto import Annotation + + +class AnnotationRepositoryInterface(ABC): + """AnnotationRepository interface.""" + + @abstractmethod + def get(self, job_id: UUID) -> Annotation | None: + """Retrieve an Annotation by its associated Job ID.""" + raise NotImplementedError() + + @abstractmethod + def put(self, annotation: Annotation, job_id: UUID) -> None: + """Update or create an Annotation.""" + raise NotImplementedError() + + @abstractmethod + def delete(self, job_id: UUID) -> None: + """Delete an Annotation by its associated Job ID.""" + raise NotImplementedError() + + @abstractmethod + def list_all(self) -> list[UUID]: + """List all Job IDs with associated Annotations in the repository.""" + raise NotImplementedError() diff --git a/data_store/interfaces/image_repository_interface.py b/data_store/interfaces/image_repository_interface.py new file mode 100644 index 0000000..1db616e --- /dev/null +++ b/data_store/interfaces/image_repository_interface.py @@ -0,0 +1,29 @@ +"""Definition of ImageRepositoryInterface""" + +from uuid import UUID +from abc import ABC, abstractmethod +from PIL import Image + + +class ImageRepositoryInterface(ABC): + """ImageRepository interface.""" + + @abstractmethod + def get(self, image_id: UUID) -> Image.Image | None: + """Retrieve an Image by its ID.""" + raise NotImplementedError() + + @abstractmethod + def put(self, image: Image.Image, image_id: UUID) -> None: + """Update or create an Image.""" + raise NotImplementedError() + + @abstractmethod + def delete(self, image_id: UUID) -> None: + """Delete an Image by its ID.""" + raise NotImplementedError() + + @abstractmethod + def list_all(self) -> list[UUID]: + """List all image IDs in the repository.""" + raise NotImplementedError() diff --git a/data_store/interfaces/job_repository_interface.py b/data_store/interfaces/job_repository_interface.py new file mode 100644 index 0000000..d5b563f --- /dev/null +++ b/data_store/interfaces/job_repository_interface.py @@ -0,0 +1,30 @@ +"""Definition of JobRepositoryInterface.""" + +from uuid import UUID +from abc import ABC, abstractmethod + +from data_store.dto import Job + + +class JobRepositoryInterface(ABC): + """JobRepository interface.""" + + @abstractmethod + def get(self, job_id: UUID) -> Job | None: + """Retrieve a Job by its ID.""" + raise NotImplementedError() + + @abstractmethod + def put(self, job: Job) -> None: + """Update or create a Job.""" + raise NotImplementedError() + + @abstractmethod + def delete(self, job_id: UUID) -> None: + """Delete a Job by its ID.""" + raise NotImplementedError() + + @abstractmethod + def list_all(self) -> list[UUID]: + """List all Job IDs in the repository.""" + raise NotImplementedError() diff --git a/data_store/repositories/__init__.py b/data_store/repositories/__init__.py new file mode 100644 index 0000000..7c5d3f5 --- /dev/null +++ b/data_store/repositories/__init__.py @@ -0,0 +1,14 @@ +""" +Repositories package for visual-semiotic-ai-analysis. +Exposes repository implementations for use throughout the project. +""" + +from .annotation_repository import AnnotationRepository +from .image_repository import ImageRepository +from .job_repository import JobRepository + +__all__ = [ + "AnnotationRepository", + "ImageRepository", + "JobRepository", +] diff --git a/data_store/repositories/annotation_repository.py b/data_store/repositories/annotation_repository.py new file mode 100644 index 0000000..06c91af --- /dev/null +++ b/data_store/repositories/annotation_repository.py @@ -0,0 +1,106 @@ +"""Definition of AnnotationRepository.""" + +from __future__ import annotations +from uuid import UUID +import json +from pathlib import Path +from io import BytesIO + +from python_repositories.adapters import MinioAdapter + +from data_store.interfaces import AnnotationRepositoryInterface +from data_store.dto import ( + Annotation, + DistanceEnum, + AngleEnum, + PointOfViewEnum, + ContactEnum, +) + + +class AnnotationRepository(MinioAdapter, AnnotationRepositoryInterface): + """AnnotationRepository implementation using MinIO as the backend.""" + + encoding: str = "utf-8" + data_format: str = "json" + folder_name: str = "annotations" + + @classmethod + def _object_name(cls, job_id: UUID) -> str: + """Generate the object name for a given job ID.""" + # Check input + if not isinstance(job_id, UUID): + raise ValueError("job_id must be a valid UUID.") + # Return object name + return f"{cls.folder_name}/{job_id}.{cls.data_format}" + + def __enter__(self) -> AnnotationRepository: + """Enter the runtime context related to this object.""" + super().__enter__() + return self + + def get(self, job_id: UUID) -> Annotation | None: + """Retrieve an Annotation by its job ID.""" + # Check input + if not isinstance(job_id, UUID): + raise ValueError("job_id must be a valid UUID.") + # Get object + object_name = self._object_name(job_id) + buffer = self._get(object_name) + if buffer is None: + return None + # Convert buffer to Annotation + try: + data_str = buffer.read().decode(self.encoding) + data = json.loads(data_str) + annotation = Annotation( + distance=DistanceEnum(data["distance"]), + angle=AngleEnum(data["angle"]), + point_of_view=PointOfViewEnum(data["point_of_view"]), + contact=ContactEnum(data["contact"]), + ) + except (KeyError, ValueError) as e: + self.logger.error( + "Failed to parse Annotation from data", + object_name=object_name, + error=str(e), + ) + return None + return annotation + + def put(self, annotation: Annotation, job_id: UUID) -> None: + """Update or create an Annotation.""" + # Check inputs + if not isinstance(annotation, Annotation): + raise ValueError("annotation must be an Annotation instance.") + if not isinstance(job_id, UUID): + raise ValueError("job_id must be a valid UUID.") + # Convert Annotation to json + data_json = annotation.model_dump(mode="json") + data_bytes = json.dumps(data_json).encode(self.encoding) + buffer = BytesIO(data_bytes) + # Put object + object_name = self._object_name(job_id) + self._put(object_name, buffer) + + def delete(self, job_id: UUID) -> None: + """Delete an Annotation by its job ID.""" + # Check input + if not isinstance(job_id, UUID): + raise ValueError("job_id must be a valid UUID.") + # Delete object + object_name = self._object_name(job_id) + self._delete(object_name) + + def list_all(self) -> list[UUID]: + """List all job IDs in the repository.""" + # List objects in the bucket + objects = self._list_objects(prefix=self.folder_name + "/") + # Stop early if no objects + if len(objects) == 0: + return [] + # Remove folder prefix and file extension + object_stems = [Path(obj).stem for obj in objects] + # Convert to list of UUIDs + job_ids = [UUID(name) for name in object_stems] + return job_ids diff --git a/data_store/repositories/image_repository.py b/data_store/repositories/image_repository.py new file mode 100644 index 0000000..9c07a3f --- /dev/null +++ b/data_store/repositories/image_repository.py @@ -0,0 +1,82 @@ +"""Definition of ImageRepository class.""" + +from __future__ import annotations +from pathlib import Path +from io import BytesIO +from uuid import UUID +from PIL import Image + +from python_repositories.adapters import MinioAdapter + +from data_store.interfaces import ImageRepositoryInterface + + +class ImageRepository(MinioAdapter, ImageRepositoryInterface): + """ImageRepository implementation using MinIO as the backend.""" + + image_format: str = "PNG" + folder_name: str = "images" + + @classmethod + def _object_name(cls, image_id: UUID) -> str: + """Generate the object name for a given image ID.""" + # Check input + if not isinstance(image_id, UUID): + raise ValueError("image_id must be a valid UUID.") + # Return object name + return f"{cls.folder_name}/{image_id}.{cls.image_format.lower()}" + + def __enter__(self) -> ImageRepository: + """Enter the runtime context related to this object.""" + super().__enter__() + return self + + def get(self, image_id: UUID) -> Image.Image | None: + """Retrieve an Image by its ID.""" + # Check input + if not isinstance(image_id, UUID): + raise ValueError("image_id must be a valid UUID.") + # Get object + object_name = self._object_name(image_id) + buffer = self._get(object_name) + if buffer is None: + return None + # Convert bytes back to PIL Image + image: Image.Image = Image.open(buffer, formats=[self.image_format]) + return image + + def put(self, image: Image.Image, image_id: UUID) -> None: + """Update or create an Image.""" + # Check inputs + if not isinstance(image, Image.Image): + raise ValueError("image must be a PIL Image instance.") + if not isinstance(image_id, UUID): + raise ValueError("image_id must be a valid UUID.") + # Convert image to bytes + buffer = BytesIO() + image.save(buffer, self.image_format) + # Put object + object_name = self._object_name(image_id) + self._put(object_name, buffer) + + def delete(self, image_id: UUID) -> None: + """Delete an Image by its ID.""" + # Check input + if not isinstance(image_id, UUID): + raise ValueError("image_id must be a valid UUID.") + # Delete object + object_name = self._object_name(image_id) + self._delete(object_name) + + def list_all(self) -> list[UUID]: + """List all image IDs in the repository.""" + # List objects in the bucket + objects = self._list_objects(prefix=self.folder_name + "/") + # Stop early if no objects + if len(objects) == 0: + return [] + # Remove folder prefix and file extension + object_stems = [Path(obj).stem for obj in objects] + # Convert to list of UUIDs + image_ids = [UUID(name) for name in object_stems] + return image_ids diff --git a/data_store/repositories/job_repository.py b/data_store/repositories/job_repository.py new file mode 100644 index 0000000..1eed322 --- /dev/null +++ b/data_store/repositories/job_repository.py @@ -0,0 +1,78 @@ +"""Definition of JobRepository class.""" + +from __future__ import annotations +from uuid import UUID +from python_repositories.adapters import MinioAdapter +from data_store.interfaces import JobRepositoryInterface +from data_store.repositories import AnnotationRepository, ImageRepository +from data_store.dto import Job + + +class JobRepository(MinioAdapter, JobRepositoryInterface): + """JobRepository implementation using MinIO as the backend.""" + + def __enter__(self) -> JobRepository: + """Enter the runtime context related to this object.""" + super().__enter__() + return self + + def get(self, job_id: UUID) -> Job | None: + """Retrieve a Job by its ID.""" + # Check input + if not isinstance(job_id, UUID): + raise ValueError("job_id must be a valid UUID.") + # Get image + with ImageRepository() as image_repo: + image = image_repo.get(job_id) + if image is None: + self.logger.warning(f"Image for job ID {job_id} not found.") + return None + # Get annotation + with AnnotationRepository() as annotation_repo: + annotation = annotation_repo.get(job_id) + if annotation is None: + self.logger.warning(f"Annotation for job ID {job_id} not found.") + return None + # Create Job DTO + job = Job( + job_id=job_id, + image=image, + annotation=annotation, + ) + return job + + def put(self, job: Job) -> None: + """Update or create a Job.""" + # Check input + if not isinstance(job, Job): + raise ValueError("job must be a Job instance.") + # Store image + with ImageRepository() as image_repo: + image_repo.put(job.image, job.job_id) + # Store annotation + with AnnotationRepository() as annotation_repo: + annotation_repo.put(job.annotation, job.job_id) + + def delete(self, job_id: UUID) -> None: + """Delete a Job by its ID.""" + # Check input + if not isinstance(job_id, UUID): + raise ValueError("job_id must be a valid UUID.") + # Delete image + with ImageRepository() as image_repo: + image_repo.delete(job_id) + # Delete annotation + with AnnotationRepository() as annotation_repo: + annotation_repo.delete(job_id) + + def list_all(self) -> list[UUID]: + """List all Job IDs.""" + # List image IDs + with ImageRepository() as image_repo: + image_ids = set(image_repo.list_all()) + # List annotation IDs + with AnnotationRepository() as annotation_repo: + annotation_ids = set(annotation_repo.list_all()) + # Find intersection of IDs + job_ids = list(image_ids.intersection(annotation_ids)) + return job_ids diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..a35820c --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,84 @@ +[project] +name = "visual-semiotic-ai-analysis" +version = "0.1.0" +description = "Add your description here" +authors = [ + { name = "Brian Bjarke Jensen", email = "schnitzelen@gmail.com" } +] +readme = "README.md" +requires-python = ">=3.12" +license = { text = "MIT" } +classifiers = [ + "Programming Language :: Python :: 3", + "License :: OSI Approved :: MIT License", + "Operating System :: OS Independent", +] +dependencies = [ + "pandas>=2.3.2", + "pillow>=11.3.0", + "pydantic>=2.11.9", + "python-repositories[minio]>=0.2.0", + "python-utils>=0.1.1", +] + +[build-system] +requires = ["uv_build"] +build-backend = "uv_build" + +[tool.uv.build-backend] +module-name = [ + "data_store", +] +module-root = "." + +[tool.uv.sources] +python-repositories = { index = "gitea" } +python-utils = { index = "gitea" } + +[[tool.uv.index]] +name = "threadripper-proxpi-cache" +url = "http://10.0.0.2:5001/index/" +default = true + +[[tool.uv.index]] +name = "gitea" +url = "https://gitea.gt-proj.com/api/packages/brian/pypi/simple/" +explicit = true + +[tool.mypy] +python_version = "3.12" +warn_return_any = true # nudge to use stricter types +warn_unused_configs = true # nudge to remove unused configs +disallow_untyped_defs = true # disallow untyped function definitions +disallow_incomplete_defs = true # ensure all parts of a function has type annotation +check_untyped_defs = true # dont skip untyped functions +disallow_untyped_decorators = false # allow untyped decorators to keep code more readable +no_implicit_optional = true # disallow implicit optional types leading to None-mess +warn_redundant_casts = true # nudge to use explicit type casts +warn_unused_ignores = true # nudge to remove unused ignores +warn_no_return = true # catch missing return statements +warn_unreachable = true # catch unreachable code +show_error_codes = true # show error codes in output +explicit_package_bases = true # reduce risk of import confusion +namespace_packages = true # enable namespace packages + +[[tool.mypy.overrides]] +module = "testcontainers.*" +ignore_missing_imports = true + +[[tool.mypy.overrides]] +module = "minio.*" +ignore_missing_imports = true + +[dependency-groups] +dev = [ + "mypy>=1.18.1", + "pandas-stubs>=2.3.2.250827", + "pre-commit>=4.3.0", + "pytest>=8.4.2", + "pytest-cov>=7.0.0", + "pyupgrade>=3.20.0", + "ruff>=0.13.0", + "safety>=3.2.11", + "testcontainers>=4.13.0", +] diff --git a/tests/integration/annotation_repository_interface_test.py b/tests/integration/annotation_repository_interface_test.py new file mode 100644 index 0000000..9808e82 --- /dev/null +++ b/tests/integration/annotation_repository_interface_test.py @@ -0,0 +1,110 @@ +"""Integration tests for AnnotationRepositoryInterface.""" + +from uuid import UUID +import pytest +from data_store.interfaces import AnnotationRepositoryInterface +from data_store.dto import Annotation + + +def test_get_raises_not_implemented_if_not_overwritten( + job_id_list: list[UUID], +) -> None: + """Test that calling get on a subclass without get implemented raises NotImplementedError.""" + + class Incomplete(AnnotationRepositoryInterface): + """A class missing the get method.""" + + def get(self, job_id: UUID) -> Annotation | None: + return super().get(job_id) # type: ignore + + def put(self, annotation: Annotation, job_id: UUID) -> None: + return None + + def delete(self, job_id: UUID) -> None: + return None + + def list_all(self) -> list[UUID]: + return [] + + instance = Incomplete() + with pytest.raises(NotImplementedError): + instance.get(job_id_list[0]) + + +def test_put_raises_not_implemented_if_not_overwritten( + annotation: Annotation, + job_id_list: list[UUID], +) -> None: + """Test that calling put on a subclass without put implemented raises NotImplementedError.""" + + class Incomplete(AnnotationRepositoryInterface): + """A class missing the put method.""" + + def get(self, job_id: UUID) -> Annotation | None: + return None + + def put(self, annotation: Annotation, job_id: UUID) -> None: + return super().put(annotation, job_id) # type: ignore + + def delete(self, job_id: UUID) -> None: + return None + + def list_all(self) -> list[UUID]: + return [] + + instance = Incomplete() + with pytest.raises(NotImplementedError): + instance.put(annotation, job_id_list[0]) + + +def test_delete_raises_not_implemented_if_not_overwritten( + job_id_list: list[UUID], +) -> None: + """Test that calling delete on a subclass without delete implemented raises NotImplementedError.""" + + class Incomplete(AnnotationRepositoryInterface): + """A class missing the delete method.""" + + def get(self, job_id: UUID) -> Annotation | None: + return None + + def put(self, annotation: Annotation, job_id: UUID) -> None: + return None + + def delete(self, job_id: UUID) -> None: + return super().delete(job_id) # type: ignore + + def list_all(self) -> list[UUID]: + return [] + + instance = Incomplete() + with pytest.raises(NotImplementedError): + instance.delete(job_id_list[0]) + + +def test_list_all_raises_not_implemented_if_not_overwritten() -> None: + """Test that calling list_all on a subclass without list_all implemented raises NotImplementedError.""" + + class Incomplete(AnnotationRepositoryInterface): + """A class missing the list_all method.""" + + def get(self, job_id: UUID) -> Annotation | None: + return None + + def put(self, annotation: Annotation, job_id: UUID) -> None: + return None + + def delete(self, job_id: UUID) -> None: + return None + + def list_all(self) -> list[UUID]: + return super().list_all() # type: ignore + + instance = Incomplete() + with pytest.raises(NotImplementedError): + instance.list_all() + + +# Allows local debugging by running file as script +if __name__ == "__main__": + pytest.main(["-s", "-v", __file__]) diff --git a/tests/integration/annotation_repository_test.py b/tests/integration/annotation_repository_test.py new file mode 100644 index 0000000..7dcd0ab --- /dev/null +++ b/tests/integration/annotation_repository_test.py @@ -0,0 +1,86 @@ +"""Integration tests for AnnotationRepository.""" + +from uuid import UUID +import pytest +from data_store.repositories.annotation_repository import AnnotationRepository +from data_store.dto import ( + Annotation, +) + + +def test_get_annotation( + annotation_in_minio: tuple[UUID, Annotation], + annotation_repository: AnnotationRepository, +) -> None: + """Test retrieving an annotation from AnnotationRepository.""" + # Arrange + job_id, expected_annotation = annotation_in_minio + # Act + retrieved_annotation = annotation_repository.get(job_id) + # Assert + assert retrieved_annotation is not None + assert isinstance(retrieved_annotation, Annotation) + assert retrieved_annotation == expected_annotation + + +def test_put_annotation( + annotation_repository: AnnotationRepository, + annotation: Annotation, + job_id_list: list[UUID], +) -> None: + """Test storing an annotation in AnnotationRepository.""" + # Arrange + job_id = job_id_list[0] + assert annotation_repository.get(job_id) is None + # Act + annotation_repository.put(annotation, job_id) + # Assert + received_annotation = annotation_repository.get(job_id) + assert received_annotation is not None + assert isinstance(received_annotation, Annotation) + assert received_annotation == annotation + + +def test_delete_annotation( + annotation_in_minio: tuple[UUID, Annotation], + annotation_repository: AnnotationRepository, +) -> None: + """Test deleting an annotation from AnnotationRepository.""" + # Arrange + job_id, _ = annotation_in_minio + assert annotation_repository.get(job_id) is not None + # Act + annotation_repository.delete(job_id) + # Assert + assert annotation_repository.get(job_id) is None + + +def test_list_all_annotations( + annotation_in_minio: tuple[UUID, Annotation], + annotation_repository: AnnotationRepository, +) -> None: + """Test listing all annotations in AnnotationRepository.""" + # Arrange + job_id, _ = annotation_in_minio + # Act + annotation_ids = annotation_repository.list_all() + # Assert + assert isinstance(annotation_ids, list) + assert all(isinstance(i, UUID) for i in annotation_ids) + assert job_id in annotation_ids + + +def test_list_all_annotations_empty( + annotation_repository: AnnotationRepository, +) -> None: + """Test listing all annotations in an empty AnnotationRepository.""" + # Act + annotation_ids = annotation_repository.list_all() + # Assert + assert isinstance(annotation_ids, list) + assert len(annotation_ids) == 0 + + +# Allows local debugging by running file as script +if __name__ == "__main__": + pytest.main(["-s", "-v", __file__]) diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py new file mode 100644 index 0000000..566594c --- /dev/null +++ b/tests/integration/conftest.py @@ -0,0 +1,340 @@ +"""Integration test configuration.""" + +import logging +import os +import shutil +import tempfile +from pathlib import Path +import json +from collections.abc import Generator +from uuid import UUID +from io import BytesIO +import pandas as pd +from PIL import Image +import pytest +import structlog +from minio import Minio, S3Error +from testcontainers.minio import MinioContainer +from python_repositories.adapters import MinioAdapter +from data_store.repositories import ( + ImageRepository, + AnnotationRepository, + JobRepository, +) +from data_store.dto import ( + Annotation, + DistanceEnum, + AngleEnum, + PointOfViewEnum, + ContactEnum, + Job, +) + +# Last Docker image with a useful WebUI +MINIO_DOCKER_IMAGE = "minio/minio:RELEASE.2023-03-20T20-16-18Z" + + +@pytest.fixture(scope="session", autouse=True) +def configure_logging() -> None: + """Configure logging for the test session.""" + # Configure structlog + structlog.configure( + processors=[ + structlog.stdlib.filter_by_level, + structlog.stdlib.add_logger_name, + structlog.stdlib.add_log_level, + structlog.processors.TimeStamper(fmt="iso"), + structlog.processors.JSONRenderer(), + ], + logger_factory=structlog.stdlib.LoggerFactory(), + wrapper_class=structlog.stdlib.BoundLogger, + cache_logger_on_first_use=True, + ) + # Set up basic logging configuration + logging.basicConfig(level=logging.ERROR) + + +@pytest.fixture(scope="session") +def minio_container() -> Generator[dict[str, str]]: + """Set up MinIO container and provide credentials for testing.""" + # Set variables + access_key = "minioadmin" + secret_key = "minioadmin" + bucket_name = "test-bucket" + # Start container + container = MinioContainer( + image=MINIO_DOCKER_IMAGE, + access_key=access_key, + secret_key=secret_key, + ).with_bind_ports( # expose webUI on 9001 + container=9001, + host=9001, + ) + container.start() + # Build environment variables dictionary + minio_host = container.get_container_host_ip() + minio_port = container.get_exposed_port(9000) + minio_endpoint = f"{minio_host}:{minio_port}" + env_vars = { + "MINIO_ENDPOINT": minio_endpoint, + "MINIO_ACCESS_KEY": access_key, + "MINIO_SECRET_KEY": secret_key, + "MINIO_BUCKET": bucket_name, + } + + yield env_vars + + # Stop container + container.stop() + + +@pytest.fixture(scope="session", autouse=True) +def set_environment_variables( + minio_container: dict[str, str], +) -> Generator[dict[str, str]]: + """Set environment variables needed for tests.""" + # Build environment variables dictionary + env_vars = {} + env_vars.update(minio_container) + # Set environment variables + for key, value in env_vars.items(): + os.environ[key] = value + + yield env_vars + + # Cleanup + for key in env_vars: + _ = os.environ.pop(key, default=None) + + +@pytest.fixture(scope="session") +def job_id_list() -> Generator[list[UUID]]: + """Provide a list of job IDs for testing.""" + yield [ + UUID("d358cbba-75be-4c38-becd-7abf338ca941"), + UUID("56d20d25-b733-4ed3-880c-732d7257dcaa"), + UUID("8019292f-8353-43d7-a189-076c6630de7b"), + ] + + +@pytest.fixture(scope="session") +def csv_data_file( + job_id_list: list[UUID], +) -> Generator[Path]: + """Create a CSV data file for testing.""" + # Create csv content + csv_data = pd.DataFrame( + { + "job_id": job_id_list, + "distance": [ + "close", + "long", + "wrong", + ], + "angle": ["high", "low", "wrong"], + "point_of_view": ["frontal", "oblique", "wrong"], + "contact": ["offer", "demand", "wrong"], + } + ) + # Create data directory and file path + data_dir = Path(tempfile.mkdtemp()) + data_path = data_dir / "annotations.csv" + # Write CSV content to file + csv_data.to_csv(data_path, header=True, index=False) + + yield data_path + + # Cleanup + shutil.rmtree(data_dir) + + +@pytest.fixture(scope="session") +def raw_minio_client( + set_environment_variables: dict[str, str], +) -> Generator[Minio]: + """Provide a MinIO client for testing.""" + # Create MinIO client + client = Minio( + endpoint=set_environment_variables["MINIO_ENDPOINT"], + access_key=set_environment_variables["MINIO_ACCESS_KEY"], + secret_key=set_environment_variables["MINIO_SECRET_KEY"], + secure=False, + ) + # Create bucket if it doesn't exist + bucket_name = set_environment_variables["MINIO_BUCKET"] + try: + if not client.bucket_exists(bucket_name): + client.make_bucket(bucket_name) + except S3Error as e: + raise RuntimeError(f"Failed to create or access bucket: {e}") + + yield client + + # No explicit cleanup needed for MinIO client + + +@pytest.fixture(scope="session") +def image_repository() -> Generator[ImageRepository]: + """Provide an ImageRepository instance for testing.""" + # Instantiate and connect repository + repo = ImageRepository() + repo.connect() + + yield repo + + # Cleanup + repo.disconnect() + + +@pytest.fixture(scope="session") +def image() -> Generator[Image.Image]: + """Provide a sample image for testing.""" + img = Image.new("RGB", (10, 10)) + yield img + + +@pytest.fixture(scope="function") +def image_in_minio( + set_environment_variables: dict[str, str], + raw_minio_client: Minio, + image: Image.Image, + job_id_list: list[UUID], +) -> Generator[tuple[UUID, Image.Image]]: + """Upload a sample image to MinIO and provide its ID for testing.""" + # Prepare object name and buffer + bucket_name = set_environment_variables["MINIO_BUCKET"] + image_id = job_id_list[0] + object_name = ImageRepository._object_name(image_id) + buffer = BytesIO() + image.save(buffer, ImageRepository.image_format) + num_bytes = buffer.getbuffer().nbytes + buffer.seek(0) + # Upload image to MinIO + raw_minio_client.put_object( + bucket_name=bucket_name, + object_name=object_name, + data=buffer, + length=num_bytes, + part_size=MinioAdapter.chunk_size, + ) + buffer.close() + + yield image_id, image + + # Cleanup: remove image from MinIO + try: + raw_minio_client.remove_object( + bucket_name=bucket_name, + object_name=object_name, + ) + except S3Error as e: + raise RuntimeError(f"Failed to remove object from bucket: {e}") + + +@pytest.fixture(scope="session") +def annotation_repository() -> Generator[AnnotationRepository]: + """Provide an AnnotationRepository instance for testing.""" + # Instantiate and connect repository + repo = AnnotationRepository() + repo.connect() + + yield repo + + # Cleanup + repo.disconnect() + + +@pytest.fixture(scope="session") +def annotation() -> Generator[Annotation]: + """Provide a sample annotation for testing.""" + annotation = Annotation( + distance=DistanceEnum.CLOSE, + angle=AngleEnum.HIGH, + point_of_view=PointOfViewEnum.FRONTAL, + contact=ContactEnum.OFFER, + ) + yield annotation + + +@pytest.fixture(scope="function") +def annotation_in_minio( + set_environment_variables: dict[str, str], + raw_minio_client: Minio, + annotation: Annotation, + job_id_list: list[UUID], +) -> Generator[tuple[UUID, Annotation]]: + """Upload a sample annotation to MinIO and provide its ID for testing.""" + # Prepare object name and buffer + bucket_name = set_environment_variables["MINIO_BUCKET"] + job_id = job_id_list[0] + object_name = AnnotationRepository._object_name(job_id) + data_json = annotation.model_dump(mode="json") + data_bytes = json.dumps(data_json).encode(AnnotationRepository.encoding) + buffer = BytesIO(data_bytes) + num_bytes = buffer.getbuffer().nbytes + buffer.seek(0) + # Upload annotation to MinIO + raw_minio_client.put_object( + bucket_name=bucket_name, + object_name=object_name, + data=buffer, + length=num_bytes, + part_size=MinioAdapter.chunk_size, + ) + buffer.close() + + yield job_id, annotation + + # Cleanup: remove annotation from MinIO + try: + raw_minio_client.remove_object( + bucket_name=bucket_name, + object_name=object_name, + ) + except S3Error as e: + raise RuntimeError(f"Failed to remove object from bucket: {e}") + + +@pytest.fixture(scope="session") +def job_repository() -> Generator[JobRepository]: + """Provide a JobRepository instance for testing.""" + # Instantiate and connect repository + repo = JobRepository() + repo.connect() + + yield repo + + # Cleanup + repo.disconnect() + + +@pytest.fixture(scope="session") +def job( + job_id_list: list[UUID], + image: Image.Image, + annotation: Annotation, +) -> Generator[Job]: + """Provide a sample job for testing.""" + job = Job( + job_id=job_id_list[0], + image=image, + annotation=annotation, + ) + yield job + + +@pytest.fixture(scope="function") +def job_in_minio( + job: Job, + image_in_minio: tuple[UUID, Image.Image], + annotation_in_minio: tuple[UUID, Annotation], +) -> Generator[Job]: + """Provide a sample job with its components already in MinIO for testing.""" + # A job consists of an image and an annotation and both must be in MinIO + # before the job can be considered to be in MinIO. + # Ensure the job_id matches those of the image and annotation + image_id, _ = image_in_minio + annotation_id, _ = annotation_in_minio + assert job.job_id == annotation_id + assert job.job_id == image_id + yield job diff --git a/tests/integration/image_repository_interface_test.py b/tests/integration/image_repository_interface_test.py new file mode 100644 index 0000000..d37c3a8 --- /dev/null +++ b/tests/integration/image_repository_interface_test.py @@ -0,0 +1,110 @@ +"""Integration tests for ImageRepositoryInterface.""" + +from uuid import UUID +import pytest +from PIL import Image +from data_store.interfaces import ImageRepositoryInterface + + +def test_get_raises_not_implemented_if_not_overwritten( + job_id_list: list[UUID], +) -> None: + """Test that calling get on a subclass without get implemented raises NotImplementedError.""" + + class Incomplete(ImageRepositoryInterface): + """A class missing the get method.""" + + def get(self, image_id: UUID) -> Image.Image | None: + return super().get(image_id) # type: ignore + + def put(self, image: Image.Image, image_id: UUID) -> None: + return None + + def delete(self, image_id: UUID) -> None: + return None + + def list_all(self) -> list[UUID]: + return [] + + instance = Incomplete() + with pytest.raises(NotImplementedError): + instance.get(job_id_list[0]) + + +def test_put_raises_not_implemented_if_not_overwritten( + image: Image.Image, + job_id_list: list[UUID], +) -> None: + """Test that calling put on a subclass without put implemented raises NotImplementedError.""" + + class Incomplete(ImageRepositoryInterface): + """A class missing the put method.""" + + def get(self, image_id: UUID) -> Image.Image | None: + return None + + def put(self, image: Image.Image, image_id: UUID) -> None: + return super().put(image, image_id) # type: ignore + + def delete(self, image_id: UUID) -> None: + return None + + def list_all(self) -> list[UUID]: + return [] + + instance = Incomplete() + with pytest.raises(NotImplementedError): + instance.put(image, job_id_list[0]) + + +def test_delete_raises_not_implemented_if_not_overwritten( + job_id_list: list[UUID], +) -> None: + """Test that calling delete on a subclass without delete implemented raises NotImplementedError.""" + + class Incomplete(ImageRepositoryInterface): + """A class missing the delete method.""" + + def get(self, image_id: UUID) -> Image.Image | None: + return None + + def put(self, image: Image.Image, image_id: UUID) -> None: + return None + + def delete(self, image_id: UUID) -> None: + return super().delete(image_id) # type: ignore + + def list_all(self) -> list[UUID]: + return [] + + instance = Incomplete() + with pytest.raises(NotImplementedError): + instance.delete(job_id_list[0]) + + +def test_list_all_raises_not_implemented_if_not_overwritten() -> None: + """Test that calling list_all on a subclass without list_all implemented raises NotImplementedError.""" + + class Incomplete(ImageRepositoryInterface): + """A class missing the list_all method.""" + + def get(self, image_id: UUID) -> Image.Image | None: + return None + + def put(self, image: Image.Image, image_id: UUID) -> None: + return None + + def delete(self, image_id: UUID) -> None: + return None + + def list_all(self) -> list[UUID]: + return super().list_all() # type: ignore + + instance = Incomplete() + with pytest.raises(NotImplementedError): + instance.list_all() + + +# Allows local debugging by running file as script +if __name__ == "__main__": + pytest.main(["-s", "-v", __file__]) diff --git a/tests/integration/image_repository_test.py b/tests/integration/image_repository_test.py new file mode 100644 index 0000000..1e72bd3 --- /dev/null +++ b/tests/integration/image_repository_test.py @@ -0,0 +1,95 @@ +"""Integration tests for ImageRepository.""" + +from uuid import UUID +import pytest +from PIL import Image +from data_store.repositories.image_repository import ImageRepository + + +def same_image(img1: Image.Image, img2: Image.Image) -> bool: + """Check if two images are the same based on their attributes.""" + return ( + img1.size == img2.size + and img1.mode == img2.mode + and list(img1.getdata()) == list(img2.getdata()) + ) + + +def test_get_image( + image_in_minio: tuple[UUID, Image.Image], + image_repository: ImageRepository, +) -> None: + """Test retrieving an image from ImageRepository.""" + # Arrange + image_id, expected_image = image_in_minio + # Act + retrieved_image = image_repository.get(image_id) + # Assert + assert retrieved_image is not None + assert isinstance(retrieved_image, Image.Image) + assert same_image(retrieved_image, expected_image) + + +def test_put_image( + image_repository: ImageRepository, + image: Image.Image, + job_id_list: list[UUID], +) -> None: + """Test storing an image in ImageRepository.""" + # Arrange + image_id = job_id_list[0] + assert image_repository.get(image_id) is None + # Act + image_repository.put(image, image_id) + # Assert + received_image = image_repository.get(image_id) + assert received_image is not None + assert isinstance(received_image, Image.Image) + assert received_image.size == image.size + assert received_image.mode == image.mode + assert list(received_image.getdata()) == list(image.getdata()) + + +def test_delete_image( + image_in_minio: tuple[UUID, Image.Image], + image_repository: ImageRepository, +) -> None: + """Test deleting an image from ImageRepository.""" + # Arrange + image_id, _ = image_in_minio + assert image_repository.get(image_id) is not None + # Act + image_repository.delete(image_id) + # Assert + assert image_repository.get(image_id) is None + + +def test_list_all_images( + image_in_minio: tuple[UUID, Image.Image], + image_repository: ImageRepository, +) -> None: + """Test listing all images in ImageRepository.""" + # Arrange + image_id, _ = image_in_minio + # Act + image_ids = image_repository.list_all() + # Assert + assert isinstance(image_ids, list) + assert all(isinstance(i, UUID) for i in image_ids) + assert image_id in image_ids + + +def test_list_all_images_empty( + image_repository: ImageRepository, +) -> None: + """Test listing all images in an empty ImageRepository.""" + # Act + image_ids = image_repository.list_all() + # Assert + assert isinstance(image_ids, list) + assert len(image_ids) == 0 + + +# Allows local debugging by running file as script +if __name__ == "__main__": + pytest.main(["-s", "-v", __file__]) diff --git a/tests/integration/job_repository_interface_test.py b/tests/integration/job_repository_interface_test.py new file mode 100644 index 0000000..14d506a --- /dev/null +++ b/tests/integration/job_repository_interface_test.py @@ -0,0 +1,109 @@ +"""Integration tests for the JobRepositoryInterface.""" + +from uuid import UUID +import pytest +from data_store.interfaces import JobRepositoryInterface +from data_store.dto import Job + + +def test_get_raises_not_implemented_if_not_overwritten( + job_id_list: list[UUID], +) -> None: + """Test that calling get on a subclass without get implemented raises NotImplementedError.""" + + class Incomplete(JobRepositoryInterface): + """A class missing the get method.""" + + def get(self, job_id: UUID) -> Job | None: + return super().get(job_id) # type: ignore + + def put(self, job: Job) -> None: + return None + + def delete(self, job_id: UUID) -> None: + return None + + def list_all(self) -> list[UUID]: + return [] + + instance = Incomplete() + with pytest.raises(NotImplementedError): + instance.get(job_id_list[0]) + + +def test_put_raises_not_implemented_if_not_overwritten( + job: Job, +) -> None: + """Test that calling put on a subclass without put implemented raises NotImplementedError.""" + + class Incomplete(JobRepositoryInterface): + """A class missing the put method.""" + + def get(self, job_id: UUID) -> Job | None: + return None + + def put(self, job: Job) -> None: + return super().put(job) # type: ignore + + def delete(self, job_id: UUID) -> None: + return None + + def list_all(self) -> list[UUID]: + return [] + + instance = Incomplete() + with pytest.raises(NotImplementedError): + instance.put(job) + + +def test_delete_raises_not_implemented_if_not_overwritten( + job_id_list: list[UUID], +) -> None: + """Test that calling delete on a subclass without delete implemented raises NotImplementedError.""" + + class Incomplete(JobRepositoryInterface): + """A class missing the delete method.""" + + def get(self, job_id: UUID) -> Job | None: + return None + + def put(self, job: Job) -> None: + return None + + def delete(self, job_id: UUID) -> None: + return super().delete(job_id) # type: ignore + + def list_all(self) -> list[UUID]: + return [] + + instance = Incomplete() + with pytest.raises(NotImplementedError): + instance.delete(job_id_list[0]) + + +def test_list_all_raises_not_implemented_if_not_overwritten() -> None: + """Test that calling list_all on a subclass without list_all implemented raises NotImplementedError.""" + + class Incomplete(JobRepositoryInterface): + """A class missing the list_all method.""" + + def get(self, job_id: UUID) -> Job | None: + return None + + def put(self, job: Job) -> None: + return None + + def delete(self, job_id: UUID) -> None: + return None + + def list_all(self) -> list[UUID]: + return super().list_all() # type: ignore + + instance = Incomplete() + with pytest.raises(NotImplementedError): + instance.list_all() + + +# Allows local debugging by running file as script +if __name__ == "__main__": + pytest.main(["-s", "-v", __file__]) diff --git a/tests/integration/job_repository_test.py b/tests/integration/job_repository_test.py new file mode 100644 index 0000000..b656624 --- /dev/null +++ b/tests/integration/job_repository_test.py @@ -0,0 +1,116 @@ +"""Integration tests for JobRepository.""" + +from uuid import UUID +import pytest +from PIL import Image + +from data_store.repositories.job_repository import JobRepository +from data_store.dto import Job + + +def same_image(img1: Image.Image, img2: Image.Image) -> bool: + """Check if two images are the same based on their attributes.""" + assert img1.size == img2.size + assert img1.mode == img2.mode + assert list(img1.getdata()) == list(img2.getdata()) + return True + + +def same_job(job1: Job, job2: Job) -> bool: + """Check if two Job instances are the same based on their attributes.""" + assert job1.job_id == job2.job_id + assert same_image(job1.image, job2.image) + assert job1.annotation == job2.annotation + return True + + +def test_get_job( + job_in_minio: Job, + job_repository: JobRepository, +) -> None: + """Test retrieving a job from JobRepository.""" + # Arrange + job_id = job_in_minio.job_id + # Act + retrieved_job = job_repository.get(job_id) + # Assert + assert retrieved_job is not None + assert isinstance(retrieved_job, Job) + assert same_job(retrieved_job, job_in_minio) + + +def test_get_job_without_image_returns_none( + annotation_in_minio: tuple[UUID, object], + job_repository: JobRepository, +) -> None: + """Test retrieving a job without an image returns None.""" + # Arrange + job_id, _ = annotation_in_minio + # Act + retrieved_job = job_repository.get(job_id) + # Assert + assert retrieved_job is None + + +def test_get_job_without_annotation_returns_none( + image_in_minio: tuple[UUID, object], + job_repository: JobRepository, +) -> None: + """Test retrieving a job without an annotation returns None.""" + # Arrange + job_id, _ = image_in_minio + # Act + retrieved_job = job_repository.get(job_id) + # Assert + assert retrieved_job is None + + +def test_put_job( + job_repository: JobRepository, + job: Job, +) -> None: + """Test storing a job in JobRepository.""" + # Arrange + job_id = job.job_id + assert job_repository.get(job_id) is None + # Act + job_repository.put(job) + # Assert + received_job = job_repository.get(job_id) + assert received_job is not None + assert isinstance(received_job, Job) + assert same_job(received_job, job) + + +def test_delete_job( + job_in_minio: Job, + job_repository: JobRepository, +) -> None: + """Test deleting a job from JobRepository.""" + # Arrange + job_id = job_in_minio.job_id + assert job_repository.get(job_id) is not None + # Act + job_repository.delete(job_id) + # Assert + assert job_repository.get(job_id) is None + + +def test_list_all_jobs( + job_in_minio: Job, + job_repository: JobRepository, +) -> None: + """Test listing all job IDs from JobRepository.""" + # Arrange + job_id = job_in_minio.job_id + # Act + job_ids = job_repository.list_all() + # Assert + assert isinstance(job_ids, list) + assert all(isinstance(jid, UUID) for jid in job_ids) + assert job_id in job_ids + + +# Allows local debugging by running file as script +if __name__ == "__main__": + pytest.main(["-s", "-v", __file__]) diff --git a/tests/unit/test_annotation_repository.py b/tests/unit/test_annotation_repository.py new file mode 100644 index 0000000..e8c6b07 --- /dev/null +++ b/tests/unit/test_annotation_repository.py @@ -0,0 +1,128 @@ +"""Unit tests for AnnotationRepository class.""" + +import unittest +from unittest.mock import patch, MagicMock, _patch_dict +from uuid import UUID + +from data_store.repositories.annotation_repository import AnnotationRepository +from data_store.dto import ( + Annotation, + DistanceEnum, + AngleEnum, + PointOfViewEnum, + ContactEnum, +) + + +class TestAnnotationRepository(unittest.TestCase): + """Unit tests for AnnotationRepository class.""" + + patcher: _patch_dict + repo: AnnotationRepository + job_id: UUID + bad_job_id: str + annotation: Annotation + bad_annotation: dict + + @classmethod + def setUpClass(cls) -> None: + """Set up test case with a mocked MinioAdapter.""" + # Patch environment variables for MinioAdapter + cls.patcher = patch.dict( + "os.environ", + { + "MINIO_ENDPOINT": "localhost:9000", + "MINIO_ACCESS_KEY": "minioadmin", + "MINIO_SECRET_KEY": "minioadmin", + "MINIO_BUCKET": "test-bucket", + }, + ) + cls.patcher.start() + # Prepare AnnotationRepository + cls.repo = AnnotationRepository() + cls.repo._get = MagicMock() # type: ignore[method-assign] + cls.repo._put = MagicMock() # type: ignore[method-assign] + cls.repo._delete = MagicMock() # type: ignore[method-assign] + # Prepare other test variables + cls.job_id = UUID("d87022f8-4169-4d69-8512-bbd65cc1cb23") + cls.bad_job_id = "not-a-uuid" + cls.annotation = Annotation( + distance=DistanceEnum.CLOSE, + angle=AngleEnum.HIGH, + point_of_view=PointOfViewEnum.FRONTAL, + contact=ContactEnum.OFFER, + ) + cls.bad_annotation = {"not_an_annotation": "irrelevant value"} + + @classmethod + def tearDownClass(cls) -> None: + # Stop patching + cls.patcher.stop() + + def setUp(self) -> None: + """Set up each test with a fresh AnnotationRepository instance.""" + self.repo._get.reset_mock() # type: ignore[attr-defined] + self.repo._put.reset_mock() # type: ignore[attr-defined] + self.repo._delete.reset_mock() # type: ignore[attr-defined] + + def test_should_adhere_to_interface(self) -> None: + """Test that AnnotationRepository adheres to AnnotationRepositoryInterface.""" + # Instantiation fails if interface not adhered to + _ = AnnotationRepository() + + def test_should_have_encoding_set(self) -> None: + """Test that AnnotationRepository has encoding when instantiated.""" + self.assertTrue(hasattr(self.repo, "encoding")) + + def test_should_have_data_format_set(self) -> None: + """Test that AnnotationRepository has data_format when instantiated.""" + self.assertTrue(hasattr(self.repo, "data_format")) + + def test_should_have_folder_name_set(self) -> None: + """Test that AnnotationRepository has folder_name when instantiated.""" + self.assertTrue(hasattr(self.repo, "folder_name")) + + def test_object_name_invalid_job_id_raises_value_error(self) -> None: + """Test that _object_name() raises ValueError for invalid job_id.""" + with self.assertRaises(ValueError): + _ = self.repo._object_name(self.bad_job_id) # type: ignore + + def test_get_invalid_job_id_raises_value_error(self) -> None: + """Test that get() raises ValueError for invalid job_id.""" + with self.assertRaises(ValueError): + self.repo.get(self.bad_job_id) # type: ignore + + def test_get_data_that_cannot_be_converted_returns_none(self) -> None: + """Test that get() returns None if retrieved data cannot be converted to Annotation.""" + # Arrange + bad_data = b'{"not":"valid annotation data"}' + mock_buffer = MagicMock() + mock_buffer.read.return_value = bad_data + self.repo._get.return_value = mock_buffer # type: ignore[attr-defined] + # Act + result = self.repo.get(self.job_id) + # Assert + self.assertIsNone(result) + self.repo._get.assert_called_once_with( # type: ignore[attr-defined] + f"{self.repo.folder_name}/{self.job_id}.{self.repo.data_format}" + ) + + def test_put_invalid_job_id_raises_value_error(self) -> None: + """Test that put() raises ValueError for invalid job_id.""" + with self.assertRaises(ValueError): + self.repo.put(self.annotation, self.bad_job_id) # type: ignore + + def test_put_invalid_annotation_raises_value_error(self) -> None: + """Test that put() raises ValueError for invalid annotation.""" + with self.assertRaises(ValueError): + self.repo.put(self.bad_annotation, self.job_id) # type: ignore + + def test_delete_invalid_job_id_raises_value_error(self) -> None: + """Test that delete() raises ValueError for invalid job_id.""" + with self.assertRaises(ValueError): + self.repo.delete(self.bad_job_id) # type: ignore + + +# Allows local debugging by running file as script +if __name__ == "__main__": + unittest.main() diff --git a/tests/unit/test_image_repository.py b/tests/unit/test_image_repository.py new file mode 100644 index 0000000..01cc9c1 --- /dev/null +++ b/tests/unit/test_image_repository.py @@ -0,0 +1,98 @@ +"""Unit tests for ImageRepository class.""" + +import unittest +from unittest.mock import patch, MagicMock, _patch_dict +from uuid import UUID +from PIL import Image + +from data_store.repositories.image_repository import ImageRepository + + +class TestImageRepository(unittest.TestCase): + """Unit tests for ImageRepository class.""" + + patcher: _patch_dict + repo: ImageRepository + image: Image.Image + bad_image: str + image_id: UUID + bad_image_id: str + + @classmethod + def setUpClass(cls) -> None: + """Set up test case with a mocked MinioAdapter.""" + # Patch environment variables for MinioAdapter + cls.patcher = patch.dict( + "os.environ", + { + "MINIO_ENDPOINT": "localhost:9000", + "MINIO_ACCESS_KEY": "minioadmin", + "MINIO_SECRET_KEY": "minioadmin", + "MINIO_BUCKET": "test-bucket", + }, + ) + cls.patcher.start() + # Prepare ImageRepository with mocked MinioAdapter + cls.repo = ImageRepository() + cls.repo._get = MagicMock(return_value=None) # type: ignore[method-assign] + cls.repo._put = MagicMock(return_value=None) # type: ignore[method-assign] + cls.repo._delete = MagicMock(return_value=None) # type: ignore[method-assign] + # Prepare other test variables + cls.image = Image.new("RGB", (10, 10)) + cls.image_id = UUID("d87022f8-4169-4d69-8512-bbd65cc1cb23") + cls.bad_image = "not_an_image" + cls.bad_image_id = "not-a-uuid" + + @classmethod + def tearDownClass(cls) -> None: + # Stop patching + cls.patcher.stop() + + def setUp(self) -> None: + """Set up each test with a fresh ImageRepository instance.""" + self.repo._get.reset_mock() # type: ignore[attr-defined] + self.repo._put.reset_mock() # type: ignore[attr-defined] + self.repo._delete.reset_mock() # type: ignore[attr-defined] + + def test_should_adhere_to_interface(self) -> None: + """Test that ImageRepository adheres to ImageRepositoryInterface.""" + # Instantiation fails if interface not adhered to + _ = ImageRepository() + + def test_should_have_image_format_set(self) -> None: + """Test that ImageRepository has image_format set.""" + self.assertTrue(hasattr(self.repo, "image_format")) + + def test_should_have_folder_name_set(self) -> None: + """Test that ImageRepository has folder_name set.""" + self.assertTrue(hasattr(self.repo, "folder_name")) + + def test_object_name_invalid_image_id_raises_value_error(self) -> None: + """Test that _object_name() raises ValueError for invalid image_id.""" + with self.assertRaises(ValueError): + _ = self.repo._object_name(self.bad_image_id) # type: ignore + + def test_get_invalid_image_id_raises_value_error(self) -> None: + """Test getting an image with invalid image_id.""" + with self.assertRaises(ValueError): + self.repo.get(self.bad_image_id) # type: ignore + + def test_put_invalid_image_id_raises_value_error(self) -> None: + """Test putting an image with invalid image_id.""" + with self.assertRaises(ValueError): + self.repo.put(self.image, self.bad_image_id) # type: ignore + + def test_put_invalid_image_type_raises_value_error(self) -> None: + """Test putting an invalid image type.""" + with self.assertRaises(ValueError): + self.repo.put(self.bad_image, self.bad_image_id) # type: ignore + + def test_delete_invalid_image_id_raises_value_error(self) -> None: + """Test deleting an image with invalid image_id.""" + with self.assertRaises(ValueError): + self.repo.delete(self.bad_image_id) # type: ignore + + +# Allows local debugging by running file as script +if __name__ == "__main__": + unittest.main() diff --git a/tests/unit/test_job_repository.py b/tests/unit/test_job_repository.py new file mode 100644 index 0000000..9259ccf --- /dev/null +++ b/tests/unit/test_job_repository.py @@ -0,0 +1,85 @@ +"""Unit tests for JobRepository class.""" + +import unittest +from unittest.mock import patch, MagicMock, _patch_dict +from uuid import UUID + +from data_store.repositories.job_repository import JobRepository + + +class TestJobRepository(unittest.TestCase): + """Unit tests for JobRepository class.""" + + patcher: _patch_dict + repo: JobRepository + job_id: UUID + bad_job_id: str + + @classmethod + def setUpClass(cls) -> None: + """Set up test case with a mocked MinioAdapter.""" + # Patch environment variables for MinioAdapter + cls.patcher = patch.dict( + "os.environ", + { + "MINIO_ENDPOINT": "localhost:9000", + "MINIO_ACCESS_KEY": "minioadmin", + "MINIO_SECRET_KEY": "minioadmin", + "MINIO_BUCKET": "test-bucket", + }, + ) + cls.patcher.start() + # Prepare JobRepository + cls.repo = JobRepository() + cls.repo._get = MagicMock(return_value=None) # type: ignore[method-assign] + cls.repo._put = MagicMock(return_value=None) # type: ignore[method-assign] + cls.repo._delete = MagicMock(return_value=None) # type: ignore[method-assign] + # Prepare other test variables + cls.job_id = UUID("d87022f8-4169-4d69-8512-bbd65cc1cb23") + cls.bad_job_id = "not-a-uuid" + + @classmethod + def tearDownClass(cls) -> None: + # Stop patching + cls.patcher.stop() + + def setUp(self) -> None: + """Set up each test with a fresh JobRepository instance.""" + self.repo._get.reset_mock() # type: ignore[attr-defined] + self.repo._put.reset_mock() # type: ignore[attr-defined] + self.repo._delete.reset_mock() # type: ignore[attr-defined] + + def test_should_adhere_to_interface(self) -> None: + """Test that JobRepository adheres to JobRepositoryInterface.""" + # Instantiation fails if interface not adhered to + _ = JobRepository() + + def test_enter_calls_super_and_returns_self(self) -> None: + """Test that __enter__ calls super().__enter__() and returns self.""" + repo = JobRepository() + with patch( + "python_repositories.adapters.MinioAdapter.__enter__", return_value=None + ) as mock_super_enter: + result = repo.__enter__() + mock_super_enter.assert_called_once() + self.assertIs(result, repo) + + def test_get_invalid_job_id_raises_value_error(self) -> None: + """Test that get with invalid job_id raises ValueError.""" + with self.assertRaises(ValueError): + self.repo.get(self.bad_job_id) # type: ignore[arg-type] + + def test_put_invalid_job_raises_value_error(self) -> None: + """Test that put with invalid job raises ValueError.""" + with self.assertRaises(ValueError): + self.repo.put("not_a_job") # type: ignore[arg-type] + + def test_delete_invalid_job_id_raises_value_error(self) -> None: + """Test that delete with invalid job_id raises ValueError.""" + with self.assertRaises(ValueError): + self.repo.delete(self.bad_job_id) # type: ignore[arg-type] + + +# Allows local debugging by running file as script +if __name__ == "__main__": + unittest.main() diff --git a/uv.lock b/uv.lock new file mode 100644 index 0000000..1112153 --- /dev/null +++ b/uv.lock @@ -0,0 +1,1405 @@ +version = 1 +revision = 3 +requires-python = ">=3.12" +resolution-markers = [ + "python_full_version >= '3.14'", + "python_full_version < '3.14'", +] + +[[package]] +name = "annotated-types" +version = "0.7.0" +source = { registry = "http://10.0.0.2:5001/index/" } +sdist = { url = "http://10.0.0.2:5001/index/annotated-types/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89" } +wheels = [ + { url = "http://10.0.0.2:5001/index/annotated-types/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53" }, +] + +[[package]] +name = "argon2-cffi" +version = "25.1.0" +source = { registry = "http://10.0.0.2:5001/index/" } +dependencies = [ + { name = "argon2-cffi-bindings" }, +] +sdist = { url = "http://10.0.0.2:5001/index/argon2-cffi/argon2_cffi-25.1.0.tar.gz", hash = "sha256:694ae5cc8a42f4c4e2bf2ca0e64e51e23a040c6a517a85074683d3959e1346c1" } +wheels = [ + { url = "http://10.0.0.2:5001/index/argon2-cffi/argon2_cffi-25.1.0-py3-none-any.whl", hash = "sha256:fdc8b074db390fccb6eb4a3604ae7231f219aa669a2652e0f20e16ba513d5741" }, +] + +[[package]] +name = "argon2-cffi-bindings" +version = "25.1.0" +source = { registry = "http://10.0.0.2:5001/index/" } +dependencies = [ + { name = "cffi" }, +] +sdist = { url = "http://10.0.0.2:5001/index/argon2-cffi-bindings/argon2_cffi_bindings-25.1.0.tar.gz", hash = "sha256:b957f3e6ea4d55d820e40ff76f450952807013d361a65d7f28acc0acbf29229d" } +wheels = [ + { url = "http://10.0.0.2:5001/index/argon2-cffi-bindings/argon2_cffi_bindings-25.1.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:3d3f05610594151994ca9ccb3c771115bdb4daef161976a266f0dd8aa9996b8f" }, + { url = "http://10.0.0.2:5001/index/argon2-cffi-bindings/argon2_cffi_bindings-25.1.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:8b8efee945193e667a396cbc7b4fb7d357297d6234d30a489905d96caabde56b" }, + { url = "http://10.0.0.2:5001/index/argon2-cffi-bindings/argon2_cffi_bindings-25.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:3c6702abc36bf3ccba3f802b799505def420a1b7039862014a65db3205967f5a" }, + { url = "http://10.0.0.2:5001/index/argon2-cffi-bindings/argon2_cffi_bindings-25.1.0-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a1c70058c6ab1e352304ac7e3b52554daadacd8d453c1752e547c76e9c99ac44" }, + { url = "http://10.0.0.2:5001/index/argon2-cffi-bindings/argon2_cffi_bindings-25.1.0-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e2fd3bfbff3c5d74fef31a722f729bf93500910db650c925c2d6ef879a7e51cb" }, + { url = "http://10.0.0.2:5001/index/argon2-cffi-bindings/argon2_cffi_bindings-25.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c4f9665de60b1b0e99bcd6be4f17d90339698ce954cfd8d9cf4f91c995165a92" }, + { url = "http://10.0.0.2:5001/index/argon2-cffi-bindings/argon2_cffi_bindings-25.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ba92837e4a9aa6a508c8d2d7883ed5a8f6c308c89a4790e1e447a220deb79a85" }, + { url = "http://10.0.0.2:5001/index/argon2-cffi-bindings/argon2_cffi_bindings-25.1.0-cp314-cp314t-win32.whl", hash = "sha256:84a461d4d84ae1295871329b346a97f68eade8c53b6ed9a7ca2d7467f3c8ff6f" }, + { url = "http://10.0.0.2:5001/index/argon2-cffi-bindings/argon2_cffi_bindings-25.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b55aec3565b65f56455eebc9b9f34130440404f27fe21c3b375bf1ea4d8fbae6" }, + { url = "http://10.0.0.2:5001/index/argon2-cffi-bindings/argon2_cffi_bindings-25.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:87c33a52407e4c41f3b70a9c2d3f6056d88b10dad7695be708c5021673f55623" }, + { url = "http://10.0.0.2:5001/index/argon2-cffi-bindings/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:aecba1723ae35330a008418a91ea6cfcedf6d31e5fbaa056a166462ff066d500" }, + { url = "http://10.0.0.2:5001/index/argon2-cffi-bindings/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:2630b6240b495dfab90aebe159ff784d08ea999aa4b0d17efa734055a07d2f44" }, + { url = "http://10.0.0.2:5001/index/argon2-cffi-bindings/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:7aef0c91e2c0fbca6fc68e7555aa60ef7008a739cbe045541e438373bc54d2b0" }, + { url = "http://10.0.0.2:5001/index/argon2-cffi-bindings/argon2_cffi_bindings-25.1.0-cp39-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1e021e87faa76ae0d413b619fe2b65ab9a037f24c60a1e6cc43457ae20de6dc6" }, + { url = "http://10.0.0.2:5001/index/argon2-cffi-bindings/argon2_cffi_bindings-25.1.0-cp39-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d3e924cfc503018a714f94a49a149fdc0b644eaead5d1f089330399134fa028a" }, + { url = "http://10.0.0.2:5001/index/argon2-cffi-bindings/argon2_cffi_bindings-25.1.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c87b72589133f0346a1cb8d5ecca4b933e3c9b64656c9d175270a000e73b288d" }, + { url = "http://10.0.0.2:5001/index/argon2-cffi-bindings/argon2_cffi_bindings-25.1.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:1db89609c06afa1a214a69a462ea741cf735b29a57530478c06eb81dd403de99" }, + { url = "http://10.0.0.2:5001/index/argon2-cffi-bindings/argon2_cffi_bindings-25.1.0-cp39-abi3-win32.whl", hash = "sha256:473bcb5f82924b1becbb637b63303ec8d10e84c8d241119419897a26116515d2" }, + { url = "http://10.0.0.2:5001/index/argon2-cffi-bindings/argon2_cffi_bindings-25.1.0-cp39-abi3-win_amd64.whl", hash = "sha256:a98cd7d17e9f7ce244c0803cad3c23a7d379c301ba618a5fa76a67d116618b98" }, + { url = "http://10.0.0.2:5001/index/argon2-cffi-bindings/argon2_cffi_bindings-25.1.0-cp39-abi3-win_arm64.whl", hash = "sha256:b0fdbcf513833809c882823f98dc2f931cf659d9a1429616ac3adebb49f5db94" }, +] + +[[package]] +name = "authlib" +version = "1.6.3" +source = { registry = "http://10.0.0.2:5001/index/" } +dependencies = [ + { name = "cryptography" }, +] +sdist = { url = "http://10.0.0.2:5001/index/authlib/authlib-1.6.3.tar.gz", hash = "sha256:9f7a982cc395de719e4c2215c5707e7ea690ecf84f1ab126f28c053f4219e610" } +wheels = [ + { url = "http://10.0.0.2:5001/index/authlib/authlib-1.6.3-py2.py3-none-any.whl", hash = "sha256:7ea0f082edd95a03b7b72edac65ec7f8f68d703017d7e37573aee4fc603f2a48" }, +] + +[[package]] +name = "certifi" +version = "2025.8.3" +source = { registry = "http://10.0.0.2:5001/index/" } +sdist = { url = "http://10.0.0.2:5001/index/certifi/certifi-2025.8.3.tar.gz", hash = "sha256:e564105f78ded564e3ae7c923924435e1daa7463faeab5bb932bc53ffae63407" } +wheels = [ + { url = "http://10.0.0.2:5001/index/certifi/certifi-2025.8.3-py3-none-any.whl", hash = "sha256:f6c12493cfb1b06ba2ff328595af9350c65d6644968e5d3a2ffd78699af217a5" }, +] + +[[package]] +name = "cffi" +version = "2.0.0" +source = { registry = "http://10.0.0.2:5001/index/" } +dependencies = [ + { name = "pycparser", marker = "implementation_name != 'PyPy'" }, +] +sdist = { url = "http://10.0.0.2:5001/index/cffi/cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529" } +wheels = [ + { url = "http://10.0.0.2:5001/index/cffi/cffi-2.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6d02d6655b0e54f54c4ef0b94eb6be0607b70853c45ce98bd278dc7de718be5d" }, + { url = "http://10.0.0.2:5001/index/cffi/cffi-2.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8eca2a813c1cb7ad4fb74d368c2ffbbb4789d377ee5bb8df98373c2cc0dee76c" }, + { url = "http://10.0.0.2:5001/index/cffi/cffi-2.0.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:21d1152871b019407d8ac3985f6775c079416c282e431a4da6afe7aefd2bccbe" }, + { url = "http://10.0.0.2:5001/index/cffi/cffi-2.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b21e08af67b8a103c71a250401c78d5e0893beff75e28c53c98f4de42f774062" }, + { url = "http://10.0.0.2:5001/index/cffi/cffi-2.0.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:1e3a615586f05fc4065a8b22b8152f0c1b00cdbc60596d187c2a74f9e3036e4e" }, + { url = "http://10.0.0.2:5001/index/cffi/cffi-2.0.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:81afed14892743bbe14dacb9e36d9e0e504cd204e0b165062c488942b9718037" }, + { url = "http://10.0.0.2:5001/index/cffi/cffi-2.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3e17ed538242334bf70832644a32a7aae3d83b57567f9fd60a26257e992b79ba" }, + { url = "http://10.0.0.2:5001/index/cffi/cffi-2.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3925dd22fa2b7699ed2617149842d2e6adde22b262fcbfada50e3d195e4b3a94" }, + { url = "http://10.0.0.2:5001/index/cffi/cffi-2.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2c8f814d84194c9ea681642fd164267891702542f028a15fc97d4674b6206187" }, + { url = "http://10.0.0.2:5001/index/cffi/cffi-2.0.0-cp312-cp312-win32.whl", hash = "sha256:da902562c3e9c550df360bfa53c035b2f241fed6d9aef119048073680ace4a18" }, + { url = "http://10.0.0.2:5001/index/cffi/cffi-2.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:da68248800ad6320861f129cd9c1bf96ca849a2771a59e0344e88681905916f5" }, + { url = "http://10.0.0.2:5001/index/cffi/cffi-2.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:4671d9dd5ec934cb9a73e7ee9676f9362aba54f7f34910956b84d727b0d73fb6" }, + { url = "http://10.0.0.2:5001/index/cffi/cffi-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb" }, + { url = "http://10.0.0.2:5001/index/cffi/cffi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:45d5e886156860dc35862657e1494b9bae8dfa63bf56796f2fb56e1679fc0bca" }, + { url = "http://10.0.0.2:5001/index/cffi/cffi-2.0.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b" }, + { url = "http://10.0.0.2:5001/index/cffi/cffi-2.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d48a880098c96020b02d5a1f7d9251308510ce8858940e6fa99ece33f610838b" }, + { url = "http://10.0.0.2:5001/index/cffi/cffi-2.0.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f93fd8e5c8c0a4aa1f424d6173f14a892044054871c771f8566e4008eaa359d2" }, + { url = "http://10.0.0.2:5001/index/cffi/cffi-2.0.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:dd4f05f54a52fb558f1ba9f528228066954fee3ebe629fc1660d874d040ae5a3" }, + { url = "http://10.0.0.2:5001/index/cffi/cffi-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26" }, + { url = "http://10.0.0.2:5001/index/cffi/cffi-2.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d9b29c1f0ae438d5ee9acb31cadee00a58c46cc9c0b2f9038c6b0b3470877a8c" }, + { url = "http://10.0.0.2:5001/index/cffi/cffi-2.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6d50360be4546678fc1b79ffe7a66265e28667840010348dd69a314145807a1b" }, + { url = "http://10.0.0.2:5001/index/cffi/cffi-2.0.0-cp313-cp313-win32.whl", hash = "sha256:74a03b9698e198d47562765773b4a8309919089150a0bb17d829ad7b44b60d27" }, + { url = "http://10.0.0.2:5001/index/cffi/cffi-2.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:19f705ada2530c1167abacb171925dd886168931e0a7b78f5bffcae5c6b5be75" }, + { url = "http://10.0.0.2:5001/index/cffi/cffi-2.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:256f80b80ca3853f90c21b23ee78cd008713787b1b1e93eae9f3d6a7134abd91" }, + { url = "http://10.0.0.2:5001/index/cffi/cffi-2.0.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fc33c5141b55ed366cfaad382df24fe7dcbc686de5be719b207bb248e3053dc5" }, + { url = "http://10.0.0.2:5001/index/cffi/cffi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c654de545946e0db659b3400168c9ad31b5d29593291482c43e3564effbcee13" }, + { url = "http://10.0.0.2:5001/index/cffi/cffi-2.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:24b6f81f1983e6df8db3adc38562c83f7d4a0c36162885ec7f7b77c7dcbec97b" }, + { url = "http://10.0.0.2:5001/index/cffi/cffi-2.0.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:12873ca6cb9b0f0d3a0da705d6086fe911591737a59f28b7936bdfed27c0d47c" }, + { url = "http://10.0.0.2:5001/index/cffi/cffi-2.0.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:d9b97165e8aed9272a6bb17c01e3cc5871a594a446ebedc996e2397a1c1ea8ef" }, + { url = "http://10.0.0.2:5001/index/cffi/cffi-2.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:afb8db5439b81cf9c9d0c80404b60c3cc9c3add93e114dcae767f1477cb53775" }, + { url = "http://10.0.0.2:5001/index/cffi/cffi-2.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:737fe7d37e1a1bffe70bd5754ea763a62a066dc5913ca57e957824b72a85e205" }, + { url = "http://10.0.0.2:5001/index/cffi/cffi-2.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:38100abb9d1b1435bc4cc340bb4489635dc2f0da7456590877030c9b3d40b0c1" }, + { url = "http://10.0.0.2:5001/index/cffi/cffi-2.0.0-cp314-cp314-win32.whl", hash = "sha256:087067fa8953339c723661eda6b54bc98c5625757ea62e95eb4898ad5e776e9f" }, + { url = "http://10.0.0.2:5001/index/cffi/cffi-2.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:203a48d1fb583fc7d78a4c6655692963b860a417c0528492a6bc21f1aaefab25" }, + { url = "http://10.0.0.2:5001/index/cffi/cffi-2.0.0-cp314-cp314-win_arm64.whl", hash = "sha256:dbd5c7a25a7cb98f5ca55d258b103a2054f859a46ae11aaf23134f9cc0d356ad" }, + { url = "http://10.0.0.2:5001/index/cffi/cffi-2.0.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:9a67fc9e8eb39039280526379fb3a70023d77caec1852002b4da7e8b270c4dd9" }, + { url = "http://10.0.0.2:5001/index/cffi/cffi-2.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7a66c7204d8869299919db4d5069a82f1561581af12b11b3c9f48c584eb8743d" }, + { url = "http://10.0.0.2:5001/index/cffi/cffi-2.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7cc09976e8b56f8cebd752f7113ad07752461f48a58cbba644139015ac24954c" }, + { url = "http://10.0.0.2:5001/index/cffi/cffi-2.0.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:92b68146a71df78564e4ef48af17551a5ddd142e5190cdf2c5624d0c3ff5b2e8" }, + { url = "http://10.0.0.2:5001/index/cffi/cffi-2.0.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:b1e74d11748e7e98e2f426ab176d4ed720a64412b6a15054378afdb71e0f37dc" }, + { url = "http://10.0.0.2:5001/index/cffi/cffi-2.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:28a3a209b96630bca57cce802da70c266eb08c6e97e5afd61a75611ee6c64592" }, + { url = "http://10.0.0.2:5001/index/cffi/cffi-2.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7553fb2090d71822f02c629afe6042c299edf91ba1bf94951165613553984512" }, + { url = "http://10.0.0.2:5001/index/cffi/cffi-2.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6c6c373cfc5c83a975506110d17457138c8c63016b563cc9ed6e056a82f13ce4" }, + { url = "http://10.0.0.2:5001/index/cffi/cffi-2.0.0-cp314-cp314t-win32.whl", hash = "sha256:1fc9ea04857caf665289b7a75923f2c6ed559b8298a1b8c49e59f7dd95c8481e" }, + { url = "http://10.0.0.2:5001/index/cffi/cffi-2.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:d68b6cef7827e8641e8ef16f4494edda8b36104d79773a334beaa1e3521430f6" }, + { url = "http://10.0.0.2:5001/index/cffi/cffi-2.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0a1527a803f0a659de1af2e1fd700213caba79377e27e4693648c2923da066f9" }, +] + +[[package]] +name = "cfgv" +version = "3.4.0" +source = { registry = "http://10.0.0.2:5001/index/" } +sdist = { url = "http://10.0.0.2:5001/index/cfgv/cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560" } +wheels = [ + { url = "http://10.0.0.2:5001/index/cfgv/cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9" }, +] + +[[package]] +name = "charset-normalizer" +version = "3.4.3" +source = { registry = "http://10.0.0.2:5001/index/" } +sdist = { url = "http://10.0.0.2:5001/index/charset-normalizer/charset_normalizer-3.4.3.tar.gz", hash = "sha256:6fce4b8500244f6fcb71465d4a4930d132ba9ab8e71a7859e6a5d59851068d14" } +wheels = [ + { url = "http://10.0.0.2:5001/index/charset-normalizer/charset_normalizer-3.4.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e28e334d3ff134e88989d90ba04b47d84382a828c061d0d1027b1b12a62b39b1" }, + { url = "http://10.0.0.2:5001/index/charset-normalizer/charset_normalizer-3.4.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0cacf8f7297b0c4fcb74227692ca46b4a5852f8f4f24b3c766dd94a1075c4884" }, + { url = "http://10.0.0.2:5001/index/charset-normalizer/charset_normalizer-3.4.3-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c6fd51128a41297f5409deab284fecbe5305ebd7e5a1f959bee1c054622b7018" }, + { url = "http://10.0.0.2:5001/index/charset-normalizer/charset_normalizer-3.4.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3cfb2aad70f2c6debfbcb717f23b7eb55febc0bb23dcffc0f076009da10c6392" }, + { url = "http://10.0.0.2:5001/index/charset-normalizer/charset_normalizer-3.4.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1606f4a55c0fd363d754049cdf400175ee96c992b1f8018b993941f221221c5f" }, + { url = "http://10.0.0.2:5001/index/charset-normalizer/charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:027b776c26d38b7f15b26a5da1044f376455fb3766df8fc38563b4efbc515154" }, + { url = "http://10.0.0.2:5001/index/charset-normalizer/charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:42e5088973e56e31e4fa58eb6bd709e42fc03799c11c42929592889a2e54c491" }, + { url = "http://10.0.0.2:5001/index/charset-normalizer/charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:cc34f233c9e71701040d772aa7490318673aa7164a0efe3172b2981218c26d93" }, + { url = "http://10.0.0.2:5001/index/charset-normalizer/charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:320e8e66157cc4e247d9ddca8e21f427efc7a04bbd0ac8a9faf56583fa543f9f" }, + { url = "http://10.0.0.2:5001/index/charset-normalizer/charset_normalizer-3.4.3-cp312-cp312-win32.whl", hash = "sha256:fb6fecfd65564f208cbf0fba07f107fb661bcd1a7c389edbced3f7a493f70e37" }, + { url = "http://10.0.0.2:5001/index/charset-normalizer/charset_normalizer-3.4.3-cp312-cp312-win_amd64.whl", hash = "sha256:86df271bf921c2ee3818f0522e9a5b8092ca2ad8b065ece5d7d9d0e9f4849bcc" }, + { url = "http://10.0.0.2:5001/index/charset-normalizer/charset_normalizer-3.4.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:14c2a87c65b351109f6abfc424cab3927b3bdece6f706e4d12faaf3d52ee5efe" }, + { url = "http://10.0.0.2:5001/index/charset-normalizer/charset_normalizer-3.4.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:41d1fc408ff5fdfb910200ec0e74abc40387bccb3252f3f27c0676731df2b2c8" }, + { url = "http://10.0.0.2:5001/index/charset-normalizer/charset_normalizer-3.4.3-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1bb60174149316da1c35fa5233681f7c0f9f514509b8e399ab70fea5f17e45c9" }, + { url = "http://10.0.0.2:5001/index/charset-normalizer/charset_normalizer-3.4.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:30d006f98569de3459c2fc1f2acde170b7b2bd265dc1943e87e1a4efe1b67c31" }, + { url = "http://10.0.0.2:5001/index/charset-normalizer/charset_normalizer-3.4.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:416175faf02e4b0810f1f38bcb54682878a4af94059a1cd63b8747244420801f" }, + { url = "http://10.0.0.2:5001/index/charset-normalizer/charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6aab0f181c486f973bc7262a97f5aca3ee7e1437011ef0c2ec04b5a11d16c927" }, + { url = "http://10.0.0.2:5001/index/charset-normalizer/charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:fdabf8315679312cfa71302f9bd509ded4f2f263fb5b765cf1433b39106c3cc9" }, + { url = "http://10.0.0.2:5001/index/charset-normalizer/charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:bd28b817ea8c70215401f657edef3a8aa83c29d447fb0b622c35403780ba11d5" }, + { url = "http://10.0.0.2:5001/index/charset-normalizer/charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:18343b2d246dc6761a249ba1fb13f9ee9a2bcd95decc767319506056ea4ad4dc" }, + { url = "http://10.0.0.2:5001/index/charset-normalizer/charset_normalizer-3.4.3-cp313-cp313-win32.whl", hash = "sha256:6fb70de56f1859a3f71261cbe41005f56a7842cc348d3aeb26237560bfa5e0ce" }, + { url = "http://10.0.0.2:5001/index/charset-normalizer/charset_normalizer-3.4.3-cp313-cp313-win_amd64.whl", hash = "sha256:cf1ebb7d78e1ad8ec2a8c4732c7be2e736f6e5123a4146c5b89c9d1f585f8cef" }, + { url = "http://10.0.0.2:5001/index/charset-normalizer/charset_normalizer-3.4.3-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:3cd35b7e8aedeb9e34c41385fda4f73ba609e561faedfae0a9e75e44ac558a15" }, + { url = "http://10.0.0.2:5001/index/charset-normalizer/charset_normalizer-3.4.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b89bc04de1d83006373429975f8ef9e7932534b8cc9ca582e4db7d20d91816db" }, + { url = "http://10.0.0.2:5001/index/charset-normalizer/charset_normalizer-3.4.3-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2001a39612b241dae17b4687898843f254f8748b796a2e16f1051a17078d991d" }, + { url = "http://10.0.0.2:5001/index/charset-normalizer/charset_normalizer-3.4.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8dcfc373f888e4fb39a7bc57e93e3b845e7f462dacc008d9749568b1c4ece096" }, + { url = "http://10.0.0.2:5001/index/charset-normalizer/charset_normalizer-3.4.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:18b97b8404387b96cdbd30ad660f6407799126d26a39ca65729162fd810a99aa" }, + { url = "http://10.0.0.2:5001/index/charset-normalizer/charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ccf600859c183d70eb47e05a44cd80a4ce77394d1ac0f79dbd2dd90a69a3a049" }, + { url = "http://10.0.0.2:5001/index/charset-normalizer/charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:53cd68b185d98dde4ad8990e56a58dea83a4162161b1ea9272e5c9182ce415e0" }, + { url = "http://10.0.0.2:5001/index/charset-normalizer/charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:30a96e1e1f865f78b030d65241c1ee850cdf422d869e9028e2fc1d5e4db73b92" }, + { url = "http://10.0.0.2:5001/index/charset-normalizer/charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d716a916938e03231e86e43782ca7878fb602a125a91e7acb8b5112e2e96ac16" }, + { url = "http://10.0.0.2:5001/index/charset-normalizer/charset_normalizer-3.4.3-cp314-cp314-win32.whl", hash = "sha256:c6dbd0ccdda3a2ba7c2ecd9d77b37f3b5831687d8dc1b6ca5f56a4880cc7b7ce" }, + { url = "http://10.0.0.2:5001/index/charset-normalizer/charset_normalizer-3.4.3-cp314-cp314-win_amd64.whl", hash = "sha256:73dc19b562516fc9bcf6e5d6e596df0b4eb98d87e4f79f3ae71840e6ed21361c" }, + { url = "http://10.0.0.2:5001/index/charset-normalizer/charset_normalizer-3.4.3-py3-none-any.whl", hash = "sha256:ce571ab16d890d23b5c278547ba694193a45011ff86a9162a71307ed9f86759a" }, +] + +[[package]] +name = "click" +version = "8.2.1" +source = { registry = "http://10.0.0.2:5001/index/" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "http://10.0.0.2:5001/index/click/click-8.2.1.tar.gz", hash = "sha256:27c491cc05d968d271d5a1db13e3b5a184636d9d930f148c50b038f0d0646202" } +wheels = [ + { url = "http://10.0.0.2:5001/index/click/click-8.2.1-py3-none-any.whl", hash = "sha256:61a3265b914e850b85317d0b3109c7f8cd35a670f963866005d6ef1d5175a12b" }, +] + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "http://10.0.0.2:5001/index/" } +sdist = { url = "http://10.0.0.2:5001/index/colorama/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44" } +wheels = [ + { url = "http://10.0.0.2:5001/index/colorama/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6" }, +] + +[[package]] +name = "coverage" +version = "7.10.6" +source = { registry = "http://10.0.0.2:5001/index/" } +sdist = { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6.tar.gz", hash = "sha256:f644a3ae5933a552a29dbb9aa2f90c677a875f80ebea028e5a52a4f429044b90" } +wheels = [ + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:5b2dd6059938063a2c9fee1af729d4f2af28fd1a545e9b7652861f0d752ebcea" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:388d80e56191bf846c485c14ae2bc8898aa3124d9d35903fef7d907780477634" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:90cb5b1a4670662719591aa92d0095bb41714970c0b065b02a2610172dbf0af6" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:961834e2f2b863a0e14260a9a273aff07ff7818ab6e66d2addf5628590c628f9" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bf9a19f5012dab774628491659646335b1928cfc931bf8d97b0d5918dd58033c" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:99c4283e2a0e147b9c9cc6bc9c96124de9419d6044837e9799763a0e29a7321a" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:282b1b20f45df57cc508c1e033403f02283adfb67d4c9c35a90281d81e5c52c5" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8cdbe264f11afd69841bd8c0d83ca10b5b32853263ee62e6ac6a0ab63895f972" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp312-cp312-win32.whl", hash = "sha256:a517feaf3a0a3eca1ee985d8373135cfdedfbba3882a5eab4362bda7c7cf518d" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp312-cp312-win_amd64.whl", hash = "sha256:856986eadf41f52b214176d894a7de05331117f6035a28ac0016c0f63d887629" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp312-cp312-win_arm64.whl", hash = "sha256:acf36b8268785aad739443fa2780c16260ee3fa09d12b3a70f772ef100939d80" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ffea0575345e9ee0144dfe5701aa17f3ba546f8c3bb48db62ae101afb740e7d6" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:95d91d7317cde40a1c249d6b7382750b7e6d86fad9d8eaf4fa3f8f44cf171e80" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3e23dd5408fe71a356b41baa82892772a4cefcf758f2ca3383d2aa39e1b7a003" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:0f3f56e4cb573755e96a16501a98bf211f100463d70275759e73f3cbc00d4f27" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:db4a1d897bbbe7339946ffa2fe60c10cc81c43fab8b062d3fcb84188688174a4" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d8fd7879082953c156d5b13c74aa6cca37f6a6f4747b39538504c3f9c63d043d" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:28395ca3f71cd103b8c116333fa9db867f3a3e1ad6a084aa3725ae002b6583bc" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:61c950fc33d29c91b9e18540e1aed7d9f6787cc870a3e4032493bbbe641d12fc" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp313-cp313-win32.whl", hash = "sha256:160c00a5e6b6bdf4e5984b0ef21fc860bc94416c41b7df4d63f536d17c38902e" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp313-cp313-win_amd64.whl", hash = "sha256:628055297f3e2aa181464c3808402887643405573eb3d9de060d81531fa79d32" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp313-cp313-win_arm64.whl", hash = "sha256:df4ec1f8540b0bcbe26ca7dd0f541847cc8a108b35596f9f91f59f0c060bfdd2" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:c9a8b7a34a4de3ed987f636f71881cd3b8339f61118b1aa311fbda12741bff0b" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:8dd5af36092430c2b075cee966719898f2ae87b636cefb85a653f1d0ba5d5393" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:b0353b0f0850d49ada66fdd7d0c7cdb0f86b900bb9e367024fd14a60cecc1e27" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:d6b9ae13d5d3e8aeca9ca94198aa7b3ebbc5acfada557d724f2a1f03d2c0b0df" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:675824a363cc05781b1527b39dc2587b8984965834a748177ee3c37b64ffeafb" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:692d70ea725f471a547c305f0d0fc6a73480c62fb0da726370c088ab21aed282" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:851430a9a361c7a8484a36126d1d0ff8d529d97385eacc8dfdc9bfc8c2d2cbe4" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:d9369a23186d189b2fc95cc08b8160ba242057e887d766864f7adf3c46b2df21" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp313-cp313t-win32.whl", hash = "sha256:92be86fcb125e9bda0da7806afd29a3fd33fdf58fba5d60318399adf40bf37d0" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp313-cp313t-win_amd64.whl", hash = "sha256:6b3039e2ca459a70c79523d39347d83b73f2f06af5624905eba7ec34d64d80b5" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp313-cp313t-win_arm64.whl", hash = "sha256:3fb99d0786fe17b228eab663d16bee2288e8724d26a199c29325aac4b0319b9b" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:6008a021907be8c4c02f37cdc3ffb258493bdebfeaf9a839f9e71dfdc47b018e" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:5e75e37f23eb144e78940b40395b42f2321951206a4f50e23cfd6e8a198d3ceb" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:0f7cb359a448e043c576f0da00aa8bfd796a01b06aa610ca453d4dde09cc1034" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:c68018e4fc4e14b5668f1353b41ccf4bc83ba355f0e1b3836861c6f042d89ac1" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cd4b2b0707fc55afa160cd5fc33b27ccbf75ca11d81f4ec9863d5793fc6df56a" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:4cec13817a651f8804a86e4f79d815b3b28472c910e099e4d5a0e8a3b6a1d4cb" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:f2a6a8e06bbda06f78739f40bfb56c45d14eb8249d0f0ea6d4b3d48e1f7c695d" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:081b98395ced0d9bcf60ada7661a0b75f36b78b9d7e39ea0790bb4ed8da14747" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp314-cp314-win32.whl", hash = "sha256:6937347c5d7d069ee776b2bf4e1212f912a9f1f141a429c475e6089462fcecc5" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp314-cp314-win_amd64.whl", hash = "sha256:adec1d980fa07e60b6ef865f9e5410ba760e4e1d26f60f7e5772c73b9a5b0713" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp314-cp314-win_arm64.whl", hash = "sha256:a80f7aef9535442bdcf562e5a0d5a5538ce8abe6bb209cfbf170c462ac2c2a32" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:0de434f4fbbe5af4fa7989521c655c8c779afb61c53ab561b64dcee6149e4c65" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6e31b8155150c57e5ac43ccd289d079eb3f825187d7c66e755a055d2c85794c6" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:98cede73eb83c31e2118ae8d379c12e3e42736903a8afcca92a7218e1f2903b0" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f863c08f4ff6b64fa8045b1e3da480f5374779ef187f07b82e0538c68cb4ff8e" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2b38261034fda87be356f2c3f42221fdb4171c3ce7658066ae449241485390d5" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:0e93b1476b79eae849dc3872faeb0bf7948fd9ea34869590bc16a2a00b9c82a7" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:ff8a991f70f4c0cf53088abf1e3886edcc87d53004c7bb94e78650b4d3dac3b5" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ac765b026c9f33044419cbba1da913cfb82cca1b60598ac1c7a5ed6aac4621a0" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp314-cp314t-win32.whl", hash = "sha256:441c357d55f4936875636ef2cfb3bee36e466dcf50df9afbd398ce79dba1ebb7" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp314-cp314t-win_amd64.whl", hash = "sha256:073711de3181b2e204e4870ac83a7c4853115b42e9cd4d145f2231e12d670930" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-cp314-cp314t-win_arm64.whl", hash = "sha256:137921f2bac5559334ba66122b753db6dc5d1cf01eb7b64eb412bb0d064ef35b" }, + { url = "http://10.0.0.2:5001/index/coverage/coverage-7.10.6-py3-none-any.whl", hash = "sha256:92c4ecf6bf11b2e85fd4d8204814dc26e6a19f0c9d938c207c5cb0eadfcabbe3" }, +] + +[[package]] +name = "cryptography" +version = "46.0.1" +source = { registry = "http://10.0.0.2:5001/index/" } +dependencies = [ + { name = "cffi", marker = "platform_python_implementation != 'PyPy'" }, +] +sdist = { url = "http://10.0.0.2:5001/index/cryptography/cryptography-46.0.1.tar.gz", hash = "sha256:ed570874e88f213437f5cf758f9ef26cbfc3f336d889b1e592ee11283bb8d1c7" } +wheels = [ + { url = "http://10.0.0.2:5001/index/cryptography/cryptography-46.0.1-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:1cd6d50c1a8b79af1a6f703709d8973845f677c8e97b1268f5ff323d38ce8475" }, + { url = "http://10.0.0.2:5001/index/cryptography/cryptography-46.0.1-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0ff483716be32690c14636e54a1f6e2e1b7bf8e22ca50b989f88fa1b2d287080" }, + { url = "http://10.0.0.2:5001/index/cryptography/cryptography-46.0.1-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:9873bf7c1f2a6330bdfe8621e7ce64b725784f9f0c3a6a55c3047af5849f920e" }, + { url = "http://10.0.0.2:5001/index/cryptography/cryptography-46.0.1-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:0dfb7c88d4462a0cfdd0d87a3c245a7bc3feb59de101f6ff88194f740f72eda6" }, + { url = "http://10.0.0.2:5001/index/cryptography/cryptography-46.0.1-cp311-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e22801b61613ebdebf7deb18b507919e107547a1d39a3b57f5f855032dd7cfb8" }, + { url = "http://10.0.0.2:5001/index/cryptography/cryptography-46.0.1-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:757af4f6341ce7a1e47c326ca2a81f41d236070217e5fbbad61bbfe299d55d28" }, + { url = "http://10.0.0.2:5001/index/cryptography/cryptography-46.0.1-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:f7a24ea78de345cfa7f6a8d3bde8b242c7fac27f2bd78fa23474ca38dfaeeab9" }, + { url = "http://10.0.0.2:5001/index/cryptography/cryptography-46.0.1-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:9e8776dac9e660c22241b6587fae51a67b4b0147daa4d176b172c3ff768ad736" }, + { url = "http://10.0.0.2:5001/index/cryptography/cryptography-46.0.1-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:9f40642a140c0c8649987027867242b801486865277cbabc8c6059ddef16dc8b" }, + { url = "http://10.0.0.2:5001/index/cryptography/cryptography-46.0.1-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:449ef2b321bec7d97ef2c944173275ebdab78f3abdd005400cc409e27cd159ab" }, + { url = "http://10.0.0.2:5001/index/cryptography/cryptography-46.0.1-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2dd339ba3345b908fa3141ddba4025568fa6fd398eabce3ef72a29ac2d73ad75" }, + { url = "http://10.0.0.2:5001/index/cryptography/cryptography-46.0.1-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:7411c910fb2a412053cf33cfad0153ee20d27e256c6c3f14d7d7d1d9fec59fd5" }, + { url = "http://10.0.0.2:5001/index/cryptography/cryptography-46.0.1-cp311-abi3-win32.whl", hash = "sha256:cbb8e769d4cac884bb28e3ff620ef1001b75588a5c83c9c9f1fdc9afbe7f29b0" }, + { url = "http://10.0.0.2:5001/index/cryptography/cryptography-46.0.1-cp311-abi3-win_amd64.whl", hash = "sha256:92e8cfe8bd7dd86eac0a677499894862cd5cc2fd74de917daa881d00871ac8e7" }, + { url = "http://10.0.0.2:5001/index/cryptography/cryptography-46.0.1-cp311-abi3-win_arm64.whl", hash = "sha256:db5597a4c7353b2e5fb05a8e6cb74b56a4658a2b7bf3cb6b1821ae7e7fd6eaa0" }, + { url = "http://10.0.0.2:5001/index/cryptography/cryptography-46.0.1-cp314-cp314t-macosx_10_9_universal2.whl", hash = "sha256:4c49eda9a23019e11d32a0eb51a27b3e7ddedde91e099c0ac6373e3aacc0d2ee" }, + { url = "http://10.0.0.2:5001/index/cryptography/cryptography-46.0.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:9babb7818fdd71394e576cf26c5452df77a355eac1a27ddfa24096665a27f8fd" }, + { url = "http://10.0.0.2:5001/index/cryptography/cryptography-46.0.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:9f2c4cc63be3ef43c0221861177cee5d14b505cd4d4599a89e2cd273c4d3542a" }, + { url = "http://10.0.0.2:5001/index/cryptography/cryptography-46.0.1-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:41c281a74df173876da1dc9a9b6953d387f06e3d3ed9284e3baae3ab3f40883a" }, + { url = "http://10.0.0.2:5001/index/cryptography/cryptography-46.0.1-cp314-cp314t-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:0a17377fa52563d730248ba1f68185461fff36e8bc75d8787a7dd2e20a802b7a" }, + { url = "http://10.0.0.2:5001/index/cryptography/cryptography-46.0.1-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:0d1922d9280e08cde90b518a10cd66831f632960a8d08cb3418922d83fce6f12" }, + { url = "http://10.0.0.2:5001/index/cryptography/cryptography-46.0.1-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:af84e8e99f1a82cea149e253014ea9dc89f75b82c87bb6c7242203186f465129" }, + { url = "http://10.0.0.2:5001/index/cryptography/cryptography-46.0.1-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:ef648d2c690703501714588b2ba640facd50fd16548133b11b2859e8655a69da" }, + { url = "http://10.0.0.2:5001/index/cryptography/cryptography-46.0.1-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:e94eb5fa32a8a9f9bf991f424f002913e3dd7c699ef552db9b14ba6a76a6313b" }, + { url = "http://10.0.0.2:5001/index/cryptography/cryptography-46.0.1-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:534b96c0831855e29fc3b069b085fd185aa5353033631a585d5cd4dd5d40d657" }, + { url = "http://10.0.0.2:5001/index/cryptography/cryptography-46.0.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:f9b55038b5c6c47559aa33626d8ecd092f354e23de3c6975e4bb205df128a2a0" }, + { url = "http://10.0.0.2:5001/index/cryptography/cryptography-46.0.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ec13b7105117dbc9afd023300fb9954d72ca855c274fe563e72428ece10191c0" }, + { url = "http://10.0.0.2:5001/index/cryptography/cryptography-46.0.1-cp314-cp314t-win32.whl", hash = "sha256:504e464944f2c003a0785b81668fe23c06f3b037e9cb9f68a7c672246319f277" }, + { url = "http://10.0.0.2:5001/index/cryptography/cryptography-46.0.1-cp314-cp314t-win_amd64.whl", hash = "sha256:c52fded6383f7e20eaf70a60aeddd796b3677c3ad2922c801be330db62778e05" }, + { url = "http://10.0.0.2:5001/index/cryptography/cryptography-46.0.1-cp314-cp314t-win_arm64.whl", hash = "sha256:9495d78f52c804b5ec8878b5b8c7873aa8e63db9cd9ee387ff2db3fffe4df784" }, + { url = "http://10.0.0.2:5001/index/cryptography/cryptography-46.0.1-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:d84c40bdb8674c29fa192373498b6cb1e84f882889d21a471b45d1f868d8d44b" }, + { url = "http://10.0.0.2:5001/index/cryptography/cryptography-46.0.1-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:9ed64e5083fa806709e74fc5ea067dfef9090e5b7a2320a49be3c9df3583a2d8" }, + { url = "http://10.0.0.2:5001/index/cryptography/cryptography-46.0.1-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:341fb7a26bc9d6093c1b124b9f13acc283d2d51da440b98b55ab3f79f2522ead" }, + { url = "http://10.0.0.2:5001/index/cryptography/cryptography-46.0.1-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:6ef1488967e729948d424d09c94753d0167ce59afba8d0f6c07a22b629c557b2" }, + { url = "http://10.0.0.2:5001/index/cryptography/cryptography-46.0.1-cp38-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:7823bc7cdf0b747ecfb096d004cc41573c2f5c7e3a29861603a2871b43d3ef32" }, + { url = "http://10.0.0.2:5001/index/cryptography/cryptography-46.0.1-cp38-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:f736ab8036796f5a119ff8211deda416f8c15ce03776db704a7a4e17381cb2ef" }, + { url = "http://10.0.0.2:5001/index/cryptography/cryptography-46.0.1-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:e46710a240a41d594953012213ea8ca398cd2448fbc5d0f1be8160b5511104a0" }, + { url = "http://10.0.0.2:5001/index/cryptography/cryptography-46.0.1-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:84ef1f145de5aee82ea2447224dc23f065ff4cc5791bb3b506615957a6ba8128" }, + { url = "http://10.0.0.2:5001/index/cryptography/cryptography-46.0.1-cp38-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:9394c7d5a7565ac5f7d9ba38b2617448eba384d7b107b262d63890079fad77ca" }, + { url = "http://10.0.0.2:5001/index/cryptography/cryptography-46.0.1-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:ed957044e368ed295257ae3d212b95456bd9756df490e1ac4538857f67531fcc" }, + { url = "http://10.0.0.2:5001/index/cryptography/cryptography-46.0.1-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:f7de12fa0eee6234de9a9ce0ffcfa6ce97361db7a50b09b65c63ac58e5f22fc7" }, + { url = "http://10.0.0.2:5001/index/cryptography/cryptography-46.0.1-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:7fab1187b6c6b2f11a326f33b036f7168f5b996aedd0c059f9738915e4e8f53a" }, + { url = "http://10.0.0.2:5001/index/cryptography/cryptography-46.0.1-cp38-abi3-win32.whl", hash = "sha256:45f790934ac1018adeba46a0f7289b2b8fe76ba774a88c7f1922213a56c98bc1" }, + { url = "http://10.0.0.2:5001/index/cryptography/cryptography-46.0.1-cp38-abi3-win_amd64.whl", hash = "sha256:7176a5ab56fac98d706921f6416a05e5aff7df0e4b91516f450f8627cda22af3" }, + { url = "http://10.0.0.2:5001/index/cryptography/cryptography-46.0.1-cp38-abi3-win_arm64.whl", hash = "sha256:efc9e51c3e595267ff84adf56e9b357db89ab2279d7e375ffcaf8f678606f3d9" }, +] + +[[package]] +name = "distlib" +version = "0.4.0" +source = { registry = "http://10.0.0.2:5001/index/" } +sdist = { url = "http://10.0.0.2:5001/index/distlib/distlib-0.4.0.tar.gz", hash = "sha256:feec40075be03a04501a973d81f633735b4b69f98b05450592310c0f401a4e0d" } +wheels = [ + { url = "http://10.0.0.2:5001/index/distlib/distlib-0.4.0-py2.py3-none-any.whl", hash = "sha256:9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16" }, +] + +[[package]] +name = "docker" +version = "7.1.0" +source = { registry = "http://10.0.0.2:5001/index/" } +dependencies = [ + { name = "pywin32", marker = "sys_platform == 'win32'" }, + { name = "requests" }, + { name = "urllib3" }, +] +sdist = { url = "http://10.0.0.2:5001/index/docker/docker-7.1.0.tar.gz", hash = "sha256:ad8c70e6e3f8926cb8a92619b832b4ea5299e2831c14284663184e200546fa6c" } +wheels = [ + { url = "http://10.0.0.2:5001/index/docker/docker-7.1.0-py3-none-any.whl", hash = "sha256:c96b93b7f0a746f9e77d325bcfb87422a3d8bd4f03136ae8a85b37f1898d5fc0" }, +] + +[[package]] +name = "dparse" +version = "0.6.4" +source = { registry = "http://10.0.0.2:5001/index/" } +dependencies = [ + { name = "packaging" }, +] +sdist = { url = "http://10.0.0.2:5001/index/dparse/dparse-0.6.4.tar.gz", hash = "sha256:90b29c39e3edc36c6284c82c4132648eaf28a01863eb3c231c2512196132201a" } +wheels = [ + { url = "http://10.0.0.2:5001/index/dparse/dparse-0.6.4-py3-none-any.whl", hash = "sha256:fbab4d50d54d0e739fbb4dedfc3d92771003a5b9aa8545ca7a7045e3b174af57" }, +] + +[[package]] +name = "filelock" +version = "3.12.4" +source = { registry = "http://10.0.0.2:5001/index/" } +sdist = { url = "http://10.0.0.2:5001/index/filelock/filelock-3.12.4.tar.gz", hash = "sha256:2e6f249f1f3654291606e046b09f1fd5eac39b360664c27f5aad072012f8bcbd" } +wheels = [ + { url = "http://10.0.0.2:5001/index/filelock/filelock-3.12.4-py3-none-any.whl", hash = "sha256:08c21d87ded6e2b9da6728c3dff51baf1dcecf973b768ef35bcbc3447edb9ad4" }, +] + +[[package]] +name = "identify" +version = "2.6.14" +source = { registry = "http://10.0.0.2:5001/index/" } +sdist = { url = "http://10.0.0.2:5001/index/identify/identify-2.6.14.tar.gz", hash = "sha256:663494103b4f717cb26921c52f8751363dc89db64364cd836a9bf1535f53cd6a" } +wheels = [ + { url = "http://10.0.0.2:5001/index/identify/identify-2.6.14-py2.py3-none-any.whl", hash = "sha256:11a073da82212c6646b1f39bb20d4483bfb9543bd5566fec60053c4bb309bf2e" }, +] + +[[package]] +name = "idna" +version = "3.10" +source = { registry = "http://10.0.0.2:5001/index/" } +sdist = { url = "http://10.0.0.2:5001/index/idna/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9" } +wheels = [ + { url = "http://10.0.0.2:5001/index/idna/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3" }, +] + +[[package]] +name = "iniconfig" +version = "2.1.0" +source = { registry = "http://10.0.0.2:5001/index/" } +sdist = { url = "http://10.0.0.2:5001/index/iniconfig/iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7" } +wheels = [ + { url = "http://10.0.0.2:5001/index/iniconfig/iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760" }, +] + +[[package]] +name = "jinja2" +version = "3.1.6" +source = { registry = "http://10.0.0.2:5001/index/" } +dependencies = [ + { name = "markupsafe" }, +] +sdist = { url = "http://10.0.0.2:5001/index/jinja2/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d" } +wheels = [ + { url = "http://10.0.0.2:5001/index/jinja2/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67" }, +] + +[[package]] +name = "markdown-it-py" +version = "4.0.0" +source = { registry = "http://10.0.0.2:5001/index/" } +dependencies = [ + { name = "mdurl" }, +] +sdist = { url = "http://10.0.0.2:5001/index/markdown-it-py/markdown_it_py-4.0.0.tar.gz", hash = "sha256:cb0a2b4aa34f932c007117b194e945bd74e0ec24133ceb5bac59009cda1cb9f3" } +wheels = [ + { url = "http://10.0.0.2:5001/index/markdown-it-py/markdown_it_py-4.0.0-py3-none-any.whl", hash = "sha256:87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147" }, +] + +[[package]] +name = "markupsafe" +version = "3.0.2" +source = { registry = "http://10.0.0.2:5001/index/" } +sdist = { url = "http://10.0.0.2:5001/index/markupsafe/markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0" } +wheels = [ + { url = "http://10.0.0.2:5001/index/markupsafe/MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf" }, + { url = "http://10.0.0.2:5001/index/markupsafe/MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225" }, + { url = "http://10.0.0.2:5001/index/markupsafe/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028" }, + { url = "http://10.0.0.2:5001/index/markupsafe/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8" }, + { url = "http://10.0.0.2:5001/index/markupsafe/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c" }, + { url = "http://10.0.0.2:5001/index/markupsafe/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557" }, + { url = "http://10.0.0.2:5001/index/markupsafe/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22" }, + { url = "http://10.0.0.2:5001/index/markupsafe/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48" }, + { url = "http://10.0.0.2:5001/index/markupsafe/MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30" }, + { url = "http://10.0.0.2:5001/index/markupsafe/MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87" }, + { url = "http://10.0.0.2:5001/index/markupsafe/MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd" }, + { url = "http://10.0.0.2:5001/index/markupsafe/MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430" }, + { url = "http://10.0.0.2:5001/index/markupsafe/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094" }, + { url = "http://10.0.0.2:5001/index/markupsafe/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396" }, + { url = "http://10.0.0.2:5001/index/markupsafe/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79" }, + { url = "http://10.0.0.2:5001/index/markupsafe/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a" }, + { url = "http://10.0.0.2:5001/index/markupsafe/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca" }, + { url = "http://10.0.0.2:5001/index/markupsafe/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c" }, + { url = "http://10.0.0.2:5001/index/markupsafe/MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1" }, + { url = "http://10.0.0.2:5001/index/markupsafe/MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f" }, + { url = "http://10.0.0.2:5001/index/markupsafe/MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c" }, + { url = "http://10.0.0.2:5001/index/markupsafe/MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb" }, + { url = "http://10.0.0.2:5001/index/markupsafe/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c" }, + { url = "http://10.0.0.2:5001/index/markupsafe/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d" }, + { url = "http://10.0.0.2:5001/index/markupsafe/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe" }, + { url = "http://10.0.0.2:5001/index/markupsafe/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5" }, + { url = "http://10.0.0.2:5001/index/markupsafe/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a" }, + { url = "http://10.0.0.2:5001/index/markupsafe/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9" }, + { url = "http://10.0.0.2:5001/index/markupsafe/MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6" }, + { url = "http://10.0.0.2:5001/index/markupsafe/MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f" }, +] + +[[package]] +name = "marshmallow" +version = "4.0.1" +source = { registry = "http://10.0.0.2:5001/index/" } +sdist = { url = "http://10.0.0.2:5001/index/marshmallow/marshmallow-4.0.1.tar.gz", hash = "sha256:e1d860bd262737cb2d34e1541b84cb52c32c72c9474e3fe6f30f137ef8b0d97f" } +wheels = [ + { url = "http://10.0.0.2:5001/index/marshmallow/marshmallow-4.0.1-py3-none-any.whl", hash = "sha256:72f14ef346f81269dbddee891bac547dda1501e9e08b6a809756ea3dbb7936a1" }, +] + +[[package]] +name = "mdurl" +version = "0.1.2" +source = { registry = "http://10.0.0.2:5001/index/" } +sdist = { url = "http://10.0.0.2:5001/index/mdurl/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba" } +wheels = [ + { url = "http://10.0.0.2:5001/index/mdurl/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8" }, +] + +[[package]] +name = "minio" +version = "7.2.16" +source = { registry = "http://10.0.0.2:5001/index/" } +dependencies = [ + { name = "argon2-cffi" }, + { name = "certifi" }, + { name = "pycryptodome" }, + { name = "typing-extensions" }, + { name = "urllib3" }, +] +sdist = { url = "http://10.0.0.2:5001/index/minio/minio-7.2.16.tar.gz", hash = "sha256:81e365c8494d591d8204a63ee7596bfdf8a7d06ad1b1507d6b9c1664a95f299a" } +wheels = [ + { url = "http://10.0.0.2:5001/index/minio/minio-7.2.16-py3-none-any.whl", hash = "sha256:9288ab988ca57c181eb59a4c96187b293131418e28c164392186c2b89026b223" }, +] + +[[package]] +name = "mypy" +version = "1.18.1" +source = { registry = "http://10.0.0.2:5001/index/" } +dependencies = [ + { name = "mypy-extensions" }, + { name = "pathspec" }, + { name = "typing-extensions" }, +] +sdist = { url = "http://10.0.0.2:5001/index/mypy/mypy-1.18.1.tar.gz", hash = "sha256:9e988c64ad3ac5987f43f5154f884747faf62141b7f842e87465b45299eea5a9" } +wheels = [ + { url = "http://10.0.0.2:5001/index/mypy/mypy-1.18.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:502cde8896be8e638588b90fdcb4c5d5b8c1b004dfc63fd5604a973547367bb9" }, + { url = "http://10.0.0.2:5001/index/mypy/mypy-1.18.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7509549b5e41be279afc1228242d0e397f1af2919a8f2877ad542b199dc4083e" }, + { url = "http://10.0.0.2:5001/index/mypy/mypy-1.18.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5956ecaabb3a245e3f34100172abca1507be687377fe20e24d6a7557e07080e2" }, + { url = "http://10.0.0.2:5001/index/mypy/mypy-1.18.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8750ceb014a96c9890421c83f0db53b0f3b8633e2864c6f9bc0a8e93951ed18d" }, + { url = "http://10.0.0.2:5001/index/mypy/mypy-1.18.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fb89ea08ff41adf59476b235293679a6eb53a7b9400f6256272fb6029bec3ce5" }, + { url = "http://10.0.0.2:5001/index/mypy/mypy-1.18.1-cp312-cp312-win_amd64.whl", hash = "sha256:2657654d82fcd2a87e02a33e0d23001789a554059bbf34702d623dafe353eabf" }, + { url = "http://10.0.0.2:5001/index/mypy/mypy-1.18.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:d70d2b5baf9b9a20bc9c730015615ae3243ef47fb4a58ad7b31c3e0a59b5ef1f" }, + { url = "http://10.0.0.2:5001/index/mypy/mypy-1.18.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b8367e33506300f07a43012fc546402f283c3f8bcff1dc338636affb710154ce" }, + { url = "http://10.0.0.2:5001/index/mypy/mypy-1.18.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:913f668ec50c3337b89df22f973c1c8f0b29ee9e290a8b7fe01cc1ef7446d42e" }, + { url = "http://10.0.0.2:5001/index/mypy/mypy-1.18.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1a0e70b87eb27b33209fa4792b051c6947976f6ab829daa83819df5f58330c71" }, + { url = "http://10.0.0.2:5001/index/mypy/mypy-1.18.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c378d946e8a60be6b6ede48c878d145546fb42aad61df998c056ec151bf6c746" }, + { url = "http://10.0.0.2:5001/index/mypy/mypy-1.18.1-cp313-cp313-win_amd64.whl", hash = "sha256:2cd2c1e0f3a7465f22731987fff6fc427e3dcbb4ca5f7db5bbeaff2ff9a31f6d" }, + { url = "http://10.0.0.2:5001/index/mypy/mypy-1.18.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:ba24603c58e34dd5b096dfad792d87b304fc6470cbb1c22fd64e7ebd17edcc61" }, + { url = "http://10.0.0.2:5001/index/mypy/mypy-1.18.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ed36662fb92ae4cb3cacc682ec6656208f323bbc23d4b08d091eecfc0863d4b5" }, + { url = "http://10.0.0.2:5001/index/mypy/mypy-1.18.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:040ecc95e026f71a9ad7956fea2724466602b561e6a25c2e5584160d3833aaa8" }, + { url = "http://10.0.0.2:5001/index/mypy/mypy-1.18.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:937e3ed86cb731276706e46e03512547e43c391a13f363e08d0fee49a7c38a0d" }, + { url = "http://10.0.0.2:5001/index/mypy/mypy-1.18.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:1f95cc4f01c0f1701ca3b0355792bccec13ecb2ec1c469e5b85a6ef398398b1d" }, + { url = "http://10.0.0.2:5001/index/mypy/mypy-1.18.1-cp314-cp314-win_amd64.whl", hash = "sha256:e4f16c0019d48941220ac60b893615be2f63afedaba6a0801bdcd041b96991ce" }, + { url = "http://10.0.0.2:5001/index/mypy/mypy-1.18.1-py3-none-any.whl", hash = "sha256:b76a4de66a0ac01da1be14ecc8ae88ddea33b8380284a9e3eae39d57ebcbe26e" }, +] + +[[package]] +name = "mypy-extensions" +version = "1.1.0" +source = { registry = "http://10.0.0.2:5001/index/" } +sdist = { url = "http://10.0.0.2:5001/index/mypy-extensions/mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558" } +wheels = [ + { url = "http://10.0.0.2:5001/index/mypy-extensions/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505" }, +] + +[[package]] +name = "nodeenv" +version = "1.9.1" +source = { registry = "http://10.0.0.2:5001/index/" } +sdist = { url = "http://10.0.0.2:5001/index/nodeenv/nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f" } +wheels = [ + { url = "http://10.0.0.2:5001/index/nodeenv/nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9" }, +] + +[[package]] +name = "numpy" +version = "2.3.3" +source = { registry = "http://10.0.0.2:5001/index/" } +sdist = { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3.tar.gz", hash = "sha256:ddc7c39727ba62b80dfdbedf400d1c10ddfa8eefbd7ec8dcb118be8b56d31029" } +wheels = [ + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:cfdd09f9c84a1a934cde1eec2267f0a43a7cd44b2cca4ff95b7c0d14d144b0bf" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cb32e3cf0f762aee47ad1ddc6672988f7f27045b0783c887190545baba73aa25" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:396b254daeb0a57b1fe0ecb5e3cff6fa79a380fa97c8f7781a6d08cd429418fe" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:067e3d7159a5d8f8a0b46ee11148fc35ca9b21f61e3c49fbd0a027450e65a33b" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1c02d0629d25d426585fb2e45a66154081b9fa677bc92a881ff1d216bc9919a8" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d9192da52b9745f7f0766531dcfa978b7763916f158bb63bdb8a1eca0068ab20" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:cd7de500a5b66319db419dc3c345244404a164beae0d0937283b907d8152e6ea" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:93d4962d8f82af58f0b2eb85daaf1b3ca23fe0a85d0be8f1f2b7bb46034e56d7" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp312-cp312-win32.whl", hash = "sha256:5534ed6b92f9b7dca6c0a19d6df12d41c68b991cef051d108f6dbff3babc4ebf" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp312-cp312-win_amd64.whl", hash = "sha256:497d7cad08e7092dba36e3d296fe4c97708c93daf26643a1ae4b03f6294d30eb" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp312-cp312-win_arm64.whl", hash = "sha256:ca0309a18d4dfea6fc6262a66d06c26cfe4640c3926ceec90e57791a82b6eee5" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f5415fb78995644253370985342cd03572ef8620b934da27d77377a2285955bf" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d00de139a3324e26ed5b95870ce63be7ec7352171bc69a4cf1f157a48e3eb6b7" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:9dc13c6a5829610cc07422bc74d3ac083bd8323f14e2827d992f9e52e22cd6a6" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:d79715d95f1894771eb4e60fb23f065663b2298f7d22945d66877aadf33d00c7" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:952cfd0748514ea7c3afc729a0fc639e61655ce4c55ab9acfab14bda4f402b4c" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5b83648633d46f77039c29078751f80da65aa64d5622a3cd62aaef9d835b6c93" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b001bae8cea1c7dfdb2ae2b017ed0a6f2102d7a70059df1e338e307a4c78a8ae" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8e9aced64054739037d42fb84c54dd38b81ee238816c948c8f3ed134665dcd86" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp313-cp313-win32.whl", hash = "sha256:9591e1221db3f37751e6442850429b3aabf7026d3b05542d102944ca7f00c8a8" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp313-cp313-win_amd64.whl", hash = "sha256:f0dadeb302887f07431910f67a14d57209ed91130be0adea2f9793f1a4f817cf" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp313-cp313-win_arm64.whl", hash = "sha256:3c7cf302ac6e0b76a64c4aecf1a09e51abd9b01fc7feee80f6c43e3ab1b1dbc5" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:eda59e44957d272846bb407aad19f89dc6f58fecf3504bd144f4c5cf81a7eacc" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:823d04112bc85ef5c4fda73ba24e6096c8f869931405a80aa8b0e604510a26bc" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:40051003e03db4041aa325da2a0971ba41cf65714e65d296397cc0e32de6018b" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:6ee9086235dd6ab7ae75aba5662f582a81ced49f0f1c6de4260a78d8f2d91a19" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:94fcaa68757c3e2e668ddadeaa86ab05499a70725811e582b6a9858dd472fb30" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:da1a74b90e7483d6ce5244053399a614b1d6b7bc30a60d2f570e5071f8959d3e" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:2990adf06d1ecee3b3dcbb4977dfab6e9f09807598d647f04d385d29e7a3c3d3" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:ed635ff692483b8e3f0fcaa8e7eb8a75ee71aa6d975388224f70821421800cea" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp313-cp313t-win32.whl", hash = "sha256:a333b4ed33d8dc2b373cc955ca57babc00cd6f9009991d9edc5ddbc1bac36bcd" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp313-cp313t-win_amd64.whl", hash = "sha256:4384a169c4d8f97195980815d6fcad04933a7e1ab3b530921c3fef7a1c63426d" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp313-cp313t-win_arm64.whl", hash = "sha256:75370986cc0bc66f4ce5110ad35aae6d182cc4ce6433c40ad151f53690130bf1" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:cd052f1fa6a78dee696b58a914b7229ecfa41f0a6d96dc663c1220a55e137593" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:414a97499480067d305fcac9716c29cf4d0d76db6ebf0bf3cbce666677f12652" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:50a5fe69f135f88a2be9b6ca0481a68a136f6febe1916e4920e12f1a34e708a7" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:b912f2ed2b67a129e6a601e9d93d4fa37bef67e54cac442a2f588a54afe5c67a" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9e318ee0596d76d4cb3d78535dc005fa60e5ea348cd131a51e99d0bdbe0b54fe" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ce020080e4a52426202bdb6f7691c65bb55e49f261f31a8f506c9f6bc7450421" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:e6687dc183aa55dae4a705b35f9c0f8cb178bcaa2f029b241ac5356221d5c021" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d8f3b1080782469fdc1718c4ed1d22549b5fb12af0d57d35e992158a772a37cf" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp314-cp314-win32.whl", hash = "sha256:cb248499b0bc3be66ebd6578b83e5acacf1d6cb2a77f2248ce0e40fbec5a76d0" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp314-cp314-win_amd64.whl", hash = "sha256:691808c2b26b0f002a032c73255d0bd89751425f379f7bcd22d140db593a96e8" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp314-cp314-win_arm64.whl", hash = "sha256:9ad12e976ca7b10f1774b03615a2a4bab8addce37ecc77394d8e986927dc0dfe" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:9cc48e09feb11e1db00b320e9d30a4151f7369afb96bd0e48d942d09da3a0d00" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:901bf6123879b7f251d3631967fd574690734236075082078e0571977c6a8e6a" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:7f025652034199c301049296b59fa7d52c7e625017cae4c75d8662e377bf487d" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:533ca5f6d325c80b6007d4d7fb1984c303553534191024ec6a524a4c92a5935a" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0edd58682a399824633b66885d699d7de982800053acf20be1eaa46d92009c54" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:367ad5d8fbec5d9296d18478804a530f1191e24ab4d75ab408346ae88045d25e" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8f6ac61a217437946a1fa48d24c47c91a0c4f725237871117dea264982128097" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:179a42101b845a816d464b6fe9a845dfaf308fdfc7925387195570789bb2c970" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp314-cp314t-win32.whl", hash = "sha256:1250c5d3d2562ec4174bce2e3a1523041595f9b651065e4a4473f5f48a6bc8a5" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp314-cp314t-win_amd64.whl", hash = "sha256:b37a0b2e5935409daebe82c1e42274d30d9dd355852529eab91dab8dcca7419f" }, + { url = "http://10.0.0.2:5001/index/numpy/numpy-2.3.3-cp314-cp314t-win_arm64.whl", hash = "sha256:78c9f6560dc7e6b3990e32df7ea1a50bbd0e2a111e05209963f5ddcab7073b0b" }, +] + +[[package]] +name = "packaging" +version = "25.0" +source = { registry = "http://10.0.0.2:5001/index/" } +sdist = { url = "http://10.0.0.2:5001/index/packaging/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f" } +wheels = [ + { url = "http://10.0.0.2:5001/index/packaging/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484" }, +] + +[[package]] +name = "pandas" +version = "2.3.2" +source = { registry = "http://10.0.0.2:5001/index/" } +dependencies = [ + { name = "numpy" }, + { name = "python-dateutil" }, + { name = "pytz" }, + { name = "tzdata" }, +] +sdist = { url = "http://10.0.0.2:5001/index/pandas/pandas-2.3.2.tar.gz", hash = "sha256:ab7b58f8f82706890924ccdfb5f48002b83d2b5a3845976a9fb705d36c34dcdb" } +wheels = [ + { url = "http://10.0.0.2:5001/index/pandas/pandas-2.3.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3fbb977f802156e7a3f829e9d1d5398f6192375a3e2d1a9ee0803e35fe70a2b9" }, + { url = "http://10.0.0.2:5001/index/pandas/pandas-2.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1b9b52693123dd234b7c985c68b709b0b009f4521000d0525f2b95c22f15944b" }, + { url = "http://10.0.0.2:5001/index/pandas/pandas-2.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0bd281310d4f412733f319a5bc552f86d62cddc5f51d2e392c8787335c994175" }, + { url = "http://10.0.0.2:5001/index/pandas/pandas-2.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:96d31a6b4354e3b9b8a2c848af75d31da390657e3ac6f30c05c82068b9ed79b9" }, + { url = "http://10.0.0.2:5001/index/pandas/pandas-2.3.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:df4df0b9d02bb873a106971bb85d448378ef14b86ba96f035f50bbd3688456b4" }, + { url = "http://10.0.0.2:5001/index/pandas/pandas-2.3.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:213a5adf93d020b74327cb2c1b842884dbdd37f895f42dcc2f09d451d949f811" }, + { url = "http://10.0.0.2:5001/index/pandas/pandas-2.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:8c13b81a9347eb8c7548f53fd9a4f08d4dfe996836543f805c987bafa03317ae" }, + { url = "http://10.0.0.2:5001/index/pandas/pandas-2.3.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0c6ecbac99a354a051ef21c5307601093cb9e0f4b1855984a084bfec9302699e" }, + { url = "http://10.0.0.2:5001/index/pandas/pandas-2.3.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c6f048aa0fd080d6a06cc7e7537c09b53be6642d330ac6f54a600c3ace857ee9" }, + { url = "http://10.0.0.2:5001/index/pandas/pandas-2.3.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0064187b80a5be6f2f9c9d6bdde29372468751dfa89f4211a3c5871854cfbf7a" }, + { url = "http://10.0.0.2:5001/index/pandas/pandas-2.3.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ac8c320bded4718b298281339c1a50fb00a6ba78cb2a63521c39bec95b0209b" }, + { url = "http://10.0.0.2:5001/index/pandas/pandas-2.3.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:114c2fe4f4328cf98ce5716d1532f3ab79c5919f95a9cfee81d9140064a2e4d6" }, + { url = "http://10.0.0.2:5001/index/pandas/pandas-2.3.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:48fa91c4dfb3b2b9bfdb5c24cd3567575f4e13f9636810462ffed8925352be5a" }, + { url = "http://10.0.0.2:5001/index/pandas/pandas-2.3.2-cp313-cp313-win_amd64.whl", hash = "sha256:12d039facec710f7ba305786837d0225a3444af7bbd9c15c32ca2d40d157ed8b" }, + { url = "http://10.0.0.2:5001/index/pandas/pandas-2.3.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:c624b615ce97864eb588779ed4046186f967374185c047070545253a52ab2d57" }, + { url = "http://10.0.0.2:5001/index/pandas/pandas-2.3.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:0cee69d583b9b128823d9514171cabb6861e09409af805b54459bd0c821a35c2" }, + { url = "http://10.0.0.2:5001/index/pandas/pandas-2.3.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2319656ed81124982900b4c37f0e0c58c015af9a7bbc62342ba5ad07ace82ba9" }, + { url = "http://10.0.0.2:5001/index/pandas/pandas-2.3.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b37205ad6f00d52f16b6d09f406434ba928c1a1966e2771006a9033c736d30d2" }, + { url = "http://10.0.0.2:5001/index/pandas/pandas-2.3.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:837248b4fc3a9b83b9c6214699a13f069dc13510a6a6d7f9ba33145d2841a012" }, + { url = "http://10.0.0.2:5001/index/pandas/pandas-2.3.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:d2c3554bd31b731cd6490d94a28f3abb8dd770634a9e06eb6d2911b9827db370" }, +] + +[[package]] +name = "pandas-stubs" +version = "2.3.2.250827" +source = { registry = "http://10.0.0.2:5001/index/" } +dependencies = [ + { name = "numpy" }, + { name = "types-pytz" }, +] +sdist = { url = "http://10.0.0.2:5001/index/pandas-stubs/pandas_stubs-2.3.2.250827.tar.gz", hash = "sha256:bcc2d49a2766325e4a1a492c3eeda879e9521bb5e26e69e2bbf13e80e7ef569a" } +wheels = [ + { url = "http://10.0.0.2:5001/index/pandas-stubs/pandas_stubs-2.3.2.250827-py3-none-any.whl", hash = "sha256:3d613013b4189147a9a6bb18d8bec1e5b137de091496e9b9ff9f137ec3e223a9" }, +] + +[[package]] +name = "pathspec" +version = "0.12.1" +source = { registry = "http://10.0.0.2:5001/index/" } +sdist = { url = "http://10.0.0.2:5001/index/pathspec/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712" } +wheels = [ + { url = "http://10.0.0.2:5001/index/pathspec/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08" }, +] + +[[package]] +name = "pillow" +version = "11.3.0" +source = { registry = "http://10.0.0.2:5001/index/" } +sdist = { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0.tar.gz", hash = "sha256:3828ee7586cd0b2091b6209e5ad53e20d0649bbe87164a459d0676e035e8f523" } +wheels = [ + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fdae223722da47b024b867c1ea0be64e0df702c5e0a60e27daad39bf960dd1e4" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:921bd305b10e82b4d1f5e802b6850677f965d8394203d182f078873851dada69" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:eb76541cba2f958032d79d143b98a3a6b3ea87f0959bbe256c0b5e416599fd5d" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:67172f2944ebba3d4a7b54f2e95c786a3a50c21b88456329314caaa28cda70f6" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:97f07ed9f56a3b9b5f49d3661dc9607484e85c67e27f3e8be2c7d28ca032fec7" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:676b2815362456b5b3216b4fd5bd89d362100dc6f4945154ff172e206a22c024" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3e184b2f26ff146363dd07bde8b711833d7b0202e27d13540bfe2e35a323a809" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6be31e3fc9a621e071bc17bb7de63b85cbe0bfae91bb0363c893cbe67247780d" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp312-cp312-win32.whl", hash = "sha256:7b161756381f0918e05e7cb8a371fff367e807770f8fe92ecb20d905d0e1c149" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:a6444696fce635783440b7f7a9fc24b3ad10a9ea3f0ab66c5905be1c19ccf17d" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp312-cp312-win_arm64.whl", hash = "sha256:2aceea54f957dd4448264f9bf40875da0415c83eb85f55069d89c0ed436e3542" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:1c627742b539bba4309df89171356fcb3cc5a9178355b2727d1b74a6cf155fbd" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:30b7c02f3899d10f13d7a48163c8969e4e653f8b43416d23d13d1bbfdc93b9f8" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:7859a4cc7c9295f5838015d8cc0a9c215b77e43d07a25e460f35cf516df8626f" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ec1ee50470b0d050984394423d96325b744d55c701a439d2bd66089bff963d3c" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7db51d222548ccfd274e4572fdbf3e810a5e66b00608862f947b163e613b67dd" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:2d6fcc902a24ac74495df63faad1884282239265c6839a0a6416d33faedfae7e" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f0f5d8f4a08090c6d6d578351a2b91acf519a54986c055af27e7a93feae6d3f1" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c37d8ba9411d6003bba9e518db0db0c58a680ab9fe5179f040b0463644bc9805" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:13f87d581e71d9189ab21fe0efb5a23e9f28552d5be6979e84001d3b8505abe8" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:023f6d2d11784a465f09fd09a34b150ea4672e85fb3d05931d89f373ab14abb2" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:45dfc51ac5975b938e9809451c51734124e73b04d0f0ac621649821a63852e7b" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp313-cp313-win32.whl", hash = "sha256:a4d336baed65d50d37b88ca5b60c0fa9d81e3a87d4a7930d3880d1624d5b31f3" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:0bce5c4fd0921f99d2e858dc4d4d64193407e1b99478bc5cacecba2311abde51" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp313-cp313-win_arm64.whl", hash = "sha256:1904e1264881f682f02b7f8167935cce37bc97db457f8e7849dc3a6a52b99580" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:4c834a3921375c48ee6b9624061076bc0a32a60b5532b322cc0ea64e639dd50e" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:5e05688ccef30ea69b9317a9ead994b93975104a677a36a8ed8106be9260aa6d" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:1019b04af07fc0163e2810167918cb5add8d74674b6267616021ab558dc98ced" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f944255db153ebb2b19c51fe85dd99ef0ce494123f21b9db4877ffdfc5590c7c" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1f85acb69adf2aaee8b7da124efebbdb959a104db34d3a2cb0f3793dbae422a8" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:05f6ecbeff5005399bb48d198f098a9b4b6bdf27b8487c7f38ca16eeb070cd59" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a7bc6e6fd0395bc052f16b1a8670859964dbd7003bd0af2ff08342eb6e442cfe" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:83e1b0161c9d148125083a35c1c5a89db5b7054834fd4387499e06552035236c" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp313-cp313t-win32.whl", hash = "sha256:2a3117c06b8fb646639dce83694f2f9eac405472713fcb1ae887469c0d4f6788" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp313-cp313t-win_amd64.whl", hash = "sha256:857844335c95bea93fb39e0fa2726b4d9d758850b34075a7e3ff4f4fa3aa3b31" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp313-cp313t-win_arm64.whl", hash = "sha256:8797edc41f3e8536ae4b10897ee2f637235c94f27404cac7297f7b607dd0716e" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:d9da3df5f9ea2a89b81bb6087177fb1f4d1c7146d583a3fe5c672c0d94e55e12" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:0b275ff9b04df7b640c59ec5a3cb113eefd3795a8df80bac69646ef699c6981a" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0743841cabd3dba6a83f38a92672cccbd69af56e3e91777b0ee7f4dba4385632" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:2465a69cf967b8b49ee1b96d76718cd98c4e925414ead59fdf75cf0fd07df673" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:41742638139424703b4d01665b807c6468e23e699e8e90cffefe291c5832b027" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:93efb0b4de7e340d99057415c749175e24c8864302369e05914682ba642e5d77" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7966e38dcd0fa11ca390aed7c6f20454443581d758242023cf36fcb319b1a874" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:98a9afa7b9007c67ed84c57c9e0ad86a6000da96eaa638e4f8abe5b65ff83f0a" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp314-cp314-win32.whl", hash = "sha256:02a723e6bf909e7cea0dac1b0e0310be9d7650cd66222a5f1c571455c0a45214" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp314-cp314-win_amd64.whl", hash = "sha256:a418486160228f64dd9e9efcd132679b7a02a5f22c982c78b6fc7dab3fefb635" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp314-cp314-win_arm64.whl", hash = "sha256:155658efb5e044669c08896c0c44231c5e9abcaadbc5cd3648df2f7c0b96b9a6" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:59a03cdf019efbfeeed910bf79c7c93255c3d54bc45898ac2a4140071b02b4ae" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:f8a5827f84d973d8636e9dc5764af4f0cf2318d26744b3d902931701b0d46653" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ee92f2fd10f4adc4b43d07ec5e779932b4eb3dbfbc34790ada5a6669bc095aa6" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c96d333dcf42d01f47b37e0979b6bd73ec91eae18614864622d9b87bbd5bbf36" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4c96f993ab8c98460cd0c001447bff6194403e8b1d7e149ade5f00594918128b" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:41342b64afeba938edb034d122b2dda5db2139b9a4af999729ba8818e0056477" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:068d9c39a2d1b358eb9f245ce7ab1b5c3246c7c8c7d9ba58cfa5b43146c06e50" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:a1bc6ba083b145187f648b667e05a2534ecc4b9f2784c2cbe3089e44868f2b9b" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp314-cp314t-win32.whl", hash = "sha256:118ca10c0d60b06d006be10a501fd6bbdfef559251ed31b794668ed569c87e12" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp314-cp314t-win_amd64.whl", hash = "sha256:8924748b688aa210d79883357d102cd64690e56b923a186f35a82cbc10f997db" }, + { url = "http://10.0.0.2:5001/index/pillow/pillow-11.3.0-cp314-cp314t-win_arm64.whl", hash = "sha256:79ea0d14d3ebad43ec77ad5272e6ff9bba5b679ef73375ea760261207fa8e0aa" }, +] + +[[package]] +name = "platformdirs" +version = "4.4.0" +source = { registry = "http://10.0.0.2:5001/index/" } +sdist = { url = "http://10.0.0.2:5001/index/platformdirs/platformdirs-4.4.0.tar.gz", hash = "sha256:ca753cf4d81dc309bc67b0ea38fd15dc97bc30ce419a7f58d13eb3bf14c4febf" } +wheels = [ + { url = "http://10.0.0.2:5001/index/platformdirs/platformdirs-4.4.0-py3-none-any.whl", hash = "sha256:abd01743f24e5287cd7a5db3752faf1a2d65353f38ec26d98e25a6db65958c85" }, +] + +[[package]] +name = "pluggy" +version = "1.6.0" +source = { registry = "http://10.0.0.2:5001/index/" } +sdist = { url = "http://10.0.0.2:5001/index/pluggy/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3" } +wheels = [ + { url = "http://10.0.0.2:5001/index/pluggy/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746" }, +] + +[[package]] +name = "pre-commit" +version = "4.3.0" +source = { registry = "http://10.0.0.2:5001/index/" } +dependencies = [ + { name = "cfgv" }, + { name = "identify" }, + { name = "nodeenv" }, + { name = "pyyaml" }, + { name = "virtualenv" }, +] +sdist = { url = "http://10.0.0.2:5001/index/pre-commit/pre_commit-4.3.0.tar.gz", hash = "sha256:499fe450cc9d42e9d58e606262795ecb64dd05438943c62b66f6a8673da30b16" } +wheels = [ + { url = "http://10.0.0.2:5001/index/pre-commit/pre_commit-4.3.0-py2.py3-none-any.whl", hash = "sha256:2b0747ad7e6e967169136edffee14c16e148a778a54e4f967921aa1ebf2308d8" }, +] + +[[package]] +name = "psutil" +version = "6.0.0" +source = { registry = "http://10.0.0.2:5001/index/" } +sdist = { url = "http://10.0.0.2:5001/index/psutil/psutil-6.0.0.tar.gz", hash = "sha256:8faae4f310b6d969fa26ca0545338b21f73c6b15db7c4a8d934a5482faa818f2" } +wheels = [ + { url = "http://10.0.0.2:5001/index/psutil/psutil-6.0.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:c588a7e9b1173b6e866756dde596fd4cad94f9399daf99ad8c3258b3cb2b47a0" }, + { url = "http://10.0.0.2:5001/index/psutil/psutil-6.0.0-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ed2440ada7ef7d0d608f20ad89a04ec47d2d3ab7190896cd62ca5fc4fe08bf0" }, + { url = "http://10.0.0.2:5001/index/psutil/psutil-6.0.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fd9a97c8e94059b0ef54a7d4baf13b405011176c3b6ff257c247cae0d560ecd" }, + { url = "http://10.0.0.2:5001/index/psutil/psutil-6.0.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e2e8d0054fc88153ca0544f5c4d554d42e33df2e009c4ff42284ac9ebdef4132" }, + { url = "http://10.0.0.2:5001/index/psutil/psutil-6.0.0-cp37-abi3-win32.whl", hash = "sha256:a495580d6bae27291324fe60cea0b5a7c23fa36a7cd35035a16d93bdcf076b9d" }, + { url = "http://10.0.0.2:5001/index/psutil/psutil-6.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:33ea5e1c975250a720b3a6609c490db40dae5d83a4eb315170c4fe0d8b1f34b3" }, + { url = "http://10.0.0.2:5001/index/psutil/psutil-6.0.0-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:ffe7fc9b6b36beadc8c322f84e1caff51e8703b88eee1da46d1e3a6ae11b4fd0" }, +] + +[[package]] +name = "pycparser" +version = "2.23" +source = { registry = "http://10.0.0.2:5001/index/" } +sdist = { url = "http://10.0.0.2:5001/index/pycparser/pycparser-2.23.tar.gz", hash = "sha256:78816d4f24add8f10a06d6f05b4d424ad9e96cfebf68a4ddc99c65c0720d00c2" } +wheels = [ + { url = "http://10.0.0.2:5001/index/pycparser/pycparser-2.23-py3-none-any.whl", hash = "sha256:e5c6e8d3fbad53479cab09ac03729e0a9faf2bee3db8208a550daf5af81a5934" }, +] + +[[package]] +name = "pycryptodome" +version = "3.23.0" +source = { registry = "http://10.0.0.2:5001/index/" } +sdist = { url = "http://10.0.0.2:5001/index/pycryptodome/pycryptodome-3.23.0.tar.gz", hash = "sha256:447700a657182d60338bab09fdb27518f8856aecd80ae4c6bdddb67ff5da44ef" } +wheels = [ + { url = "http://10.0.0.2:5001/index/pycryptodome/pycryptodome-3.23.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:0011f7f00cdb74879142011f95133274741778abba114ceca229adbf8e62c3e4" }, + { url = "http://10.0.0.2:5001/index/pycryptodome/pycryptodome-3.23.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:90460fc9e088ce095f9ee8356722d4f10f86e5be06e2354230a9880b9c549aae" }, + { url = "http://10.0.0.2:5001/index/pycryptodome/pycryptodome-3.23.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4764e64b269fc83b00f682c47443c2e6e85b18273712b98aa43bcb77f8570477" }, + { url = "http://10.0.0.2:5001/index/pycryptodome/pycryptodome-3.23.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb8f24adb74984aa0e5d07a2368ad95276cf38051fe2dc6605cbcf482e04f2a7" }, + { url = "http://10.0.0.2:5001/index/pycryptodome/pycryptodome-3.23.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d97618c9c6684a97ef7637ba43bdf6663a2e2e77efe0f863cce97a76af396446" }, + { url = "http://10.0.0.2:5001/index/pycryptodome/pycryptodome-3.23.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9a53a4fe5cb075075d515797d6ce2f56772ea7e6a1e5e4b96cf78a14bac3d265" }, + { url = "http://10.0.0.2:5001/index/pycryptodome/pycryptodome-3.23.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:763d1d74f56f031788e5d307029caef067febf890cd1f8bf61183ae142f1a77b" }, + { url = "http://10.0.0.2:5001/index/pycryptodome/pycryptodome-3.23.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:954af0e2bd7cea83ce72243b14e4fb518b18f0c1649b576d114973e2073b273d" }, + { url = "http://10.0.0.2:5001/index/pycryptodome/pycryptodome-3.23.0-cp313-cp313t-win32.whl", hash = "sha256:257bb3572c63ad8ba40b89f6fc9d63a2a628e9f9708d31ee26560925ebe0210a" }, + { url = "http://10.0.0.2:5001/index/pycryptodome/pycryptodome-3.23.0-cp313-cp313t-win_amd64.whl", hash = "sha256:6501790c5b62a29fcb227bd6b62012181d886a767ce9ed03b303d1f22eb5c625" }, + { url = "http://10.0.0.2:5001/index/pycryptodome/pycryptodome-3.23.0-cp313-cp313t-win_arm64.whl", hash = "sha256:9a77627a330ab23ca43b48b130e202582e91cc69619947840ea4d2d1be21eb39" }, + { url = "http://10.0.0.2:5001/index/pycryptodome/pycryptodome-3.23.0-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:187058ab80b3281b1de11c2e6842a357a1f71b42cb1e15bce373f3d238135c27" }, + { url = "http://10.0.0.2:5001/index/pycryptodome/pycryptodome-3.23.0-cp37-abi3-macosx_10_9_x86_64.whl", hash = "sha256:cfb5cd445280c5b0a4e6187a7ce8de5a07b5f3f897f235caa11f1f435f182843" }, + { url = "http://10.0.0.2:5001/index/pycryptodome/pycryptodome-3.23.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67bd81fcbe34f43ad9422ee8fd4843c8e7198dd88dd3d40e6de42ee65fbe1490" }, + { url = "http://10.0.0.2:5001/index/pycryptodome/pycryptodome-3.23.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c8987bd3307a39bc03df5c8e0e3d8be0c4c3518b7f044b0f4c15d1aa78f52575" }, + { url = "http://10.0.0.2:5001/index/pycryptodome/pycryptodome-3.23.0-cp37-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aa0698f65e5b570426fc31b8162ed4603b0c2841cbb9088e2b01641e3065915b" }, + { url = "http://10.0.0.2:5001/index/pycryptodome/pycryptodome-3.23.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:53ecbafc2b55353edcebd64bf5da94a2a2cdf5090a6915bcca6eca6cc452585a" }, + { url = "http://10.0.0.2:5001/index/pycryptodome/pycryptodome-3.23.0-cp37-abi3-musllinux_1_2_i686.whl", hash = "sha256:156df9667ad9f2ad26255926524e1c136d6664b741547deb0a86a9acf5ea631f" }, + { url = "http://10.0.0.2:5001/index/pycryptodome/pycryptodome-3.23.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:dea827b4d55ee390dc89b2afe5927d4308a8b538ae91d9c6f7a5090f397af1aa" }, + { url = "http://10.0.0.2:5001/index/pycryptodome/pycryptodome-3.23.0-cp37-abi3-win32.whl", hash = "sha256:507dbead45474b62b2bbe318eb1c4c8ee641077532067fec9c1aa82c31f84886" }, + { url = "http://10.0.0.2:5001/index/pycryptodome/pycryptodome-3.23.0-cp37-abi3-win_amd64.whl", hash = "sha256:c75b52aacc6c0c260f204cbdd834f76edc9fb0d8e0da9fbf8352ef58202564e2" }, + { url = "http://10.0.0.2:5001/index/pycryptodome/pycryptodome-3.23.0-cp37-abi3-win_arm64.whl", hash = "sha256:11eeeb6917903876f134b56ba11abe95c0b0fd5e3330def218083c7d98bbcb3c" }, +] + +[[package]] +name = "pydantic" +version = "2.11.9" +source = { registry = "http://10.0.0.2:5001/index/" } +dependencies = [ + { name = "annotated-types" }, + { name = "pydantic-core" }, + { name = "typing-extensions" }, + { name = "typing-inspection" }, +] +sdist = { url = "http://10.0.0.2:5001/index/pydantic/pydantic-2.11.9.tar.gz", hash = "sha256:6b8ffda597a14812a7975c90b82a8a2e777d9257aba3453f973acd3c032a18e2" } +wheels = [ + { url = "http://10.0.0.2:5001/index/pydantic/pydantic-2.11.9-py3-none-any.whl", hash = "sha256:c42dd626f5cfc1c6950ce6205ea58c93efa406da65f479dcb4029d5934857da2" }, +] + +[[package]] +name = "pydantic-core" +version = "2.33.2" +source = { registry = "http://10.0.0.2:5001/index/" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "http://10.0.0.2:5001/index/pydantic-core/pydantic_core-2.33.2.tar.gz", hash = "sha256:7cb8bc3605c29176e1b105350d2e6474142d7c1bd1d9327c4a9bdb46bf827acc" } +wheels = [ + { url = "http://10.0.0.2:5001/index/pydantic-core/pydantic_core-2.33.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a7ec89dc587667f22b6a0b6579c249fca9026ce7c333fc142ba42411fa243cdc" }, + { url = "http://10.0.0.2:5001/index/pydantic-core/pydantic_core-2.33.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3c6db6e52c6d70aa0d00d45cdb9b40f0433b96380071ea80b09277dba021ddf7" }, + { url = "http://10.0.0.2:5001/index/pydantic-core/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e61206137cbc65e6d5256e1166f88331d3b6238e082d9f74613b9b765fb9025" }, + { url = "http://10.0.0.2:5001/index/pydantic-core/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb8c529b2819c37140eb51b914153063d27ed88e3bdc31b71198a198e921e011" }, + { url = "http://10.0.0.2:5001/index/pydantic-core/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c52b02ad8b4e2cf14ca7b3d918f3eb0ee91e63b3167c32591e57c4317e134f8f" }, + { url = "http://10.0.0.2:5001/index/pydantic-core/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:96081f1605125ba0855dfda83f6f3df5ec90c61195421ba72223de35ccfb2f88" }, + { url = "http://10.0.0.2:5001/index/pydantic-core/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f57a69461af2a5fa6e6bbd7a5f60d3b7e6cebb687f55106933188e79ad155c1" }, + { url = "http://10.0.0.2:5001/index/pydantic-core/pydantic_core-2.33.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:572c7e6c8bb4774d2ac88929e3d1f12bc45714ae5ee6d9a788a9fb35e60bb04b" }, + { url = "http://10.0.0.2:5001/index/pydantic-core/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:db4b41f9bd95fbe5acd76d89920336ba96f03e149097365afe1cb092fceb89a1" }, + { url = "http://10.0.0.2:5001/index/pydantic-core/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:fa854f5cf7e33842a892e5c73f45327760bc7bc516339fda888c75ae60edaeb6" }, + { url = "http://10.0.0.2:5001/index/pydantic-core/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5f483cfb75ff703095c59e365360cb73e00185e01aaea067cd19acffd2ab20ea" }, + { url = "http://10.0.0.2:5001/index/pydantic-core/pydantic_core-2.33.2-cp312-cp312-win32.whl", hash = "sha256:9cb1da0f5a471435a7bc7e439b8a728e8b61e59784b2af70d7c169f8dd8ae290" }, + { url = "http://10.0.0.2:5001/index/pydantic-core/pydantic_core-2.33.2-cp312-cp312-win_amd64.whl", hash = "sha256:f941635f2a3d96b2973e867144fde513665c87f13fe0e193c158ac51bfaaa7b2" }, + { url = "http://10.0.0.2:5001/index/pydantic-core/pydantic_core-2.33.2-cp312-cp312-win_arm64.whl", hash = "sha256:cca3868ddfaccfbc4bfb1d608e2ccaaebe0ae628e1416aeb9c4d88c001bb45ab" }, + { url = "http://10.0.0.2:5001/index/pydantic-core/pydantic_core-2.33.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1082dd3e2d7109ad8b7da48e1d4710c8d06c253cbc4a27c1cff4fbcaa97a9e3f" }, + { url = "http://10.0.0.2:5001/index/pydantic-core/pydantic_core-2.33.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f517ca031dfc037a9c07e748cefd8d96235088b83b4f4ba8939105d20fa1dcd6" }, + { url = "http://10.0.0.2:5001/index/pydantic-core/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a9f2c9dd19656823cb8250b0724ee9c60a82f3cdf68a080979d13092a3b0fef" }, + { url = "http://10.0.0.2:5001/index/pydantic-core/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2b0a451c263b01acebe51895bfb0e1cc842a5c666efe06cdf13846c7418caa9a" }, + { url = "http://10.0.0.2:5001/index/pydantic-core/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ea40a64d23faa25e62a70ad163571c0b342b8bf66d5fa612ac0dec4f069d916" }, + { url = "http://10.0.0.2:5001/index/pydantic-core/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fb2d542b4d66f9470e8065c5469ec676978d625a8b7a363f07d9a501a9cb36a" }, + { url = "http://10.0.0.2:5001/index/pydantic-core/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdac5d6ffa1b5a83bca06ffe7583f5576555e6c8b3a91fbd25ea7780f825f7d" }, + { url = "http://10.0.0.2:5001/index/pydantic-core/pydantic_core-2.33.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:04a1a413977ab517154eebb2d326da71638271477d6ad87a769102f7c2488c56" }, + { url = "http://10.0.0.2:5001/index/pydantic-core/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:c8e7af2f4e0194c22b5b37205bfb293d166a7344a5b0d0eaccebc376546d77d5" }, + { url = "http://10.0.0.2:5001/index/pydantic-core/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:5c92edd15cd58b3c2d34873597a1e20f13094f59cf88068adb18947df5455b4e" }, + { url = "http://10.0.0.2:5001/index/pydantic-core/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:65132b7b4a1c0beded5e057324b7e16e10910c106d43675d9bd87d4f38dde162" }, + { url = "http://10.0.0.2:5001/index/pydantic-core/pydantic_core-2.33.2-cp313-cp313-win32.whl", hash = "sha256:52fb90784e0a242bb96ec53f42196a17278855b0f31ac7c3cc6f5c1ec4811849" }, + { url = "http://10.0.0.2:5001/index/pydantic-core/pydantic_core-2.33.2-cp313-cp313-win_amd64.whl", hash = "sha256:c083a3bdd5a93dfe480f1125926afcdbf2917ae714bdb80b36d34318b2bec5d9" }, + { url = "http://10.0.0.2:5001/index/pydantic-core/pydantic_core-2.33.2-cp313-cp313-win_arm64.whl", hash = "sha256:e80b087132752f6b3d714f041ccf74403799d3b23a72722ea2e6ba2e892555b9" }, + { url = "http://10.0.0.2:5001/index/pydantic-core/pydantic_core-2.33.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:61c18fba8e5e9db3ab908620af374db0ac1baa69f0f32df4f61ae23f15e586ac" }, + { url = "http://10.0.0.2:5001/index/pydantic-core/pydantic_core-2.33.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95237e53bb015f67b63c91af7518a62a8660376a6a0db19b89acc77a4d6199f5" }, + { url = "http://10.0.0.2:5001/index/pydantic-core/pydantic_core-2.33.2-cp313-cp313t-win_amd64.whl", hash = "sha256:c2fc0a768ef76c15ab9238afa6da7f69895bb5d1ee83aeea2e3509af4472d0b9" }, +] + +[[package]] +name = "pygments" +version = "2.19.2" +source = { registry = "http://10.0.0.2:5001/index/" } +sdist = { url = "http://10.0.0.2:5001/index/pygments/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887" } +wheels = [ + { url = "http://10.0.0.2:5001/index/pygments/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b" }, +] + +[[package]] +name = "pytest" +version = "8.4.2" +source = { registry = "http://10.0.0.2:5001/index/" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "iniconfig" }, + { name = "packaging" }, + { name = "pluggy" }, + { name = "pygments" }, +] +sdist = { url = "http://10.0.0.2:5001/index/pytest/pytest-8.4.2.tar.gz", hash = "sha256:86c0d0b93306b961d58d62a4db4879f27fe25513d4b969df351abdddb3c30e01" } +wheels = [ + { url = "http://10.0.0.2:5001/index/pytest/pytest-8.4.2-py3-none-any.whl", hash = "sha256:872f880de3fc3a5bdc88a11b39c9710c3497a547cfa9320bc3c5e62fbf272e79" }, +] + +[[package]] +name = "pytest-cov" +version = "7.0.0" +source = { registry = "http://10.0.0.2:5001/index/" } +dependencies = [ + { name = "coverage" }, + { name = "pluggy" }, + { name = "pytest" }, +] +sdist = { url = "http://10.0.0.2:5001/index/pytest-cov/pytest_cov-7.0.0.tar.gz", hash = "sha256:33c97eda2e049a0c5298e91f519302a1334c26ac65c1a483d6206fd458361af1" } +wheels = [ + { url = "http://10.0.0.2:5001/index/pytest-cov/pytest_cov-7.0.0-py3-none-any.whl", hash = "sha256:3b8e9558b16cc1479da72058bdecf8073661c7f57f7d3c5f22a1c23507f2d861" }, +] + +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +source = { registry = "http://10.0.0.2:5001/index/" } +dependencies = [ + { name = "six" }, +] +sdist = { url = "http://10.0.0.2:5001/index/python-dateutil/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3" } +wheels = [ + { url = "http://10.0.0.2:5001/index/python-dateutil/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427" }, +] + +[[package]] +name = "python-dotenv" +version = "1.1.1" +source = { registry = "http://10.0.0.2:5001/index/" } +sdist = { url = "http://10.0.0.2:5001/index/python-dotenv/python_dotenv-1.1.1.tar.gz", hash = "sha256:a8a6399716257f45be6a007360200409fce5cda2661e3dec71d23dc15f6189ab" } +wheels = [ + { url = "http://10.0.0.2:5001/index/python-dotenv/python_dotenv-1.1.1-py3-none-any.whl", hash = "sha256:31f23644fe2602f88ff55e1f5c79ba497e01224ee7737937930c448e4d0e24dc" }, +] + +[[package]] +name = "python-repositories" +version = "0.2.2" +source = { registry = "https://gitea.gt-proj.com/api/packages/brian/pypi/simple/" } +dependencies = [ + { name = "python-utils" }, + { name = "structlog" }, +] +sdist = { url = "https://gitea.gt-proj.com/api/packages/brian/pypi/files/python-repositories/0.2.2/python_repositories-0.2.2.tar.gz", hash = "sha256:81d690ca632366f24c2cdf7d550d087810ebc6d305be5bc3e0fad6dacfd9acfe" } +wheels = [ + { url = "https://gitea.gt-proj.com/api/packages/brian/pypi/files/python-repositories/0.2.2/python_repositories-0.2.2-py3-none-any.whl", hash = "sha256:3d521b31a9ba21e2113f8ab4b24449ba6767a60c9c22cf75c29a9eb198fc250a" }, +] + +[package.optional-dependencies] +minio = [ + { name = "minio" }, +] + +[[package]] +name = "python-utils" +version = "0.1.1" +source = { registry = "https://gitea.gt-proj.com/api/packages/brian/pypi/simple/" } +sdist = { url = "https://gitea.gt-proj.com/api/packages/brian/pypi/files/python-utils/0.1.1/python_utils-0.1.1.tar.gz", hash = "sha256:f9e10fff2e15167260d841733bab08914803f7caeaf5f4b0534b730a0b418048" } +wheels = [ + { url = "https://gitea.gt-proj.com/api/packages/brian/pypi/files/python-utils/0.1.1/python_utils-0.1.1-py3-none-any.whl", hash = "sha256:ad06d94a36c828084b61b3e6b97f3c0f0fab3522ea18e603ed37c8abee49bdac" }, +] + +[[package]] +name = "pytz" +version = "2025.2" +source = { registry = "http://10.0.0.2:5001/index/" } +sdist = { url = "http://10.0.0.2:5001/index/pytz/pytz-2025.2.tar.gz", hash = "sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3" } +wheels = [ + { url = "http://10.0.0.2:5001/index/pytz/pytz-2025.2-py2.py3-none-any.whl", hash = "sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00" }, +] + +[[package]] +name = "pyupgrade" +version = "3.20.0" +source = { registry = "http://10.0.0.2:5001/index/" } +dependencies = [ + { name = "tokenize-rt" }, +] +sdist = { url = "http://10.0.0.2:5001/index/pyupgrade/pyupgrade-3.20.0.tar.gz", hash = "sha256:dd6a16c13fc1a7db45796008689a9a35420bd364d681430f640c5e54a3d351ea" } +wheels = [ + { url = "http://10.0.0.2:5001/index/pyupgrade/pyupgrade-3.20.0-py2.py3-none-any.whl", hash = "sha256:cd5bf842b863f50adad324a01c30aef60b9f698a9814848094818659c92cd1f4" }, +] + +[[package]] +name = "pywin32" +version = "311" +source = { registry = "http://10.0.0.2:5001/index/" } +wheels = [ + { url = "http://10.0.0.2:5001/index/pywin32/pywin32-311-cp312-cp312-win32.whl", hash = "sha256:750ec6e621af2b948540032557b10a2d43b0cee2ae9758c54154d711cc852d31" }, + { url = "http://10.0.0.2:5001/index/pywin32/pywin32-311-cp312-cp312-win_amd64.whl", hash = "sha256:b8c095edad5c211ff31c05223658e71bf7116daa0ecf3ad85f3201ea3190d067" }, + { url = "http://10.0.0.2:5001/index/pywin32/pywin32-311-cp312-cp312-win_arm64.whl", hash = "sha256:e286f46a9a39c4a18b319c28f59b61de793654af2f395c102b4f819e584b5852" }, + { url = "http://10.0.0.2:5001/index/pywin32/pywin32-311-cp313-cp313-win32.whl", hash = "sha256:f95ba5a847cba10dd8c4d8fefa9f2a6cf283b8b88ed6178fa8a6c1ab16054d0d" }, + { url = "http://10.0.0.2:5001/index/pywin32/pywin32-311-cp313-cp313-win_amd64.whl", hash = "sha256:718a38f7e5b058e76aee1c56ddd06908116d35147e133427e59a3983f703a20d" }, + { url = "http://10.0.0.2:5001/index/pywin32/pywin32-311-cp313-cp313-win_arm64.whl", hash = "sha256:7b4075d959648406202d92a2310cb990fea19b535c7f4a78d3f5e10b926eeb8a" }, + { url = "http://10.0.0.2:5001/index/pywin32/pywin32-311-cp314-cp314-win32.whl", hash = "sha256:b7a2c10b93f8986666d0c803ee19b5990885872a7de910fc460f9b0c2fbf92ee" }, + { url = "http://10.0.0.2:5001/index/pywin32/pywin32-311-cp314-cp314-win_amd64.whl", hash = "sha256:3aca44c046bd2ed8c90de9cb8427f581c479e594e99b5c0bb19b29c10fd6cb87" }, + { url = "http://10.0.0.2:5001/index/pywin32/pywin32-311-cp314-cp314-win_arm64.whl", hash = "sha256:a508e2d9025764a8270f93111a970e1d0fbfc33f4153b388bb649b7eec4f9b42" }, +] + +[[package]] +name = "pyyaml" +version = "6.0.2" +source = { registry = "http://10.0.0.2:5001/index/" } +sdist = { url = "http://10.0.0.2:5001/index/pyyaml/pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e" } +wheels = [ + { url = "http://10.0.0.2:5001/index/pyyaml/PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab" }, + { url = "http://10.0.0.2:5001/index/pyyaml/PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725" }, + { url = "http://10.0.0.2:5001/index/pyyaml/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5" }, + { url = "http://10.0.0.2:5001/index/pyyaml/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425" }, + { url = "http://10.0.0.2:5001/index/pyyaml/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476" }, + { url = "http://10.0.0.2:5001/index/pyyaml/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48" }, + { url = "http://10.0.0.2:5001/index/pyyaml/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b" }, + { url = "http://10.0.0.2:5001/index/pyyaml/PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4" }, + { url = "http://10.0.0.2:5001/index/pyyaml/PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8" }, + { url = "http://10.0.0.2:5001/index/pyyaml/PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba" }, + { url = "http://10.0.0.2:5001/index/pyyaml/PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1" }, + { url = "http://10.0.0.2:5001/index/pyyaml/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133" }, + { url = "http://10.0.0.2:5001/index/pyyaml/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484" }, + { url = "http://10.0.0.2:5001/index/pyyaml/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5" }, + { url = "http://10.0.0.2:5001/index/pyyaml/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc" }, + { url = "http://10.0.0.2:5001/index/pyyaml/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652" }, + { url = "http://10.0.0.2:5001/index/pyyaml/PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183" }, + { url = "http://10.0.0.2:5001/index/pyyaml/PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563" }, +] + +[[package]] +name = "requests" +version = "2.32.5" +source = { registry = "http://10.0.0.2:5001/index/" } +dependencies = [ + { name = "certifi" }, + { name = "charset-normalizer" }, + { name = "idna" }, + { name = "urllib3" }, +] +sdist = { url = "http://10.0.0.2:5001/index/requests/requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf" } +wheels = [ + { url = "http://10.0.0.2:5001/index/requests/requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6" }, +] + +[[package]] +name = "rich" +version = "14.1.0" +source = { registry = "http://10.0.0.2:5001/index/" } +dependencies = [ + { name = "markdown-it-py" }, + { name = "pygments" }, +] +sdist = { url = "http://10.0.0.2:5001/index/rich/rich-14.1.0.tar.gz", hash = "sha256:e497a48b844b0320d45007cdebfeaeed8db2a4f4bcf49f15e455cfc4af11eaa8" } +wheels = [ + { url = "http://10.0.0.2:5001/index/rich/rich-14.1.0-py3-none-any.whl", hash = "sha256:536f5f1785986d6dbdea3c75205c473f970777b4a0d6c6dd1b696aa05a3fa04f" }, +] + +[[package]] +name = "ruamel-yaml" +version = "0.18.15" +source = { registry = "http://10.0.0.2:5001/index/" } +dependencies = [ + { name = "ruamel-yaml-clib", marker = "python_full_version < '3.14' and platform_python_implementation == 'CPython'" }, +] +sdist = { url = "http://10.0.0.2:5001/index/ruamel-yaml/ruamel.yaml-0.18.15.tar.gz", hash = "sha256:dbfca74b018c4c3fba0b9cc9ee33e53c371194a9000e694995e620490fd40700" } +wheels = [ + { url = "http://10.0.0.2:5001/index/ruamel-yaml/ruamel.yaml-0.18.15-py3-none-any.whl", hash = "sha256:148f6488d698b7a5eded5ea793a025308b25eca97208181b6a026037f391f701" }, +] + +[[package]] +name = "ruamel-yaml-clib" +version = "0.2.12" +source = { registry = "http://10.0.0.2:5001/index/" } +sdist = { url = "http://10.0.0.2:5001/index/ruamel-yaml-clib/ruamel.yaml.clib-0.2.12.tar.gz", hash = "sha256:6c8fbb13ec503f99a91901ab46e0b07ae7941cd527393187039aec586fdfd36f" } +wheels = [ + { url = "http://10.0.0.2:5001/index/ruamel-yaml-clib/ruamel.yaml.clib-0.2.12-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:20b0f8dc160ba83b6dcc0e256846e1a02d044e13f7ea74a3d1d56ede4e48c632" }, + { url = "http://10.0.0.2:5001/index/ruamel-yaml-clib/ruamel.yaml.clib-0.2.12-cp312-cp312-manylinux2014_aarch64.whl", hash = "sha256:943f32bc9dedb3abff9879edc134901df92cfce2c3d5c9348f172f62eb2d771d" }, + { url = "http://10.0.0.2:5001/index/ruamel-yaml-clib/ruamel.yaml.clib-0.2.12-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95c3829bb364fdb8e0332c9931ecf57d9be3519241323c5274bd82f709cebc0c" }, + { url = "http://10.0.0.2:5001/index/ruamel-yaml-clib/ruamel.yaml.clib-0.2.12-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:749c16fcc4a2b09f28843cda5a193e0283e47454b63ec4b81eaa2242f50e4ccd" }, + { url = "http://10.0.0.2:5001/index/ruamel-yaml-clib/ruamel.yaml.clib-0.2.12-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bf165fef1f223beae7333275156ab2022cffe255dcc51c27f066b4370da81e31" }, + { url = "http://10.0.0.2:5001/index/ruamel-yaml-clib/ruamel.yaml.clib-0.2.12-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:32621c177bbf782ca5a18ba4d7af0f1082a3f6e517ac2a18b3974d4edf349680" }, + { url = "http://10.0.0.2:5001/index/ruamel-yaml-clib/ruamel.yaml.clib-0.2.12-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b82a7c94a498853aa0b272fd5bc67f29008da798d4f93a2f9f289feb8426a58d" }, + { url = "http://10.0.0.2:5001/index/ruamel-yaml-clib/ruamel.yaml.clib-0.2.12-cp312-cp312-win32.whl", hash = "sha256:e8c4ebfcfd57177b572e2040777b8abc537cdef58a2120e830124946aa9b42c5" }, + { url = "http://10.0.0.2:5001/index/ruamel-yaml-clib/ruamel.yaml.clib-0.2.12-cp312-cp312-win_amd64.whl", hash = "sha256:0467c5965282c62203273b838ae77c0d29d7638c8a4e3a1c8bdd3602c10904e4" }, + { url = "http://10.0.0.2:5001/index/ruamel-yaml-clib/ruamel.yaml.clib-0.2.12-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:4c8c5d82f50bb53986a5e02d1b3092b03622c02c2eb78e29bec33fd9593bae1a" }, + { url = "http://10.0.0.2:5001/index/ruamel-yaml-clib/ruamel.yaml.clib-0.2.12-cp313-cp313-manylinux2014_aarch64.whl", hash = "sha256:e7e3736715fbf53e9be2a79eb4db68e4ed857017344d697e8b9749444ae57475" }, + { url = "http://10.0.0.2:5001/index/ruamel-yaml-clib/ruamel.yaml.clib-0.2.12-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b7e75b4965e1d4690e93021adfcecccbca7d61c7bddd8e22406ef2ff20d74ef" }, + { url = "http://10.0.0.2:5001/index/ruamel-yaml-clib/ruamel.yaml.clib-0.2.12-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:96777d473c05ee3e5e3c3e999f5d23c6f4ec5b0c38c098b3a5229085f74236c6" }, + { url = "http://10.0.0.2:5001/index/ruamel-yaml-clib/ruamel.yaml.clib-0.2.12-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:3bc2a80e6420ca8b7d3590791e2dfc709c88ab9152c00eeb511c9875ce5778bf" }, + { url = "http://10.0.0.2:5001/index/ruamel-yaml-clib/ruamel.yaml.clib-0.2.12-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:e188d2699864c11c36cdfdada94d781fd5d6b0071cd9c427bceb08ad3d7c70e1" }, + { url = "http://10.0.0.2:5001/index/ruamel-yaml-clib/ruamel.yaml.clib-0.2.12-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4f6f3eac23941b32afccc23081e1f50612bdbe4e982012ef4f5797986828cd01" }, + { url = "http://10.0.0.2:5001/index/ruamel-yaml-clib/ruamel.yaml.clib-0.2.12-cp313-cp313-win32.whl", hash = "sha256:6442cb36270b3afb1b4951f060eccca1ce49f3d087ca1ca4563a6eb479cb3de6" }, + { url = "http://10.0.0.2:5001/index/ruamel-yaml-clib/ruamel.yaml.clib-0.2.12-cp313-cp313-win_amd64.whl", hash = "sha256:e5b8daf27af0b90da7bb903a876477a9e6d7270be6146906b276605997c7e9a3" }, +] + +[[package]] +name = "ruff" +version = "0.13.0" +source = { registry = "http://10.0.0.2:5001/index/" } +sdist = { url = "http://10.0.0.2:5001/index/ruff/ruff-0.13.0.tar.gz", hash = "sha256:5b4b1ee7eb35afae128ab94459b13b2baaed282b1fb0f472a73c82c996c8ae60" } +wheels = [ + { url = "http://10.0.0.2:5001/index/ruff/ruff-0.13.0-py3-none-linux_armv6l.whl", hash = "sha256:137f3d65d58ee828ae136a12d1dc33d992773d8f7644bc6b82714570f31b2004" }, + { url = "http://10.0.0.2:5001/index/ruff/ruff-0.13.0-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:21ae48151b66e71fd111b7d79f9ad358814ed58c339631450c66a4be33cc28b9" }, + { url = "http://10.0.0.2:5001/index/ruff/ruff-0.13.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:64de45f4ca5441209e41742d527944635a05a6e7c05798904f39c85bafa819e3" }, + { url = "http://10.0.0.2:5001/index/ruff/ruff-0.13.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2b2c653ae9b9d46e0ef62fc6fbf5b979bda20a0b1d2b22f8f7eb0cde9f4963b8" }, + { url = "http://10.0.0.2:5001/index/ruff/ruff-0.13.0-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4cec632534332062bc9eb5884a267b689085a1afea9801bf94e3ba7498a2d207" }, + { url = "http://10.0.0.2:5001/index/ruff/ruff-0.13.0-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dcd628101d9f7d122e120ac7c17e0a0f468b19bc925501dbe03c1cb7f5415b24" }, + { url = "http://10.0.0.2:5001/index/ruff/ruff-0.13.0-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:afe37db8e1466acb173bb2a39ca92df00570e0fd7c94c72d87b51b21bb63efea" }, + { url = "http://10.0.0.2:5001/index/ruff/ruff-0.13.0-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0f96a8d90bb258d7d3358b372905fe7333aaacf6c39e2408b9f8ba181f4b6ef2" }, + { url = "http://10.0.0.2:5001/index/ruff/ruff-0.13.0-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:94b5e3d883e4f924c5298e3f2ee0f3085819c14f68d1e5b6715597681433f153" }, + { url = "http://10.0.0.2:5001/index/ruff/ruff-0.13.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:03447f3d18479df3d24917a92d768a89f873a7181a064858ea90a804a7538991" }, + { url = "http://10.0.0.2:5001/index/ruff/ruff-0.13.0-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:fbc6b1934eb1c0033da427c805e27d164bb713f8e273a024a7e86176d7f462cf" }, + { url = "http://10.0.0.2:5001/index/ruff/ruff-0.13.0-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:a8ab6a3e03665d39d4a25ee199d207a488724f022db0e1fe4002968abdb8001b" }, + { url = "http://10.0.0.2:5001/index/ruff/ruff-0.13.0-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:d2a5c62f8ccc6dd2fe259917482de7275cecc86141ee10432727c4816235bc41" }, + { url = "http://10.0.0.2:5001/index/ruff/ruff-0.13.0-py3-none-musllinux_1_2_i686.whl", hash = "sha256:b7b85ca27aeeb1ab421bc787009831cffe6048faae08ad80867edab9f2760945" }, + { url = "http://10.0.0.2:5001/index/ruff/ruff-0.13.0-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:79ea0c44a3032af768cabfd9616e44c24303af49d633b43e3a5096e009ebe823" }, + { url = "http://10.0.0.2:5001/index/ruff/ruff-0.13.0-py3-none-win32.whl", hash = "sha256:4e473e8f0e6a04e4113f2e1de12a5039579892329ecc49958424e5568ef4f768" }, + { url = "http://10.0.0.2:5001/index/ruff/ruff-0.13.0-py3-none-win_amd64.whl", hash = "sha256:48e5c25c7a3713eea9ce755995767f4dcd1b0b9599b638b12946e892123d1efb" }, + { url = "http://10.0.0.2:5001/index/ruff/ruff-0.13.0-py3-none-win_arm64.whl", hash = "sha256:ab80525317b1e1d38614addec8ac954f1b3e662de9d59114ecbf771d00cf613e" }, +] + +[[package]] +name = "safety" +version = "3.2.11" +source = { registry = "http://10.0.0.2:5001/index/" } +dependencies = [ + { name = "authlib" }, + { name = "click" }, + { name = "dparse" }, + { name = "filelock" }, + { name = "jinja2" }, + { name = "marshmallow" }, + { name = "packaging" }, + { name = "psutil" }, + { name = "pydantic" }, + { name = "requests" }, + { name = "rich" }, + { name = "ruamel-yaml" }, + { name = "safety-schemas" }, + { name = "setuptools" }, + { name = "typer" }, + { name = "typing-extensions" }, + { name = "urllib3" }, +] +sdist = { url = "http://10.0.0.2:5001/index/safety/safety-3.2.11.tar.gz", hash = "sha256:70a3b7cc75ba41907bf1705bcbbeab232688657c21088e108712ecb601fe0f20" } +wheels = [ + { url = "http://10.0.0.2:5001/index/safety/safety-3.2.11-py3-none-any.whl", hash = "sha256:3c339c380c9ea6a2d3ab09e88c01ee7ecaabaf963a1c98c021e13aacb9eeea3a" }, +] + +[[package]] +name = "safety-schemas" +version = "0.0.16" +source = { registry = "http://10.0.0.2:5001/index/" } +dependencies = [ + { name = "dparse" }, + { name = "packaging" }, + { name = "pydantic" }, + { name = "ruamel-yaml" }, + { name = "typing-extensions" }, +] +sdist = { url = "http://10.0.0.2:5001/index/safety-schemas/safety_schemas-0.0.16.tar.gz", hash = "sha256:3bb04d11bd4b5cc79f9fa183c658a6a8cf827a9ceec443a5ffa6eed38a50a24e" } +wheels = [ + { url = "http://10.0.0.2:5001/index/safety-schemas/safety_schemas-0.0.16-py3-none-any.whl", hash = "sha256:6760515d3fd1e6535b251cd73014bd431d12fe0bfb8b6e8880a9379b5ab7aa44" }, +] + +[[package]] +name = "setuptools" +version = "80.9.0" +source = { registry = "http://10.0.0.2:5001/index/" } +sdist = { url = "http://10.0.0.2:5001/index/setuptools/setuptools-80.9.0.tar.gz", hash = "sha256:f36b47402ecde768dbfafc46e8e4207b4360c654f1f3bb84475f0a28628fb19c" } +wheels = [ + { url = "http://10.0.0.2:5001/index/setuptools/setuptools-80.9.0-py3-none-any.whl", hash = "sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922" }, +] + +[[package]] +name = "shellingham" +version = "1.5.4" +source = { registry = "http://10.0.0.2:5001/index/" } +sdist = { url = "http://10.0.0.2:5001/index/shellingham/shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de" } +wheels = [ + { url = "http://10.0.0.2:5001/index/shellingham/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686" }, +] + +[[package]] +name = "six" +version = "1.17.0" +source = { registry = "http://10.0.0.2:5001/index/" } +sdist = { url = "http://10.0.0.2:5001/index/six/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81" } +wheels = [ + { url = "http://10.0.0.2:5001/index/six/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274" }, +] + +[[package]] +name = "structlog" +version = "25.4.0" +source = { registry = "http://10.0.0.2:5001/index/" } +sdist = { url = "http://10.0.0.2:5001/index/structlog/structlog-25.4.0.tar.gz", hash = "sha256:186cd1b0a8ae762e29417095664adf1d6a31702160a46dacb7796ea82f7409e4" } +wheels = [ + { url = "http://10.0.0.2:5001/index/structlog/structlog-25.4.0-py3-none-any.whl", hash = "sha256:fe809ff5c27e557d14e613f45ca441aabda051d119ee5a0102aaba6ce40eed2c" }, +] + +[[package]] +name = "testcontainers" +version = "4.13.0" +source = { registry = "http://10.0.0.2:5001/index/" } +dependencies = [ + { name = "docker" }, + { name = "python-dotenv" }, + { name = "typing-extensions" }, + { name = "urllib3" }, + { name = "wrapt" }, +] +sdist = { url = "http://10.0.0.2:5001/index/testcontainers/testcontainers-4.13.0.tar.gz", hash = "sha256:ee2bc39324eeeeb710be779208ae070c8373fa9058861859203f536844b0f412" } +wheels = [ + { url = "http://10.0.0.2:5001/index/testcontainers/testcontainers-4.13.0-py3-none-any.whl", hash = "sha256:784292e0a3f3a4588fbbf5d6649adda81fea5fd61ad3dc73f50a7a903904aade" }, +] + +[[package]] +name = "tokenize-rt" +version = "6.2.0" +source = { registry = "http://10.0.0.2:5001/index/" } +sdist = { url = "http://10.0.0.2:5001/index/tokenize-rt/tokenize_rt-6.2.0.tar.gz", hash = "sha256:8439c042b330c553fdbe1758e4a05c0ed460dbbbb24a606f11f0dee75da4cad6" } +wheels = [ + { url = "http://10.0.0.2:5001/index/tokenize-rt/tokenize_rt-6.2.0-py2.py3-none-any.whl", hash = "sha256:a152bf4f249c847a66497a4a95f63376ed68ac6abf092a2f7cfb29d044ecff44" }, +] + +[[package]] +name = "typer" +version = "0.17.4" +source = { registry = "http://10.0.0.2:5001/index/" } +dependencies = [ + { name = "click" }, + { name = "rich" }, + { name = "shellingham" }, + { name = "typing-extensions" }, +] +sdist = { url = "http://10.0.0.2:5001/index/typer/typer-0.17.4.tar.gz", hash = "sha256:b77dc07d849312fd2bb5e7f20a7af8985c7ec360c45b051ed5412f64d8dc1580" } +wheels = [ + { url = "http://10.0.0.2:5001/index/typer/typer-0.17.4-py3-none-any.whl", hash = "sha256:015534a6edaa450e7007eba705d5c18c3349dcea50a6ad79a5ed530967575824" }, +] + +[[package]] +name = "types-pytz" +version = "2025.2.0.20250809" +source = { registry = "http://10.0.0.2:5001/index/" } +sdist = { url = "http://10.0.0.2:5001/index/types-pytz/types_pytz-2025.2.0.20250809.tar.gz", hash = "sha256:222e32e6a29bb28871f8834e8785e3801f2dc4441c715cd2082b271eecbe21e5" } +wheels = [ + { url = "http://10.0.0.2:5001/index/types-pytz/types_pytz-2025.2.0.20250809-py3-none-any.whl", hash = "sha256:4f55ed1b43e925cf851a756fe1707e0f5deeb1976e15bf844bcaa025e8fbd0db" }, +] + +[[package]] +name = "typing-extensions" +version = "4.15.0" +source = { registry = "http://10.0.0.2:5001/index/" } +sdist = { url = "http://10.0.0.2:5001/index/typing-extensions/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466" } +wheels = [ + { url = "http://10.0.0.2:5001/index/typing-extensions/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548" }, +] + +[[package]] +name = "typing-inspection" +version = "0.4.1" +source = { registry = "http://10.0.0.2:5001/index/" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "http://10.0.0.2:5001/index/typing-inspection/typing_inspection-0.4.1.tar.gz", hash = "sha256:6ae134cc0203c33377d43188d4064e9b357dba58cff3185f22924610e70a9d28" } +wheels = [ + { url = "http://10.0.0.2:5001/index/typing-inspection/typing_inspection-0.4.1-py3-none-any.whl", hash = "sha256:389055682238f53b04f7badcb49b989835495a96700ced5dab2d8feae4b26f51" }, +] + +[[package]] +name = "tzdata" +version = "2025.2" +source = { registry = "http://10.0.0.2:5001/index/" } +sdist = { url = "http://10.0.0.2:5001/index/tzdata/tzdata-2025.2.tar.gz", hash = "sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9" } +wheels = [ + { url = "http://10.0.0.2:5001/index/tzdata/tzdata-2025.2-py2.py3-none-any.whl", hash = "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8" }, +] + +[[package]] +name = "urllib3" +version = "2.5.0" +source = { registry = "http://10.0.0.2:5001/index/" } +sdist = { url = "http://10.0.0.2:5001/index/urllib3/urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760" } +wheels = [ + { url = "http://10.0.0.2:5001/index/urllib3/urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc" }, +] + +[[package]] +name = "virtualenv" +version = "20.34.0" +source = { registry = "http://10.0.0.2:5001/index/" } +dependencies = [ + { name = "distlib" }, + { name = "filelock" }, + { name = "platformdirs" }, +] +sdist = { url = "http://10.0.0.2:5001/index/virtualenv/virtualenv-20.34.0.tar.gz", hash = "sha256:44815b2c9dee7ed86e387b842a84f20b93f7f417f95886ca1996a72a4138eb1a" } +wheels = [ + { url = "http://10.0.0.2:5001/index/virtualenv/virtualenv-20.34.0-py3-none-any.whl", hash = "sha256:341f5afa7eee943e4984a9207c025feedd768baff6753cd660c857ceb3e36026" }, +] + +[[package]] +name = "visual-semiotic-ai-analysis" +version = "0.1.0" +source = { editable = "." } +dependencies = [ + { name = "pandas" }, + { name = "pillow" }, + { name = "pydantic" }, + { name = "python-repositories", extra = ["minio"] }, + { name = "python-utils" }, +] + +[package.dev-dependencies] +dev = [ + { name = "mypy" }, + { name = "pandas-stubs" }, + { name = "pre-commit" }, + { name = "pytest" }, + { name = "pytest-cov" }, + { name = "pyupgrade" }, + { name = "ruff" }, + { name = "safety" }, + { name = "testcontainers" }, +] + +[package.metadata] +requires-dist = [ + { name = "pandas", specifier = ">=2.3.2" }, + { name = "pillow", specifier = ">=11.3.0" }, + { name = "pydantic", specifier = ">=2.11.9" }, + { name = "python-repositories", extras = ["minio"], specifier = ">=0.2.0", index = "https://gitea.gt-proj.com/api/packages/brian/pypi/simple/" }, + { name = "python-utils", specifier = ">=0.1.1", index = "https://gitea.gt-proj.com/api/packages/brian/pypi/simple/" }, +] + +[package.metadata.requires-dev] +dev = [ + { name = "mypy", specifier = ">=1.18.1" }, + { name = "pandas-stubs", specifier = ">=2.3.2.250827" }, + { name = "pre-commit", specifier = ">=4.3.0" }, + { name = "pytest", specifier = ">=8.4.2" }, + { name = "pytest-cov", specifier = ">=7.0.0" }, + { name = "pyupgrade", specifier = ">=3.20.0" }, + { name = "ruff", specifier = ">=0.13.0" }, + { name = "safety", specifier = ">=3.2.11" }, + { name = "testcontainers", specifier = ">=4.13.0" }, +] + +[[package]] +name = "wrapt" +version = "1.17.3" +source = { registry = "http://10.0.0.2:5001/index/" } +sdist = { url = "http://10.0.0.2:5001/index/wrapt/wrapt-1.17.3.tar.gz", hash = "sha256:f66eb08feaa410fe4eebd17f2a2c8e2e46d3476e9f8c783daa8e09e0faa666d0" } +wheels = [ + { url = "http://10.0.0.2:5001/index/wrapt/wrapt-1.17.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:ab232e7fdb44cdfbf55fc3afa31bcdb0d8980b9b95c38b6405df2acb672af0e0" }, + { url = "http://10.0.0.2:5001/index/wrapt/wrapt-1.17.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:9baa544e6acc91130e926e8c802a17f3b16fbea0fd441b5a60f5cf2cc5c3deba" }, + { url = "http://10.0.0.2:5001/index/wrapt/wrapt-1.17.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6b538e31eca1a7ea4605e44f81a48aa24c4632a277431a6ed3f328835901f4fd" }, + { url = "http://10.0.0.2:5001/index/wrapt/wrapt-1.17.3-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:042ec3bb8f319c147b1301f2393bc19dba6e176b7da446853406d041c36c7828" }, + { url = "http://10.0.0.2:5001/index/wrapt/wrapt-1.17.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3af60380ba0b7b5aeb329bc4e402acd25bd877e98b3727b0135cb5c2efdaefe9" }, + { url = "http://10.0.0.2:5001/index/wrapt/wrapt-1.17.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0b02e424deef65c9f7326d8c19220a2c9040c51dc165cddb732f16198c168396" }, + { url = "http://10.0.0.2:5001/index/wrapt/wrapt-1.17.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:74afa28374a3c3a11b3b5e5fca0ae03bef8450d6aa3ab3a1e2c30e3a75d023dc" }, + { url = "http://10.0.0.2:5001/index/wrapt/wrapt-1.17.3-cp312-cp312-win32.whl", hash = "sha256:4da9f45279fff3543c371d5ababc57a0384f70be244de7759c85a7f989cb4ebe" }, + { url = "http://10.0.0.2:5001/index/wrapt/wrapt-1.17.3-cp312-cp312-win_amd64.whl", hash = "sha256:e71d5c6ebac14875668a1e90baf2ea0ef5b7ac7918355850c0908ae82bcb297c" }, + { url = "http://10.0.0.2:5001/index/wrapt/wrapt-1.17.3-cp312-cp312-win_arm64.whl", hash = "sha256:604d076c55e2fdd4c1c03d06dc1a31b95130010517b5019db15365ec4a405fc6" }, + { url = "http://10.0.0.2:5001/index/wrapt/wrapt-1.17.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a47681378a0439215912ef542c45a783484d4dd82bac412b71e59cf9c0e1cea0" }, + { url = "http://10.0.0.2:5001/index/wrapt/wrapt-1.17.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:54a30837587c6ee3cd1a4d1c2ec5d24e77984d44e2f34547e2323ddb4e22eb77" }, + { url = "http://10.0.0.2:5001/index/wrapt/wrapt-1.17.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:16ecf15d6af39246fe33e507105d67e4b81d8f8d2c6598ff7e3ca1b8a37213f7" }, + { url = "http://10.0.0.2:5001/index/wrapt/wrapt-1.17.3-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:6fd1ad24dc235e4ab88cda009e19bf347aabb975e44fd5c2fb22a3f6e4141277" }, + { url = "http://10.0.0.2:5001/index/wrapt/wrapt-1.17.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0ed61b7c2d49cee3c027372df5809a59d60cf1b6c2f81ee980a091f3afed6a2d" }, + { url = "http://10.0.0.2:5001/index/wrapt/wrapt-1.17.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:423ed5420ad5f5529db9ce89eac09c8a2f97da18eb1c870237e84c5a5c2d60aa" }, + { url = "http://10.0.0.2:5001/index/wrapt/wrapt-1.17.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e01375f275f010fcbf7f643b4279896d04e571889b8a5b3f848423d91bf07050" }, + { url = "http://10.0.0.2:5001/index/wrapt/wrapt-1.17.3-cp313-cp313-win32.whl", hash = "sha256:53e5e39ff71b3fc484df8a522c933ea2b7cdd0d5d15ae82e5b23fde87d44cbd8" }, + { url = "http://10.0.0.2:5001/index/wrapt/wrapt-1.17.3-cp313-cp313-win_amd64.whl", hash = "sha256:1f0b2f40cf341ee8cc1a97d51ff50dddb9fcc73241b9143ec74b30fc4f44f6cb" }, + { url = "http://10.0.0.2:5001/index/wrapt/wrapt-1.17.3-cp313-cp313-win_arm64.whl", hash = "sha256:7425ac3c54430f5fc5e7b6f41d41e704db073309acfc09305816bc6a0b26bb16" }, + { url = "http://10.0.0.2:5001/index/wrapt/wrapt-1.17.3-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:cf30f6e3c077c8e6a9a7809c94551203c8843e74ba0c960f4a98cd80d4665d39" }, + { url = "http://10.0.0.2:5001/index/wrapt/wrapt-1.17.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:e228514a06843cae89621384cfe3a80418f3c04aadf8a3b14e46a7be704e4235" }, + { url = "http://10.0.0.2:5001/index/wrapt/wrapt-1.17.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:5ea5eb3c0c071862997d6f3e02af1d055f381b1d25b286b9d6644b79db77657c" }, + { url = "http://10.0.0.2:5001/index/wrapt/wrapt-1.17.3-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:281262213373b6d5e4bb4353bc36d1ba4084e6d6b5d242863721ef2bf2c2930b" }, + { url = "http://10.0.0.2:5001/index/wrapt/wrapt-1.17.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dc4a8d2b25efb6681ecacad42fca8859f88092d8732b170de6a5dddd80a1c8fa" }, + { url = "http://10.0.0.2:5001/index/wrapt/wrapt-1.17.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:373342dd05b1d07d752cecbec0c41817231f29f3a89aa8b8843f7b95992ed0c7" }, + { url = "http://10.0.0.2:5001/index/wrapt/wrapt-1.17.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d40770d7c0fd5cbed9d84b2c3f2e156431a12c9a37dc6284060fb4bec0b7ffd4" }, + { url = "http://10.0.0.2:5001/index/wrapt/wrapt-1.17.3-cp314-cp314-win32.whl", hash = "sha256:fbd3c8319de8e1dc79d346929cd71d523622da527cca14e0c1d257e31c2b8b10" }, + { url = "http://10.0.0.2:5001/index/wrapt/wrapt-1.17.3-cp314-cp314-win_amd64.whl", hash = "sha256:e1a4120ae5705f673727d3253de3ed0e016f7cd78dc463db1b31e2463e1f3cf6" }, + { url = "http://10.0.0.2:5001/index/wrapt/wrapt-1.17.3-cp314-cp314-win_arm64.whl", hash = "sha256:507553480670cab08a800b9463bdb881b2edeed77dc677b0a5915e6106e91a58" }, + { url = "http://10.0.0.2:5001/index/wrapt/wrapt-1.17.3-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:ed7c635ae45cfbc1a7371f708727bf74690daedc49b4dba310590ca0bd28aa8a" }, + { url = "http://10.0.0.2:5001/index/wrapt/wrapt-1.17.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:249f88ed15503f6492a71f01442abddd73856a0032ae860de6d75ca62eed8067" }, + { url = "http://10.0.0.2:5001/index/wrapt/wrapt-1.17.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5a03a38adec8066d5a37bea22f2ba6bbf39fcdefbe2d91419ab864c3fb515454" }, + { url = "http://10.0.0.2:5001/index/wrapt/wrapt-1.17.3-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:5d4478d72eb61c36e5b446e375bbc49ed002430d17cdec3cecb36993398e1a9e" }, + { url = "http://10.0.0.2:5001/index/wrapt/wrapt-1.17.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:223db574bb38637e8230eb14b185565023ab624474df94d2af18f1cdb625216f" }, + { url = "http://10.0.0.2:5001/index/wrapt/wrapt-1.17.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e405adefb53a435f01efa7ccdec012c016b5a1d3f35459990afc39b6be4d5056" }, + { url = "http://10.0.0.2:5001/index/wrapt/wrapt-1.17.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:88547535b787a6c9ce4086917b6e1d291aa8ed914fdd3a838b3539dc95c12804" }, + { url = "http://10.0.0.2:5001/index/wrapt/wrapt-1.17.3-cp314-cp314t-win32.whl", hash = "sha256:41b1d2bc74c2cac6f9074df52b2efbef2b30bdfe5f40cb78f8ca22963bc62977" }, + { url = "http://10.0.0.2:5001/index/wrapt/wrapt-1.17.3-cp314-cp314t-win_amd64.whl", hash = "sha256:73d496de46cd2cdbdbcce4ae4bcdb4afb6a11234a1df9c085249d55166b95116" }, + { url = "http://10.0.0.2:5001/index/wrapt/wrapt-1.17.3-cp314-cp314t-win_arm64.whl", hash = "sha256:f38e60678850c42461d4202739f9bf1e3a737c7ad283638251e79cc49effb6b6" }, + { url = "http://10.0.0.2:5001/index/wrapt/wrapt-1.17.3-py3-none-any.whl", hash = "sha256:7171ae35d2c33d326ac19dd8facb1e82e5fd04ef8c6c0e394d7af55a55051c22" }, +] From 25286c3eab0d58095e64e0c844581de86bed96dd Mon Sep 17 00:00:00 2001 From: Brian Bjarke Jensen Date: Thu, 18 Sep 2025 12:20:34 +0200 Subject: [PATCH 2/4] fixed CI step --- .gitea/workflows/code-quality.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitea/workflows/code-quality.yml b/.gitea/workflows/code-quality.yml index e0bf4fd..273d281 100644 --- a/.gitea/workflows/code-quality.yml +++ b/.gitea/workflows/code-quality.yml @@ -40,4 +40,5 @@ jobs: - name: Prettier format run: | - uv run prettier --check . + npm install --save-dev --save-exact prettier + npx prettier --check . From f96159829cf3539a99aba179bc283bf6b6c9177c Mon Sep 17 00:00:00 2001 From: Brian Bjarke Jensen Date: Thu, 18 Sep 2025 12:24:56 +0200 Subject: [PATCH 3/4] fixed pytest in CI --- .gitea/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitea/workflows/test.yml b/.gitea/workflows/test.yml index a75c48c..0edfdf9 100644 --- a/.gitea/workflows/test.yml +++ b/.gitea/workflows/test.yml @@ -29,7 +29,7 @@ jobs: - name: Run pytest env: PYTHONPATH: . - run: uv run pytest --cov=python_repositories --cov-report=term-missing > coverage.txt + run: uv run pytest --cov=data_store --cov-report=term-missing > coverage.txt - name: Post coverage summary to PR env: From f8e435bfe225bf2ad2d378cff9c39fec29e139b9 Mon Sep 17 00:00:00 2001 From: Brian Bjarke Jensen Date: Thu, 18 Sep 2025 12:40:57 +0200 Subject: [PATCH 4/4] removed bound ports to avoid clashing with servers minio instance --- tests/integration/conftest.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index 566594c..16f2dc8 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -66,9 +66,6 @@ def minio_container() -> Generator[dict[str, str]]: image=MINIO_DOCKER_IMAGE, access_key=access_key, secret_key=secret_key, - ).with_bind_ports( # expose webUI on 9001 - container=9001, - host=9001, ) container.start() # Build environment variables dictionary