diff --git a/CHANGELOG.md b/CHANGELOG.md index 65b71765..5ed705a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,8 @@ ## Release (2025-MM-DD) +- `cdn`: [v1.6.0](services/cdn/CHANGELOG.md#v160) + - **Feature:** Added Attribute `LogSink` to `ConfigPatch` + - **Feature:** Added Attribute `Geofencing` to `DistributionPayload`, `HttpBackend` and `HttpBackendPatch` + - **Feature:** Added new function `GetLogsSearchFilters` - `modelserving`: [v0.2.1](services/modelserving/CHANGELOG.md#v021) - **Feature:** Extend enums in field `type` in model `Model`: `audio`, `image` - `objectstorage`: [v1.2.0](services/objectstorage/CHANGELOG.md#v120) @@ -23,8 +27,11 @@ - **Feature:** Add new field `kubernetes` to `Nodepool` model - `serviceaccount`: [v0.4.1](services/serviceaccount/CHANGELOG.md#v041) - **Improvement:** Improve error handling for `CreateShortLivedAccessToken` -- `stackitmarketplace`: [v1.8.0](services/stackitmarketplace/CHANGELOG.md#v180) - - **Feature:** Add new field `free_trial` in `CatalogProductOverview` model +- `stackitmarketplace`: + - [v1.9.0](services/stackitmarketplace/CHANGELOG.md#v190) + - **Feature:** Added `RequestPrivatePlan` to `InquiriesCreateInquiryPayload` + - [v1.8.0](services/stackitmarketplace/CHANGELOG.md#v180) + - **Feature:** Add new field `free_trial` in `CatalogProductOverview` model ## Release (2025-08-29) - `kms`: [v0.3.0](services/kms/CHANGELOG.md#v030) diff --git a/services/cdn/CHANGELOG.md b/services/cdn/CHANGELOG.md index 08454539..78f55976 100644 --- a/services/cdn/CHANGELOG.md +++ b/services/cdn/CHANGELOG.md @@ -1,3 +1,8 @@ +## v1.6.0 +- **Feature:** Added Attribute `LogSink` to `ConfigPatch` +- **Feature:** Added Attribute `Geofencing` to `DistributionPayload`, `HttpBackend` and `HttpBackendPatch` +- **Feature:** Added new function `GetLogsSearchFilters` + ## v1.5.0 - **Feature:** Added new filter functions `DataCenterRegion`, `RequestCountryCode`, `StatusCode` and `CacheHit` - **Feature:** Added Attribute `LogSink` and `Certificate` diff --git a/services/cdn/pyproject.toml b/services/cdn/pyproject.toml index 051c1040..da9cd314 100644 --- a/services/cdn/pyproject.toml +++ b/services/cdn/pyproject.toml @@ -3,7 +3,7 @@ name = "stackit-cdn" [tool.poetry] name = "stackit-cdn" -version = "v1.5.0" +version = "v1.6.0" authors = [ "STACKIT Developer Tools ", ] diff --git a/services/cdn/src/stackit/cdn/__init__.py b/services/cdn/src/stackit/cdn/__init__.py index 4dec4f51..5c6e0dfb 100644 --- a/services/cdn/src/stackit/cdn/__init__.py +++ b/services/cdn/src/stackit/cdn/__init__.py @@ -54,6 +54,7 @@ "GetCustomDomainResponseCertificate", "GetDistributionResponse", "GetLogsResponse", + "GetLogsSearchFiltersResponse", "GetStatisticsResponse", "HttpBackend", "HttpBackendPatch", @@ -152,6 +153,9 @@ GetDistributionResponse as GetDistributionResponse, ) from stackit.cdn.models.get_logs_response import GetLogsResponse as GetLogsResponse +from stackit.cdn.models.get_logs_search_filters_response import ( + GetLogsSearchFiltersResponse as GetLogsSearchFiltersResponse, +) from stackit.cdn.models.get_statistics_response import ( GetStatisticsResponse as GetStatisticsResponse, ) diff --git a/services/cdn/src/stackit/cdn/api/default_api.py b/services/cdn/src/stackit/cdn/api/default_api.py index 6468b2ad..b5e2172a 100644 --- a/services/cdn/src/stackit/cdn/api/default_api.py +++ b/services/cdn/src/stackit/cdn/api/default_api.py @@ -36,6 +36,9 @@ from stackit.cdn.models.get_custom_domain_response import GetCustomDomainResponse from stackit.cdn.models.get_distribution_response import GetDistributionResponse from stackit.cdn.models.get_logs_response import GetLogsResponse +from stackit.cdn.models.get_logs_search_filters_response import ( + GetLogsSearchFiltersResponse, +) from stackit.cdn.models.get_statistics_response import GetStatisticsResponse from stackit.cdn.models.list_distributions_response import ListDistributionsResponse from stackit.cdn.models.patch_distribution_payload import PatchDistributionPayload @@ -1968,7 +1971,7 @@ def get_logs( sort_by: Annotated[ Optional[StrictStr], Field( - description="The following sort options exist. We default to `timestamp` - `timestamp` - Sort by log message time stamp. " + description="Sorts the log messages by a specific field. Defaults to `timestamp`. Supported sort options: - `timestamp` - `dataCenterRegion` - `requestCountryCode` - `statusCode` - `cacheHit` - `size` - `path` - `host` " ), ] = None, sort_order: Optional[StrictStr] = None, @@ -2021,7 +2024,7 @@ def get_logs( :type page_size: int :param page_identifier: Identifier is returned by the previous response and is used to request the next page. As the `pageIdentifier` encodes an element, inserts during pagination will *not* shift the result. So a scenario like: - Start listing first page - Insert new element - Start listing second page will *never* result in an element from the first page to get \"pushed\" to the second page, like it could occur with basic limit + offset pagination. The identifier should be treated as an opaque string and never modified. Only pass values returned by the API. :type page_identifier: str - :param sort_by: The following sort options exist. We default to `timestamp` - `timestamp` - Sort by log message time stamp. + :param sort_by: Sorts the log messages by a specific field. Defaults to `timestamp`. Supported sort options: - `timestamp` - `dataCenterRegion` - `requestCountryCode` - `statusCode` - `cacheHit` - `size` - `path` - `host` :type sort_by: str :param sort_order: :type sort_order: str @@ -2116,7 +2119,7 @@ def get_logs_with_http_info( sort_by: Annotated[ Optional[StrictStr], Field( - description="The following sort options exist. We default to `timestamp` - `timestamp` - Sort by log message time stamp. " + description="Sorts the log messages by a specific field. Defaults to `timestamp`. Supported sort options: - `timestamp` - `dataCenterRegion` - `requestCountryCode` - `statusCode` - `cacheHit` - `size` - `path` - `host` " ), ] = None, sort_order: Optional[StrictStr] = None, @@ -2169,7 +2172,7 @@ def get_logs_with_http_info( :type page_size: int :param page_identifier: Identifier is returned by the previous response and is used to request the next page. As the `pageIdentifier` encodes an element, inserts during pagination will *not* shift the result. So a scenario like: - Start listing first page - Insert new element - Start listing second page will *never* result in an element from the first page to get \"pushed\" to the second page, like it could occur with basic limit + offset pagination. The identifier should be treated as an opaque string and never modified. Only pass values returned by the API. :type page_identifier: str - :param sort_by: The following sort options exist. We default to `timestamp` - `timestamp` - Sort by log message time stamp. + :param sort_by: Sorts the log messages by a specific field. Defaults to `timestamp`. Supported sort options: - `timestamp` - `dataCenterRegion` - `requestCountryCode` - `statusCode` - `cacheHit` - `size` - `path` - `host` :type sort_by: str :param sort_order: :type sort_order: str @@ -2264,7 +2267,7 @@ def get_logs_without_preload_content( sort_by: Annotated[ Optional[StrictStr], Field( - description="The following sort options exist. We default to `timestamp` - `timestamp` - Sort by log message time stamp. " + description="Sorts the log messages by a specific field. Defaults to `timestamp`. Supported sort options: - `timestamp` - `dataCenterRegion` - `requestCountryCode` - `statusCode` - `cacheHit` - `size` - `path` - `host` " ), ] = None, sort_order: Optional[StrictStr] = None, @@ -2317,7 +2320,7 @@ def get_logs_without_preload_content( :type page_size: int :param page_identifier: Identifier is returned by the previous response and is used to request the next page. As the `pageIdentifier` encodes an element, inserts during pagination will *not* shift the result. So a scenario like: - Start listing first page - Insert new element - Start listing second page will *never* result in an element from the first page to get \"pushed\" to the second page, like it could occur with basic limit + offset pagination. The identifier should be treated as an opaque string and never modified. Only pass values returned by the API. :type page_identifier: str - :param sort_by: The following sort options exist. We default to `timestamp` - `timestamp` - Sort by log message time stamp. + :param sort_by: Sorts the log messages by a specific field. Defaults to `timestamp`. Supported sort options: - `timestamp` - `dataCenterRegion` - `requestCountryCode` - `statusCode` - `cacheHit` - `size` - `path` - `host` :type sort_by: str :param sort_order: :type sort_order: str @@ -2486,6 +2489,288 @@ def _get_logs_serialize( _request_auth=_request_auth, ) + @validate_call + def get_logs_search_filters( + self, + project_id: Annotated[StrictStr, Field(description="Your STACKIT Project ID")], + distribution_id: Annotated[StrictStr, Field(description="Your CDN distribution ID")], + filter: Annotated[ + StrictStr, + Field( + description="Required filter for search suggestions (e.g., status=4, requestCountry, cacheHit=tru, dataCenterRegion). The filter query cannot be empty." + ), + ], + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]], + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> GetLogsSearchFiltersResponse: + """Get relevant search filters for this distribution based on user input + + + :param project_id: Your STACKIT Project ID (required) + :type project_id: str + :param distribution_id: Your CDN distribution ID (required) + :type distribution_id: str + :param filter: Required filter for search suggestions (e.g., status=4, requestCountry, cacheHit=tru, dataCenterRegion). The filter query cannot be empty. (required) + :type filter: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_logs_search_filters_serialize( + project_id=project_id, + distribution_id=distribution_id, + filter=filter, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index, + ) + + _response_types_map: Dict[str, Optional[str]] = { + "200": "GetLogsSearchFiltersResponse", + "400": "GenericJSONResponse", + "401": "str", + "422": "GenericJSONResponse", + "500": "GenericJSONResponse", + } + response_data = self.api_client.call_api(*_param, _request_timeout=_request_timeout) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + @validate_call + def get_logs_search_filters_with_http_info( + self, + project_id: Annotated[StrictStr, Field(description="Your STACKIT Project ID")], + distribution_id: Annotated[StrictStr, Field(description="Your CDN distribution ID")], + filter: Annotated[ + StrictStr, + Field( + description="Required filter for search suggestions (e.g., status=4, requestCountry, cacheHit=tru, dataCenterRegion). The filter query cannot be empty." + ), + ], + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]], + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[GetLogsSearchFiltersResponse]: + """Get relevant search filters for this distribution based on user input + + + :param project_id: Your STACKIT Project ID (required) + :type project_id: str + :param distribution_id: Your CDN distribution ID (required) + :type distribution_id: str + :param filter: Required filter for search suggestions (e.g., status=4, requestCountry, cacheHit=tru, dataCenterRegion). The filter query cannot be empty. (required) + :type filter: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_logs_search_filters_serialize( + project_id=project_id, + distribution_id=distribution_id, + filter=filter, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index, + ) + + _response_types_map: Dict[str, Optional[str]] = { + "200": "GetLogsSearchFiltersResponse", + "400": "GenericJSONResponse", + "401": "str", + "422": "GenericJSONResponse", + "500": "GenericJSONResponse", + } + response_data = self.api_client.call_api(*_param, _request_timeout=_request_timeout) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + @validate_call + def get_logs_search_filters_without_preload_content( + self, + project_id: Annotated[StrictStr, Field(description="Your STACKIT Project ID")], + distribution_id: Annotated[StrictStr, Field(description="Your CDN distribution ID")], + filter: Annotated[ + StrictStr, + Field( + description="Required filter for search suggestions (e.g., status=4, requestCountry, cacheHit=tru, dataCenterRegion). The filter query cannot be empty." + ), + ], + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]], + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Get relevant search filters for this distribution based on user input + + + :param project_id: Your STACKIT Project ID (required) + :type project_id: str + :param distribution_id: Your CDN distribution ID (required) + :type distribution_id: str + :param filter: Required filter for search suggestions (e.g., status=4, requestCountry, cacheHit=tru, dataCenterRegion). The filter query cannot be empty. (required) + :type filter: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_logs_search_filters_serialize( + project_id=project_id, + distribution_id=distribution_id, + filter=filter, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index, + ) + + _response_types_map: Dict[str, Optional[str]] = { + "200": "GetLogsSearchFiltersResponse", + "400": "GenericJSONResponse", + "401": "str", + "422": "GenericJSONResponse", + "500": "GenericJSONResponse", + } + response_data = self.api_client.call_api(*_param, _request_timeout=_request_timeout) + return response_data.response + + def _get_logs_search_filters_serialize( + self, + project_id, + distribution_id, + filter, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = {} + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + if project_id is not None: + _path_params["projectId"] = project_id + if distribution_id is not None: + _path_params["distributionId"] = distribution_id + # process the query parameters + if filter is not None: + + _query_params.append(("filter", filter)) + + # process the header parameters + # process the form parameters + # process the body parameter + + # set the HTTP header `Accept` + if "Accept" not in _header_params: + _header_params["Accept"] = self.api_client.select_header_accept(["application/json", "text/plain"]) + + # authentication setting + _auth_settings: List[str] = [] + + return self.api_client.param_serialize( + method="GET", + resource_path="/v1beta/projects/{projectId}/distributions/{distributionId}/logs/searchFilters", + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth, + ) + @validate_call def get_statistics( self, diff --git a/services/cdn/src/stackit/cdn/models/__init__.py b/services/cdn/src/stackit/cdn/models/__init__.py index 02646f44..0f332fc8 100644 --- a/services/cdn/src/stackit/cdn/models/__init__.py +++ b/services/cdn/src/stackit/cdn/models/__init__.py @@ -56,6 +56,9 @@ ) from stackit.cdn.models.get_distribution_response import GetDistributionResponse from stackit.cdn.models.get_logs_response import GetLogsResponse +from stackit.cdn.models.get_logs_search_filters_response import ( + GetLogsSearchFiltersResponse, +) from stackit.cdn.models.get_statistics_response import GetStatisticsResponse from stackit.cdn.models.http_backend import HttpBackend from stackit.cdn.models.http_backend_patch import HttpBackendPatch diff --git a/services/cdn/src/stackit/cdn/models/config_patch.py b/services/cdn/src/stackit/cdn/models/config_patch.py index 143e796b..05ead0ea 100644 --- a/services/cdn/src/stackit/cdn/models/config_patch.py +++ b/services/cdn/src/stackit/cdn/models/config_patch.py @@ -22,6 +22,7 @@ from stackit.cdn.models.http_backend_patch import HttpBackendPatch from stackit.cdn.models.optimizer_patch import OptimizerPatch +from stackit.cdn.models.patch_loki_log_sink import PatchLokiLogSink from stackit.cdn.models.region import Region @@ -46,6 +47,7 @@ class ConfigPatch(BaseModel): description="Sets the default cache duration for the distribution. The default cache duration is applied when a 'Cache-Control' header is not presented in the origin's response. We use ISO8601 duration format for cache duration (e.g. P1DT2H30M) ", alias="defaultCacheDuration", ) + log_sink: Optional[PatchLokiLogSink] = Field(default=None, alias="logSink") monthly_limit_bytes: Optional[Annotated[int, Field(strict=True, ge=0)]] = Field( default=None, description="Sets the monthly limit of bandwidth in bytes that the pullzone is allowed to use. ", @@ -58,6 +60,7 @@ class ConfigPatch(BaseModel): "blockedCountries", "blockedIPs", "defaultCacheDuration", + "logSink", "monthlyLimitBytes", "optimizer", "regions", @@ -103,6 +106,9 @@ def to_dict(self) -> Dict[str, Any]: # override the default output from pydantic by calling `to_dict()` of backend if self.backend: _dict["backend"] = self.backend.to_dict() + # override the default output from pydantic by calling `to_dict()` of log_sink + if self.log_sink: + _dict["logSink"] = self.log_sink.to_dict() # override the default output from pydantic by calling `to_dict()` of optimizer if self.optimizer: _dict["optimizer"] = self.optimizer.to_dict() @@ -111,6 +117,11 @@ def to_dict(self) -> Dict[str, Any]: if self.default_cache_duration is None and "default_cache_duration" in self.model_fields_set: _dict["defaultCacheDuration"] = None + # set to None if log_sink (nullable) is None + # and model_fields_set contains the field + if self.log_sink is None and "log_sink" in self.model_fields_set: + _dict["logSink"] = None + # set to None if monthly_limit_bytes (nullable) is None # and model_fields_set contains the field if self.monthly_limit_bytes is None and "monthly_limit_bytes" in self.model_fields_set: @@ -133,6 +144,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "blockedCountries": obj.get("blockedCountries"), "blockedIPs": obj.get("blockedIPs"), "defaultCacheDuration": obj.get("defaultCacheDuration"), + "logSink": PatchLokiLogSink.from_dict(obj["logSink"]) if obj.get("logSink") is not None else None, "monthlyLimitBytes": obj.get("monthlyLimitBytes"), "optimizer": OptimizerPatch.from_dict(obj["optimizer"]) if obj.get("optimizer") is not None else None, "regions": obj.get("regions"), diff --git a/services/cdn/src/stackit/cdn/models/create_distribution_payload.py b/services/cdn/src/stackit/cdn/models/create_distribution_payload.py index 4750e761..58a1e7d9 100644 --- a/services/cdn/src/stackit/cdn/models/create_distribution_payload.py +++ b/services/cdn/src/stackit/cdn/models/create_distribution_payload.py @@ -45,6 +45,10 @@ class CreateDistributionPayload(BaseModel): description="Sets the default cache duration for the distribution. The default cache duration is applied when a 'Cache-Control' header is not presented in the origin's response. We use ISO8601 duration format for cache duration (e.g. P1DT2H30M) ", alias="defaultCacheDuration", ) + geofencing: Optional[Dict[str, List[StrictStr]]] = Field( + default=None, + description="An object mapping multiple alternative origins to country codes. Any request from one of those country codes will route to the alternative origin. Do note that country codes may only be used once. You can not have a country be assigned to multiple alternative origins. ", + ) intent_id: Optional[StrictStr] = Field( default=None, description="While optional, it is greatly encouraged to provide an `intentId`. This is used to deduplicate requests. If multiple POST-Requests with the same `intentId` for a given `projectId` are received, all but the first request are dropped. ", @@ -73,6 +77,7 @@ class CreateDistributionPayload(BaseModel): "blockedCountries", "blockedIPs", "defaultCacheDuration", + "geofencing", "intentId", "logSink", "monthlyLimitBytes", @@ -141,6 +146,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "blockedCountries": obj.get("blockedCountries"), "blockedIPs": obj.get("blockedIPs"), "defaultCacheDuration": obj.get("defaultCacheDuration"), + "geofencing": obj.get("geofencing"), "intentId": obj.get("intentId"), "logSink": PatchLokiLogSink.from_dict(obj["logSink"]) if obj.get("logSink") is not None else None, "monthlyLimitBytes": obj.get("monthlyLimitBytes"), diff --git a/services/cdn/src/stackit/cdn/models/get_logs_search_filters_response.py b/services/cdn/src/stackit/cdn/models/get_logs_search_filters_response.py new file mode 100644 index 00000000..6bb7a7e3 --- /dev/null +++ b/services/cdn/src/stackit/cdn/models/get_logs_search_filters_response.py @@ -0,0 +1,81 @@ +# coding: utf-8 + +""" + CDN API + + API used to create and manage your CDN distributions. + + The version of the OpenAPI document: 1beta.0.0 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + +from __future__ import annotations + +import json +import pprint +from typing import Any, ClassVar, Dict, List, Optional, Set + +from pydantic import BaseModel, ConfigDict, StrictStr +from typing_extensions import Self + + +class GetLogsSearchFiltersResponse(BaseModel): + """ + GetLogsSearchFiltersResponse + """ # noqa: E501 + + filters: List[StrictStr] + __properties: ClassVar[List[str]] = ["filters"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of GetLogsSearchFiltersResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of GetLogsSearchFiltersResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({"filters": obj.get("filters")}) + return _obj diff --git a/services/cdn/src/stackit/cdn/models/http_backend.py b/services/cdn/src/stackit/cdn/models/http_backend.py index 1d96f899..03f46c2e 100644 --- a/services/cdn/src/stackit/cdn/models/http_backend.py +++ b/services/cdn/src/stackit/cdn/models/http_backend.py @@ -26,13 +26,16 @@ class HttpBackend(BaseModel): HttpBackend """ # noqa: E501 + geofencing: Dict[str, List[StrictStr]] = Field( + description="An object mapping multiple alternative origins to country codes. Any request from one of those country codes will route to the alternative origin. Do note that country codes may only be used once. You cannot have a country be assigned to multiple alternative origins. " + ) origin_request_headers: Dict[str, StrictStr] = Field( description="Headers that will be sent with every request to the configured origin. **WARNING**: Do not store sensitive values in the headers. The configuration is stored as plain text. ", alias="originRequestHeaders", ) origin_url: StrictStr = Field(alias="originUrl") type: StrictStr - __properties: ClassVar[List[str]] = ["originRequestHeaders", "originUrl", "type"] + __properties: ClassVar[List[str]] = ["geofencing", "originRequestHeaders", "originUrl", "type"] model_config = ConfigDict( populate_by_name=True, @@ -84,6 +87,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: _obj = cls.model_validate( { + "geofencing": obj.get("geofencing"), "originRequestHeaders": obj.get("originRequestHeaders"), "originUrl": obj.get("originUrl"), "type": obj.get("type"), diff --git a/services/cdn/src/stackit/cdn/models/http_backend_patch.py b/services/cdn/src/stackit/cdn/models/http_backend_patch.py index c6660787..f40b606e 100644 --- a/services/cdn/src/stackit/cdn/models/http_backend_patch.py +++ b/services/cdn/src/stackit/cdn/models/http_backend_patch.py @@ -26,6 +26,10 @@ class HttpBackendPatch(BaseModel): A partial HTTP Backend """ # noqa: E501 + geofencing: Optional[Dict[str, List[StrictStr]]] = Field( + default=None, + description="An object mapping multiple alternative origins to country codes. Any request from one of those country codes will route to the alternative origin. Do note that country codes may only be used once. You cannot have a country be assigned to multiple alternative origins. ", + ) origin_request_headers: Optional[Dict[str, StrictStr]] = Field( default=None, description="Headers that will be sent with every request to the configured origin. **WARNING**: Do not store sensitive values in the headers. The configuration is stored as plain text. ", @@ -33,7 +37,7 @@ class HttpBackendPatch(BaseModel): ) origin_url: Optional[StrictStr] = Field(default=None, alias="originUrl") type: StrictStr = Field(description="This property is required to determine the used backend type.") - __properties: ClassVar[List[str]] = ["originRequestHeaders", "originUrl", "type"] + __properties: ClassVar[List[str]] = ["geofencing", "originRequestHeaders", "originUrl", "type"] model_config = ConfigDict( populate_by_name=True, @@ -85,6 +89,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: _obj = cls.model_validate( { + "geofencing": obj.get("geofencing"), "originRequestHeaders": obj.get("originRequestHeaders"), "originUrl": obj.get("originUrl"), "type": obj.get("type"), diff --git a/services/cdn/src/stackit/cdn/models/put_custom_domain_custom_certificate.py b/services/cdn/src/stackit/cdn/models/put_custom_domain_custom_certificate.py index f85caf1a..8cd6b4d5 100644 --- a/services/cdn/src/stackit/cdn/models/put_custom_domain_custom_certificate.py +++ b/services/cdn/src/stackit/cdn/models/put_custom_domain_custom_certificate.py @@ -26,8 +26,8 @@ class PutCustomDomainCustomCertificate(BaseModel): Returned if a custom certificate is used. Response does not contain the certificate or key. """ # noqa: E501 - certificate: StrictStr = Field(description="base64-encoded certificate") - key: StrictStr = Field(description="base64-encoded key") + certificate: StrictStr = Field(description="base64-encoded PEM-encoded certificate") + key: StrictStr = Field(description="base64-encoded PEM encoded key") type: StrictStr __properties: ClassVar[List[str]] = ["certificate", "key", "type"] diff --git a/services/stackitmarketplace/CHANGELOG.md b/services/stackitmarketplace/CHANGELOG.md index 4b703c02..ee866cca 100644 --- a/services/stackitmarketplace/CHANGELOG.md +++ b/services/stackitmarketplace/CHANGELOG.md @@ -1,3 +1,6 @@ +## v1.9.0 +- **Feature:** Added `RequestPrivatePlan` to `InquiriesCreateInquiryPayload` + ## v1.8.0 - **Feature:** Add new field `free_trial` in `CatalogProductOverview` model diff --git a/services/stackitmarketplace/pyproject.toml b/services/stackitmarketplace/pyproject.toml index 56f3d4ba..fb9d4a13 100644 --- a/services/stackitmarketplace/pyproject.toml +++ b/services/stackitmarketplace/pyproject.toml @@ -3,7 +3,7 @@ name = "stackit-stackitmarketplace" [tool.poetry] name = "stackit-stackitmarketplace" -version = "v1.8.0" +version = "v1.9.0" authors = [ "STACKIT Developer Tools ", ] diff --git a/services/stackitmarketplace/src/stackit/stackitmarketplace/__init__.py b/services/stackitmarketplace/src/stackit/stackitmarketplace/__init__.py index 328ff4ca..46342167 100644 --- a/services/stackitmarketplace/src/stackit/stackitmarketplace/__init__.py +++ b/services/stackitmarketplace/src/stackit/stackitmarketplace/__init__.py @@ -51,6 +51,7 @@ "InquiryContactSales", "InquiryFormType", "InquiryRegisterTesting", + "InquiryRequestPrivatePlan", "InquirySuggestProduct", "ListCatalogProductsResponse", "ListVendorSubscriptionsResponse", @@ -61,6 +62,7 @@ "PricingOptionUnit", "ProductLifecycleState", "RegisterTesting", + "RequestPrivatePlan", "ResolveCustomerPayload", "ServiceCertificate", "SubscriptionLifecycleState", @@ -144,6 +146,9 @@ from stackit.stackitmarketplace.models.inquiry_register_testing import ( InquiryRegisterTesting as InquiryRegisterTesting, ) +from stackit.stackitmarketplace.models.inquiry_request_private_plan import ( + InquiryRequestPrivatePlan as InquiryRequestPrivatePlan, +) from stackit.stackitmarketplace.models.inquiry_suggest_product import ( InquirySuggestProduct as InquirySuggestProduct, ) @@ -168,6 +173,9 @@ from stackit.stackitmarketplace.models.register_testing import ( RegisterTesting as RegisterTesting, ) +from stackit.stackitmarketplace.models.request_private_plan import ( + RequestPrivatePlan as RequestPrivatePlan, +) from stackit.stackitmarketplace.models.resolve_customer_payload import ( ResolveCustomerPayload as ResolveCustomerPayload, ) diff --git a/services/stackitmarketplace/src/stackit/stackitmarketplace/api/default_api.py b/services/stackitmarketplace/src/stackit/stackitmarketplace/api/default_api.py index 037ebfb0..31d9445f 100644 --- a/services/stackitmarketplace/src/stackit/stackitmarketplace/api/default_api.py +++ b/services/stackitmarketplace/src/stackit/stackitmarketplace/api/default_api.py @@ -873,7 +873,7 @@ def inquiries_create_inquiry( ) -> None: """Create inquiry - Create an inquiry to contact sales, become a vendor, or suggest a product. Requests are limited to 10 per 5 minutes. + Create an inquiry to contact sales, become a vendor, request a private plan, register for testing, or suggest a product. Requests are limited to 10 per 5 minutes. :param inquiries_create_inquiry_payload: (required) :type inquiries_create_inquiry_payload: InquiriesCreateInquiryPayload @@ -937,7 +937,7 @@ def inquiries_create_inquiry_with_http_info( ) -> ApiResponse[None]: """Create inquiry - Create an inquiry to contact sales, become a vendor, or suggest a product. Requests are limited to 10 per 5 minutes. + Create an inquiry to contact sales, become a vendor, request a private plan, register for testing, or suggest a product. Requests are limited to 10 per 5 minutes. :param inquiries_create_inquiry_payload: (required) :type inquiries_create_inquiry_payload: InquiriesCreateInquiryPayload @@ -1001,7 +1001,7 @@ def inquiries_create_inquiry_without_preload_content( ) -> RESTResponseType: """Create inquiry - Create an inquiry to contact sales, become a vendor, or suggest a product. Requests are limited to 10 per 5 minutes. + Create an inquiry to contact sales, become a vendor, request a private plan, register for testing, or suggest a product. Requests are limited to 10 per 5 minutes. :param inquiries_create_inquiry_payload: (required) :type inquiries_create_inquiry_payload: InquiriesCreateInquiryPayload diff --git a/services/stackitmarketplace/src/stackit/stackitmarketplace/models/__init__.py b/services/stackitmarketplace/src/stackit/stackitmarketplace/models/__init__.py index 809baaad..aaa781e8 100644 --- a/services/stackitmarketplace/src/stackit/stackitmarketplace/models/__init__.py +++ b/services/stackitmarketplace/src/stackit/stackitmarketplace/models/__init__.py @@ -63,6 +63,9 @@ from stackit.stackitmarketplace.models.inquiry_register_testing import ( InquiryRegisterTesting, ) +from stackit.stackitmarketplace.models.inquiry_request_private_plan import ( + InquiryRequestPrivatePlan, +) from stackit.stackitmarketplace.models.inquiry_suggest_product import ( InquirySuggestProduct, ) @@ -81,6 +84,7 @@ ProductLifecycleState, ) from stackit.stackitmarketplace.models.register_testing import RegisterTesting +from stackit.stackitmarketplace.models.request_private_plan import RequestPrivatePlan from stackit.stackitmarketplace.models.resolve_customer_payload import ( ResolveCustomerPayload, ) diff --git a/services/stackitmarketplace/src/stackit/stackitmarketplace/models/inquiries_create_inquiry_payload.py b/services/stackitmarketplace/src/stackit/stackitmarketplace/models/inquiries_create_inquiry_payload.py index d06e4a20..23b837d4 100644 --- a/services/stackitmarketplace/src/stackit/stackitmarketplace/models/inquiries_create_inquiry_payload.py +++ b/services/stackitmarketplace/src/stackit/stackitmarketplace/models/inquiries_create_inquiry_payload.py @@ -29,10 +29,17 @@ from stackit.stackitmarketplace.models.become_vendor import BecomeVendor from stackit.stackitmarketplace.models.contact_sales import ContactSales from stackit.stackitmarketplace.models.register_testing import RegisterTesting +from stackit.stackitmarketplace.models.request_private_plan import RequestPrivatePlan from stackit.stackitmarketplace.models.suggest_product import SuggestProduct -INQUIRIESCREATEINQUIRYPAYLOAD_ONE_OF_SCHEMAS = ["BecomeVendor", "ContactSales", "RegisterTesting", "SuggestProduct"] +INQUIRIESCREATEINQUIRYPAYLOAD_ONE_OF_SCHEMAS = [ + "BecomeVendor", + "ContactSales", + "RegisterTesting", + "RequestPrivatePlan", + "SuggestProduct", +] class InquiriesCreateInquiryPayload(BaseModel): @@ -46,10 +53,20 @@ class InquiriesCreateInquiryPayload(BaseModel): oneof_schema_2_validator: Optional[ContactSales] = None # data type: BecomeVendor oneof_schema_3_validator: Optional[BecomeVendor] = None + # data type: RequestPrivatePlan + oneof_schema_4_validator: Optional[RequestPrivatePlan] = None # data type: RegisterTesting - oneof_schema_4_validator: Optional[RegisterTesting] = None - actual_instance: Optional[Union[BecomeVendor, ContactSales, RegisterTesting, SuggestProduct]] = None - one_of_schemas: Set[str] = {"BecomeVendor", "ContactSales", "RegisterTesting", "SuggestProduct"} + oneof_schema_5_validator: Optional[RegisterTesting] = None + actual_instance: Optional[ + Union[BecomeVendor, ContactSales, RegisterTesting, RequestPrivatePlan, SuggestProduct] + ] = None + one_of_schemas: Set[str] = { + "BecomeVendor", + "ContactSales", + "RegisterTesting", + "RequestPrivatePlan", + "SuggestProduct", + } model_config = ConfigDict( validate_assignment=True, @@ -86,6 +103,11 @@ def actual_instance_must_validate_oneof(cls, v): error_messages.append(f"Error! Input type `{type(v)}` is not `BecomeVendor`") else: match += 1 + # validate data type: RequestPrivatePlan + if not isinstance(v, RequestPrivatePlan): + error_messages.append(f"Error! Input type `{type(v)}` is not `RequestPrivatePlan`") + else: + match += 1 # validate data type: RegisterTesting if not isinstance(v, RegisterTesting): error_messages.append(f"Error! Input type `{type(v)}` is not `RegisterTesting`") @@ -94,7 +116,7 @@ def actual_instance_must_validate_oneof(cls, v): if match == 0: # no match raise ValueError( - "No match found when setting `actual_instance` in InquiriesCreateInquiryPayload with oneOf schemas: BecomeVendor, ContactSales, RegisterTesting, SuggestProduct. Details: " + "No match found when setting `actual_instance` in InquiriesCreateInquiryPayload with oneOf schemas: BecomeVendor, ContactSales, RegisterTesting, RequestPrivatePlan, SuggestProduct. Details: " + ", ".join(error_messages) ) else: @@ -129,6 +151,12 @@ def from_json(cls, json_str: str) -> Self: match += 1 except (ValidationError, ValueError) as e: error_messages.append(str(e)) + # deserialize data into RequestPrivatePlan + try: + instance.actual_instance = RequestPrivatePlan.from_json(json_str) + match += 1 + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) # deserialize data into RegisterTesting try: instance.actual_instance = RegisterTesting.from_json(json_str) @@ -139,13 +167,13 @@ def from_json(cls, json_str: str) -> Self: if match > 1: # more than 1 match raise ValueError( - "Multiple matches found when deserializing the JSON string into InquiriesCreateInquiryPayload with oneOf schemas: BecomeVendor, ContactSales, RegisterTesting, SuggestProduct. Details: " + "Multiple matches found when deserializing the JSON string into InquiriesCreateInquiryPayload with oneOf schemas: BecomeVendor, ContactSales, RegisterTesting, RequestPrivatePlan, SuggestProduct. Details: " + ", ".join(error_messages) ) elif match == 0: # no match raise ValueError( - "No match found when deserializing the JSON string into InquiriesCreateInquiryPayload with oneOf schemas: BecomeVendor, ContactSales, RegisterTesting, SuggestProduct. Details: " + "No match found when deserializing the JSON string into InquiriesCreateInquiryPayload with oneOf schemas: BecomeVendor, ContactSales, RegisterTesting, RequestPrivatePlan, SuggestProduct. Details: " + ", ".join(error_messages) ) else: @@ -161,7 +189,11 @@ def to_json(self) -> str: else: return json.dumps(self.actual_instance) - def to_dict(self) -> Optional[Union[Dict[str, Any], BecomeVendor, ContactSales, RegisterTesting, SuggestProduct]]: + def to_dict( + self, + ) -> Optional[ + Union[Dict[str, Any], BecomeVendor, ContactSales, RegisterTesting, RequestPrivatePlan, SuggestProduct] + ]: """Returns the dict representation of the actual instance""" if self.actual_instance is None: return None diff --git a/services/stackitmarketplace/src/stackit/stackitmarketplace/models/inquiry_form_type.py b/services/stackitmarketplace/src/stackit/stackitmarketplace/models/inquiry_form_type.py index faca4e00..a7a2ece9 100644 --- a/services/stackitmarketplace/src/stackit/stackitmarketplace/models/inquiry_form_type.py +++ b/services/stackitmarketplace/src/stackit/stackitmarketplace/models/inquiry_form_type.py @@ -32,6 +32,7 @@ class InquiryFormType(str, Enum): CONTACT_SALES = "CONTACT_SALES" BECOME_VENDOR = "BECOME_VENDOR" REGISTER_TESTING = "REGISTER_TESTING" + REQUEST_PRIVATE_PLAN = "REQUEST_PRIVATE_PLAN" @classmethod def from_json(cls, json_str: str) -> Self: diff --git a/services/stackitmarketplace/src/stackit/stackitmarketplace/models/inquiry_request_private_plan.py b/services/stackitmarketplace/src/stackit/stackitmarketplace/models/inquiry_request_private_plan.py new file mode 100644 index 00000000..f4ca93c2 --- /dev/null +++ b/services/stackitmarketplace/src/stackit/stackitmarketplace/models/inquiry_request_private_plan.py @@ -0,0 +1,129 @@ +# coding: utf-8 + +""" + STACKIT Marketplace API + + API to manage STACKIT Marketplace. + + The version of the OpenAPI document: 1 + Contact: marketplace@stackit.cloud + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + +from __future__ import annotations + +import json +import pprint +import re # noqa: F401 +from typing import Any, ClassVar, Dict, List, Optional, Set + +from pydantic import BaseModel, ConfigDict, Field, StrictStr, field_validator +from typing_extensions import Annotated, Self + + +class InquiryRequestPrivatePlan(BaseModel): + """ + Request a private plan. + """ # noqa: E501 + + company_name: Annotated[str, Field(strict=True, max_length=512)] = Field( + description="The company name.", alias="companyName" + ) + contact_email: StrictStr = Field(description="A e-mail address.", alias="contactEmail") + full_name: Annotated[str, Field(strict=True, max_length=512)] = Field( + description="The full name of the contact person.", alias="fullName" + ) + message: Annotated[str, Field(strict=True, max_length=512)] = Field(description="A custom message.") + product_id: Annotated[str, Field(min_length=10, strict=True, max_length=29)] = Field( + description="The user-readable product ID.", alias="productId" + ) + __properties: ClassVar[List[str]] = ["companyName", "contactEmail", "fullName", "message", "productId"] + + @field_validator("company_name") + def company_name_validate_regular_expression(cls, value): + """Validates the regular expression""" + if not re.match(r"^[a-zA-ZäüöÄÜÖ0-9,.!?()@\/:=\n\t -]+$", value): + raise ValueError(r"must validate the regular expression /^[a-zA-ZäüöÄÜÖ0-9,.!?()@\/:=\n\t -]+$/") + return value + + @field_validator("full_name") + def full_name_validate_regular_expression(cls, value): + """Validates the regular expression""" + if not re.match(r"^[a-zA-ZäüöÄÜÖ0-9,.!?()@\/:=\n\t -]+$", value): + raise ValueError(r"must validate the regular expression /^[a-zA-ZäüöÄÜÖ0-9,.!?()@\/:=\n\t -]+$/") + return value + + @field_validator("message") + def message_validate_regular_expression(cls, value): + """Validates the regular expression""" + if not re.match(r"^[a-zA-ZäüöÄÜÖ0-9,.!?()@\/:=\n\t -]+$", value): + raise ValueError(r"must validate the regular expression /^[a-zA-ZäüöÄÜÖ0-9,.!?()@\/:=\n\t -]+$/") + return value + + @field_validator("product_id") + def product_id_validate_regular_expression(cls, value): + """Validates the regular expression""" + if not re.match(r"^[a-z0-9-]{1,20}-[0-9a-f]{8}$", value): + raise ValueError(r"must validate the regular expression /^[a-z0-9-]{1,20}-[0-9a-f]{8}$/") + return value + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of InquiryRequestPrivatePlan from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of InquiryRequestPrivatePlan from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "companyName": obj.get("companyName"), + "contactEmail": obj.get("contactEmail"), + "fullName": obj.get("fullName"), + "message": obj.get("message"), + "productId": obj.get("productId"), + } + ) + return _obj diff --git a/services/stackitmarketplace/src/stackit/stackitmarketplace/models/request_private_plan.py b/services/stackitmarketplace/src/stackit/stackitmarketplace/models/request_private_plan.py new file mode 100644 index 00000000..e5cfb65e --- /dev/null +++ b/services/stackitmarketplace/src/stackit/stackitmarketplace/models/request_private_plan.py @@ -0,0 +1,100 @@ +# coding: utf-8 + +""" + STACKIT Marketplace API + + API to manage STACKIT Marketplace. + + The version of the OpenAPI document: 1 + Contact: marketplace@stackit.cloud + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + +from __future__ import annotations + +import json +import pprint +from typing import Any, ClassVar, Dict, List, Optional, Set + +from pydantic import BaseModel, ConfigDict, Field +from typing_extensions import Self + +from stackit.stackitmarketplace.models.inquiry_form_type import InquiryFormType +from stackit.stackitmarketplace.models.inquiry_request_private_plan import ( + InquiryRequestPrivatePlan, +) + + +class RequestPrivatePlan(BaseModel): + """ + Request a private plan. + """ # noqa: E501 + + request_private_plan: InquiryRequestPrivatePlan = Field(alias="requestPrivatePlan") + type: InquiryFormType + __properties: ClassVar[List[str]] = ["requestPrivatePlan", "type"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of RequestPrivatePlan from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of request_private_plan + if self.request_private_plan: + _dict["requestPrivatePlan"] = self.request_private_plan.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of RequestPrivatePlan from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "requestPrivatePlan": ( + InquiryRequestPrivatePlan.from_dict(obj["requestPrivatePlan"]) + if obj.get("requestPrivatePlan") is not None + else None + ), + "type": obj.get("type"), + } + ) + return _obj