From 2d67517fa4d6a147adb731d8b5f7dde8be943d17 Mon Sep 17 00:00:00 2001 From: Ramin Gharib Date: Tue, 9 Apr 2024 13:36:05 +0200 Subject: [PATCH 1/8] Add Stateful Stream Apps component --- .../kubernetes/pvc_handler.py | 47 +++++ .../streams_bootstrap/streams/model.py | 42 ++++- .../streams_bootstrap/streams/streams_app.py | 45 ++++- tests/components/test_streams_app.py | 168 +++++++++++++++++- 4 files changed, 297 insertions(+), 5 deletions(-) create mode 100644 kpops/component_handlers/kubernetes/pvc_handler.py diff --git a/kpops/component_handlers/kubernetes/pvc_handler.py b/kpops/component_handlers/kubernetes/pvc_handler.py new file mode 100644 index 000000000..5653b5297 --- /dev/null +++ b/kpops/component_handlers/kubernetes/pvc_handler.py @@ -0,0 +1,47 @@ +import json +import logging +import subprocess + +log = logging.getLogger("PVC_handler") + + +# TODO: Use official Kubernetes client for Python to do this task + + +class PVCHandler: + def __init__(self, app_name: str, namespace: str): + self.app_name = app_name + self.namespace = namespace + + @property + def pvc_names(self) -> list[str]: + pvc_data = subprocess.check_output( + [ + "kubectl", + "get", + "-n", + f"{self.namespace}", + "pvc", + "-l", + f"app={self.app_name}", + "-o", + "json", + ] + ) + pvc_list = json.loads(pvc_data) + + pvc_names = [pvc["metadata"]["name"] for pvc in pvc_list["items"]] + log.debug( + f"In namespace '{self.namespace}' StatefulSet '{self.app_name}' has corresponding PVCs: '{pvc_names}'" + ) + return pvc_names + + def delete_pvcs(self) -> None: + pvc_names = self.pvc_names + log.debug( + f"Deleting in namespace '{self.namespace}' StatefulSet '{self.app_name}' PVCs '{pvc_names}'" + ) + subprocess.run( + ["kubectl", "delete", "-n", f"{self.namespace}", "pvc", *pvc_names], + check=False, + ) diff --git a/kpops/components/streams_bootstrap/streams/model.py b/kpops/components/streams_bootstrap/streams/model.py index 5db08c31c..c668d41ac 100644 --- a/kpops/components/streams_bootstrap/streams/model.py +++ b/kpops/components/streams_bootstrap/streams/model.py @@ -3,7 +3,7 @@ from typing import Any import pydantic -from pydantic import ConfigDict, Field, model_validator +from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator from kpops.components.base_components.kafka_app import ( KafkaAppValues, @@ -221,3 +221,43 @@ class StreamsAppValues(KafkaAppValues): description=describe_attr("autoscaling", __doc__), ) model_config = ConfigDict(extra="allow") + + +class PersistenceConfig(BaseModel): + enabled: bool = Field( + default=False, description="Whether create PVCs for the StatefulSet." + ) + size: str = Field( + default=None, + description="The size of the PersistentVolume to allocate to each streams pod in the StatefulSet.", + ) + + @model_validator(mode="after") + def validate_mandatory_fields_are_set( + self: PersistenceConfig, + ) -> PersistenceConfig: # TODO: typing.Self for Python 3.11+ + if self.enabled and self.size is None: + msg = ( + "If app.persistence.enabled is set to true, " + "the field app.persistence.size needs to be set." + ) + raise ValidationError(msg) + return self + + +class StatefulStreamsAppValues(StreamsAppValues): + stateful_set: bool = Field( + default=True, frozen=True, serialization_alias="statefulSet" + ) + persistence: PersistenceConfig + + @field_validator("streams", mode="before", check_fields=False) + @classmethod + def enable_static_membership( + cls, + streams: StreamsConfig | dict[str, Any], + ) -> StreamsConfig: + if isinstance(streams, StreamsConfig): + streams = streams.model_dump() + streams["staticMembership"] = True + return StreamsConfig(**streams) diff --git a/kpops/components/streams_bootstrap/streams/streams_app.py b/kpops/components/streams_bootstrap/streams/streams_app.py index 47a96cce9..96933b860 100644 --- a/kpops/components/streams_bootstrap/streams/streams_app.py +++ b/kpops/components/streams_bootstrap/streams/streams_app.py @@ -1,8 +1,10 @@ +import logging from functools import cached_property from pydantic import Field, computed_field from typing_extensions import override +from kpops.component_handlers.kubernetes.pvc_handler import PVCHandler from kpops.components.base_components.kafka_app import ( KafkaApp, KafkaAppCleaner, @@ -10,9 +12,14 @@ from kpops.components.base_components.models.topic import KafkaTopic from kpops.components.streams_bootstrap import StreamsBootstrap from kpops.components.streams_bootstrap.app_type import AppType -from kpops.components.streams_bootstrap.streams.model import StreamsAppValues +from kpops.components.streams_bootstrap.streams.model import ( + StatefulStreamsAppValues, + StreamsAppValues, +) from kpops.utils.docstring import describe_attr +log = logging.getLogger("StreamsApp") + class StreamsAppCleaner(KafkaAppCleaner): from_: None = None @@ -25,6 +32,27 @@ def helm_chart(self) -> str: return f"{self.repo_config.repository_name}/{AppType.CLEANUP_STREAMS_APP.value}" +class StatefulStreamsAppCleaner(StreamsAppCleaner): + from_: None = None + to: None = None + app: StatefulStreamsAppValues + + @cached_property + def pvc_handler(self) -> PVCHandler: + return PVCHandler(self.full_name, self.namespace) + + @override + async def clean(self, dry_run: bool) -> None: + await super().clean(dry_run) + if dry_run: + log.info( + f"Deleting the PVCs {self.pvc_handler.pvc_names} for StatefulSet '{self.full_name}'" + ) + if not dry_run and self.app.persistence.enabled: + log.info(f"Deleting the PVCs for StatefulSet '{self.full_name}'") + self.pvc_handler.delete_pvcs() + + class StreamsApp(KafkaApp, StreamsBootstrap): """StreamsApp component that configures a streams-bootstrap app. @@ -107,3 +135,18 @@ async def reset(self, dry_run: bool) -> None: async def clean(self, dry_run: bool) -> None: self._cleaner.app.streams.delete_output = True await self._cleaner.clean(dry_run) + + +class StatefulStreamsApp(StreamsApp): + app: StatefulStreamsAppValues = Field( + default=..., + ) + + @computed_field + @cached_property + def _cleaner(self) -> StatefulStreamsAppCleaner: + return StatefulStreamsAppCleaner( + config=self.config, + handlers=self.handlers, + **self.model_dump(by_alias=True, exclude={"_cleaner", "from_", "to"}), + ) diff --git a/tests/components/test_streams_app.py b/tests/components/test_streams_app.py index 942493721..fdaab3f76 100644 --- a/tests/components/test_streams_app.py +++ b/tests/components/test_streams_app.py @@ -1,5 +1,5 @@ from pathlib import Path -from unittest.mock import ANY, AsyncMock +from unittest.mock import ANY, AsyncMock, MagicMock import pytest from pytest_mock import MockerFixture @@ -20,8 +20,15 @@ OutputTopicTypes, TopicConfig, ) -from kpops.components.streams_bootstrap.streams.model import StreamsAppAutoScaling -from kpops.components.streams_bootstrap.streams.streams_app import StreamsAppCleaner +from kpops.components.streams_bootstrap.streams.model import ( + PersistenceConfig, + StreamsAppAutoScaling, +) +from kpops.components.streams_bootstrap.streams.streams_app import ( + StatefulStreamsApp, + StatefulStreamsAppCleaner, + StreamsAppCleaner, +) from kpops.config import KpopsConfig, TopicNameConfig from kpops.pipeline import ValidationError from tests.components import PIPELINE_BASE_DIR @@ -90,6 +97,30 @@ def streams_app( }, ) + @pytest.fixture() + def stateful_streams_app( + self, config: KpopsConfig, handlers: ComponentHandlers + ) -> StatefulStreamsApp: + return StatefulStreamsApp( + name=STREAMS_APP_NAME, + config=config, + handlers=handlers, + **{ + "namespace": "test-namespace", + "app": { + "streams": {"brokers": "fake-broker:9092"}, + "persistence": {"enabled": True, "size": "5Gi"}, + }, + "to": { + "topics": { + "streams-app-output-topic": TopicConfig( + type=OutputTopicTypes.OUTPUT, partitions_count=10 + ), + } + }, + }, + ) + def test_cleaner(self, streams_app: StreamsApp): cleaner = streams_app._cleaner assert isinstance(cleaner, StreamsAppCleaner) @@ -661,3 +692,134 @@ async def test_get_input_output_topics( KafkaTopic(name="topic-extra3"), KafkaTopic(name="topic-extra"), ] + + def test_stateful_cleaner_is_correct_instance( + self, stateful_streams_app: StatefulStreamsApp + ): + cleaner = stateful_streams_app._cleaner + assert isinstance(cleaner, StreamsAppCleaner) + assert not hasattr(cleaner, "_cleaner") + + def test_raise_validation_error_when_persistence_enabled_and_size_not_set( + self, stateful_streams_app: StatefulStreamsApp + ): + with pytest.raises(ValidationError) as error: + stateful_streams_app.app.persistence = PersistenceConfig( + enabled=True, + ) + msg = ( + "If app.persistence.enabled is set to true, " + "the field app.persistence.size needs to be set." + ) + assert str(error.value) == msg + + @pytest.mark.asyncio() + @pytest.mark.skip(reason="For some reason the helm is not mocked!") + async def test_stateful_clean_with_dry_run_true( + self, stateful_streams_app: StatefulStreamsApp, mocker: MockerFixture + ): + cleaner = stateful_streams_app._cleaner + assert isinstance(cleaner, StatefulStreamsAppCleaner) + + mock_helm_upgrade_install = mocker.patch.object(cleaner.helm, "upgrade_install") + mock_helm_uninstall = mocker.patch.object(cleaner.helm, "uninstall") + mock_delete_pvcs = mocker.patch.object(cleaner.pvc_handler, "delete_pvcs") + + mock = MagicMock() + mock.attach_mock(mock_helm_upgrade_install, "helm_upgrade_install") + mock.attach_mock(mock_helm_uninstall, "helm_uninstall") + mock.attach_mock(mock_delete_pvcs, "delete_pvcs") + + dry_run = True + await stateful_streams_app.clean(dry_run=dry_run) + + mock.assert_has_calls( + [ + mocker.call.helm_uninstall( + "test-namespace", + STREAMS_APP_CLEAN_RELEASE_NAME, + dry_run, + ), + ANY, # __bool__ + ANY, # __str__ + mocker.call.helm_upgrade_install( + STREAMS_APP_CLEAN_RELEASE_NAME, + "bakdata-streams-bootstrap/streams-app-cleanup-job", + dry_run, + "test-namespace", + { + "nameOverride": STREAMS_APP_CLEAN_HELM_NAME_OVERRIDE, + "streams": { + "brokers": "fake-broker:9092", + "outputTopic": "streams-app-output-topic", + "deleteOutput": True, + }, + }, + HelmUpgradeInstallFlags( + version="2.9.0", wait=True, wait_for_jobs=True + ), + ), + mocker.call.helm_uninstall( + "test-namespace", + STREAMS_APP_CLEAN_RELEASE_NAME, + dry_run, + ), + ] + ) + + @pytest.mark.asyncio() + @pytest.mark.skip(reason="For some reason the call stack is wrong!") + async def test_stateful_clean_with_dry_run_false( + self, stateful_streams_app: StatefulStreamsApp, mocker: MockerFixture + ): + cleaner = stateful_streams_app._cleaner + assert isinstance(cleaner, StatefulStreamsAppCleaner) + + mock_helm_upgrade_install = mocker.patch.object(cleaner.helm, "upgrade_install") + mock_helm_uninstall = mocker.patch.object(cleaner.helm, "uninstall") + mock_delete_pvcs = mocker.patch.object(cleaner.pvc_handler, "delete_pvcs") + + mock = MagicMock() + mock.attach_mock(mock_helm_upgrade_install, "helm_upgrade_install") + mock.attach_mock(mock_helm_uninstall, "helm_uninstall") + mock.attach_mock(mock_delete_pvcs, "delete_pvcs") + + dry_run = False + await stateful_streams_app.clean(dry_run=dry_run) + + mock.assert_has_calls( + [ + mocker.call.helm_uninstall( + "test-namespace", + STREAMS_APP_CLEAN_RELEASE_NAME, + dry_run, + ), + ANY, # __bool__ + ANY, # __str__ + mocker.call.helm_upgrade_install( + STREAMS_APP_CLEAN_RELEASE_NAME, + "bakdata-streams-bootstrap/streams-app-cleanup-job", + dry_run, + "test-namespace", + { + "nameOverride": STREAMS_APP_CLEAN_HELM_NAME_OVERRIDE, + "streams": { + "brokers": "fake-broker:9092", + "outputTopic": "streams-app-output-topic", + "deleteOutput": True, + }, + }, + HelmUpgradeInstallFlags( + version="2.9.0", wait=True, wait_for_jobs=True + ), + ), + mocker.call.helm_uninstall( + "test-namespace", + STREAMS_APP_CLEAN_RELEASE_NAME, + dry_run, + ), + ANY, # __bool__ + ANY, # __str__ + mocker.call.delete_pvcs(), + ] + ) From 0bec09e910321c385fed43034833b4d3b6df9516 Mon Sep 17 00:00:00 2001 From: Ramin Gharib Date: Tue, 9 Apr 2024 14:47:41 +0200 Subject: [PATCH 2/8] Move cleaning of PVCs to streams apps --- docs/docs/schema/defaults.json | 58 +++++++++++++++ docs/docs/schema/pipeline.json | 58 +++++++++++++++ .../streams_bootstrap/streams/model.py | 72 ++++++++++--------- .../streams_bootstrap/streams/streams_app.py | 26 ++----- tests/components/test_streams_app.py | 30 ++++---- 5 files changed, 170 insertions(+), 74 deletions(-) diff --git a/docs/docs/schema/defaults.json b/docs/docs/schema/defaults.json index aa09a6927..ae4af6582 100644 --- a/docs/docs/schema/defaults.json +++ b/docs/docs/schema/defaults.json @@ -738,6 +738,45 @@ "title": "OutputTopicTypes", "type": "string" }, + "PersistenceConfig": { + "description": "streams-bootstrap persistence configurations.\n\n:param enabled: Whether to use a persistent volume to store the state of the streams app.\n:param size: The size of the PersistentVolume to allocate to each streams pod in the StatefulSet.\n:param storage_class: Storage class to use for the persistent volume.", + "properties": { + "enabled": { + "default": false, + "description": "Whether to use a persistent volume to store the state of the streams app.\t", + "title": "Enabled", + "type": "boolean" + }, + "size": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "The size of the PersistentVolume to allocate to each streams pod in the StatefulSet.", + "title": "Size" + }, + "storage_class": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Storage class to use for the persistent volume.", + "title": "Storage Class" + } + }, + "title": "PersistenceConfig", + "type": "object" + }, "PipelineComponent": { "additionalProperties": true, "description": "Base class for all components.", @@ -1248,6 +1287,25 @@ "description": "Helm chart name override, assigned automatically", "title": "Nameoverride" }, + "persistence": { + "allOf": [ + { + "$ref": "#/$defs/PersistenceConfig" + } + ], + "default": { + "enabled": false, + "size": null, + "storage_class": null + }, + "description": "" + }, + "statefulSet": { + "default": false, + "description": "Whether to use a Statefulset instead of a Deployment to deploy the streams app.", + "title": "Statefulset", + "type": "boolean" + }, "streams": { "allOf": [ { diff --git a/docs/docs/schema/pipeline.json b/docs/docs/schema/pipeline.json index fa3897370..ea33470b3 100644 --- a/docs/docs/schema/pipeline.json +++ b/docs/docs/schema/pipeline.json @@ -453,6 +453,45 @@ "title": "OutputTopicTypes", "type": "string" }, + "PersistenceConfig": { + "description": "streams-bootstrap persistence configurations.\n\n:param enabled: Whether to use a persistent volume to store the state of the streams app.\n:param size: The size of the PersistentVolume to allocate to each streams pod in the StatefulSet.\n:param storage_class: Storage class to use for the persistent volume.", + "properties": { + "enabled": { + "default": false, + "description": "Whether to use a persistent volume to store the state of the streams app.\t", + "title": "Enabled", + "type": "boolean" + }, + "size": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "The size of the PersistentVolume to allocate to each streams pod in the StatefulSet.", + "title": "Size" + }, + "storage_class": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Storage class to use for the persistent volume.", + "title": "Storage Class" + } + }, + "title": "PersistenceConfig", + "type": "object" + }, "ProducerApp": { "additionalProperties": true, "description": "Producer component.\nThis producer holds configuration to use as values for the streams-bootstrap producer Helm chart. Note that the producer does not support error topics.", @@ -916,6 +955,25 @@ "description": "Helm chart name override, assigned automatically", "title": "Nameoverride" }, + "persistence": { + "allOf": [ + { + "$ref": "#/$defs/PersistenceConfig" + } + ], + "default": { + "enabled": false, + "size": null, + "storage_class": null + }, + "description": "" + }, + "statefulSet": { + "default": false, + "description": "Whether to use a Statefulset instead of a Deployment to deploy the streams app.", + "title": "Statefulset", + "type": "boolean" + }, "streams": { "allOf": [ { diff --git a/kpops/components/streams_bootstrap/streams/model.py b/kpops/components/streams_bootstrap/streams/model.py index c668d41ac..df2348773 100644 --- a/kpops/components/streams_bootstrap/streams/model.py +++ b/kpops/components/streams_bootstrap/streams/model.py @@ -3,7 +3,7 @@ from typing import Any import pydantic -from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator +from pydantic import BaseModel, ConfigDict, Field, model_validator from kpops.components.base_components.kafka_app import ( KafkaAppValues, @@ -203,34 +203,26 @@ def validate_mandatory_fields_are_set( return self -class StreamsAppValues(KafkaAppValues): - """streams-bootstrap app configurations. - - The attributes correspond to keys and values that are used as values for the streams bootstrap helm chart. +class PersistenceConfig(BaseModel): + """streams-bootstrap persistence configurations. - :param streams: streams-bootstrap streams section - :param autoscaling: Kubernetes event-driven autoscaling config, defaults to None + :param enabled: Whether to use a persistent volume to store the state of the streams app. + :param size: The size of the PersistentVolume to allocate to each streams pod in the StatefulSet. + :param storage_class: Storage class to use for the persistent volume. """ - streams: StreamsConfig = Field( - default=..., - description=describe_attr("streams", __doc__), - ) - autoscaling: StreamsAppAutoScaling | None = Field( - default=None, - description=describe_attr("autoscaling", __doc__), - ) - model_config = ConfigDict(extra="allow") - - -class PersistenceConfig(BaseModel): enabled: bool = Field( - default=False, description="Whether create PVCs for the StatefulSet." + default=False, + description="Whether to use a persistent volume to store the state of the streams app. ", ) - size: str = Field( + size: str | None = Field( default=None, description="The size of the PersistentVolume to allocate to each streams pod in the StatefulSet.", ) + storage_class: str | None = Field( + default=None, + description="Storage class to use for the persistent volume.", + ) @model_validator(mode="after") def validate_mandatory_fields_are_set( @@ -245,19 +237,29 @@ def validate_mandatory_fields_are_set( return self -class StatefulStreamsAppValues(StreamsAppValues): +class StreamsAppValues(KafkaAppValues): + """streams-bootstrap app configurations. + + The attributes correspond to keys and values that are used as values for the streams bootstrap helm chart. + + :param streams: streams-bootstrap streams section + :param autoscaling: Kubernetes event-driven autoscaling config, defaults to None + """ + + streams: StreamsConfig = Field( + default=..., + description=describe_attr("streams", __doc__), + ) + autoscaling: StreamsAppAutoScaling | None = Field( + default=None, + description=describe_attr("autoscaling", __doc__), + ) stateful_set: bool = Field( - default=True, frozen=True, serialization_alias="statefulSet" + default=False, + description="Whether to use a Statefulset instead of a Deployment to deploy the streams app.", ) - persistence: PersistenceConfig - - @field_validator("streams", mode="before", check_fields=False) - @classmethod - def enable_static_membership( - cls, - streams: StreamsConfig | dict[str, Any], - ) -> StreamsConfig: - if isinstance(streams, StreamsConfig): - streams = streams.model_dump() - streams["staticMembership"] = True - return StreamsConfig(**streams) + persistence: PersistenceConfig = Field( + default=PersistenceConfig(), + description=describe_attr("persistence", __doc__), + ) + model_config = ConfigDict(extra="allow") diff --git a/kpops/components/streams_bootstrap/streams/streams_app.py b/kpops/components/streams_bootstrap/streams/streams_app.py index 96933b860..5d497109f 100644 --- a/kpops/components/streams_bootstrap/streams/streams_app.py +++ b/kpops/components/streams_bootstrap/streams/streams_app.py @@ -13,7 +13,6 @@ from kpops.components.streams_bootstrap import StreamsBootstrap from kpops.components.streams_bootstrap.app_type import AppType from kpops.components.streams_bootstrap.streams.model import ( - StatefulStreamsAppValues, StreamsAppValues, ) from kpops.utils.docstring import describe_attr @@ -31,12 +30,6 @@ class StreamsAppCleaner(KafkaAppCleaner): def helm_chart(self) -> str: return f"{self.repo_config.repository_name}/{AppType.CLEANUP_STREAMS_APP.value}" - -class StatefulStreamsAppCleaner(StreamsAppCleaner): - from_: None = None - to: None = None - app: StatefulStreamsAppValues - @cached_property def pvc_handler(self) -> PVCHandler: return PVCHandler(self.full_name, self.namespace) @@ -44,6 +37,10 @@ def pvc_handler(self) -> PVCHandler: @override async def clean(self, dry_run: bool) -> None: await super().clean(dry_run) + if self.app.stateful_set: + await self.clean_pvcs(dry_run) + + async def clean_pvcs(self, dry_run): if dry_run: log.info( f"Deleting the PVCs {self.pvc_handler.pvc_names} for StatefulSet '{self.full_name}'" @@ -135,18 +132,3 @@ async def reset(self, dry_run: bool) -> None: async def clean(self, dry_run: bool) -> None: self._cleaner.app.streams.delete_output = True await self._cleaner.clean(dry_run) - - -class StatefulStreamsApp(StreamsApp): - app: StatefulStreamsAppValues = Field( - default=..., - ) - - @computed_field - @cached_property - def _cleaner(self) -> StatefulStreamsAppCleaner: - return StatefulStreamsAppCleaner( - config=self.config, - handlers=self.handlers, - **self.model_dump(by_alias=True, exclude={"_cleaner", "from_", "to"}), - ) diff --git a/tests/components/test_streams_app.py b/tests/components/test_streams_app.py index fdaab3f76..32d238110 100644 --- a/tests/components/test_streams_app.py +++ b/tests/components/test_streams_app.py @@ -25,8 +25,6 @@ StreamsAppAutoScaling, ) from kpops.components.streams_bootstrap.streams.streams_app import ( - StatefulStreamsApp, - StatefulStreamsAppCleaner, StreamsAppCleaner, ) from kpops.config import KpopsConfig, TopicNameConfig @@ -100,16 +98,19 @@ def streams_app( @pytest.fixture() def stateful_streams_app( self, config: KpopsConfig, handlers: ComponentHandlers - ) -> StatefulStreamsApp: - return StatefulStreamsApp( + ) -> StreamsApp: + return StreamsApp( name=STREAMS_APP_NAME, config=config, handlers=handlers, **{ "namespace": "test-namespace", "app": { - "streams": {"brokers": "fake-broker:9092"}, + "statefulSet": True, "persistence": {"enabled": True, "size": "5Gi"}, + "streams": { + "brokers": "fake-broker:9092", + }, }, "to": { "topics": { @@ -693,15 +694,8 @@ async def test_get_input_output_topics( KafkaTopic(name="topic-extra"), ] - def test_stateful_cleaner_is_correct_instance( - self, stateful_streams_app: StatefulStreamsApp - ): - cleaner = stateful_streams_app._cleaner - assert isinstance(cleaner, StreamsAppCleaner) - assert not hasattr(cleaner, "_cleaner") - def test_raise_validation_error_when_persistence_enabled_and_size_not_set( - self, stateful_streams_app: StatefulStreamsApp + self, stateful_streams_app: StreamsApp ): with pytest.raises(ValidationError) as error: stateful_streams_app.app.persistence = PersistenceConfig( @@ -716,10 +710,10 @@ def test_raise_validation_error_when_persistence_enabled_and_size_not_set( @pytest.mark.asyncio() @pytest.mark.skip(reason="For some reason the helm is not mocked!") async def test_stateful_clean_with_dry_run_true( - self, stateful_streams_app: StatefulStreamsApp, mocker: MockerFixture + self, stateful_streams_app: StreamsApp, mocker: MockerFixture ): cleaner = stateful_streams_app._cleaner - assert isinstance(cleaner, StatefulStreamsAppCleaner) + assert isinstance(cleaner, StreamsAppCleaner) mock_helm_upgrade_install = mocker.patch.object(cleaner.helm, "upgrade_install") mock_helm_uninstall = mocker.patch.object(cleaner.helm, "uninstall") @@ -733,6 +727,8 @@ async def test_stateful_clean_with_dry_run_true( dry_run = True await stateful_streams_app.clean(dry_run=dry_run) + # TODO: Assert Log + mock.assert_has_calls( [ mocker.call.helm_uninstall( @@ -770,10 +766,10 @@ async def test_stateful_clean_with_dry_run_true( @pytest.mark.asyncio() @pytest.mark.skip(reason="For some reason the call stack is wrong!") async def test_stateful_clean_with_dry_run_false( - self, stateful_streams_app: StatefulStreamsApp, mocker: MockerFixture + self, stateful_streams_app: StreamsApp, mocker: MockerFixture ): cleaner = stateful_streams_app._cleaner - assert isinstance(cleaner, StatefulStreamsAppCleaner) + assert isinstance(cleaner, StreamsAppCleaner) mock_helm_upgrade_install = mocker.patch.object(cleaner.helm, "upgrade_install") mock_helm_uninstall = mocker.patch.object(cleaner.helm, "uninstall") From f2aa7b7627fd8ba8cbfb3bdc0d1e178c5b90e096 Mon Sep 17 00:00:00 2001 From: Ramin Gharib Date: Tue, 9 Apr 2024 16:10:25 +0200 Subject: [PATCH 3/8] fix test --- tests/components/test_streams_app.py | 59 +--------------------------- 1 file changed, 2 insertions(+), 57 deletions(-) diff --git a/tests/components/test_streams_app.py b/tests/components/test_streams_app.py index 32d238110..4058741fd 100644 --- a/tests/components/test_streams_app.py +++ b/tests/components/test_streams_app.py @@ -708,63 +708,6 @@ def test_raise_validation_error_when_persistence_enabled_and_size_not_set( assert str(error.value) == msg @pytest.mark.asyncio() - @pytest.mark.skip(reason="For some reason the helm is not mocked!") - async def test_stateful_clean_with_dry_run_true( - self, stateful_streams_app: StreamsApp, mocker: MockerFixture - ): - cleaner = stateful_streams_app._cleaner - assert isinstance(cleaner, StreamsAppCleaner) - - mock_helm_upgrade_install = mocker.patch.object(cleaner.helm, "upgrade_install") - mock_helm_uninstall = mocker.patch.object(cleaner.helm, "uninstall") - mock_delete_pvcs = mocker.patch.object(cleaner.pvc_handler, "delete_pvcs") - - mock = MagicMock() - mock.attach_mock(mock_helm_upgrade_install, "helm_upgrade_install") - mock.attach_mock(mock_helm_uninstall, "helm_uninstall") - mock.attach_mock(mock_delete_pvcs, "delete_pvcs") - - dry_run = True - await stateful_streams_app.clean(dry_run=dry_run) - - # TODO: Assert Log - - mock.assert_has_calls( - [ - mocker.call.helm_uninstall( - "test-namespace", - STREAMS_APP_CLEAN_RELEASE_NAME, - dry_run, - ), - ANY, # __bool__ - ANY, # __str__ - mocker.call.helm_upgrade_install( - STREAMS_APP_CLEAN_RELEASE_NAME, - "bakdata-streams-bootstrap/streams-app-cleanup-job", - dry_run, - "test-namespace", - { - "nameOverride": STREAMS_APP_CLEAN_HELM_NAME_OVERRIDE, - "streams": { - "brokers": "fake-broker:9092", - "outputTopic": "streams-app-output-topic", - "deleteOutput": True, - }, - }, - HelmUpgradeInstallFlags( - version="2.9.0", wait=True, wait_for_jobs=True - ), - ), - mocker.call.helm_uninstall( - "test-namespace", - STREAMS_APP_CLEAN_RELEASE_NAME, - dry_run, - ), - ] - ) - - @pytest.mark.asyncio() - @pytest.mark.skip(reason="For some reason the call stack is wrong!") async def test_stateful_clean_with_dry_run_false( self, stateful_streams_app: StreamsApp, mocker: MockerFixture ): @@ -799,6 +742,8 @@ async def test_stateful_clean_with_dry_run_false( "test-namespace", { "nameOverride": STREAMS_APP_CLEAN_HELM_NAME_OVERRIDE, + "statefulSet": True, + "persistence": {"enabled": True, "size": "5Gi"}, "streams": { "brokers": "fake-broker:9092", "outputTopic": "streams-app-output-topic", From 322642a44d9d8f0b8e9b8d6c2c9640c56dac5b10 Mon Sep 17 00:00:00 2001 From: Ramin Gharib Date: Thu, 11 Apr 2024 09:46:20 +0200 Subject: [PATCH 4/8] update snapshots --- .../kubernetes/pvc_handler.py | 73 +-- .../streams_bootstrap/streams/streams_app.py | 7 +- poetry.lock | 442 +++++++++++++++++- pyproject.toml | 1 + .../test_generate/atm-fraud/pipeline.yaml | 18 + .../test_generate/word-count/pipeline.yaml | 6 + .../test_default_config/pipeline.yaml | 6 + .../test_inflate_pipeline/pipeline.yaml | 18 + .../pipeline.yaml | 6 + .../test_load_pipeline/pipeline.yaml | 12 + .../test_no_input_topic/pipeline.yaml | 12 + .../pipeline.yaml | 6 + .../test_pipelines_with_envs/pipeline.yaml | 12 + .../test_read_from_component/pipeline.yaml | 54 +++ .../pipeline.yaml | 12 + .../pipeline.yaml | 6 + .../pipeline.yaml | 6 + .../test_with_env_defaults/pipeline.yaml | 6 + 18 files changed, 663 insertions(+), 40 deletions(-) diff --git a/kpops/component_handlers/kubernetes/pvc_handler.py b/kpops/component_handlers/kubernetes/pvc_handler.py index 5653b5297..052485ccb 100644 --- a/kpops/component_handlers/kubernetes/pvc_handler.py +++ b/kpops/component_handlers/kubernetes/pvc_handler.py @@ -1,11 +1,9 @@ -import json import logging -import subprocess - -log = logging.getLogger("PVC_handler") +from kubernetes_asyncio import client, config +from kubernetes_asyncio.client import ApiClient -# TODO: Use official Kubernetes client for Python to do this task +log = logging.getLogger("PVC_handler") class PVCHandler: @@ -13,35 +11,38 @@ def __init__(self, app_name: str, namespace: str): self.app_name = app_name self.namespace = namespace + @classmethod + async def create(cls, app_name: str, namespace: str): + self = cls(app_name, namespace) + await config.load_kube_config() + return self + @property - def pvc_names(self) -> list[str]: - pvc_data = subprocess.check_output( - [ - "kubectl", - "get", - "-n", - f"{self.namespace}", - "pvc", - "-l", - f"app={self.app_name}", - "-o", - "json", - ] - ) - pvc_list = json.loads(pvc_data) - - pvc_names = [pvc["metadata"]["name"] for pvc in pvc_list["items"]] - log.debug( - f"In namespace '{self.namespace}' StatefulSet '{self.app_name}' has corresponding PVCs: '{pvc_names}'" - ) - return pvc_names - - def delete_pvcs(self) -> None: - pvc_names = self.pvc_names - log.debug( - f"Deleting in namespace '{self.namespace}' StatefulSet '{self.app_name}' PVCs '{pvc_names}'" - ) - subprocess.run( - ["kubectl", "delete", "-n", f"{self.namespace}", "pvc", *pvc_names], - check=False, - ) + async def pvc_names(self) -> list[str]: + async with ApiClient() as api: + core_v1_api = client.CoreV1Api(api) + pvc_list = core_v1_api.list_namespaced_persistent_volume_claim( + self.namespace, label_selector=f"app={self.app_name}" + ) + + pvc_names = [pvc.metadata.name for pvc in pvc_list.items] + if not pvc_names: + log.warning( + f"No PVCs found for app '{self.app_name}', in namespace '{self.namespace}'" + ) + log.debug( + f"In namespace '{self.namespace}' StatefulSet '{self.app_name}' has corresponding PVCs: '{pvc_names}'" + ) + return pvc_names + + async def delete_pvcs(self) -> None: + async with ApiClient() as api: + core_v1_api = client.CoreV1Api(api) + pvc_names = await self.pvc_names + log.debug( + f"Deleting in namespace '{self.namespace}' StatefulSet '{self.app_name}' PVCs '{pvc_names}'" + ) + for pvc_name in pvc_names: + core_v1_api.delete_namespaced_persistent_volume_claim( + pvc_name, self.namespace + ) diff --git a/kpops/components/streams_bootstrap/streams/streams_app.py b/kpops/components/streams_bootstrap/streams/streams_app.py index 5d497109f..dcc5b7d1e 100644 --- a/kpops/components/streams_bootstrap/streams/streams_app.py +++ b/kpops/components/streams_bootstrap/streams/streams_app.py @@ -40,14 +40,15 @@ async def clean(self, dry_run: bool) -> None: if self.app.stateful_set: await self.clean_pvcs(dry_run) - async def clean_pvcs(self, dry_run): + async def clean_pvcs(self, dry_run: bool) -> None: if dry_run: + pvc_names = await self.pvc_handler.pvc_names log.info( - f"Deleting the PVCs {self.pvc_handler.pvc_names} for StatefulSet '{self.full_name}'" + f"Deleting the PVCs {pvc_names} for StatefulSet '{self.full_name}'" ) if not dry_run and self.app.persistence.enabled: log.info(f"Deleting the PVCs for StatefulSet '{self.full_name}'") - self.pvc_handler.delete_pvcs() + await self.pvc_handler.delete_pvcs() class StreamsApp(KafkaApp, StreamsBootstrap): diff --git a/poetry.lock b/poetry.lock index fbf97254b..1089dfff0 100644 --- a/poetry.lock +++ b/poetry.lock @@ -11,6 +11,116 @@ files = [ {file = "aiofiles-23.1.0.tar.gz", hash = "sha256:edd247df9a19e0db16534d4baaf536d6609a43e1de5401d7a4c1c148753a1635"}, ] +[[package]] +name = "aiohttp" +version = "3.9.3" +description = "Async http client/server framework (asyncio)" +optional = false +python-versions = ">=3.8" +files = [ + {file = "aiohttp-3.9.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:939677b61f9d72a4fa2a042a5eee2a99a24001a67c13da113b2e30396567db54"}, + {file = "aiohttp-3.9.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1f5cd333fcf7590a18334c90f8c9147c837a6ec8a178e88d90a9b96ea03194cc"}, + {file = "aiohttp-3.9.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:82e6aa28dd46374f72093eda8bcd142f7771ee1eb9d1e223ff0fa7177a96b4a5"}, + {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f56455b0c2c7cc3b0c584815264461d07b177f903a04481dfc33e08a89f0c26b"}, + {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bca77a198bb6e69795ef2f09a5f4c12758487f83f33d63acde5f0d4919815768"}, + {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e083c285857b78ee21a96ba1eb1b5339733c3563f72980728ca2b08b53826ca5"}, + {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ab40e6251c3873d86ea9b30a1ac6d7478c09277b32e14745d0d3c6e76e3c7e29"}, + {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:df822ee7feaaeffb99c1a9e5e608800bd8eda6e5f18f5cfb0dc7eeb2eaa6bbec"}, + {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:acef0899fea7492145d2bbaaaec7b345c87753168589cc7faf0afec9afe9b747"}, + {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:cd73265a9e5ea618014802ab01babf1940cecb90c9762d8b9e7d2cc1e1969ec6"}, + {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:a78ed8a53a1221393d9637c01870248a6f4ea5b214a59a92a36f18151739452c"}, + {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:6b0e029353361f1746bac2e4cc19b32f972ec03f0f943b390c4ab3371840aabf"}, + {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7cf5c9458e1e90e3c390c2639f1017a0379a99a94fdfad3a1fd966a2874bba52"}, + {file = "aiohttp-3.9.3-cp310-cp310-win32.whl", hash = "sha256:3e59c23c52765951b69ec45ddbbc9403a8761ee6f57253250c6e1536cacc758b"}, + {file = "aiohttp-3.9.3-cp310-cp310-win_amd64.whl", hash = "sha256:055ce4f74b82551678291473f66dc9fb9048a50d8324278751926ff0ae7715e5"}, + {file = "aiohttp-3.9.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6b88f9386ff1ad91ace19d2a1c0225896e28815ee09fc6a8932fded8cda97c3d"}, + {file = "aiohttp-3.9.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c46956ed82961e31557b6857a5ca153c67e5476972e5f7190015018760938da2"}, + {file = "aiohttp-3.9.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:07b837ef0d2f252f96009e9b8435ec1fef68ef8b1461933253d318748ec1acdc"}, + {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad46e6f620574b3b4801c68255492e0159d1712271cc99d8bdf35f2043ec266"}, + {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ed3e046ea7b14938112ccd53d91c1539af3e6679b222f9469981e3dac7ba1ce"}, + {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:039df344b45ae0b34ac885ab5b53940b174530d4dd8a14ed8b0e2155b9dddccb"}, + {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7943c414d3a8d9235f5f15c22ace69787c140c80b718dcd57caaade95f7cd93b"}, + {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84871a243359bb42c12728f04d181a389718710129b36b6aad0fc4655a7647d4"}, + {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:5eafe2c065df5401ba06821b9a054d9cb2848867f3c59801b5d07a0be3a380ae"}, + {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:9d3c9b50f19704552f23b4eaea1fc082fdd82c63429a6506446cbd8737823da3"}, + {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:f033d80bc6283092613882dfe40419c6a6a1527e04fc69350e87a9df02bbc283"}, + {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:2c895a656dd7e061b2fd6bb77d971cc38f2afc277229ce7dd3552de8313a483e"}, + {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1f5a71d25cd8106eab05f8704cd9167b6e5187bcdf8f090a66c6d88b634802b4"}, + {file = "aiohttp-3.9.3-cp311-cp311-win32.whl", hash = "sha256:50fca156d718f8ced687a373f9e140c1bb765ca16e3d6f4fe116e3df7c05b2c5"}, + {file = "aiohttp-3.9.3-cp311-cp311-win_amd64.whl", hash = "sha256:5fe9ce6c09668063b8447f85d43b8d1c4e5d3d7e92c63173e6180b2ac5d46dd8"}, + {file = "aiohttp-3.9.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:38a19bc3b686ad55804ae931012f78f7a534cce165d089a2059f658f6c91fa60"}, + {file = "aiohttp-3.9.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:770d015888c2a598b377bd2f663adfd947d78c0124cfe7b959e1ef39f5b13869"}, + {file = "aiohttp-3.9.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ee43080e75fc92bf36219926c8e6de497f9b247301bbf88c5c7593d931426679"}, + {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:52df73f14ed99cee84865b95a3d9e044f226320a87af208f068ecc33e0c35b96"}, + {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc9b311743a78043b26ffaeeb9715dc360335e5517832f5a8e339f8a43581e4d"}, + {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b955ed993491f1a5da7f92e98d5dad3c1e14dc175f74517c4e610b1f2456fb11"}, + {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:504b6981675ace64c28bf4a05a508af5cde526e36492c98916127f5a02354d53"}, + {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a6fe5571784af92b6bc2fda8d1925cccdf24642d49546d3144948a6a1ed58ca5"}, + {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ba39e9c8627edc56544c8628cc180d88605df3892beeb2b94c9bc857774848ca"}, + {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:e5e46b578c0e9db71d04c4b506a2121c0cb371dd89af17a0586ff6769d4c58c1"}, + {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:938a9653e1e0c592053f815f7028e41a3062e902095e5a7dc84617c87267ebd5"}, + {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:c3452ea726c76e92f3b9fae4b34a151981a9ec0a4847a627c43d71a15ac32aa6"}, + {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ff30218887e62209942f91ac1be902cc80cddb86bf00fbc6783b7a43b2bea26f"}, + {file = "aiohttp-3.9.3-cp312-cp312-win32.whl", hash = "sha256:38f307b41e0bea3294a9a2a87833191e4bcf89bb0365e83a8be3a58b31fb7f38"}, + {file = "aiohttp-3.9.3-cp312-cp312-win_amd64.whl", hash = "sha256:b791a3143681a520c0a17e26ae7465f1b6f99461a28019d1a2f425236e6eedb5"}, + {file = "aiohttp-3.9.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:0ed621426d961df79aa3b963ac7af0d40392956ffa9be022024cd16297b30c8c"}, + {file = "aiohttp-3.9.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7f46acd6a194287b7e41e87957bfe2ad1ad88318d447caf5b090012f2c5bb528"}, + {file = "aiohttp-3.9.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:feeb18a801aacb098220e2c3eea59a512362eb408d4afd0c242044c33ad6d542"}, + {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f734e38fd8666f53da904c52a23ce517f1b07722118d750405af7e4123933511"}, + {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b40670ec7e2156d8e57f70aec34a7216407848dfe6c693ef131ddf6e76feb672"}, + {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fdd215b7b7fd4a53994f238d0f46b7ba4ac4c0adb12452beee724ddd0743ae5d"}, + {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:017a21b0df49039c8f46ca0971b3a7fdc1f56741ab1240cb90ca408049766168"}, + {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e99abf0bba688259a496f966211c49a514e65afa9b3073a1fcee08856e04425b"}, + {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:648056db9a9fa565d3fa851880f99f45e3f9a771dd3ff3bb0c048ea83fb28194"}, + {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8aacb477dc26797ee089721536a292a664846489c49d3ef9725f992449eda5a8"}, + {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:522a11c934ea660ff8953eda090dcd2154d367dec1ae3c540aff9f8a5c109ab4"}, + {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:5bce0dc147ca85caa5d33debc4f4d65e8e8b5c97c7f9f660f215fa74fc49a321"}, + {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4b4af9f25b49a7be47c0972139e59ec0e8285c371049df1a63b6ca81fdd216a2"}, + {file = "aiohttp-3.9.3-cp38-cp38-win32.whl", hash = "sha256:298abd678033b8571995650ccee753d9458dfa0377be4dba91e4491da3f2be63"}, + {file = "aiohttp-3.9.3-cp38-cp38-win_amd64.whl", hash = "sha256:69361bfdca5468c0488d7017b9b1e5ce769d40b46a9f4a2eed26b78619e9396c"}, + {file = "aiohttp-3.9.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:0fa43c32d1643f518491d9d3a730f85f5bbaedcbd7fbcae27435bb8b7a061b29"}, + {file = "aiohttp-3.9.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:835a55b7ca49468aaaac0b217092dfdff370e6c215c9224c52f30daaa735c1c1"}, + {file = "aiohttp-3.9.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:06a9b2c8837d9a94fae16c6223acc14b4dfdff216ab9b7202e07a9a09541168f"}, + {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:abf151955990d23f84205286938796c55ff11bbfb4ccfada8c9c83ae6b3c89a3"}, + {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:59c26c95975f26e662ca78fdf543d4eeaef70e533a672b4113dd888bd2423caa"}, + {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f95511dd5d0e05fd9728bac4096319f80615aaef4acbecb35a990afebe953b0e"}, + {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:595f105710293e76b9dc09f52e0dd896bd064a79346234b521f6b968ffdd8e58"}, + {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7c8b816c2b5af5c8a436df44ca08258fc1a13b449393a91484225fcb7545533"}, + {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f1088fa100bf46e7b398ffd9904f4808a0612e1d966b4aa43baa535d1b6341eb"}, + {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f59dfe57bb1ec82ac0698ebfcdb7bcd0e99c255bd637ff613760d5f33e7c81b3"}, + {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:361a1026c9dd4aba0109e4040e2aecf9884f5cfe1b1b1bd3d09419c205e2e53d"}, + {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:363afe77cfcbe3a36353d8ea133e904b108feea505aa4792dad6585a8192c55a"}, + {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8e2c45c208c62e955e8256949eb225bd8b66a4c9b6865729a786f2aa79b72e9d"}, + {file = "aiohttp-3.9.3-cp39-cp39-win32.whl", hash = "sha256:f7217af2e14da0856e082e96ff637f14ae45c10a5714b63c77f26d8884cf1051"}, + {file = "aiohttp-3.9.3-cp39-cp39-win_amd64.whl", hash = "sha256:27468897f628c627230dba07ec65dc8d0db566923c48f29e084ce382119802bc"}, + {file = "aiohttp-3.9.3.tar.gz", hash = "sha256:90842933e5d1ff760fae6caca4b2b3edba53ba8f4b71e95dacf2818a2aca06f7"}, +] + +[package.dependencies] +aiosignal = ">=1.1.2" +async-timeout = {version = ">=4.0,<5.0", markers = "python_version < \"3.11\""} +attrs = ">=17.3.0" +frozenlist = ">=1.1.1" +multidict = ">=4.5,<7.0" +yarl = ">=1.0,<2.0" + +[package.extras] +speedups = ["Brotli", "aiodns", "brotlicffi"] + +[[package]] +name = "aiosignal" +version = "1.3.1" +description = "aiosignal: a list of registered asynchronous callbacks" +optional = false +python-versions = ">=3.7" +files = [ + {file = "aiosignal-1.3.1-py3-none-any.whl", hash = "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17"}, + {file = "aiosignal-1.3.1.tar.gz", hash = "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc"}, +] + +[package.dependencies] +frozenlist = ">=1.1.0" + [[package]] name = "annotated-types" version = "0.5.0" @@ -44,6 +154,17 @@ doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphin test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] trio = ["trio (>=0.23)"] +[[package]] +name = "async-timeout" +version = "4.0.3" +description = "Timeout context manager for asyncio programs" +optional = false +python-versions = ">=3.7" +files = [ + {file = "async-timeout-4.0.3.tar.gz", hash = "sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f"}, + {file = "async_timeout-4.0.3-py3-none-any.whl", hash = "sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028"}, +] + [[package]] name = "attrs" version = "22.1.0" @@ -340,6 +461,92 @@ files = [ docs = ["furo (>=2022.9.29)", "sphinx (>=5.3)", "sphinx-autodoc-typehints (>=1.19.5)"] testing = ["covdefaults (>=2.2.2)", "coverage (>=6.5)", "pytest (>=7.2)", "pytest-cov (>=4)", "pytest-timeout (>=2.1)"] +[[package]] +name = "frozenlist" +version = "1.4.1" +description = "A list-like structure which implements collections.abc.MutableSequence" +optional = false +python-versions = ">=3.8" +files = [ + {file = "frozenlist-1.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f9aa1878d1083b276b0196f2dfbe00c9b7e752475ed3b682025ff20c1c1f51ac"}, + {file = "frozenlist-1.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:29acab3f66f0f24674b7dc4736477bcd4bc3ad4b896f5f45379a67bce8b96868"}, + {file = "frozenlist-1.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:74fb4bee6880b529a0c6560885fce4dc95936920f9f20f53d99a213f7bf66776"}, + {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:590344787a90ae57d62511dd7c736ed56b428f04cd8c161fcc5e7232c130c69a"}, + {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:068b63f23b17df8569b7fdca5517edef76171cf3897eb68beb01341131fbd2ad"}, + {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c849d495bf5154cd8da18a9eb15db127d4dba2968d88831aff6f0331ea9bd4c"}, + {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9750cc7fe1ae3b1611bb8cfc3f9ec11d532244235d75901fb6b8e42ce9229dfe"}, + {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9b2de4cf0cdd5bd2dee4c4f63a653c61d2408055ab77b151c1957f221cabf2a"}, + {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0633c8d5337cb5c77acbccc6357ac49a1770b8c487e5b3505c57b949b4b82e98"}, + {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:27657df69e8801be6c3638054e202a135c7f299267f1a55ed3a598934f6c0d75"}, + {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:f9a3ea26252bd92f570600098783d1371354d89d5f6b7dfd87359d669f2109b5"}, + {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:4f57dab5fe3407b6c0c1cc907ac98e8a189f9e418f3b6e54d65a718aaafe3950"}, + {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e02a0e11cf6597299b9f3bbd3f93d79217cb90cfd1411aec33848b13f5c656cc"}, + {file = "frozenlist-1.4.1-cp310-cp310-win32.whl", hash = "sha256:a828c57f00f729620a442881cc60e57cfcec6842ba38e1b19fd3e47ac0ff8dc1"}, + {file = "frozenlist-1.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:f56e2333dda1fe0f909e7cc59f021eba0d2307bc6f012a1ccf2beca6ba362439"}, + {file = "frozenlist-1.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a0cb6f11204443f27a1628b0e460f37fb30f624be6051d490fa7d7e26d4af3d0"}, + {file = "frozenlist-1.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b46c8ae3a8f1f41a0d2ef350c0b6e65822d80772fe46b653ab6b6274f61d4a49"}, + {file = "frozenlist-1.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fde5bd59ab5357e3853313127f4d3565fc7dad314a74d7b5d43c22c6a5ed2ced"}, + {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:722e1124aec435320ae01ee3ac7bec11a5d47f25d0ed6328f2273d287bc3abb0"}, + {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2471c201b70d58a0f0c1f91261542a03d9a5e088ed3dc6c160d614c01649c106"}, + {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c757a9dd70d72b076d6f68efdbb9bc943665ae954dad2801b874c8c69e185068"}, + {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f146e0911cb2f1da549fc58fc7bcd2b836a44b79ef871980d605ec392ff6b0d2"}, + {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f9c515e7914626b2a2e1e311794b4c35720a0be87af52b79ff8e1429fc25f19"}, + {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c302220494f5c1ebeb0912ea782bcd5e2f8308037b3c7553fad0e48ebad6ad82"}, + {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:442acde1e068288a4ba7acfe05f5f343e19fac87bfc96d89eb886b0363e977ec"}, + {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:1b280e6507ea8a4fa0c0a7150b4e526a8d113989e28eaaef946cc77ffd7efc0a"}, + {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:fe1a06da377e3a1062ae5fe0926e12b84eceb8a50b350ddca72dc85015873f74"}, + {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:db9e724bebd621d9beca794f2a4ff1d26eed5965b004a97f1f1685a173b869c2"}, + {file = "frozenlist-1.4.1-cp311-cp311-win32.whl", hash = "sha256:e774d53b1a477a67838a904131c4b0eef6b3d8a651f8b138b04f748fccfefe17"}, + {file = "frozenlist-1.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:fb3c2db03683b5767dedb5769b8a40ebb47d6f7f45b1b3e3b4b51ec8ad9d9825"}, + {file = "frozenlist-1.4.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:1979bc0aeb89b33b588c51c54ab0161791149f2461ea7c7c946d95d5f93b56ae"}, + {file = "frozenlist-1.4.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cc7b01b3754ea68a62bd77ce6020afaffb44a590c2289089289363472d13aedb"}, + {file = "frozenlist-1.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c9c92be9fd329ac801cc420e08452b70e7aeab94ea4233a4804f0915c14eba9b"}, + {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c3894db91f5a489fc8fa6a9991820f368f0b3cbdb9cd8849547ccfab3392d86"}, + {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba60bb19387e13597fb059f32cd4d59445d7b18b69a745b8f8e5db0346f33480"}, + {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8aefbba5f69d42246543407ed2461db31006b0f76c4e32dfd6f42215a2c41d09"}, + {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780d3a35680ced9ce682fbcf4cb9c2bad3136eeff760ab33707b71db84664e3a"}, + {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9acbb16f06fe7f52f441bb6f413ebae6c37baa6ef9edd49cdd567216da8600cd"}, + {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:23b701e65c7b36e4bf15546a89279bd4d8675faabc287d06bbcfac7d3c33e1e6"}, + {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:3e0153a805a98f5ada7e09826255ba99fb4f7524bb81bf6b47fb702666484ae1"}, + {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:dd9b1baec094d91bf36ec729445f7769d0d0cf6b64d04d86e45baf89e2b9059b"}, + {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:1a4471094e146b6790f61b98616ab8e44f72661879cc63fa1049d13ef711e71e"}, + {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5667ed53d68d91920defdf4035d1cdaa3c3121dc0b113255124bcfada1cfa1b8"}, + {file = "frozenlist-1.4.1-cp312-cp312-win32.whl", hash = "sha256:beee944ae828747fd7cb216a70f120767fc9f4f00bacae8543c14a6831673f89"}, + {file = "frozenlist-1.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:64536573d0a2cb6e625cf309984e2d873979709f2cf22839bf2d61790b448ad5"}, + {file = "frozenlist-1.4.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:20b51fa3f588ff2fe658663db52a41a4f7aa6c04f6201449c6c7c476bd255c0d"}, + {file = "frozenlist-1.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:410478a0c562d1a5bcc2f7ea448359fcb050ed48b3c6f6f4f18c313a9bdb1826"}, + {file = "frozenlist-1.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c6321c9efe29975232da3bd0af0ad216800a47e93d763ce64f291917a381b8eb"}, + {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48f6a4533887e189dae092f1cf981f2e3885175f7a0f33c91fb5b7b682b6bab6"}, + {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6eb73fa5426ea69ee0e012fb59cdc76a15b1283d6e32e4f8dc4482ec67d1194d"}, + {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fbeb989b5cc29e8daf7f976b421c220f1b8c731cbf22b9130d8815418ea45887"}, + {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:32453c1de775c889eb4e22f1197fe3bdfe457d16476ea407472b9442e6295f7a"}, + {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:693945278a31f2086d9bf3df0fe8254bbeaef1fe71e1351c3bd730aa7d31c41b"}, + {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:1d0ce09d36d53bbbe566fe296965b23b961764c0bcf3ce2fa45f463745c04701"}, + {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:3a670dc61eb0d0eb7080890c13de3066790f9049b47b0de04007090807c776b0"}, + {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:dca69045298ce5c11fd539682cff879cc1e664c245d1c64da929813e54241d11"}, + {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a06339f38e9ed3a64e4c4e43aec7f59084033647f908e4259d279a52d3757d09"}, + {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b7f2f9f912dca3934c1baec2e4585a674ef16fe00218d833856408c48d5beee7"}, + {file = "frozenlist-1.4.1-cp38-cp38-win32.whl", hash = "sha256:e7004be74cbb7d9f34553a5ce5fb08be14fb33bc86f332fb71cbe5216362a497"}, + {file = "frozenlist-1.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:5a7d70357e7cee13f470c7883a063aae5fe209a493c57d86eb7f5a6f910fae09"}, + {file = "frozenlist-1.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:bfa4a17e17ce9abf47a74ae02f32d014c5e9404b6d9ac7f729e01562bbee601e"}, + {file = "frozenlist-1.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b7e3ed87d4138356775346e6845cccbe66cd9e207f3cd11d2f0b9fd13681359d"}, + {file = "frozenlist-1.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c99169d4ff810155ca50b4da3b075cbde79752443117d89429595c2e8e37fed8"}, + {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:edb678da49d9f72c9f6c609fbe41a5dfb9a9282f9e6a2253d5a91e0fc382d7c0"}, + {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6db4667b187a6742b33afbbaf05a7bc551ffcf1ced0000a571aedbb4aa42fc7b"}, + {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55fdc093b5a3cb41d420884cdaf37a1e74c3c37a31f46e66286d9145d2063bd0"}, + {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82e8211d69a4f4bc360ea22cd6555f8e61a1bd211d1d5d39d3d228b48c83a897"}, + {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89aa2c2eeb20957be2d950b85974b30a01a762f3308cd02bb15e1ad632e22dc7"}, + {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9d3e0c25a2350080e9319724dede4f31f43a6c9779be48021a7f4ebde8b2d742"}, + {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7268252af60904bf52c26173cbadc3a071cece75f873705419c8681f24d3edea"}, + {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:0c250a29735d4f15321007fb02865f0e6b6a41a6b88f1f523ca1596ab5f50bd5"}, + {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:96ec70beabbd3b10e8bfe52616a13561e58fe84c0101dd031dc78f250d5128b9"}, + {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:23b2d7679b73fe0e5a4560b672a39f98dfc6f60df63823b0a9970525325b95f6"}, + {file = "frozenlist-1.4.1-cp39-cp39-win32.whl", hash = "sha256:a7496bfe1da7fb1a4e1cc23bb67c58fab69311cc7d32b5a99c2007b4b2a0e932"}, + {file = "frozenlist-1.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:e6a20a581f9ce92d389a8c7d7c3dd47c81fd5d6e655c8dddf341e14aa48659d0"}, + {file = "frozenlist-1.4.1-py3-none-any.whl", hash = "sha256:04ced3e6a46b4cfffe20f9ae482818e34eba9b5fb0ce4056e4cc9b6e212d09b7"}, + {file = "frozenlist-1.4.1.tar.gz", hash = "sha256:c037a86e8513059a2613aaba4d817bb90b9d9b6b69aace3ce9c877e8c8ed402b"}, +] + [[package]] name = "ghp-import" version = "2.1.0" @@ -485,6 +692,26 @@ pyrsistent = ">=0.14.0,<0.17.0 || >0.17.0,<0.17.1 || >0.17.1,<0.17.2 || >0.17.2" format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=1.11)"] +[[package]] +name = "kubernetes-asyncio" +version = "29.0.0" +description = "Kubernetes asynchronous python client" +optional = false +python-versions = "*" +files = [ + {file = "kubernetes_asyncio-29.0.0-py3-none-any.whl", hash = "sha256:9dd911260e89d984479f23b1000b8713d35b68fbd92873473449b5558da1a3f4"}, + {file = "kubernetes_asyncio-29.0.0.tar.gz", hash = "sha256:99ff1fea4df062adb7a6e48962ad2504459165ffd7542013bc3d72d9ab3817be"}, +] + +[package.dependencies] +aiohttp = ">=3.9.0,<4.0.0" +certifi = ">=14.05.14" +python-dateutil = ">=2.5.3" +pyyaml = ">=3.12" +setuptools = ">=21.0.0" +six = ">=1.9.0" +urllib3 = ">=1.24.2" + [[package]] name = "markdown" version = "3.3.7" @@ -713,6 +940,105 @@ files = [ {file = "mkdocs_material_extensions-1.3.tar.gz", hash = "sha256:f0446091503acb110a7cab9349cbc90eeac51b58d1caa92a704a81ca1e24ddbd"}, ] +[[package]] +name = "multidict" +version = "6.0.5" +description = "multidict implementation" +optional = false +python-versions = ">=3.7" +files = [ + {file = "multidict-6.0.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:228b644ae063c10e7f324ab1ab6b548bdf6f8b47f3ec234fef1093bc2735e5f9"}, + {file = "multidict-6.0.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:896ebdcf62683551312c30e20614305f53125750803b614e9e6ce74a96232604"}, + {file = "multidict-6.0.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:411bf8515f3be9813d06004cac41ccf7d1cd46dfe233705933dd163b60e37600"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d147090048129ce3c453f0292e7697d333db95e52616b3793922945804a433c"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:215ed703caf15f578dca76ee6f6b21b7603791ae090fbf1ef9d865571039ade5"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c6390cf87ff6234643428991b7359b5f59cc15155695deb4eda5c777d2b880f"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fd81c4ebdb4f214161be351eb5bcf385426bf023041da2fd9e60681f3cebae"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3cc2ad10255f903656017363cd59436f2111443a76f996584d1077e43ee51182"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6939c95381e003f54cd4c5516740faba40cf5ad3eeff460c3ad1d3e0ea2549bf"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:220dd781e3f7af2c2c1053da9fa96d9cf3072ca58f057f4c5adaaa1cab8fc442"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:766c8f7511df26d9f11cd3a8be623e59cca73d44643abab3f8c8c07620524e4a"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:fe5d7785250541f7f5019ab9cba2c71169dc7d74d0f45253f8313f436458a4ef"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c1c1496e73051918fcd4f58ff2e0f2f3066d1c76a0c6aeffd9b45d53243702cc"}, + {file = "multidict-6.0.5-cp310-cp310-win32.whl", hash = "sha256:7afcdd1fc07befad18ec4523a782cde4e93e0a2bf71239894b8d61ee578c1319"}, + {file = "multidict-6.0.5-cp310-cp310-win_amd64.whl", hash = "sha256:99f60d34c048c5c2fabc766108c103612344c46e35d4ed9ae0673d33c8fb26e8"}, + {file = "multidict-6.0.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f285e862d2f153a70586579c15c44656f888806ed0e5b56b64489afe4a2dbfba"}, + {file = "multidict-6.0.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:53689bb4e102200a4fafa9de9c7c3c212ab40a7ab2c8e474491914d2305f187e"}, + {file = "multidict-6.0.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:612d1156111ae11d14afaf3a0669ebf6c170dbb735e510a7438ffe2369a847fd"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7be7047bd08accdb7487737631d25735c9a04327911de89ff1b26b81745bd4e3"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de170c7b4fe6859beb8926e84f7d7d6c693dfe8e27372ce3b76f01c46e489fcf"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:04bde7a7b3de05732a4eb39c94574db1ec99abb56162d6c520ad26f83267de29"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85f67aed7bb647f93e7520633d8f51d3cbc6ab96957c71272b286b2f30dc70ed"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:425bf820055005bfc8aa9a0b99ccb52cc2f4070153e34b701acc98d201693733"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d3eb1ceec286eba8220c26f3b0096cf189aea7057b6e7b7a2e60ed36b373b77f"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7901c05ead4b3fb75113fb1dd33eb1253c6d3ee37ce93305acd9d38e0b5f21a4"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e0e79d91e71b9867c73323a3444724d496c037e578a0e1755ae159ba14f4f3d1"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:29bfeb0dff5cb5fdab2023a7a9947b3b4af63e9c47cae2a10ad58394b517fddc"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e030047e85cbcedbfc073f71836d62dd5dadfbe7531cae27789ff66bc551bd5e"}, + {file = "multidict-6.0.5-cp311-cp311-win32.whl", hash = "sha256:2f4848aa3baa109e6ab81fe2006c77ed4d3cd1e0ac2c1fbddb7b1277c168788c"}, + {file = "multidict-6.0.5-cp311-cp311-win_amd64.whl", hash = "sha256:2faa5ae9376faba05f630d7e5e6be05be22913782b927b19d12b8145968a85ea"}, + {file = "multidict-6.0.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:51d035609b86722963404f711db441cf7134f1889107fb171a970c9701f92e1e"}, + {file = "multidict-6.0.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cbebcd5bcaf1eaf302617c114aa67569dd3f090dd0ce8ba9e35e9985b41ac35b"}, + {file = "multidict-6.0.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2ffc42c922dbfddb4a4c3b438eb056828719f07608af27d163191cb3e3aa6cc5"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ceb3b7e6a0135e092de86110c5a74e46bda4bd4fbfeeb3a3bcec79c0f861e450"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:79660376075cfd4b2c80f295528aa6beb2058fd289f4c9252f986751a4cd0496"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e4428b29611e989719874670fd152b6625500ad6c686d464e99f5aaeeaca175a"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d84a5c3a5f7ce6db1f999fb9438f686bc2e09d38143f2d93d8406ed2dd6b9226"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:76c0de87358b192de7ea9649beb392f107dcad9ad27276324c24c91774ca5271"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:79a6d2ba910adb2cbafc95dad936f8b9386e77c84c35bc0add315b856d7c3abb"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:92d16a3e275e38293623ebf639c471d3e03bb20b8ebb845237e0d3664914caef"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:fb616be3538599e797a2017cccca78e354c767165e8858ab5116813146041a24"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:14c2976aa9038c2629efa2c148022ed5eb4cb939e15ec7aace7ca932f48f9ba6"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:435a0984199d81ca178b9ae2c26ec3d49692d20ee29bc4c11a2a8d4514c67eda"}, + {file = "multidict-6.0.5-cp312-cp312-win32.whl", hash = "sha256:9fe7b0653ba3d9d65cbe7698cca585bf0f8c83dbbcc710db9c90f478e175f2d5"}, + {file = "multidict-6.0.5-cp312-cp312-win_amd64.whl", hash = "sha256:01265f5e40f5a17f8241d52656ed27192be03bfa8764d88e8220141d1e4b3556"}, + {file = "multidict-6.0.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:19fe01cea168585ba0f678cad6f58133db2aa14eccaf22f88e4a6dccadfad8b3"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6bf7a982604375a8d49b6cc1b781c1747f243d91b81035a9b43a2126c04766f5"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:107c0cdefe028703fb5dafe640a409cb146d44a6ae201e55b35a4af8e95457dd"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:403c0911cd5d5791605808b942c88a8155c2592e05332d2bf78f18697a5fa15e"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aeaf541ddbad8311a87dd695ed9642401131ea39ad7bc8cf3ef3967fd093b626"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e4972624066095e52b569e02b5ca97dbd7a7ddd4294bf4e7247d52635630dd83"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d946b0a9eb8aaa590df1fe082cee553ceab173e6cb5b03239716338629c50c7a"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b55358304d7a73d7bdf5de62494aaf70bd33015831ffd98bc498b433dfe5b10c"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:a3145cb08d8625b2d3fee1b2d596a8766352979c9bffe5d7833e0503d0f0b5e5"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:d65f25da8e248202bd47445cec78e0025c0fe7582b23ec69c3b27a640dd7a8e3"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c9bf56195c6bbd293340ea82eafd0071cb3d450c703d2c93afb89f93b8386ccc"}, + {file = "multidict-6.0.5-cp37-cp37m-win32.whl", hash = "sha256:69db76c09796b313331bb7048229e3bee7928eb62bab5e071e9f7fcc4879caee"}, + {file = "multidict-6.0.5-cp37-cp37m-win_amd64.whl", hash = "sha256:fce28b3c8a81b6b36dfac9feb1de115bab619b3c13905b419ec71d03a3fc1423"}, + {file = "multidict-6.0.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:76f067f5121dcecf0d63a67f29080b26c43c71a98b10c701b0677e4a065fbd54"}, + {file = "multidict-6.0.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b82cc8ace10ab5bd93235dfaab2021c70637005e1ac787031f4d1da63d493c1d"}, + {file = "multidict-6.0.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5cb241881eefd96b46f89b1a056187ea8e9ba14ab88ba632e68d7a2ecb7aadf7"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8e94e6912639a02ce173341ff62cc1201232ab86b8a8fcc05572741a5dc7d93"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09a892e4a9fb47331da06948690ae38eaa2426de97b4ccbfafbdcbe5c8f37ff8"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55205d03e8a598cfc688c71ca8ea5f66447164efff8869517f175ea632c7cb7b"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37b15024f864916b4951adb95d3a80c9431299080341ab9544ed148091b53f50"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2a1dee728b52b33eebff5072817176c172050d44d67befd681609b4746e1c2e"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:edd08e6f2f1a390bf137080507e44ccc086353c8e98c657e666c017718561b89"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:60d698e8179a42ec85172d12f50b1668254628425a6bd611aba022257cac1386"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:3d25f19500588cbc47dc19081d78131c32637c25804df8414463ec908631e453"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:4cc0ef8b962ac7a5e62b9e826bd0cd5040e7d401bc45a6835910ed699037a461"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:eca2e9d0cc5a889850e9bbd68e98314ada174ff6ccd1129500103df7a94a7a44"}, + {file = "multidict-6.0.5-cp38-cp38-win32.whl", hash = "sha256:4a6a4f196f08c58c59e0b8ef8ec441d12aee4125a7d4f4fef000ccb22f8d7241"}, + {file = "multidict-6.0.5-cp38-cp38-win_amd64.whl", hash = "sha256:0275e35209c27a3f7951e1ce7aaf93ce0d163b28948444bec61dd7badc6d3f8c"}, + {file = "multidict-6.0.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e7be68734bd8c9a513f2b0cfd508802d6609da068f40dc57d4e3494cefc92929"}, + {file = "multidict-6.0.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1d9ea7a7e779d7a3561aade7d596649fbecfa5c08a7674b11b423783217933f9"}, + {file = "multidict-6.0.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ea1456df2a27c73ce51120fa2f519f1bea2f4a03a917f4a43c8707cf4cbbae1a"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf590b134eb70629e350691ecca88eac3e3b8b3c86992042fb82e3cb1830d5e1"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5c0631926c4f58e9a5ccce555ad7747d9a9f8b10619621f22f9635f069f6233e"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dce1c6912ab9ff5f179eaf6efe7365c1f425ed690b03341911bf4939ef2f3046"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0868d64af83169e4d4152ec612637a543f7a336e4a307b119e98042e852ad9c"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:141b43360bfd3bdd75f15ed811850763555a251e38b2405967f8e25fb43f7d40"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7df704ca8cf4a073334e0427ae2345323613e4df18cc224f647f251e5e75a527"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6214c5a5571802c33f80e6c84713b2c79e024995b9c5897f794b43e714daeec9"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:cd6c8fca38178e12c00418de737aef1261576bd1b6e8c6134d3e729a4e858b38"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:e02021f87a5b6932fa6ce916ca004c4d441509d33bbdbeca70d05dff5e9d2479"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ebd8d160f91a764652d3e51ce0d2956b38efe37c9231cd82cfc0bed2e40b581c"}, + {file = "multidict-6.0.5-cp39-cp39-win32.whl", hash = "sha256:04da1bb8c8dbadf2a18a452639771951c662c5ad03aefe4884775454be322c9b"}, + {file = "multidict-6.0.5-cp39-cp39-win_amd64.whl", hash = "sha256:d6f6d4f185481c9669b9447bf9d9cf3b95a0e9df9d169bbc17e363b7d5487755"}, + {file = "multidict-6.0.5-py3-none-any.whl", hash = "sha256:0d63c74e3d7ab26de115c49bffc92cc77ed23395303d496eae515d4204a625e7"}, + {file = "multidict-6.0.5.tar.gz", hash = "sha256:f7e301075edaf50500f0b341543c41194d8df3ae5caf4702f2095f3ca73dd8da"}, +] + [[package]] name = "networkx" version = "3.1" @@ -1357,6 +1683,7 @@ files = [ {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, + {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, @@ -1364,8 +1691,16 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, + {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, + {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, + {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, + {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, @@ -1382,6 +1717,7 @@ files = [ {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, + {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, @@ -1389,6 +1725,7 @@ files = [ {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, + {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, @@ -1860,7 +2197,110 @@ files = [ [package.extras] watchmedo = ["PyYAML (>=3.10)"] +[[package]] +name = "yarl" +version = "1.9.4" +description = "Yet another URL library" +optional = false +python-versions = ">=3.7" +files = [ + {file = "yarl-1.9.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a8c1df72eb746f4136fe9a2e72b0c9dc1da1cbd23b5372f94b5820ff8ae30e0e"}, + {file = "yarl-1.9.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a3a6ed1d525bfb91b3fc9b690c5a21bb52de28c018530ad85093cc488bee2dd2"}, + {file = "yarl-1.9.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c38c9ddb6103ceae4e4498f9c08fac9b590c5c71b0370f98714768e22ac6fa66"}, + {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d9e09c9d74f4566e905a0b8fa668c58109f7624db96a2171f21747abc7524234"}, + {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8477c1ee4bd47c57d49621a062121c3023609f7a13b8a46953eb6c9716ca392"}, + {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5ff2c858f5f6a42c2a8e751100f237c5e869cbde669a724f2062d4c4ef93551"}, + {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:357495293086c5b6d34ca9616a43d329317feab7917518bc97a08f9e55648455"}, + {file = "yarl-1.9.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54525ae423d7b7a8ee81ba189f131054defdb122cde31ff17477951464c1691c"}, + {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:801e9264d19643548651b9db361ce3287176671fb0117f96b5ac0ee1c3530d53"}, + {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e516dc8baf7b380e6c1c26792610230f37147bb754d6426462ab115a02944385"}, + {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:7d5aaac37d19b2904bb9dfe12cdb08c8443e7ba7d2852894ad448d4b8f442863"}, + {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:54beabb809ffcacbd9d28ac57b0db46e42a6e341a030293fb3185c409e626b8b"}, + {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bac8d525a8dbc2a1507ec731d2867025d11ceadcb4dd421423a5d42c56818541"}, + {file = "yarl-1.9.4-cp310-cp310-win32.whl", hash = "sha256:7855426dfbddac81896b6e533ebefc0af2f132d4a47340cee6d22cac7190022d"}, + {file = "yarl-1.9.4-cp310-cp310-win_amd64.whl", hash = "sha256:848cd2a1df56ddbffeb375535fb62c9d1645dde33ca4d51341378b3f5954429b"}, + {file = "yarl-1.9.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:35a2b9396879ce32754bd457d31a51ff0a9d426fd9e0e3c33394bf4b9036b099"}, + {file = "yarl-1.9.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c7d56b293cc071e82532f70adcbd8b61909eec973ae9d2d1f9b233f3d943f2c"}, + {file = "yarl-1.9.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d8a1c6c0be645c745a081c192e747c5de06e944a0d21245f4cf7c05e457c36e0"}, + {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b3c1ffe10069f655ea2d731808e76e0f452fc6c749bea04781daf18e6039525"}, + {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:549d19c84c55d11687ddbd47eeb348a89df9cb30e1993f1b128f4685cd0ebbf8"}, + {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7409f968456111140c1c95301cadf071bd30a81cbd7ab829169fb9e3d72eae9"}, + {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e23a6d84d9d1738dbc6e38167776107e63307dfc8ad108e580548d1f2c587f42"}, + {file = "yarl-1.9.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d8b889777de69897406c9fb0b76cdf2fd0f31267861ae7501d93003d55f54fbe"}, + {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:03caa9507d3d3c83bca08650678e25364e1843b484f19986a527630ca376ecce"}, + {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4e9035df8d0880b2f1c7f5031f33f69e071dfe72ee9310cfc76f7b605958ceb9"}, + {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:c0ec0ed476f77db9fb29bca17f0a8fcc7bc97ad4c6c1d8959c507decb22e8572"}, + {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:ee04010f26d5102399bd17f8df8bc38dc7ccd7701dc77f4a68c5b8d733406958"}, + {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:49a180c2e0743d5d6e0b4d1a9e5f633c62eca3f8a86ba5dd3c471060e352ca98"}, + {file = "yarl-1.9.4-cp311-cp311-win32.whl", hash = "sha256:81eb57278deb6098a5b62e88ad8281b2ba09f2f1147c4767522353eaa6260b31"}, + {file = "yarl-1.9.4-cp311-cp311-win_amd64.whl", hash = "sha256:d1d2532b340b692880261c15aee4dc94dd22ca5d61b9db9a8a361953d36410b1"}, + {file = "yarl-1.9.4-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0d2454f0aef65ea81037759be5ca9947539667eecebca092733b2eb43c965a81"}, + {file = "yarl-1.9.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:44d8ffbb9c06e5a7f529f38f53eda23e50d1ed33c6c869e01481d3fafa6b8142"}, + {file = "yarl-1.9.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:aaaea1e536f98754a6e5c56091baa1b6ce2f2700cc4a00b0d49eca8dea471074"}, + {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3777ce5536d17989c91696db1d459574e9a9bd37660ea7ee4d3344579bb6f129"}, + {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fc5fc1eeb029757349ad26bbc5880557389a03fa6ada41703db5e068881e5f2"}, + {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea65804b5dc88dacd4a40279af0cdadcfe74b3e5b4c897aa0d81cf86927fee78"}, + {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa102d6d280a5455ad6a0f9e6d769989638718e938a6a0a2ff3f4a7ff8c62cc4"}, + {file = "yarl-1.9.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09efe4615ada057ba2d30df871d2f668af661e971dfeedf0c159927d48bbeff0"}, + {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:008d3e808d03ef28542372d01057fd09168419cdc8f848efe2804f894ae03e51"}, + {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:6f5cb257bc2ec58f437da2b37a8cd48f666db96d47b8a3115c29f316313654ff"}, + {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:992f18e0ea248ee03b5a6e8b3b4738850ae7dbb172cc41c966462801cbf62cf7"}, + {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:0e9d124c191d5b881060a9e5060627694c3bdd1fe24c5eecc8d5d7d0eb6faabc"}, + {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3986b6f41ad22988e53d5778f91855dc0399b043fc8946d4f2e68af22ee9ff10"}, + {file = "yarl-1.9.4-cp312-cp312-win32.whl", hash = "sha256:4b21516d181cd77ebd06ce160ef8cc2a5e9ad35fb1c5930882baff5ac865eee7"}, + {file = "yarl-1.9.4-cp312-cp312-win_amd64.whl", hash = "sha256:a9bd00dc3bc395a662900f33f74feb3e757429e545d831eef5bb280252631984"}, + {file = "yarl-1.9.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:63b20738b5aac74e239622d2fe30df4fca4942a86e31bf47a81a0e94c14df94f"}, + {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7d7f7de27b8944f1fee2c26a88b4dabc2409d2fea7a9ed3df79b67277644e17"}, + {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c74018551e31269d56fab81a728f683667e7c28c04e807ba08f8c9e3bba32f14"}, + {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ca06675212f94e7a610e85ca36948bb8fc023e458dd6c63ef71abfd482481aa5"}, + {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5aef935237d60a51a62b86249839b51345f47564208c6ee615ed2a40878dccdd"}, + {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2b134fd795e2322b7684155b7855cc99409d10b2e408056db2b93b51a52accc7"}, + {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d25039a474c4c72a5ad4b52495056f843a7ff07b632c1b92ea9043a3d9950f6e"}, + {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f7d6b36dd2e029b6bcb8a13cf19664c7b8e19ab3a58e0fefbb5b8461447ed5ec"}, + {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:957b4774373cf6f709359e5c8c4a0af9f6d7875db657adb0feaf8d6cb3c3964c"}, + {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:d7eeb6d22331e2fd42fce928a81c697c9ee2d51400bd1a28803965883e13cead"}, + {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:6a962e04b8f91f8c4e5917e518d17958e3bdee71fd1d8b88cdce74dd0ebbf434"}, + {file = "yarl-1.9.4-cp37-cp37m-win32.whl", hash = "sha256:f3bc6af6e2b8f92eced34ef6a96ffb248e863af20ef4fde9448cc8c9b858b749"}, + {file = "yarl-1.9.4-cp37-cp37m-win_amd64.whl", hash = "sha256:ad4d7a90a92e528aadf4965d685c17dacff3df282db1121136c382dc0b6014d2"}, + {file = "yarl-1.9.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ec61d826d80fc293ed46c9dd26995921e3a82146feacd952ef0757236fc137be"}, + {file = "yarl-1.9.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8be9e837ea9113676e5754b43b940b50cce76d9ed7d2461df1af39a8ee674d9f"}, + {file = "yarl-1.9.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:bef596fdaa8f26e3d66af846bbe77057237cb6e8efff8cd7cc8dff9a62278bbf"}, + {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d47552b6e52c3319fede1b60b3de120fe83bde9b7bddad11a69fb0af7db32f1"}, + {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84fc30f71689d7fc9168b92788abc977dc8cefa806909565fc2951d02f6b7d57"}, + {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4aa9741085f635934f3a2583e16fcf62ba835719a8b2b28fb2917bb0537c1dfa"}, + {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:206a55215e6d05dbc6c98ce598a59e6fbd0c493e2de4ea6cc2f4934d5a18d130"}, + {file = "yarl-1.9.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07574b007ee20e5c375a8fe4a0789fad26db905f9813be0f9fef5a68080de559"}, + {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5a2e2433eb9344a163aced6a5f6c9222c0786e5a9e9cac2c89f0b28433f56e23"}, + {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:6ad6d10ed9b67a382b45f29ea028f92d25bc0bc1daf6c5b801b90b5aa70fb9ec"}, + {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:6fe79f998a4052d79e1c30eeb7d6c1c1056ad33300f682465e1b4e9b5a188b78"}, + {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a825ec844298c791fd28ed14ed1bffc56a98d15b8c58a20e0e08c1f5f2bea1be"}, + {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8619d6915b3b0b34420cf9b2bb6d81ef59d984cb0fde7544e9ece32b4b3043c3"}, + {file = "yarl-1.9.4-cp38-cp38-win32.whl", hash = "sha256:686a0c2f85f83463272ddffd4deb5e591c98aac1897d65e92319f729c320eece"}, + {file = "yarl-1.9.4-cp38-cp38-win_amd64.whl", hash = "sha256:a00862fb23195b6b8322f7d781b0dc1d82cb3bcac346d1e38689370cc1cc398b"}, + {file = "yarl-1.9.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:604f31d97fa493083ea21bd9b92c419012531c4e17ea6da0f65cacdcf5d0bd27"}, + {file = "yarl-1.9.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8a854227cf581330ffa2c4824d96e52ee621dd571078a252c25e3a3b3d94a1b1"}, + {file = "yarl-1.9.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ba6f52cbc7809cd8d74604cce9c14868306ae4aa0282016b641c661f981a6e91"}, + {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a6327976c7c2f4ee6816eff196e25385ccc02cb81427952414a64811037bbc8b"}, + {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8397a3817d7dcdd14bb266283cd1d6fc7264a48c186b986f32e86d86d35fbac5"}, + {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e0381b4ce23ff92f8170080c97678040fc5b08da85e9e292292aba67fdac6c34"}, + {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:23d32a2594cb5d565d358a92e151315d1b2268bc10f4610d098f96b147370136"}, + {file = "yarl-1.9.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ddb2a5c08a4eaaba605340fdee8fc08e406c56617566d9643ad8bf6852778fc7"}, + {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:26a1dc6285e03f3cc9e839a2da83bcbf31dcb0d004c72d0730e755b33466c30e"}, + {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:18580f672e44ce1238b82f7fb87d727c4a131f3a9d33a5e0e82b793362bf18b4"}, + {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:29e0f83f37610f173eb7e7b5562dd71467993495e568e708d99e9d1944f561ec"}, + {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:1f23e4fe1e8794f74b6027d7cf19dc25f8b63af1483d91d595d4a07eca1fb26c"}, + {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:db8e58b9d79200c76956cefd14d5c90af54416ff5353c5bfd7cbe58818e26ef0"}, + {file = "yarl-1.9.4-cp39-cp39-win32.whl", hash = "sha256:c7224cab95645c7ab53791022ae77a4509472613e839dab722a72abe5a684575"}, + {file = "yarl-1.9.4-cp39-cp39-win_amd64.whl", hash = "sha256:824d6c50492add5da9374875ce72db7a0733b29c2394890aef23d533106e2b15"}, + {file = "yarl-1.9.4-py3-none-any.whl", hash = "sha256:928cecb0ef9d5a7946eb6ff58417ad2fe9375762382f1bf5c55e61645f2c43ad"}, + {file = "yarl-1.9.4.tar.gz", hash = "sha256:566db86717cf8080b99b58b083b773a908ae40f06681e87e589a976faf8246bf"}, +] + +[package.dependencies] +idna = ">=2.0" +multidict = ">=4.0" + [metadata] lock-version = "2.0" python-versions = ">=3.10, <3.13" -content-hash = "f21962e604d76ff8a2743774ade55e142a91caa69c2e0f624460f31a8e49bce6" +content-hash = "dc29f4a291f406a5d651b0a82645fd8457387a4a821d71a4da1a7a3bffa18d7e" diff --git a/pyproject.toml b/pyproject.toml index 2116ae3e1..f3403f486 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -36,6 +36,7 @@ dictdiffer = "^0.9.0" python-schema-registry-client = "^2.4.1" httpx = "^0 >=0.24.1" networkx = "^3.1" +kubernetes-asyncio = "^29.0.0" [tool.poetry.group.dev.dependencies] pytest = "^7.1.2" diff --git a/tests/pipeline/snapshots/test_example/test_generate/atm-fraud/pipeline.yaml b/tests/pipeline/snapshots/test_example/test_generate/atm-fraud/pipeline.yaml index 2b70e2340..528da26bb 100644 --- a/tests/pipeline/snapshots/test_example/test_generate/atm-fraud/pipeline.yaml +++ b/tests/pipeline/snapshots/test_example/test_generate/atm-fraud/pipeline.yaml @@ -138,10 +138,13 @@ imageTag: 1.0.0 labels: pipeline: atm-fraud + persistence: + enabled: false prometheus: jmx: enabled: false replicaCount: 1 + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 errorTopic: atm-fraud-transaction-joiner-dead-letter-topic @@ -171,10 +174,13 @@ imageTag: 1.0.0 labels: pipeline: atm-fraud + persistence: + enabled: false prometheus: jmx: enabled: false replicaCount: 1 + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 errorTopic: atm-fraud-transaction-joiner-dead-letter-topic @@ -214,10 +220,13 @@ imageTag: 1.0.0 labels: pipeline: atm-fraud + persistence: + enabled: false prometheus: jmx: enabled: false replicaCount: 1 + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 errorTopic: atm-fraud-fraud-detector-dead-letter-topic @@ -247,10 +256,13 @@ imageTag: 1.0.0 labels: pipeline: atm-fraud + persistence: + enabled: false prometheus: jmx: enabled: false replicaCount: 1 + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 errorTopic: atm-fraud-fraud-detector-dead-letter-topic @@ -290,10 +302,13 @@ imageTag: 1.0.0 labels: pipeline: atm-fraud + persistence: + enabled: false prometheus: jmx: enabled: false replicaCount: 1 + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 errorTopic: atm-fraud-account-linker-dead-letter-topic @@ -326,10 +341,13 @@ imageTag: 1.0.0 labels: pipeline: atm-fraud + persistence: + enabled: false prometheus: jmx: enabled: false replicaCount: 1 + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 errorTopic: atm-fraud-account-linker-dead-letter-topic diff --git a/tests/pipeline/snapshots/test_example/test_generate/word-count/pipeline.yaml b/tests/pipeline/snapshots/test_example/test_generate/word-count/pipeline.yaml index bf3dc5ec3..7e7d16fe8 100644 --- a/tests/pipeline/snapshots/test_example/test_generate/word-count/pipeline.yaml +++ b/tests/pipeline/snapshots/test_example/test_generate/word-count/pipeline.yaml @@ -64,10 +64,13 @@ imageTag: 1.0.0 labels: pipeline: word-count + persistence: + enabled: false prometheus: jmx: enabled: false replicaCount: 1 + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 errorTopic: word-count-word-counter-dead-letter-topic @@ -95,10 +98,13 @@ imageTag: 1.0.0 labels: pipeline: word-count + persistence: + enabled: false prometheus: jmx: enabled: false replicaCount: 1 + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 errorTopic: word-count-word-counter-dead-letter-topic diff --git a/tests/pipeline/snapshots/test_generate/test_default_config/pipeline.yaml b/tests/pipeline/snapshots/test_generate/test_default_config/pipeline.yaml index 3e48a620d..cbd0e251e 100644 --- a/tests/pipeline/snapshots/test_generate/test_default_config/pipeline.yaml +++ b/tests/pipeline/snapshots/test_generate/test_default_config/pipeline.yaml @@ -52,6 +52,9 @@ image: some-image labels: pipeline: resources-custom-config + persistence: + enabled: false + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 config: @@ -76,6 +79,9 @@ image: some-image labels: pipeline: resources-custom-config + persistence: + enabled: false + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 config: diff --git a/tests/pipeline/snapshots/test_generate/test_inflate_pipeline/pipeline.yaml b/tests/pipeline/snapshots/test_generate/test_inflate_pipeline/pipeline.yaml index 78c09b189..e5e003376 100644 --- a/tests/pipeline/snapshots/test_generate/test_inflate_pipeline/pipeline.yaml +++ b/tests/pipeline/snapshots/test_generate/test_inflate_pipeline/pipeline.yaml @@ -64,11 +64,14 @@ topics: [] commandLine: CONVERT_XML: true + persistence: + enabled: false resources: limits: memory: 2G requests: memory: 2G + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 config: @@ -102,11 +105,14 @@ topics: [] commandLine: CONVERT_XML: true + persistence: + enabled: false resources: limits: memory: 2G requests: memory: 2G + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 config: @@ -158,10 +164,13 @@ TYPE: nothing image: fake-registry/filter imageTag: 2.4.1 + persistence: + enabled: false replicaCount: 4 resources: requests: memory: 3G + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 config: @@ -198,10 +207,13 @@ TYPE: nothing image: fake-registry/filter imageTag: 2.4.1 + persistence: + enabled: false replicaCount: 4 resources: requests: memory: 3G + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 config: @@ -281,6 +293,9 @@ type: kafka-sink-connector - _cleaner: app: + persistence: + enabled: false + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 config: @@ -302,6 +317,9 @@ type: streams-app-cleaner version: 2.4.2 app: + persistence: + enabled: false + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 config: diff --git a/tests/pipeline/snapshots/test_generate/test_kafka_connect_sink_weave_from_topics/pipeline.yaml b/tests/pipeline/snapshots/test_generate/test_kafka_connect_sink_weave_from_topics/pipeline.yaml index ded2c268c..bb569e772 100644 --- a/tests/pipeline/snapshots/test_generate/test_kafka_connect_sink_weave_from_topics/pipeline.yaml +++ b/tests/pipeline/snapshots/test_generate/test_kafka_connect_sink_weave_from_topics/pipeline.yaml @@ -1,6 +1,9 @@ - _cleaner: app: image: fake-image + persistence: + enabled: false + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 config: @@ -23,6 +26,9 @@ version: 2.4.2 app: image: fake-image + persistence: + enabled: false + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 config: diff --git a/tests/pipeline/snapshots/test_generate/test_load_pipeline/pipeline.yaml b/tests/pipeline/snapshots/test_generate/test_load_pipeline/pipeline.yaml index e75009bb1..87a88601c 100644 --- a/tests/pipeline/snapshots/test_generate/test_load_pipeline/pipeline.yaml +++ b/tests/pipeline/snapshots/test_generate/test_load_pipeline/pipeline.yaml @@ -64,11 +64,14 @@ topics: [] commandLine: CONVERT_XML: true + persistence: + enabled: false resources: limits: memory: 2G requests: memory: 2G + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 config: @@ -102,11 +105,14 @@ topics: [] commandLine: CONVERT_XML: true + persistence: + enabled: false resources: limits: memory: 2G requests: memory: 2G + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 config: @@ -158,10 +164,13 @@ TYPE: nothing image: fake-registry/filter imageTag: 2.4.1 + persistence: + enabled: false replicaCount: 4 resources: requests: memory: 3G + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 config: @@ -198,10 +207,13 @@ TYPE: nothing image: fake-registry/filter imageTag: 2.4.1 + persistence: + enabled: false replicaCount: 4 resources: requests: memory: 3G + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 config: diff --git a/tests/pipeline/snapshots/test_generate/test_no_input_topic/pipeline.yaml b/tests/pipeline/snapshots/test_generate/test_no_input_topic/pipeline.yaml index 9165b293b..a77aea9be 100644 --- a/tests/pipeline/snapshots/test_generate/test_no_input_topic/pipeline.yaml +++ b/tests/pipeline/snapshots/test_generate/test_no_input_topic/pipeline.yaml @@ -2,11 +2,14 @@ app: commandLine: CONVERT_XML: true + persistence: + enabled: false resources: limits: memory: 2G requests: memory: 2G + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 config: @@ -29,11 +32,14 @@ app: commandLine: CONVERT_XML: true + persistence: + enabled: false resources: limits: memory: 2G requests: memory: 2G + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 config: @@ -71,6 +77,9 @@ version: 2.4.2 - _cleaner: app: + persistence: + enabled: false + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 config: @@ -94,6 +103,9 @@ type: streams-app-cleaner version: 2.4.2 app: + persistence: + enabled: false + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 config: diff --git a/tests/pipeline/snapshots/test_generate/test_no_user_defined_components/pipeline.yaml b/tests/pipeline/snapshots/test_generate/test_no_user_defined_components/pipeline.yaml index d030b4b5d..d8850383e 100644 --- a/tests/pipeline/snapshots/test_generate/test_no_user_defined_components/pipeline.yaml +++ b/tests/pipeline/snapshots/test_generate/test_no_user_defined_components/pipeline.yaml @@ -1,6 +1,9 @@ - _cleaner: app: image: fake-image + persistence: + enabled: false + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 config: @@ -23,6 +26,9 @@ version: 2.4.2 app: image: fake-image + persistence: + enabled: false + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 config: diff --git a/tests/pipeline/snapshots/test_generate/test_pipelines_with_envs/pipeline.yaml b/tests/pipeline/snapshots/test_generate/test_pipelines_with_envs/pipeline.yaml index 13dacf995..344e9c5b1 100644 --- a/tests/pipeline/snapshots/test_generate/test_pipelines_with_envs/pipeline.yaml +++ b/tests/pipeline/snapshots/test_generate/test_pipelines_with_envs/pipeline.yaml @@ -64,11 +64,14 @@ topics: [] commandLine: CONVERT_XML: true + persistence: + enabled: false resources: limits: memory: 2G requests: memory: 2G + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 config: @@ -102,11 +105,14 @@ topics: [] commandLine: CONVERT_XML: true + persistence: + enabled: false resources: limits: memory: 2G requests: memory: 2G + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 config: @@ -158,10 +164,13 @@ TYPE: nothing image: fake-registry/filter imageTag: 2.4.1 + persistence: + enabled: false replicaCount: 4 resources: requests: memory: 3G + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 config: @@ -198,10 +207,13 @@ TYPE: nothing image: fake-registry/filter imageTag: 2.4.1 + persistence: + enabled: false replicaCount: 4 resources: requests: memory: 3G + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 config: diff --git a/tests/pipeline/snapshots/test_generate/test_read_from_component/pipeline.yaml b/tests/pipeline/snapshots/test_generate/test_read_from_component/pipeline.yaml index c3e7f554a..761f21e63 100644 --- a/tests/pipeline/snapshots/test_generate/test_read_from_component/pipeline.yaml +++ b/tests/pipeline/snapshots/test_generate/test_read_from_component/pipeline.yaml @@ -89,6 +89,9 @@ - resources-read-from-component-inflate-step image: fake-registry/filter imageTag: 2.4.1 + persistence: + enabled: false + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 config: @@ -123,6 +126,9 @@ - resources-read-from-component-inflate-step image: fake-registry/filter imageTag: 2.4.1 + persistence: + enabled: false + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 config: @@ -202,6 +208,9 @@ type: kafka-sink-connector - _cleaner: app: + persistence: + enabled: false + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 config: @@ -223,6 +232,9 @@ type: streams-app-cleaner version: 2.4.2 app: + persistence: + enabled: false + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 config: @@ -269,6 +281,9 @@ - resources-read-from-component-inflate-step-without-prefix image: fake-registry/filter imageTag: 2.4.1 + persistence: + enabled: false + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 config: @@ -303,6 +318,9 @@ - resources-read-from-component-inflate-step-without-prefix image: fake-registry/filter imageTag: 2.4.1 + persistence: + enabled: false + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 config: @@ -382,6 +400,9 @@ type: kafka-sink-connector - _cleaner: app: + persistence: + enabled: false + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 config: @@ -403,6 +424,9 @@ type: streams-app-cleaner version: 2.4.2 app: + persistence: + enabled: false + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 config: @@ -436,6 +460,9 @@ version: 2.4.2 - _cleaner: app: + persistence: + enabled: false + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 config: @@ -457,6 +484,9 @@ type: streams-app-cleaner version: 2.4.2 app: + persistence: + enabled: false + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 config: @@ -495,6 +525,9 @@ version: 2.4.2 - _cleaner: app: + persistence: + enabled: false + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 config: @@ -516,6 +549,9 @@ type: streams-app-cleaner version: 2.4.2 app: + persistence: + enabled: false + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 config: @@ -553,6 +589,9 @@ version: 2.4.2 - _cleaner: app: + persistence: + enabled: false + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 config: @@ -574,6 +613,9 @@ type: streams-app-cleaner version: 2.4.2 app: + persistence: + enabled: false + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 config: @@ -611,6 +653,9 @@ version: 2.4.2 - _cleaner: app: + persistence: + enabled: false + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 config: @@ -631,6 +676,9 @@ type: streams-app-cleaner version: 2.4.2 app: + persistence: + enabled: false + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 config: @@ -665,6 +713,9 @@ version: 2.4.2 - _cleaner: app: + persistence: + enabled: false + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 config: @@ -685,6 +736,9 @@ type: streams-app-cleaner version: 2.4.2 app: + persistence: + enabled: false + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 config: diff --git a/tests/pipeline/snapshots/test_generate/test_substitute_in_component/pipeline.yaml b/tests/pipeline/snapshots/test_generate/test_substitute_in_component/pipeline.yaml index 3699c56d6..8ca686f30 100644 --- a/tests/pipeline/snapshots/test_generate/test_substitute_in_component/pipeline.yaml +++ b/tests/pipeline/snapshots/test_generate/test_substitute_in_component/pipeline.yaml @@ -72,11 +72,14 @@ topics: [] commandLine: CONVERT_XML: true + persistence: + enabled: false resources: limits: memory: 2G requests: memory: 2G + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 config: @@ -110,11 +113,14 @@ topics: [] commandLine: CONVERT_XML: true + persistence: + enabled: false resources: limits: memory: 2G requests: memory: 2G + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 config: @@ -172,10 +178,13 @@ app_type: filter filter: filter-app-filter test_placeholder_in_placeholder: filter-app-filter + persistence: + enabled: false replicaCount: 4 resources: requests: memory: 3G + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 config: @@ -218,10 +227,13 @@ app_type: filter filter: filter-app-filter test_placeholder_in_placeholder: filter-app-filter + persistence: + enabled: false replicaCount: 4 resources: requests: memory: 3G + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 config: diff --git a/tests/pipeline/snapshots/test_generate/test_with_custom_config_with_absolute_defaults_path/pipeline.yaml b/tests/pipeline/snapshots/test_generate/test_with_custom_config_with_absolute_defaults_path/pipeline.yaml index 1ce162f25..f78e8f0d1 100644 --- a/tests/pipeline/snapshots/test_generate/test_with_custom_config_with_absolute_defaults_path/pipeline.yaml +++ b/tests/pipeline/snapshots/test_generate/test_with_custom_config_with_absolute_defaults_path/pipeline.yaml @@ -52,6 +52,9 @@ image: some-image labels: pipeline: resources-custom-config + persistence: + enabled: false + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 config: @@ -76,6 +79,9 @@ image: some-image labels: pipeline: resources-custom-config + persistence: + enabled: false + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 config: diff --git a/tests/pipeline/snapshots/test_generate/test_with_custom_config_with_relative_defaults_path/pipeline.yaml b/tests/pipeline/snapshots/test_generate/test_with_custom_config_with_relative_defaults_path/pipeline.yaml index 1ce162f25..f78e8f0d1 100644 --- a/tests/pipeline/snapshots/test_generate/test_with_custom_config_with_relative_defaults_path/pipeline.yaml +++ b/tests/pipeline/snapshots/test_generate/test_with_custom_config_with_relative_defaults_path/pipeline.yaml @@ -52,6 +52,9 @@ image: some-image labels: pipeline: resources-custom-config + persistence: + enabled: false + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 config: @@ -76,6 +79,9 @@ image: some-image labels: pipeline: resources-custom-config + persistence: + enabled: false + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 config: diff --git a/tests/pipeline/snapshots/test_generate/test_with_env_defaults/pipeline.yaml b/tests/pipeline/snapshots/test_generate/test_with_env_defaults/pipeline.yaml index 8f8ddf7cb..cea0b2660 100644 --- a/tests/pipeline/snapshots/test_generate/test_with_env_defaults/pipeline.yaml +++ b/tests/pipeline/snapshots/test_generate/test_with_env_defaults/pipeline.yaml @@ -1,6 +1,9 @@ - _cleaner: app: image: fake-image + persistence: + enabled: false + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 config: @@ -23,6 +26,9 @@ version: 2.9.0 app: image: fake-image + persistence: + enabled: false + statefulSet: false streams: brokers: http://k8kafka-cp-kafka-headless.kpops.svc.cluster.local:9092 config: From 4654198f5c584c6556ca88474a9e194abc23dcbe Mon Sep 17 00:00:00 2001 From: Ramin Gharib Date: Mon, 22 Apr 2024 16:42:35 +0200 Subject: [PATCH 5/8] Fix tests --- .../kubernetes/pvc_handler.py | 9 +-- .../streams_bootstrap/streams/streams_app.py | 2 +- tests/kubernetes/__init__.py | 0 tests/kubernetes/test_pvc_handler.py | 56 +++++++++++++++++++ 4 files changed, 62 insertions(+), 5 deletions(-) create mode 100644 tests/kubernetes/__init__.py create mode 100644 tests/kubernetes/test_pvc_handler.py diff --git a/kpops/component_handlers/kubernetes/pvc_handler.py b/kpops/component_handlers/kubernetes/pvc_handler.py index 052485ccb..be6a7239b 100644 --- a/kpops/component_handlers/kubernetes/pvc_handler.py +++ b/kpops/component_handlers/kubernetes/pvc_handler.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import logging from kubernetes_asyncio import client, config @@ -12,13 +14,12 @@ def __init__(self, app_name: str, namespace: str): self.namespace = namespace @classmethod - async def create(cls, app_name: str, namespace: str): + async def create(cls, app_name: str, namespace: str) -> PVCHandler: self = cls(app_name, namespace) await config.load_kube_config() return self - @property - async def pvc_names(self) -> list[str]: + async def get_pvc_names(self) -> list[str]: async with ApiClient() as api: core_v1_api = client.CoreV1Api(api) pvc_list = core_v1_api.list_namespaced_persistent_volume_claim( @@ -38,7 +39,7 @@ async def pvc_names(self) -> list[str]: async def delete_pvcs(self) -> None: async with ApiClient() as api: core_v1_api = client.CoreV1Api(api) - pvc_names = await self.pvc_names + pvc_names = await self.get_pvc_names() log.debug( f"Deleting in namespace '{self.namespace}' StatefulSet '{self.app_name}' PVCs '{pvc_names}'" ) diff --git a/kpops/components/streams_bootstrap/streams/streams_app.py b/kpops/components/streams_bootstrap/streams/streams_app.py index dcc5b7d1e..ac24702e3 100644 --- a/kpops/components/streams_bootstrap/streams/streams_app.py +++ b/kpops/components/streams_bootstrap/streams/streams_app.py @@ -42,7 +42,7 @@ async def clean(self, dry_run: bool) -> None: async def clean_pvcs(self, dry_run: bool) -> None: if dry_run: - pvc_names = await self.pvc_handler.pvc_names + pvc_names = await self.pvc_handler.get_pvc_names() log.info( f"Deleting the PVCs {pvc_names} for StatefulSet '{self.full_name}'" ) diff --git a/tests/kubernetes/__init__.py b/tests/kubernetes/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/kubernetes/test_pvc_handler.py b/tests/kubernetes/test_pvc_handler.py new file mode 100644 index 000000000..403cd586d --- /dev/null +++ b/tests/kubernetes/test_pvc_handler.py @@ -0,0 +1,56 @@ +from unittest.mock import AsyncMock, MagicMock, patch + +import pytest +from pytest_mock import MockerFixture + +from kpops.component_handlers.kubernetes.pvc_handler import PVCHandler + +MODULE = "kpops.component_handlers.kubernetes.pvc_handler" + + +@pytest.fixture +def pvc_handler(): + return PVCHandler("test-app", "test-namespace") + + +async def pvc_names_return_value() -> list[str]: + return ["test-pvc"] + + +@pytest.mark.asyncio +async def test_create(pvc_handler: PVCHandler): + with patch(f"{MODULE}.config.load_kube_config") as mock_load_kube_config: + pvc_handler = await PVCHandler.create("test-app", "test-namespace") + mock_load_kube_config.assert_called_once() + assert isinstance(pvc_handler, PVCHandler) + assert pvc_handler.namespace == "test-namespace" + assert pvc_handler.app_name == "test-app" + + +@pytest.mark.asyncio +async def test_pvc_names(pvc_handler: PVCHandler): + mock_pvc = MagicMock() + mock_pvc.metadata.name = "test-pvc" + + with patch(f"{MODULE}.client.CoreV1Api") as mock_core_v1_api: + mock_core_v1_api.return_value.list_namespaced_persistent_volume_claim.return_value.items = [ + mock_pvc + ] + pvc_names = await pvc_handler.get_pvc_names() + + assert pvc_names == ["test-pvc"] + + +@pytest.mark.asyncio +async def test_delete_pvcs(pvc_handler: PVCHandler, mocker: MockerFixture): + mock = mocker.patch( + f"{MODULE}.PVCHandler.get_pvc_names", + new_callable=AsyncMock, + return_value=["test-pvc"], + ) + print(mock) + with patch(f"{MODULE}.client.CoreV1Api") as mock_core_v1_api: + await pvc_handler.delete_pvcs() + mock_core_v1_api.return_value.delete_namespaced_persistent_volume_claim.assert_called_once_with( + "test-pvc", "test-namespace" + ) From 2fcb40d5ac239c0d6e92a08bd438e12c1b84b7bd Mon Sep 17 00:00:00 2001 From: Ramin Gharib Date: Mon, 22 Apr 2024 16:43:31 +0200 Subject: [PATCH 6/8] Update files --- tests/kubernetes/test_pvc_handler.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/tests/kubernetes/test_pvc_handler.py b/tests/kubernetes/test_pvc_handler.py index 403cd586d..6eebb9579 100644 --- a/tests/kubernetes/test_pvc_handler.py +++ b/tests/kubernetes/test_pvc_handler.py @@ -43,14 +43,13 @@ async def test_pvc_names(pvc_handler: PVCHandler): @pytest.mark.asyncio async def test_delete_pvcs(pvc_handler: PVCHandler, mocker: MockerFixture): - mock = mocker.patch( + mocker.patch( f"{MODULE}.PVCHandler.get_pvc_names", new_callable=AsyncMock, return_value=["test-pvc"], ) - print(mock) - with patch(f"{MODULE}.client.CoreV1Api") as mock_core_v1_api: - await pvc_handler.delete_pvcs() - mock_core_v1_api.return_value.delete_namespaced_persistent_volume_claim.assert_called_once_with( - "test-pvc", "test-namespace" - ) + mock_core_v1_api = mocker.patch(f"{MODULE}.client.CoreV1Api") + await pvc_handler.delete_pvcs() + mock_core_v1_api.return_value.delete_namespaced_persistent_volume_claim.assert_called_once_with( + "test-pvc", "test-namespace" + ) From 9cbfc0fb90f407e230e87d69f3c33ebbf4bc133c Mon Sep 17 00:00:00 2001 From: Ramin Gharib Date: Mon, 22 Apr 2024 16:45:05 +0200 Subject: [PATCH 7/8] Update files --- tests/kubernetes/test_pvc_handler.py | 32 ++++++++++++---------------- 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/tests/kubernetes/test_pvc_handler.py b/tests/kubernetes/test_pvc_handler.py index 6eebb9579..77bec8419 100644 --- a/tests/kubernetes/test_pvc_handler.py +++ b/tests/kubernetes/test_pvc_handler.py @@ -1,4 +1,4 @@ -from unittest.mock import AsyncMock, MagicMock, patch +from unittest.mock import AsyncMock, MagicMock import pytest from pytest_mock import MockerFixture @@ -13,30 +13,26 @@ def pvc_handler(): return PVCHandler("test-app", "test-namespace") -async def pvc_names_return_value() -> list[str]: - return ["test-pvc"] - - @pytest.mark.asyncio -async def test_create(pvc_handler: PVCHandler): - with patch(f"{MODULE}.config.load_kube_config") as mock_load_kube_config: - pvc_handler = await PVCHandler.create("test-app", "test-namespace") - mock_load_kube_config.assert_called_once() - assert isinstance(pvc_handler, PVCHandler) - assert pvc_handler.namespace == "test-namespace" - assert pvc_handler.app_name == "test-app" +async def test_create(pvc_handler: PVCHandler, mocker: MockerFixture): + mock_load_kube_config = mocker.patch(f"{MODULE}.config.load_kube_config") + pvc_handler = await PVCHandler.create("test-app", "test-namespace") + mock_load_kube_config.assert_called_once() + assert isinstance(pvc_handler, PVCHandler) + assert pvc_handler.namespace == "test-namespace" + assert pvc_handler.app_name == "test-app" @pytest.mark.asyncio -async def test_pvc_names(pvc_handler: PVCHandler): +async def test_pvc_names(pvc_handler: PVCHandler, mocker: MockerFixture): mock_pvc = MagicMock() mock_pvc.metadata.name = "test-pvc" - with patch(f"{MODULE}.client.CoreV1Api") as mock_core_v1_api: - mock_core_v1_api.return_value.list_namespaced_persistent_volume_claim.return_value.items = [ - mock_pvc - ] - pvc_names = await pvc_handler.get_pvc_names() + mock_core_v1_api = mocker.patch(f"{MODULE}.client.CoreV1Api") + mock_core_v1_api.return_value.list_namespaced_persistent_volume_claim.return_value.items = [ + mock_pvc + ] + pvc_names = await pvc_handler.get_pvc_names() assert pvc_names == ["test-pvc"] From a53904f5d755e02a964d567cedd3cf90e48bdd0e Mon Sep 17 00:00:00 2001 From: Ramin Gharib Date: Thu, 25 Apr 2024 13:36:14 +0200 Subject: [PATCH 8/8] Clean up --- .../kubernetes/pvc_handler.py | 4 ++-- .../streams_bootstrap/streams/streams_app.py | 2 +- tests/components/test_streams_app.py | 2 +- tests/kubernetes/test_pvc_handler.py | 23 +++++++++++-------- 4 files changed, 18 insertions(+), 13 deletions(-) diff --git a/kpops/component_handlers/kubernetes/pvc_handler.py b/kpops/component_handlers/kubernetes/pvc_handler.py index be6a7239b..0c17e9a4c 100644 --- a/kpops/component_handlers/kubernetes/pvc_handler.py +++ b/kpops/component_handlers/kubernetes/pvc_handler.py @@ -19,7 +19,7 @@ async def create(cls, app_name: str, namespace: str) -> PVCHandler: await config.load_kube_config() return self - async def get_pvc_names(self) -> list[str]: + async def list_pvcs(self) -> list[str]: async with ApiClient() as api: core_v1_api = client.CoreV1Api(api) pvc_list = core_v1_api.list_namespaced_persistent_volume_claim( @@ -39,7 +39,7 @@ async def get_pvc_names(self) -> list[str]: async def delete_pvcs(self) -> None: async with ApiClient() as api: core_v1_api = client.CoreV1Api(api) - pvc_names = await self.get_pvc_names() + pvc_names = await self.list_pvcs() log.debug( f"Deleting in namespace '{self.namespace}' StatefulSet '{self.app_name}' PVCs '{pvc_names}'" ) diff --git a/kpops/components/streams_bootstrap/streams/streams_app.py b/kpops/components/streams_bootstrap/streams/streams_app.py index f307ffa57..2f15be10b 100644 --- a/kpops/components/streams_bootstrap/streams/streams_app.py +++ b/kpops/components/streams_bootstrap/streams/streams_app.py @@ -42,7 +42,7 @@ async def clean(self, dry_run: bool) -> None: async def clean_pvcs(self, dry_run: bool) -> None: if dry_run: - pvc_names = await self.pvc_handler.get_pvc_names() + pvc_names = await self.pvc_handler.list_pvcs() log.info( f"Deleting the PVCs {pvc_names} for StatefulSet '{self.full_name}'" ) diff --git a/tests/components/test_streams_app.py b/tests/components/test_streams_app.py index 052cecad4..e272f7f2e 100644 --- a/tests/components/test_streams_app.py +++ b/tests/components/test_streams_app.py @@ -789,7 +789,7 @@ async def test_stateful_clean_with_dry_run_true( mocker.patch.object(cleaner, "destroy") mocker.patch.object(cleaner, "deploy") - mock_get_pvc_names = mocker.patch.object(cleaner.pvc_handler, "get_pvc_names") + mock_get_pvc_names = mocker.patch.object(cleaner.pvc_handler, "list_pvcs") mock_get_pvc_names.return_value = pvc_names dry_run = True diff --git a/tests/kubernetes/test_pvc_handler.py b/tests/kubernetes/test_pvc_handler.py index 77bec8419..c3c1b4ec8 100644 --- a/tests/kubernetes/test_pvc_handler.py +++ b/tests/kubernetes/test_pvc_handler.py @@ -1,4 +1,4 @@ -from unittest.mock import AsyncMock, MagicMock +from unittest.mock import MagicMock import pytest from pytest_mock import MockerFixture @@ -32,20 +32,25 @@ async def test_pvc_names(pvc_handler: PVCHandler, mocker: MockerFixture): mock_core_v1_api.return_value.list_namespaced_persistent_volume_claim.return_value.items = [ mock_pvc ] - pvc_names = await pvc_handler.get_pvc_names() + pvcs = await pvc_handler.list_pvcs() - assert pvc_names == ["test-pvc"] + assert pvcs == ["test-pvc"] @pytest.mark.asyncio async def test_delete_pvcs(pvc_handler: PVCHandler, mocker: MockerFixture): - mocker.patch( - f"{MODULE}.PVCHandler.get_pvc_names", - new_callable=AsyncMock, - return_value=["test-pvc"], + mocker.patch.object( + pvc_handler, "list_pvcs", return_value=["test-pvc-1", "test-pvc-2"] ) mock_core_v1_api = mocker.patch(f"{MODULE}.client.CoreV1Api") await pvc_handler.delete_pvcs() - mock_core_v1_api.return_value.delete_namespaced_persistent_volume_claim.assert_called_once_with( - "test-pvc", "test-namespace" + mock_core_v1_api.return_value.assert_has_calls( + [ + mocker.call.delete_namespaced_persistent_volume_claim( + "test-pvc-1", "test-namespace" + ), + mocker.call.delete_namespaced_persistent_volume_claim( + "test-pvc-2", "test-namespace" + ), + ] )