From 775e7ce773db42cbbccceb8a9aa5aeeb31e813e9 Mon Sep 17 00:00:00 2001 From: Marco Antonio Gil Date: Fri, 27 Feb 2026 15:10:14 +0100 Subject: [PATCH 1/3] PTHMINT-99: Use PEP 585 built-in generics Migrate typing annotations to built-in generics (list, dict, etc.) and tidy imports across the codebase for Python 3.9+ compatibility. Updated various modules to replace typing.List/Dict/Type/Iterator with modern equivalents, adjusted some Optional and Union hints, and simplified imports. Added [tool.ruff] target-version = "py39" to pyproject.toml. Also tightened tests: assert recurring_id presence and use identity check for boolean in an assertion. --- pyproject.toml | 3 ++ src/multisafepay/api/base/decorator.py | 36 +++++++++---------- src/multisafepay/api/base/listings/listing.py | 13 +++---- .../api/base/response/custom_api_response.py | 4 +-- .../request/components/checkout_data.py | 8 ++--- .../paths/orders/response/order_response.py | 8 ++--- .../response/components/brand.py | 4 +-- .../response/payment_method.py | 12 +++---- .../transactions/response/transaction.py | 6 ++-- .../api/shared/cart/shopping_cart.py | 8 ++--- .../api/shared/checkout/checkout_options.py | 6 ++-- .../api/shared/checkout/tax_rule.py | 8 ++--- src/multisafepay/client/client.py | 26 +++++++------- src/multisafepay/exception/api.py | 4 +-- src/multisafepay/util/address_parser.py | 5 ++- src/multisafepay/util/message.py | 6 ++-- .../value_object/decimal_amount.py | 4 +-- .../recurring_manager/test_recurring.py | 7 +++- 18 files changed, 88 insertions(+), 80 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index f671aa7..b21d57c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -135,3 +135,6 @@ ignore = [ "TRY300", ] select = ["ALL"] + +[tool.ruff] +target-version = "py39" diff --git a/src/multisafepay/api/base/decorator.py b/src/multisafepay/api/base/decorator.py index 15f748a..679d5b8 100644 --- a/src/multisafepay/api/base/decorator.py +++ b/src/multisafepay/api/base/decorator.py @@ -7,7 +7,7 @@ """Decorator class for response model transformations and dependencies.""" -from typing import Any, Dict, List, Optional +from typing import Any, Optional class Decorator: @@ -20,9 +20,9 @@ class Decorator: """ - dependencies: Optional[Dict] + dependencies: Optional[dict] - def __init__(self: "Decorator", dependencies: Dict = None) -> None: + def __init__(self: "Decorator", dependencies: dict = None) -> None: """ Initialize the Decorator with optional dependencies. @@ -35,7 +35,7 @@ def __init__(self: "Decorator", dependencies: Dict = None) -> None: def adapt_checkout_options( self: "Decorator", - checkout_options: Optional[Dict], + checkout_options: Optional[dict], ) -> "Decorator": """ Adapt the checkout options and update the dependencies. @@ -59,7 +59,7 @@ def adapt_checkout_options( ) return self - def adapt_costs(self: "Decorator", costs: Optional[Dict]) -> "Decorator": + def adapt_costs(self: "Decorator", costs: Optional[dict]) -> "Decorator": """ Adapt the costs and update the dependencies. @@ -82,7 +82,7 @@ def adapt_costs(self: "Decorator", costs: Optional[Dict]) -> "Decorator": def adapt_custom_info( self: "Decorator", - custom_info: Optional[Dict], + custom_info: Optional[dict], ) -> "Decorator": """ Adapt the custom information and update the dependencies. @@ -107,7 +107,7 @@ def adapt_custom_info( def adapt_customer( self: "Decorator", - customer: Optional[Dict], + customer: Optional[dict], ) -> "Decorator": """ Adapt the customer information and update the dependencies. @@ -130,7 +130,7 @@ def adapt_customer( def adapt_order_adjustment( self: "Decorator", - order_adjustment: Optional[Dict], + order_adjustment: Optional[dict], ) -> "Decorator": """ Adapt the order adjustment and update the dependencies. @@ -157,7 +157,7 @@ def adapt_order_adjustment( def adapt_payment_details( self: "Decorator", - payment_details: Optional[Dict], + payment_details: Optional[dict], ) -> "Decorator": """ Adapt the payment details and update the dependencies. @@ -184,7 +184,7 @@ def adapt_payment_details( def adapt_payment_methods( self: "Decorator", - payment_methods: Optional[Dict], + payment_methods: Optional[dict], ) -> "Decorator": """ Adapt the payment methods and update the dependencies. @@ -209,7 +209,7 @@ def adapt_payment_methods( def adapt_shopping_cart( self: "Decorator", - shopping_cart: Optional[Dict], + shopping_cart: Optional[dict], ) -> "Decorator": """ Adapt the shopping cart and update the dependencies. @@ -233,7 +233,7 @@ def adapt_shopping_cart( def adapt_related_transactions( self: "Decorator", - related_transactions: Optional[Dict], + related_transactions: Optional[dict], ) -> "Decorator": """ Adapt the related transactions and update the dependencies. @@ -258,7 +258,7 @@ def adapt_related_transactions( ] return self - def adapt_apps(self: "Decorator", apps: Optional[Dict]) -> "Decorator": + def adapt_apps(self: "Decorator", apps: Optional[dict]) -> "Decorator": """ Adapt the apps and update the dependencies. @@ -282,7 +282,7 @@ def adapt_apps(self: "Decorator", apps: Optional[Dict]) -> "Decorator": def adapt_brands( self: "Decorator", - brands: Optional[List[Optional[Dict]]], + brands: Optional[list[Optional[dict]]], ) -> "Decorator": """ Adapt the brands and update the dependencies. @@ -308,7 +308,7 @@ def adapt_brands( def adapt_icon_urls( self: "Decorator", - icon_urls: Optional[Dict], + icon_urls: Optional[dict], ) -> "Decorator": """ Adapt the icon URLs and update the dependencies. @@ -333,7 +333,7 @@ def adapt_icon_urls( def adapt_tokenization( self: "Decorator", - tokenization: Optional[Dict], + tokenization: Optional[dict], ) -> "Decorator": """ Adapt the tokenization and update the dependencies. @@ -360,7 +360,7 @@ def adapt_tokenization( def adapt_allowed_amount( self: "Decorator", - allowed_amount: Optional[Dict], + allowed_amount: Optional[dict], ) -> "Decorator": """ Adapt the allowed amount and update the dependencies. @@ -384,7 +384,7 @@ def adapt_allowed_amount( ) return self - def get_dependencies(self: "Decorator") -> Dict[str, Any]: + def get_dependencies(self: "Decorator") -> dict[str, Any]: """ Get the current dependencies. diff --git a/src/multisafepay/api/base/listings/listing.py b/src/multisafepay/api/base/listings/listing.py index ce3ee65..738f743 100644 --- a/src/multisafepay/api/base/listings/listing.py +++ b/src/multisafepay/api/base/listings/listing.py @@ -7,7 +7,8 @@ """Generic listing container for API response collections.""" -from typing import Any, Dict, Generic, Iterator, List, TypeVar +from collections.abc import Iterator +from typing import Any, Generic, TypeVar from pydantic.main import BaseModel @@ -24,13 +25,13 @@ class Listing(Generic[T], BaseModel): """ - data: List[T] + data: list[T] def __init__( self: "Listing", - data: List[Any], + data: list[Any], class_type: type, - **kwargs: Dict[str, Any], + **kwargs: dict[str, Any], ) -> None: """ Initialize the Listing with data and a class type. @@ -42,7 +43,7 @@ def __init__( **kwargs: Additional keyword arguments to pass to the class type constructor. """ - elements: List[T] = [] + elements: list[T] = [] if data: for item_data in data: if item_data: @@ -92,7 +93,7 @@ def __len__(self: "Listing") -> int: """ return len(self.data) - def get_data(self: "Listing") -> List[T]: + def get_data(self: "Listing") -> list[T]: """ Get the list of items in the listing. diff --git a/src/multisafepay/api/base/response/custom_api_response.py b/src/multisafepay/api/base/response/custom_api_response.py index aa90b13..d45a5e5 100644 --- a/src/multisafepay/api/base/response/custom_api_response.py +++ b/src/multisafepay/api/base/response/custom_api_response.py @@ -7,7 +7,7 @@ """Custom API response class with generic typing support for flexible response handling.""" -from typing import Any, Dict, Optional, Union +from typing import Any, Optional, Union from multisafepay.api.base.response.api_response import ApiResponse @@ -27,7 +27,7 @@ class CustomApiResponse(ApiResponse): def __init__( self: "CustomApiResponse", data: Optional[Union[dict, list]], - **kwargs: Dict[str, Any], + **kwargs: dict[str, Any], ) -> None: """ Initialize the CustomApiResponse with optional data and additional keyword arguments. diff --git a/src/multisafepay/api/paths/orders/order_id/refund/request/components/checkout_data.py b/src/multisafepay/api/paths/orders/order_id/refund/request/components/checkout_data.py index 198f2c0..50db766 100644 --- a/src/multisafepay/api/paths/orders/order_id/refund/request/components/checkout_data.py +++ b/src/multisafepay/api/paths/orders/order_id/refund/request/components/checkout_data.py @@ -7,7 +7,7 @@ """Checkout data model for refund request checkout information and configuration.""" -from typing import List, Optional +from typing import Optional from multisafepay.api.shared.cart.cart_item import CartItem from multisafepay.api.shared.cart.shopping_cart import ShoppingCart @@ -25,11 +25,11 @@ class CheckoutData(RequestModel): """ - items: Optional[List[CartItem]] + items: Optional[list[CartItem]] def add_items( self: "CheckoutData", - items: Optional[List[CartItem]] = None, + items: Optional[list[CartItem]] = None, ) -> "CheckoutData": """ Adds multiple items to the checkout data. @@ -74,7 +74,7 @@ def add_item( self.items.append(item) return self - def get_items(self: "CheckoutData") -> Optional[List[CartItem]]: + def get_items(self: "CheckoutData") -> Optional[list[CartItem]]: """ Retrieves all items from the checkout data. diff --git a/src/multisafepay/api/paths/orders/response/order_response.py b/src/multisafepay/api/paths/orders/response/order_response.py index 71aabde..4581929 100644 --- a/src/multisafepay/api/paths/orders/response/order_response.py +++ b/src/multisafepay/api/paths/orders/response/order_response.py @@ -7,7 +7,7 @@ """Order response models for handling order API responses and data structures.""" -from typing import List, Optional +from typing import Optional from multisafepay.api.base.decorator import Decorator from multisafepay.api.paths.orders.response.components.order_adjustment import ( @@ -74,7 +74,7 @@ class Order(ResponseModel): amount: Optional[int] amount_refunded: Optional[int] checkout_options: Optional[CheckoutOptions] - costs: Optional[List[Costs]] + costs: Optional[list[Costs]] created: Optional[str] modified: Optional[str] currency: Optional[str] @@ -88,10 +88,10 @@ class Order(ResponseModel): order_id: Optional[str] order_total: Optional[float] payment_details: Optional[PaymentDetails] - payment_methods: Optional[List[PaymentMethod]] + payment_methods: Optional[list[PaymentMethod]] reason: Optional[str] reason_code: Optional[str] - related_transactions: Optional[List[Transaction]] + related_transactions: Optional[list[Transaction]] shopping_cart: Optional[ShoppingCart] status: Optional[str] transaction_id: Optional[str] diff --git a/src/multisafepay/api/paths/payment_methods/response/components/brand.py b/src/multisafepay/api/paths/payment_methods/response/components/brand.py index e920e8f..5ca520e 100644 --- a/src/multisafepay/api/paths/payment_methods/response/components/brand.py +++ b/src/multisafepay/api/paths/payment_methods/response/components/brand.py @@ -7,7 +7,7 @@ """Brand model for payment method branding information and display settings.""" -from typing import List, Optional +from typing import Optional from multisafepay.api.paths.payment_methods.response.components.icon_urls import ( IconUrls, @@ -28,7 +28,7 @@ class Brand(ResponseModel): """ - allowed_countries: Optional[List[str]] + allowed_countries: Optional[list[str]] icon_urls: Optional[IconUrls] id: Optional[str] name: Optional[str] diff --git a/src/multisafepay/api/paths/payment_methods/response/payment_method.py b/src/multisafepay/api/paths/payment_methods/response/payment_method.py index 143f2d1..f24a1e9 100644 --- a/src/multisafepay/api/paths/payment_methods/response/payment_method.py +++ b/src/multisafepay/api/paths/payment_methods/response/payment_method.py @@ -7,7 +7,7 @@ """Payment method response model for handling payment method configurations and options.""" -from typing import List, Optional +from typing import Optional from multisafepay.api.base.decorator import Decorator from multisafepay.api.paths.payment_methods.response.components.allowed_amount import ( @@ -55,17 +55,17 @@ class PaymentMethod(ResponseModel): additional_data: Optional[dict] allowed_amount: Optional[AllowedAmount] - allowed_countries: Optional[List[str]] - allowed_currencies: Optional[List[str]] + allowed_countries: Optional[list[str]] + allowed_currencies: Optional[list[str]] apps: Optional[Apps] - brands: Optional[List[Brand]] + brands: Optional[list[Brand]] description: Optional[str] icon_urls: Optional[IconUrls] id: Optional[str] label: Optional[str] name: Optional[str] - preferred_countries: Optional[List[str]] - required_customer_data: Optional[List[str]] + preferred_countries: Optional[list[str]] + required_customer_data: Optional[list[str]] tokenization: Optional[Tokenization] type: Optional[str] shopping_cart_required: Optional[bool] diff --git a/src/multisafepay/api/paths/transactions/response/transaction.py b/src/multisafepay/api/paths/transactions/response/transaction.py index e296518..c941a52 100644 --- a/src/multisafepay/api/paths/transactions/response/transaction.py +++ b/src/multisafepay/api/paths/transactions/response/transaction.py @@ -7,7 +7,7 @@ """Transaction response model for handling transaction data and status information.""" -from typing import List, Optional +from typing import Optional from multisafepay.api.base.decorator import Decorator from multisafepay.api.shared.costs import Costs @@ -55,7 +55,7 @@ class Transaction(ResponseModel): amount: Optional[int] completed: Optional[str] - costs: Optional[List[Costs]] + costs: Optional[list[Costs]] created: Optional[str] modified: Optional[str] currency: Optional[str] @@ -68,7 +68,7 @@ class Transaction(ResponseModel): net: Optional[int] order_id: Optional[str] payment_method: Optional[str] - payment_methods: Optional[List[PaymentMethod]] + payment_methods: Optional[list[PaymentMethod]] reason: Optional[str] reason_code: Optional[str] site_id: Optional[str] diff --git a/src/multisafepay/api/shared/cart/shopping_cart.py b/src/multisafepay/api/shared/cart/shopping_cart.py index 36a3524..d2defe3 100644 --- a/src/multisafepay/api/shared/cart/shopping_cart.py +++ b/src/multisafepay/api/shared/cart/shopping_cart.py @@ -7,7 +7,7 @@ """Shopping cart model for managing cart items in order processing.""" -from typing import List, Optional +from typing import Optional from multisafepay.api.shared.cart.cart_item import CartItem from multisafepay.model.api_model import ApiModel @@ -23,9 +23,9 @@ class ShoppingCart(ApiModel): """ - items: Optional[List[CartItem]] + items: Optional[list[CartItem]] - def get_items(self: "ShoppingCart") -> Optional[List[CartItem]]: + def get_items(self: "ShoppingCart") -> Optional[list[CartItem]]: """ Get the list of items in the shopping cart. @@ -38,7 +38,7 @@ def get_items(self: "ShoppingCart") -> Optional[List[CartItem]]: def add_items( self: "ShoppingCart", - items: Optional[List[CartItem]], + items: Optional[list[CartItem]], ) -> "ShoppingCart": """ Add multiple items to the shopping cart. diff --git a/src/multisafepay/api/shared/checkout/checkout_options.py b/src/multisafepay/api/shared/checkout/checkout_options.py index 32d7fb0..436bf66 100644 --- a/src/multisafepay/api/shared/checkout/checkout_options.py +++ b/src/multisafepay/api/shared/checkout/checkout_options.py @@ -7,7 +7,7 @@ """Checkout options model for configuring tax rules and checkout behavior.""" -from typing import List, Optional +from typing import Optional from multisafepay.api.shared.checkout.default_tax_rate import DefaultTaxRate from multisafepay.api.shared.checkout.tax_rule import TaxRule @@ -26,7 +26,7 @@ class CheckoutOptions(ApiModel): """ default: Optional[DefaultTaxRate] - alternate: Optional[List[TaxRule]] + alternate: Optional[list[TaxRule]] def add_default( self: "CheckoutOptions", @@ -49,7 +49,7 @@ def add_default( def add_alternate( self: "CheckoutOptions", - alternate: List[TaxRule], + alternate: list[TaxRule], ) -> "CheckoutOptions": """ Add alternate tax rates to the checkout options. diff --git a/src/multisafepay/api/shared/checkout/tax_rule.py b/src/multisafepay/api/shared/checkout/tax_rule.py index cb391be..1a0732d 100644 --- a/src/multisafepay/api/shared/checkout/tax_rule.py +++ b/src/multisafepay/api/shared/checkout/tax_rule.py @@ -7,7 +7,7 @@ """Tax rule model for defining taxation rules and rates in checkout processing.""" -from typing import Any, Dict, List, Optional, Union +from typing import Any, Optional, Union from multisafepay.api.shared.checkout.tax_rate import TaxRate from multisafepay.model.api_model import ApiModel @@ -26,7 +26,7 @@ class TaxRule(ApiModel): """ name: Optional[str] - rules: Optional[List[TaxRate]] + rules: Optional[list[TaxRate]] standalone: Optional[Any] def add_name(self: "TaxRule", name: str) -> "TaxRule": @@ -45,7 +45,7 @@ def add_name(self: "TaxRule", name: str) -> "TaxRule": self.name = name return self - def add_rules(self: "TaxRule", rules: List[TaxRate]) -> "TaxRule": + def add_rules(self: "TaxRule", rules: list[TaxRate]) -> "TaxRule": """ Add a list of tax rates to the tax rule. @@ -101,7 +101,7 @@ def add_rule(self: "TaxRule", rule: Optional[TaxRate]) -> "TaxRule": return self @staticmethod - def from_dict(d: Optional[Dict]) -> Optional["TaxRule"]: + def from_dict(d: Optional[dict]) -> Optional["TaxRule"]: """ Create a TaxRule instance from a dictionary. diff --git a/src/multisafepay/client/client.py b/src/multisafepay/client/client.py index 4635d93..8bf5aa8 100644 --- a/src/multisafepay/client/client.py +++ b/src/multisafepay/client/client.py @@ -7,7 +7,7 @@ """HTTP client module for making API requests to MultiSafepay services.""" -from typing import Any, Dict, Optional +from typing import Any, Optional from multisafepay.api.base.response.api_response import ApiResponse from requests import Request, Session @@ -69,8 +69,8 @@ def __init__( def create_get_request( self: "Client", endpoint: str, - params: Dict[str, Any] = None, - context: Dict[str, Any] = None, + params: dict[str, Any] = None, + context: dict[str, Any] = None, ) -> ApiResponse: """ Create a GET request. @@ -97,9 +97,9 @@ def create_get_request( def create_post_request( self: "Client", endpoint: str, - params: Dict[str, Any] = None, + params: dict[str, Any] = None, request_body: str = None, - context: Dict[str, Any] = None, + context: dict[str, Any] = None, ) -> ApiResponse: """ Create a POST request. @@ -127,9 +127,9 @@ def create_post_request( def create_patch_request( self: "Client", endpoint: str, - params: Dict[str, Any] = None, + params: dict[str, Any] = None, request_body: str = None, - context: Dict[str, Any] = None, + context: dict[str, Any] = None, ) -> ApiResponse: """ Create a PATCH request. @@ -157,8 +157,8 @@ def create_patch_request( def create_delete_request( self: "Client", endpoint: str, - params: Dict[str, Any] = None, - context: Dict[str, Any] = None, + params: dict[str, Any] = None, + context: dict[str, Any] = None, ) -> ApiResponse: """ Create a DELETE request. @@ -180,7 +180,7 @@ def create_delete_request( def _build_url( self: "Client", endpoint: str, - params: Optional[Dict[str, Any]] = None, + params: Optional[dict[str, Any]] = None, ) -> str: """ Build the full URL for the request. @@ -208,9 +208,9 @@ def _create_request( self: "Client", method: str, url: str, - params: Optional[Dict[str, Any]] = None, - request_body: Optional[Dict[str, Any]] = None, - context: Dict[str, Any] = None, + params: Optional[dict[str, Any]] = None, + request_body: Optional[dict[str, Any]] = None, + context: Optional[dict[str, Any]] = None, ) -> ApiResponse: """ Create and send an HTTP request. diff --git a/src/multisafepay/exception/api.py b/src/multisafepay/exception/api.py index 91b49de..4163ae3 100644 --- a/src/multisafepay/exception/api.py +++ b/src/multisafepay/exception/api.py @@ -8,7 +8,7 @@ """Base API exception classes for MultiSafepay SDK errors.""" import json -from typing import Dict, List, Optional, Union +from typing import Optional, Union class ApiException(Exception): @@ -119,7 +119,7 @@ def get_context_as_array(self: "ApiException") -> list: def get_context_value( self: "ApiException", name: str, - ) -> Optional[Union[str, int, float, bool, Dict, List]]: + ) -> Optional[Union[str, int, float, bool, dict, list]]: """ Get a specific context value by name. diff --git a/src/multisafepay/util/address_parser.py b/src/multisafepay/util/address_parser.py index ba9468c..17c4379 100644 --- a/src/multisafepay/util/address_parser.py +++ b/src/multisafepay/util/address_parser.py @@ -8,7 +8,6 @@ """Address parsing utilities for extracting street and house number information.""" import re -from typing import List class AddressParser: @@ -22,7 +21,7 @@ def parse( self: "AddressParser", address1: str, address2: str = "", - ) -> List[str]: + ) -> list[str]: """ Parses and splits up an address in street and house number. @@ -61,7 +60,7 @@ def extract_street_and_apartment( group1: str, group2: str, group3: str, - ) -> List[str]: + ) -> list[str]: """ Extract the street and apartment from the matched RegEx results. diff --git a/src/multisafepay/util/message.py b/src/multisafepay/util/message.py index 772e3d3..8f0db71 100644 --- a/src/multisafepay/util/message.py +++ b/src/multisafepay/util/message.py @@ -7,7 +7,7 @@ """Message utilities for handling API error messages and notifications.""" -from typing import Dict, Iterator, List +from collections.abc import Iterator from pydantic import BaseModel, Field @@ -35,7 +35,7 @@ class MessageList(BaseModel): """ - __root__: List[Message] = Field(default_factory=list) + __root__: list[Message] = Field(default_factory=list) def __iter__(self: "MessageList") -> Iterator[Message]: """ @@ -90,7 +90,7 @@ def add_message(self: "MessageList", message: str) -> "MessageList": self.__root__.append(Message(message=message)) return self - def get_messages(self: "MessageList") -> List[Dict]: + def get_messages(self: "MessageList") -> list[dict]: """ Get all messages in the list. diff --git a/src/multisafepay/value_object/decimal_amount.py b/src/multisafepay/value_object/decimal_amount.py index ed8dedd..df43b73 100644 --- a/src/multisafepay/value_object/decimal_amount.py +++ b/src/multisafepay/value_object/decimal_amount.py @@ -8,7 +8,7 @@ """DecimalAmount value object for monetary amounts.""" from decimal import Decimal -from typing import Type, Union +from typing import Union from multisafepay.model.inmutable_model import InmutableModel from pydantic import validator @@ -28,7 +28,7 @@ class DecimalAmount(InmutableModel): @validator("amount", pre=True) def convert_to_decimal( - cls: Type["DecimalAmount"], + cls: type["DecimalAmount"], value: Union[str, float, Decimal], ) -> Decimal: """ diff --git a/tests/multisafepay/e2e/examples/recurring_manager/test_recurring.py b/tests/multisafepay/e2e/examples/recurring_manager/test_recurring.py index 7f02202..5fd4e07 100644 --- a/tests/multisafepay/e2e/examples/recurring_manager/test_recurring.py +++ b/tests/multisafepay/e2e/examples/recurring_manager/test_recurring.py @@ -120,6 +120,11 @@ def test_recurring(sdk: Sdk): assert isinstance(order, Order) + recurring_id = getattr(order.payment_details, "recurring_id", None) + assert ( + recurring_id + ), "Expected order.payment_details.recurring_id to be set" + recurring_manager = sdk.get_recurring_manager() response = recurring_manager.get_list(reference) @@ -156,4 +161,4 @@ def test_recurring(sdk: Sdk): assert isinstance(delete_response, CustomApiResponse) delete_data_response = delete_response.get_body_data() assert isinstance(delete_data_response, dict) - assert delete_data_response.get("removed") == True + assert delete_data_response.get("removed") is True From 18ea2b525cea5605cc47c8262c4d6707a5fe8fe1 Mon Sep 17 00:00:00 2001 From: Marco Antonio Gil Date: Fri, 27 Feb 2026 15:21:40 +0100 Subject: [PATCH 2/3] Bump pylint to ^3.3.0 and regen lockfile Update pyproject.toml to require pylint ^3.3.0 and regenerate poetry.lock (Poetry 2.2.1) to lock the updated dependencies. This ensures dev tooling uses the newer pylint release and related dependency constraints are refreshed. --- poetry.lock | 32 ++++++++++++++++---------------- pyproject.toml | 2 +- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/poetry.lock b/poetry.lock index b7d7c9e..1eb6d0d 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,19 +1,19 @@ -# This file is automatically @generated by Poetry 2.1.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.2.1 and should not be changed by hand. [[package]] name = "astroid" -version = "3.2.4" +version = "3.3.11" description = "An abstract syntax tree for Python with inference support." optional = false -python-versions = ">=3.8.0" +python-versions = ">=3.9.0" groups = ["dev"] files = [ - {file = "astroid-3.2.4-py3-none-any.whl", hash = "sha256:413658a61eeca6202a59231abb473f932038fbcbf1666587f66d482083413a25"}, - {file = "astroid-3.2.4.tar.gz", hash = "sha256:0e14202810b30da1b735827f78f5157be2bbd4a7a59b7707ca0bfc2fb4c0063a"}, + {file = "astroid-3.3.11-py3-none-any.whl", hash = "sha256:54c760ae8322ece1abd213057c4b5bba7c49818853fc901ef09719a60dbf9dec"}, + {file = "astroid-3.3.11.tar.gz", hash = "sha256:1e5a5011af2920c7c67a53f65d536d65bfa7116feeaf2354d8b94f29573bb0ce"}, ] [package.dependencies] -typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.11\""} +typing-extensions = {version = ">=4", markers = "python_version < \"3.11\""} [[package]] name = "black" @@ -576,30 +576,30 @@ email = ["email-validator (>=1.0.3)"] [[package]] name = "pylint" -version = "3.2.7" +version = "3.3.9" description = "python code static checker" optional = false -python-versions = ">=3.8.0" +python-versions = ">=3.9.0" groups = ["dev"] files = [ - {file = "pylint-3.2.7-py3-none-any.whl", hash = "sha256:02f4aedeac91be69fb3b4bea997ce580a4ac68ce58b89eaefeaf06749df73f4b"}, - {file = "pylint-3.2.7.tar.gz", hash = "sha256:1b7a721b575eaeaa7d39db076b6e7743c993ea44f57979127c517c6c572c803e"}, + {file = "pylint-3.3.9-py3-none-any.whl", hash = "sha256:01f9b0462c7730f94786c283f3e52a1fbdf0494bbe0971a78d7277ef46a751e7"}, + {file = "pylint-3.3.9.tar.gz", hash = "sha256:d312737d7b25ccf6b01cc4ac629b5dcd14a0fcf3ec392735ac70f137a9d5f83a"}, ] [package.dependencies] -astroid = ">=3.2.4,<=3.3.0-dev0" +astroid = ">=3.3.8,<=3.4.0.dev0" colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} dill = [ {version = ">=0.2", markers = "python_version < \"3.11\""}, {version = ">=0.3.7", markers = "python_version >= \"3.12\""}, {version = ">=0.3.6", markers = "python_version == \"3.11\""}, ] -isort = ">=4.2.5,<5.13.0 || >5.13.0,<6" +isort = ">=4.2.5,<5.13 || >5.13,<7" mccabe = ">=0.6,<0.8" -platformdirs = ">=2.2.0" -tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +platformdirs = ">=2.2" +tomli = {version = ">=1.1", markers = "python_version < \"3.11\""} tomlkit = ">=0.10.1" -typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\""} +typing-extensions = {version = ">=3.10", markers = "python_version < \"3.10\""} [package.extras] spelling = ["pyenchant (>=3.2,<4.0)"] @@ -815,4 +815,4 @@ zstd = ["zstandard (>=0.18.0)"] [metadata] lock-version = "2.1" python-versions = ">=3.9,<3.14" -content-hash = "4b9d6336cc1be3bc5c2141efcd80295bcf4515aa31abd8e5d666727463f804a0" +content-hash = "2cf426317f376698126b13ce081d9f86a901fee0fb9f44e2f064619835893b7f" diff --git a/pyproject.toml b/pyproject.toml index b21d57c..9d6add7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -18,7 +18,7 @@ urllib3 = ">=2.5.0" [tool.poetry.group.dev.dependencies] black = "^24.4.2" mypy = "^1.10.0" -pylint = "^3.2.2" +pylint = "^3.3.0" pytest = "^8.2.1" pytest-cov = "^5.0.0" ruff = "^0.4.4" From 2778ba1f9d9f74170ad2ded83d0296811bf67f2b Mon Sep 17 00:00:00 2001 From: Marco Antonio Gil Date: Fri, 27 Feb 2026 15:37:44 +0100 Subject: [PATCH 3/3] PTHMINT-99: Consolidate ruff config and fix validator hint Move and consolidate the [tool.ruff] block in pyproject.toml (add target-version = "py39" and remove duplicate section). Update DecimalAmount.validator signature to use a string forward reference for cls ("DecimalAmount") instead of type[...] to avoid typing/forward-reference issues on Python 3.9 and keep annotations consistet. --- pyproject.toml | 6 +++--- src/multisafepay/value_object/decimal_amount.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 9d6add7..0cd69c4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -93,6 +93,9 @@ disable = [ "W1514", ] +[tool.ruff] +target-version = "py39" + [tool.ruff.lint] extend-safe-fixes = [ "D400", # docstrings should end with a period @@ -135,6 +138,3 @@ ignore = [ "TRY300", ] select = ["ALL"] - -[tool.ruff] -target-version = "py39" diff --git a/src/multisafepay/value_object/decimal_amount.py b/src/multisafepay/value_object/decimal_amount.py index df43b73..ff71f2d 100644 --- a/src/multisafepay/value_object/decimal_amount.py +++ b/src/multisafepay/value_object/decimal_amount.py @@ -28,7 +28,7 @@ class DecimalAmount(InmutableModel): @validator("amount", pre=True) def convert_to_decimal( - cls: type["DecimalAmount"], + cls: "DecimalAmount", value: Union[str, float, Decimal], ) -> Decimal: """