diff --git a/CHANGELOG.md b/CHANGELOG.md index 12034a7e..b7789c47 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## Release (2025-05-XX) +- `stackitmarketplace`[v1.0.0](services/stackitmarketplace/CHANGELOG.md#v100-2025-05-05) + - **Breaking Change:** + - Introduced dedicated type for product id with appropriate validations + - **Feature:** + - subscription products contain the plan id + ## Release (2025-04-30) - `stackitmarketplace`: [v0.4.0](services/stackitmarketplace/CHANGELOG.md#v040-2025-04-16) - **Feature:** Add new `InquiryContactSales`, `InquirySuggestProduct`, `PriceType`, `PricingOption` and `DeliveryMethod` diff --git a/services/stackitmarketplace/CHANGELOG.md b/services/stackitmarketplace/CHANGELOG.md index 0707e3b3..b1365bf6 100644 --- a/services/stackitmarketplace/CHANGELOG.md +++ b/services/stackitmarketplace/CHANGELOG.md @@ -1,3 +1,9 @@ +## v1.0.0 (2025-05-05) +- **Breaking Change:** + - Introduced dedicated type for product id with appropriate validations +- **Feature:** + - subscription products contain the plan id + ## v0.4.0 (2025-04-16) - **Feature:** Add new `InquiryContactSales`, `InquirySuggestProduct`, `PriceType`, `PricingOption` and `DeliveryMethod` diff --git a/services/stackitmarketplace/src/stackit/stackitmarketplace/api/default_api.py b/services/stackitmarketplace/src/stackit/stackitmarketplace/api/default_api.py index 49ae5561..9491852a 100644 --- a/services/stackitmarketplace/src/stackit/stackitmarketplace/api/default_api.py +++ b/services/stackitmarketplace/src/stackit/stackitmarketplace/api/default_api.py @@ -346,7 +346,7 @@ def _approve_subscription_serialize( @validate_call def get_catalog_product( self, - product_id: Annotated[str, Field(min_length=36, strict=True, max_length=36, description="The product ID.")], + product_id: Annotated[str, Field(min_length=10, strict=True, max_length=29, description="The product ID.")], locale: Annotated[Optional[StrictStr], Field(description="The language of the response.")] = None, _request_timeout: Union[ None, @@ -414,7 +414,7 @@ def get_catalog_product( @validate_call def get_catalog_product_with_http_info( self, - product_id: Annotated[str, Field(min_length=36, strict=True, max_length=36, description="The product ID.")], + product_id: Annotated[str, Field(min_length=10, strict=True, max_length=29, description="The product ID.")], locale: Annotated[Optional[StrictStr], Field(description="The language of the response.")] = None, _request_timeout: Union[ None, @@ -482,7 +482,7 @@ def get_catalog_product_with_http_info( @validate_call def get_catalog_product_without_preload_content( self, - product_id: Annotated[str, Field(min_length=36, strict=True, max_length=36, description="The product ID.")], + product_id: Annotated[str, Field(min_length=10, strict=True, max_length=29, description="The product ID.")], locale: Annotated[Optional[StrictStr], Field(description="The language of the response.")] = None, _request_timeout: Union[ None, @@ -1132,7 +1132,7 @@ def list_catalog_products( sort: Annotated[ Optional[StrictStr], Field( - description="Sort the products based on attributes and order (if specified). E.g `name:asc`. The supported attributes are `name`, `price`, and `deliveryMethod`. To set the sort order, append `asc` (ascending) or `desc` (descending) to the attribute, e.g. `name:asc`. To sort by multiple attributes, separate them with a comma. E.g `name,price:desc`. The order can be ommited to sort by the default order. E.g `name`." + description="Sort the products based on attributes and order e.g. `name:asc`. Attributes with scalar types (`createdAt`, `isProductListing`) or keywords (`name`, `deliveryMethod`, `lifecycleState`, `vendor.name`) can be used as sort criteria. To set the sort order, append `asc` (ascending) or `desc` (descending) to the attribute, e.g. `name:asc`. To sort by multiple attributes, separate them with a comma. E.g `name:asc,price:desc`." ), ] = None, _request_timeout: Union[ @@ -1157,7 +1157,7 @@ def list_catalog_products( :type locale: str :param filter: Filter the products based on attributes. E.g `deliveryMethod eq \"SAAS\"`. The supported attributes are `deliveryMethod`, `priceType`, `category`, `vendorId`, `vendorName`, and `name`. The supported operators are `eq`. Filters can be joined with `and` or `or`. :type filter: str - :param sort: Sort the products based on attributes and order (if specified). E.g `name:asc`. The supported attributes are `name`, `price`, and `deliveryMethod`. To set the sort order, append `asc` (ascending) or `desc` (descending) to the attribute, e.g. `name:asc`. To sort by multiple attributes, separate them with a comma. E.g `name,price:desc`. The order can be ommited to sort by the default order. E.g `name`. + :param sort: Sort the products based on attributes and order e.g. `name:asc`. Attributes with scalar types (`createdAt`, `isProductListing`) or keywords (`name`, `deliveryMethod`, `lifecycleState`, `vendor.name`) can be used as sort criteria. To set the sort order, append `asc` (ascending) or `desc` (descending) to the attribute, e.g. `name:asc`. To sort by multiple attributes, separate them with a comma. E.g `name:asc,price:desc`. :type sort: str :param _request_timeout: timeout setting for this request. If one number provided, it will be total request @@ -1235,7 +1235,7 @@ def list_catalog_products_with_http_info( sort: Annotated[ Optional[StrictStr], Field( - description="Sort the products based on attributes and order (if specified). E.g `name:asc`. The supported attributes are `name`, `price`, and `deliveryMethod`. To set the sort order, append `asc` (ascending) or `desc` (descending) to the attribute, e.g. `name:asc`. To sort by multiple attributes, separate them with a comma. E.g `name,price:desc`. The order can be ommited to sort by the default order. E.g `name`." + description="Sort the products based on attributes and order e.g. `name:asc`. Attributes with scalar types (`createdAt`, `isProductListing`) or keywords (`name`, `deliveryMethod`, `lifecycleState`, `vendor.name`) can be used as sort criteria. To set the sort order, append `asc` (ascending) or `desc` (descending) to the attribute, e.g. `name:asc`. To sort by multiple attributes, separate them with a comma. E.g `name:asc,price:desc`." ), ] = None, _request_timeout: Union[ @@ -1260,7 +1260,7 @@ def list_catalog_products_with_http_info( :type locale: str :param filter: Filter the products based on attributes. E.g `deliveryMethod eq \"SAAS\"`. The supported attributes are `deliveryMethod`, `priceType`, `category`, `vendorId`, `vendorName`, and `name`. The supported operators are `eq`. Filters can be joined with `and` or `or`. :type filter: str - :param sort: Sort the products based on attributes and order (if specified). E.g `name:asc`. The supported attributes are `name`, `price`, and `deliveryMethod`. To set the sort order, append `asc` (ascending) or `desc` (descending) to the attribute, e.g. `name:asc`. To sort by multiple attributes, separate them with a comma. E.g `name,price:desc`. The order can be ommited to sort by the default order. E.g `name`. + :param sort: Sort the products based on attributes and order e.g. `name:asc`. Attributes with scalar types (`createdAt`, `isProductListing`) or keywords (`name`, `deliveryMethod`, `lifecycleState`, `vendor.name`) can be used as sort criteria. To set the sort order, append `asc` (ascending) or `desc` (descending) to the attribute, e.g. `name:asc`. To sort by multiple attributes, separate them with a comma. E.g `name:asc,price:desc`. :type sort: str :param _request_timeout: timeout setting for this request. If one number provided, it will be total request @@ -1338,7 +1338,7 @@ def list_catalog_products_without_preload_content( sort: Annotated[ Optional[StrictStr], Field( - description="Sort the products based on attributes and order (if specified). E.g `name:asc`. The supported attributes are `name`, `price`, and `deliveryMethod`. To set the sort order, append `asc` (ascending) or `desc` (descending) to the attribute, e.g. `name:asc`. To sort by multiple attributes, separate them with a comma. E.g `name,price:desc`. The order can be ommited to sort by the default order. E.g `name`." + description="Sort the products based on attributes and order e.g. `name:asc`. Attributes with scalar types (`createdAt`, `isProductListing`) or keywords (`name`, `deliveryMethod`, `lifecycleState`, `vendor.name`) can be used as sort criteria. To set the sort order, append `asc` (ascending) or `desc` (descending) to the attribute, e.g. `name:asc`. To sort by multiple attributes, separate them with a comma. E.g `name:asc,price:desc`." ), ] = None, _request_timeout: Union[ @@ -1363,7 +1363,7 @@ def list_catalog_products_without_preload_content( :type locale: str :param filter: Filter the products based on attributes. E.g `deliveryMethod eq \"SAAS\"`. The supported attributes are `deliveryMethod`, `priceType`, `category`, `vendorId`, `vendorName`, and `name`. The supported operators are `eq`. Filters can be joined with `and` or `or`. :type filter: str - :param sort: Sort the products based on attributes and order (if specified). E.g `name:asc`. The supported attributes are `name`, `price`, and `deliveryMethod`. To set the sort order, append `asc` (ascending) or `desc` (descending) to the attribute, e.g. `name:asc`. To sort by multiple attributes, separate them with a comma. E.g `name,price:desc`. The order can be ommited to sort by the default order. E.g `name`. + :param sort: Sort the products based on attributes and order e.g. `name:asc`. Attributes with scalar types (`createdAt`, `isProductListing`) or keywords (`name`, `deliveryMethod`, `lifecycleState`, `vendor.name`) can be used as sort criteria. To set the sort order, append `asc` (ascending) or `desc` (descending) to the attribute, e.g. `name:asc`. To sort by multiple attributes, separate them with a comma. E.g `name:asc,price:desc`. :type sort: str :param _request_timeout: timeout setting for this request. If one number provided, it will be total request @@ -1501,7 +1501,7 @@ def list_vendor_subscriptions( ), ] = None, product_id: Annotated[ - Optional[Annotated[str, Field(min_length=36, strict=True, max_length=36)]], + Optional[Annotated[str, Field(min_length=10, strict=True, max_length=29)]], Field(description="The product ID."), ] = None, _request_timeout: Union[ @@ -1593,7 +1593,7 @@ def list_vendor_subscriptions_with_http_info( ), ] = None, product_id: Annotated[ - Optional[Annotated[str, Field(min_length=36, strict=True, max_length=36)]], + Optional[Annotated[str, Field(min_length=10, strict=True, max_length=29)]], Field(description="The product ID."), ] = None, _request_timeout: Union[ @@ -1685,7 +1685,7 @@ def list_vendor_subscriptions_without_preload_content( ), ] = None, product_id: Annotated[ - Optional[Annotated[str, Field(min_length=36, strict=True, max_length=36)]], + Optional[Annotated[str, Field(min_length=10, strict=True, max_length=29)]], Field(description="The product ID."), ] = None, _request_timeout: Union[ diff --git a/services/stackitmarketplace/src/stackit/stackitmarketplace/configuration.py b/services/stackitmarketplace/src/stackit/stackitmarketplace/configuration.py index 11ea4a83..eaa1facc 100644 --- a/services/stackitmarketplace/src/stackit/stackitmarketplace/configuration.py +++ b/services/stackitmarketplace/src/stackit/stackitmarketplace/configuration.py @@ -1,5 +1,10 @@ # coding: utf-8 +import sys + +import os + + """ STACKIT Marketplace API @@ -12,8 +17,6 @@ Do not edit the class manually. """ # noqa: E501 docstring might be too long -import os - class HostConfiguration: def __init__( @@ -30,6 +33,7 @@ def __init__( "as a function argument instead of being set in the client configuration.\n" "Once all services have migrated, the methods to specify the region in the client configuration " "will be removed.", + file=sys.stderr, ) """Constructor """ diff --git a/services/stackitmarketplace/src/stackit/stackitmarketplace/models/catalog_product_detail.py b/services/stackitmarketplace/src/stackit/stackitmarketplace/models/catalog_product_detail.py index c8b8f6c1..181da1af 100644 --- a/services/stackitmarketplace/src/stackit/stackitmarketplace/models/catalog_product_detail.py +++ b/services/stackitmarketplace/src/stackit/stackitmarketplace/models/catalog_product_detail.py @@ -76,7 +76,9 @@ class CatalogProductDetail(BaseModel): pricing_options: List[CatalogProductPricingOption] = Field( description="The list of pricing options.", alias="pricingOptions" ) - product_id: object = Field(alias="productId") + product_id: Annotated[str, Field(min_length=10, strict=True, max_length=29)] = Field( + description="The user-readable product ID.", alias="productId" + ) summary: StrictStr = Field(description="The short summary of the product.") support_faq: Optional[Annotated[str, Field(strict=True, max_length=512)]] = Field( default=None, description="The support FAQ URL.", alias="supportFaq" @@ -132,6 +134,13 @@ def name_validate_regular_expression(cls, 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 + @field_validator("support_faq") def support_faq_validate_regular_expression(cls, value): """Validates the regular expression""" diff --git a/services/stackitmarketplace/src/stackit/stackitmarketplace/models/catalog_product_overview.py b/services/stackitmarketplace/src/stackit/stackitmarketplace/models/catalog_product_overview.py index 7fd32535..4bd2629a 100644 --- a/services/stackitmarketplace/src/stackit/stackitmarketplace/models/catalog_product_overview.py +++ b/services/stackitmarketplace/src/stackit/stackitmarketplace/models/catalog_product_overview.py @@ -47,7 +47,9 @@ class CatalogProductOverview(BaseModel): lifecycle_state: ProductLifecycleState = Field(alias="lifecycleState") logo: Optional[Union[StrictBytes, StrictStr]] = Field(default=None, description="The logo base64 encoded.") name: Annotated[str, Field(strict=True, max_length=512)] = Field(description="The name of the product.") - product_id: object = Field(alias="productId") + product_id: Annotated[str, Field(min_length=10, strict=True, max_length=29)] = Field( + description="The user-readable product ID.", alias="productId" + ) summary: Annotated[str, Field(strict=True, max_length=512)] = Field(description="The short summary of the product.") vendor: CatalogProductOverviewVendor __properties: ClassVar[List[str]] = [ @@ -67,6 +69,13 @@ def name_validate_regular_expression(cls, 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 + @field_validator("summary") def summary_validate_regular_expression(cls, value): """Validates the regular expression""" diff --git a/services/stackitmarketplace/src/stackit/stackitmarketplace/models/inquiry_contact_sales.py b/services/stackitmarketplace/src/stackit/stackitmarketplace/models/inquiry_contact_sales.py index 92b0076e..955395c9 100644 --- a/services/stackitmarketplace/src/stackit/stackitmarketplace/models/inquiry_contact_sales.py +++ b/services/stackitmarketplace/src/stackit/stackitmarketplace/models/inquiry_contact_sales.py @@ -36,7 +36,9 @@ class InquiryContactSales(BaseModel): 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: object = Field(alias="productId") + 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") @@ -60,6 +62,13 @@ def message_validate_regular_expression(cls, 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, diff --git a/services/stackitmarketplace/src/stackit/stackitmarketplace/models/subscription_product.py b/services/stackitmarketplace/src/stackit/stackitmarketplace/models/subscription_product.py index d571bdb1..c3f8698d 100644 --- a/services/stackitmarketplace/src/stackit/stackitmarketplace/models/subscription_product.py +++ b/services/stackitmarketplace/src/stackit/stackitmarketplace/models/subscription_product.py @@ -38,13 +38,18 @@ class SubscriptionProduct(BaseModel): lifecycle_state: ProductLifecycleState = Field(alias="lifecycleState") price_type: PriceType = Field(alias="priceType") pricing_plan: StrictStr = Field(description="Additional price type information.", alias="pricingPlan") - product_id: object = Field(alias="productId") + product_id: Annotated[str, Field(min_length=10, strict=True, max_length=29)] = Field( + description="The user-readable product ID.", alias="productId" + ) product_name: Annotated[str, Field(strict=True, max_length=512)] = Field( description="The name of the product.", alias="productName" ) vendor_name: Annotated[str, Field(strict=True, max_length=512)] = Field( description="The product's vendor name.", alias="vendorName" ) + vendor_plan_id: Optional[Annotated[str, Field(strict=True)]] = Field( + default=None, description="The vendor provided plan ID.", alias="vendorPlanId" + ) vendor_product_id: Optional[Annotated[str, Field(strict=True)]] = Field( default=None, description="The vendor provided product ID.", alias="vendorProductId" ) @@ -59,10 +64,18 @@ class SubscriptionProduct(BaseModel): "productId", "productName", "vendorName", + "vendorPlanId", "vendorProductId", "vendorWebsiteUrl", ] + @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 + @field_validator("product_name") def product_name_validate_regular_expression(cls, value): """Validates the regular expression""" @@ -77,6 +90,16 @@ def vendor_name_validate_regular_expression(cls, value): raise ValueError(r"must validate the regular expression /^[a-zA-ZäüöÄÜÖ0-9,.!?()@\/:=\n\t -]+$/") return value + @field_validator("vendor_plan_id") + def vendor_plan_id_validate_regular_expression(cls, value): + """Validates the regular expression""" + if value is None: + return value + + if not re.match(r"^[a-zA-Z0-9](?:[a-zA-Z0-9_+&-]){0,39}$", value): + raise ValueError(r"must validate the regular expression /^[a-zA-Z0-9](?:[a-zA-Z0-9_+&-]){0,39}$/") + return value + @field_validator("vendor_product_id") def vendor_product_id_validate_regular_expression(cls, value): """Validates the regular expression""" @@ -153,6 +176,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "productId": obj.get("productId"), "productName": obj.get("productName"), "vendorName": obj.get("vendorName"), + "vendorPlanId": obj.get("vendorPlanId"), "vendorProductId": obj.get("vendorProductId"), "vendorWebsiteUrl": obj.get("vendorWebsiteUrl"), }