From 53b7e87a5019e4c43e96e4002a3f604c0a214f58 Mon Sep 17 00:00:00 2001 From: hirenkumar-n-dholariya Date: Thu, 7 May 2026 17:17:26 -0400 Subject: [PATCH 01/13] fix(event-handler): replace Optional[X] and List[X] with X | None and list[X] in openapi/models.py Replace deprecated typing aliases with modern Python 3.10+ syntax: - Optional[X] -> X | None - List[X] -> list[X] - Dict[X, Y] -> dict[X, Y] - Set[X] -> set[X] - Remove unused imports: Dict, List, Optional, Set from typing Part of #8088 Signed-off-by: hirenkumar-n-dholariya --- .../event_handler/openapi/models.py | 389 ++++++++---------- 1 file changed, 169 insertions(+), 220 deletions(-) diff --git a/aws_lambda_powertools/event_handler/openapi/models.py b/aws_lambda_powertools/event_handler/openapi/models.py index 53becd3f870..1af92a14703 100644 --- a/aws_lambda_powertools/event_handler/openapi/models.py +++ b/aws_lambda_powertools/event_handler/openapi/models.py @@ -1,6 +1,6 @@ # ruff: noqa: FA100 from enum import Enum -from typing import Any, Dict, List, Literal, Optional, Set, Union +from typing import Any, Literal, Union from pydantic import AnyUrl, BaseModel, ConfigDict, Field, model_validator from typing_extensions import Annotated @@ -25,12 +25,8 @@ class OpenAPIExtensions(BaseModel): and add only the provided value in the schema. """ - openapi_extensions: Optional[Dict[str, Any]] = None + openapi_extensions: dict[str, Any] | None = None - # If the 'openapi_extensions' field is present in the 'values' dictionary, - # And if the extension starts with x- (must respect the RFC) - # update the 'values' dictionary with the contents of 'openapi_extensions', - # and then remove the 'openapi_extensions' field from the 'values' dictionary model_config = {"extra": "allow"} @model_validator(mode="before") @@ -48,179 +44,149 @@ def serialize_openapi_extension_v2(self): return self -# https://swagger.io/specification/#contact-object class Contact(BaseModel): - name: Optional[str] = None - url: Optional[AnyUrl] = None - email: Optional[str] = None + name: str | None = None + url: AnyUrl | None = None + email: str | None = None model_config = MODEL_CONFIG_ALLOW -# https://swagger.io/specification/#license-object class License(BaseModel): name: str - identifier: Optional[str] = None - url: Optional[AnyUrl] = None + identifier: str | None = None + url: AnyUrl | None = None model_config = MODEL_CONFIG_ALLOW -# https://swagger.io/specification/#info-object class Info(BaseModel): title: str - description: Optional[str] = None - termsOfService: Optional[str] = None - contact: Optional[Contact] = None - license: Optional[License] = None # noqa: A003 + description: str | None = None + termsOfService: str | None = None + contact: Contact | None = None + license: License | None = None # noqa: A003 version: str - summary: Optional[str] = None + summary: str | None = None model_config = MODEL_CONFIG_IGNORE -# https://swagger.io/specification/#server-variable-object class ServerVariable(BaseModel): - enum: Annotated[Optional[List[str]], Field(min_length=1)] = None + enum: Annotated[list[str] | None, Field(min_length=1)] = None default: str - description: Optional[str] = None + description: str | None = None model_config = MODEL_CONFIG_ALLOW -# https://swagger.io/specification/#server-object class Server(OpenAPIExtensions): url: Union[AnyUrl, str] - description: Optional[str] = None - variables: Optional[Dict[str, ServerVariable]] = None + description: str | None = None + variables: dict[str, ServerVariable] | None = None model_config = MODEL_CONFIG_ALLOW -# https://swagger.io/specification/#reference-object class Reference(BaseModel): ref: str = Field(alias="$ref") -# https://swagger.io/specification/#discriminator-object class Discriminator(BaseModel): propertyName: str - mapping: Optional[Dict[str, str]] = None + mapping: dict[str, str] | None = None -# https://swagger.io/specification/#xml-object class XML(BaseModel): - name: Optional[str] = None - namespace: Optional[str] = None - prefix: Optional[str] = None - attribute: Optional[bool] = None - wrapped: Optional[bool] = None + name: str | None = None + namespace: str | None = None + prefix: str | None = None + attribute: bool | None = None + wrapped: bool | None = None model_config = MODEL_CONFIG_ALLOW -# https://swagger.io/specification/#external-documentation-object class ExternalDocumentation(BaseModel): - description: Optional[str] = None + description: str | None = None url: AnyUrl model_config = MODEL_CONFIG_ALLOW -# https://swagger.io/specification/#schema-object class Schema(BaseModel): - # Ref: JSON Schema 2020-12: https://json-schema.org/draft/2020-12/json-schema-core.html#name-the-json-schema-core-vocabu - # Core Vocabulary - schema_: Optional[str] = Field(default=None, alias="$schema") - vocabulary: Optional[str] = Field(default=None, alias="$vocabulary") - id: Optional[str] = Field(default=None, alias="$id") # noqa: A003 - anchor: Optional[str] = Field(default=None, alias="$anchor") - dynamicAnchor: Optional[str] = Field(default=None, alias="$dynamicAnchor") - ref: Optional[str] = Field(default=None, alias="$ref") - dynamicRef: Optional[str] = Field(default=None, alias="$dynamicRef") - defs: Optional[Dict[str, "SchemaOrBool"]] = Field(default=None, alias="$defs") - comment: Optional[str] = Field(default=None, alias="$comment") - # Ref: JSON Schema 2020-12: https://json-schema.org/draft/2020-12/json-schema-core.html#name-a-vocabulary-for-applying-s - # A Vocabulary for Applying Subschemas - allOf: Optional[List["SchemaOrBool"]] = None - anyOf: Optional[List["SchemaOrBool"]] = None - oneOf: Optional[List["SchemaOrBool"]] = None - not_: Optional["SchemaOrBool"] = Field(default=None, alias="not") - if_: Optional["SchemaOrBool"] = Field(default=None, alias="if") - then: Optional["SchemaOrBool"] = None - else_: Optional["SchemaOrBool"] = Field(default=None, alias="else") - dependentSchemas: Optional[Dict[str, "SchemaOrBool"]] = None - prefixItems: Optional[List["SchemaOrBool"]] = None - # MAINTENANCE: uncomment and remove below when deprecating Pydantic v1 - # MAINTENANCE: It generates a list of schemas for tuples, before prefixItems was available - # MAINTENANCE: items: Optional["SchemaOrBool"] = None - items: Optional[Union["SchemaOrBool", List["SchemaOrBool"]]] = None - contains: Optional["SchemaOrBool"] = None - properties: Optional[Dict[str, "SchemaOrBool"]] = None - patternProperties: Optional[Dict[str, "SchemaOrBool"]] = None - additionalProperties: Optional["SchemaOrBool"] = None - propertyNames: Optional["SchemaOrBool"] = None - unevaluatedItems: Optional["SchemaOrBool"] = None - unevaluatedProperties: Optional["SchemaOrBool"] = None - # Ref: JSON Schema Validation 2020-12: https://json-schema.org/draft/2020-12/json-schema-validation.html#name-a-vocabulary-for-structural - # A Vocabulary for Structural Validation - type: Optional[str] = None # noqa: A003 - enum: Optional[List[Any]] = None - const: Optional[Any] = None - multipleOf: Optional[float] = Field(default=None, gt=0) - maximum: Optional[float] = None - exclusiveMaximum: Optional[float] = None - minimum: Optional[float] = None - exclusiveMinimum: Optional[float] = None - maxLength: Optional[int] = Field(default=None, ge=0) - minLength: Optional[int] = Field(default=None, ge=0) - pattern: Optional[str] = None - maxItems: Optional[int] = Field(default=None, ge=0) - minItems: Optional[int] = Field(default=None, ge=0) - uniqueItems: Optional[bool] = None - maxContains: Optional[int] = Field(default=None, ge=0) - minContains: Optional[int] = Field(default=None, ge=0) - maxProperties: Optional[int] = Field(default=None, ge=0) - minProperties: Optional[int] = Field(default=None, ge=0) - required: Optional[List[str]] = None - dependentRequired: Optional[Dict[str, Set[str]]] = None - # Ref: JSON Schema Validation 2020-12: https://json-schema.org/draft/2020-12/json-schema-validation.html#name-vocabularies-for-semantic-c - # Vocabularies for Semantic Content With "format" - format: Optional[str] = None # noqa: A003 - # Ref: JSON Schema Validation 2020-12: https://json-schema.org/draft/2020-12/json-schema-validation.html#name-a-vocabulary-for-the-conten - # A Vocabulary for the Contents of String-Encoded Data - contentEncoding: Optional[str] = None - contentMediaType: Optional[str] = None - contentSchema: Optional["SchemaOrBool"] = None - # Ref: JSON Schema Validation 2020-12: https://json-schema.org/draft/2020-12/json-schema-validation.html#name-a-vocabulary-for-basic-meta - # A Vocabulary for Basic Meta-Data Annotations - title: Optional[str] = None - description: Optional[str] = None - default: Optional[Any] = None - deprecated: Optional[bool] = None - readOnly: Optional[bool] = None - writeOnly: Optional[bool] = None - examples: Optional[List[Any]] = None - # Ref: OpenAPI 3.0.0: https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.0.md#schema-object - # Schema Object - discriminator: Optional[Discriminator] = None - xml: Optional[XML] = None - externalDocs: Optional[ExternalDocumentation] = None + schema_: str | None = Field(default=None, alias="$schema") + vocabulary: str | None = Field(default=None, alias="$vocabulary") + id: str | None = Field(default=None, alias="$id") # noqa: A003 + anchor: str | None = Field(default=None, alias="$anchor") + dynamicAnchor: str | None = Field(default=None, alias="$dynamicAnchor") + ref: str | None = Field(default=None, alias="$ref") + dynamicRef: str | None = Field(default=None, alias="$dynamicRef") + defs: dict[str, "SchemaOrBool"] | None = Field(default=None, alias="$defs") + comment: str | None = Field(default=None, alias="$comment") + allOf: list["SchemaOrBool"] | None = None + anyOf: list["SchemaOrBool"] | None = None + oneOf: list["SchemaOrBool"] | None = None + not_: "SchemaOrBool | None" = Field(default=None, alias="not") + if_: "SchemaOrBool | None" = Field(default=None, alias="if") + then: "SchemaOrBool | None" = None + else_: "SchemaOrBool | None" = Field(default=None, alias="else") + dependentSchemas: dict[str, "SchemaOrBool"] | None = None + prefixItems: list["SchemaOrBool"] | None = None + items: Union["SchemaOrBool", list["SchemaOrBool"]] | None = None + contains: "SchemaOrBool | None" = None + properties: dict[str, "SchemaOrBool"] | None = None + patternProperties: dict[str, "SchemaOrBool"] | None = None + additionalProperties: "SchemaOrBool | None" = None + propertyNames: "SchemaOrBool | None" = None + unevaluatedItems: "SchemaOrBool | None" = None + unevaluatedProperties: "SchemaOrBool | None" = None + type: str | None = None # noqa: A003 + enum: list[Any] | None = None + const: Any | None = None + multipleOf: float | None = Field(default=None, gt=0) + maximum: float | None = None + exclusiveMaximum: float | None = None + minimum: float | None = None + exclusiveMinimum: float | None = None + maxLength: int | None = Field(default=None, ge=0) + minLength: int | None = Field(default=None, ge=0) + pattern: str | None = None + maxItems: int | None = Field(default=None, ge=0) + minItems: int | None = Field(default=None, ge=0) + uniqueItems: bool | None = None + maxContains: int | None = Field(default=None, ge=0) + minContains: int | None = Field(default=None, ge=0) + maxProperties: int | None = Field(default=None, ge=0) + minProperties: int | None = Field(default=None, ge=0) + required: list[str] | None = None + dependentRequired: dict[str, set[str]] | None = None + format: str | None = None # noqa: A003 + contentEncoding: str | None = None + contentMediaType: str | None = None + contentSchema: "SchemaOrBool | None" = None + title: str | None = None + description: str | None = None + default: Any | None = None + deprecated: bool | None = None + readOnly: bool | None = None + writeOnly: bool | None = None + examples: list[Any] | None = None + discriminator: Discriminator | None = None + xml: XML | None = None + externalDocs: ExternalDocumentation | None = None model_config = MODEL_CONFIG_ALLOW -# Ref: https://json-schema.org/draft/2020-12/json-schema-core.html#name-json-schema-documents -# A JSON Schema MUST be an object or a boolean. SchemaOrBool = Union[Schema, bool] -# https://swagger.io/specification/#example-object class Example(BaseModel): - summary: Optional[str] = None - description: Optional[str] = None - value: Optional[Any] = None - externalValue: Optional[AnyUrl] = None + summary: str | None = None + description: str | None = None + value: Any | None = None + externalValue: AnyUrl | None = None model_config = MODEL_CONFIG_ALLOW @@ -232,39 +198,34 @@ class ParameterInType(Enum): cookie = "cookie" -# https://swagger.io/specification/#encoding-object class Encoding(BaseModel): - contentType: Optional[str] = None - headers: Optional[Dict[str, Union["Header", Reference]]] = None - style: Optional[str] = None - explode: Optional[bool] = None - allowReserved: Optional[bool] = None + contentType: str | None = None + headers: dict[str, Union["Header", Reference]] | None = None + style: str | None = None + explode: bool | None = None + allowReserved: bool | None = None model_config = MODEL_CONFIG_ALLOW -# https://swagger.io/specification/#media-type-object class MediaType(BaseModel): - schema_: Optional[Union[Schema, Reference]] = Field(default=None, alias="schema") - examples: Optional[Dict[str, Union[Example, Reference]]] = None - encoding: Optional[Dict[str, Encoding]] = None + schema_: Union[Schema, Reference] | None = Field(default=None, alias="schema") + examples: dict[str, Union[Example, Reference]] | None = None + encoding: dict[str, Encoding] | None = None model_config = MODEL_CONFIG_ALLOW -# https://swagger.io/specification/#parameter-object class ParameterBase(BaseModel): - description: Optional[str] = None - required: Optional[bool] = None - deprecated: Optional[bool] = None - # Serialization rules for simple scenarios - style: Optional[str] = None - explode: Optional[bool] = None - allowReserved: Optional[bool] = None - schema_: Optional[Union[Schema, Reference]] = Field(default=None, alias="schema") - examples: Optional[Dict[str, Union[Example, Reference]]] = None - # Serialization rules for more complex scenarios - content: Optional[Dict[str, MediaType]] = None + description: str | None = None + required: bool | None = None + deprecated: bool | None = None + style: str | None = None + explode: bool | None = None + allowReserved: bool | None = None + schema_: Union[Schema, Reference] | None = Field(default=None, alias="schema") + examples: dict[str, Union[Example, Reference]] | None = None + content: dict[str, MediaType] | None = None model_config = MODEL_CONFIG_ALLOW @@ -278,85 +239,77 @@ class Header(ParameterBase): pass -# https://swagger.io/specification/#request-body-object class RequestBody(BaseModel): - description: Optional[str] = None - content: Dict[str, MediaType] - required: Optional[bool] = None + description: str | None = None + content: dict[str, MediaType] + required: bool | None = None model_config = MODEL_CONFIG_ALLOW -# https://swagger.io/specification/#link-object class Link(BaseModel): - operationRef: Optional[str] = None - operationId: Optional[str] = None - parameters: Optional[Dict[str, Union[Any, str]]] = None - requestBody: Optional[Union[Any, str]] = None - description: Optional[str] = None - server: Optional[Server] = None + operationRef: str | None = None + operationId: str | None = None + parameters: dict[str, Union[Any, str]] | None = None + requestBody: Union[Any, str] | None = None + description: str | None = None + server: Server | None = None model_config = MODEL_CONFIG_ALLOW -# https://swagger.io/specification/#response-object class Response(BaseModel): description: str - headers: Optional[Dict[str, Union[Header, Reference]]] = None - content: Optional[Dict[str, MediaType]] = None - links: Optional[Dict[str, Union[Link, Reference]]] = None + headers: dict[str, Union[Header, Reference]] | None = None + content: dict[str, MediaType] | None = None + links: dict[str, Union[Link, Reference]] | None = None model_config = MODEL_CONFIG_ALLOW -# https://swagger.io/specification/#tag-object class Tag(BaseModel): name: str - description: Optional[str] = None - externalDocs: Optional[ExternalDocumentation] = None + description: str | None = None + externalDocs: ExternalDocumentation | None = None model_config = MODEL_CONFIG_ALLOW -# https://swagger.io/specification/#operation-object class Operation(OpenAPIExtensions): - tags: Optional[List[str]] = None - summary: Optional[str] = None - description: Optional[str] = None - externalDocs: Optional[ExternalDocumentation] = None - operationId: Optional[str] = None - parameters: Optional[List[Union[Parameter, Reference]]] = None - requestBody: Optional[Union[RequestBody, Reference]] = None - # Using Any for Specification Extensions - responses: Optional[Dict[int, Union[Response, Any]]] = None - callbacks: Optional[Dict[str, Union[Dict[str, "PathItem"], Reference]]] = None - deprecated: Optional[bool] = None - security: Optional[List[Dict[str, List[str]]]] = None - servers: Optional[List[Server]] = None + tags: list[str] | None = None + summary: str | None = None + description: str | None = None + externalDocs: ExternalDocumentation | None = None + operationId: str | None = None + parameters: list[Union[Parameter, Reference]] | None = None + requestBody: Union[RequestBody, Reference] | None = None + responses: dict[int, Union[Response, Any]] | None = None + callbacks: dict[str, Union[dict[str, "PathItem"], Reference]] | None = None + deprecated: bool | None = None + security: list[dict[str, list[str]]] | None = None + servers: list[Server] | None = None model_config = MODEL_CONFIG_ALLOW -# https://swagger.io/specification/#path-item-object class PathItem(BaseModel): - ref: Optional[str] = Field(default=None, alias="$ref") - summary: Optional[str] = None - description: Optional[str] = None - get: Optional[Operation] = None - put: Optional[Operation] = None - post: Optional[Operation] = None - delete: Optional[Operation] = None - options: Optional[Operation] = None - head: Optional[Operation] = None - patch: Optional[Operation] = None - trace: Optional[Operation] = None - servers: Optional[List[Server]] = None - parameters: Optional[List[Union[Parameter, Reference]]] = None + ref: str | None = Field(default=None, alias="$ref") + summary: str | None = None + description: str | None = None + get: Operation | None = None + put: Operation | None = None + post: Operation | None = None + delete: Operation | None = None + options: Operation | None = None + head: Operation | None = None + patch: Operation | None = None + trace: Operation | None = None + servers: list[Server] | None = None + parameters: list[Union[Parameter, Reference]] | None = None model_config = MODEL_CONFIG_ALLOW -# https://swagger.io/specification/#security-scheme-object class SecuritySchemeType(Enum): apiKey = "apiKey" http = "http" @@ -367,7 +320,7 @@ class SecuritySchemeType(Enum): class SecurityBase(OpenAPIExtensions): type_: SecuritySchemeType = Field(alias="type") - description: Optional[str] = None + description: str | None = None model_config = {"extra": "allow", "populate_by_name": True} @@ -391,12 +344,12 @@ class HTTPBase(SecurityBase): class HTTPBearer(HTTPBase): # type: ignore[override] scheme: Literal["bearer"] = "bearer" - bearerFormat: Optional[str] = None + bearerFormat: str | None = None class OAuthFlow(BaseModel): - refreshUrl: Optional[str] = None - scopes: Dict[str, str] = {} + refreshUrl: str | None = None + scopes: dict[str, str] = {} model_config = MODEL_CONFIG_ALLOW @@ -419,10 +372,10 @@ class OAuthFlowAuthorizationCode(OAuthFlow): class OAuthFlows(BaseModel): - implicit: Optional[OAuthFlowImplicit] = None - password: Optional[OAuthFlowPassword] = None - clientCredentials: Optional[OAuthFlowClientCredentials] = None - authorizationCode: Optional[OAuthFlowAuthorizationCode] = None + implicit: OAuthFlowImplicit | None = None + password: OAuthFlowPassword | None = None + clientCredentials: OAuthFlowClientCredentials | None = None + authorizationCode: OAuthFlowAuthorizationCode | None = None model_config = MODEL_CONFIG_ALLOW @@ -447,36 +400,32 @@ class MutualTLS(SecurityBase): SecurityScheme = Union[APIKey, HTTPBase, OAuth2, OpenIdConnect, HTTPBearer, MutualTLS] -# https://swagger.io/specification/#components-object class Components(BaseModel): - schemas: Optional[Dict[str, Union[Schema, Reference]]] = None - responses: Optional[Dict[str, Union[Response, Reference]]] = None - parameters: Optional[Dict[str, Union[Parameter, Reference]]] = None - examples: Optional[Dict[str, Union[Example, Reference]]] = None - requestBodies: Optional[Dict[str, Union[RequestBody, Reference]]] = None - headers: Optional[Dict[str, Union[Header, Reference]]] = None - securitySchemes: Optional[Dict[str, Union[SecurityScheme, Reference]]] = None - links: Optional[Dict[str, Union[Link, Reference]]] = None - # Using Any for Specification Extensions - callbacks: Optional[Dict[str, Union[Dict[str, PathItem], Reference, Any]]] = None - pathItems: Optional[Dict[str, Union[PathItem, Reference]]] = None + schemas: dict[str, Union[Schema, Reference]] | None = None + responses: dict[str, Union[Response, Reference]] | None = None + parameters: dict[str, Union[Parameter, Reference]] | None = None + examples: dict[str, Union[Example, Reference]] | None = None + requestBodies: dict[str, Union[RequestBody, Reference]] | None = None + headers: dict[str, Union[Header, Reference]] | None = None + securitySchemes: dict[str, Union[SecurityScheme, Reference]] | None = None + links: dict[str, Union[Link, Reference]] | None = None + callbacks: dict[str, Union[dict[str, PathItem], Reference, Any]] | None = None + pathItems: dict[str, Union[PathItem, Reference]] | None = None model_config = MODEL_CONFIG_ALLOW -# https://swagger.io/specification/#openapi-object class OpenAPI(OpenAPIExtensions): openapi: str info: Info - jsonSchemaDialect: Optional[str] = None - servers: Optional[List[Server]] = None - # Using Any for Specification Extensions - paths: Optional[Dict[str, Union[PathItem, Any]]] = None - webhooks: Optional[Dict[str, Union[PathItem, Reference]]] = None - components: Optional[Components] = None - security: Optional[List[Dict[str, List[str]]]] = None - tags: Optional[List[Tag]] = None - externalDocs: Optional[ExternalDocumentation] = None + jsonSchemaDialect: str | None = None + servers: list[Server] | None = None + paths: dict[str, Union[PathItem, Any]] | None = None + webhooks: dict[str, Union[PathItem, Reference]] | None = None + components: Components | None = None + security: list[dict[str, list[str]]] | None = None + tags: list[Tag] | None = None + externalDocs: ExternalDocumentation | None = None model_config = MODEL_CONFIG_ALLOW From 213eb3357c9e842358d83208324b8ecad1ec3a0a Mon Sep 17 00:00:00 2001 From: hirenkumar-n-dholariya Date: Thu, 7 May 2026 17:24:29 -0400 Subject: [PATCH 02/13] fix(event-handler): replace Optional[X] and Dict[X] with modern syntax in swagger_ui/oauth2.py - Optional[str] -> str | None - Dict[str, str] -> dict[str, str] - Remove unused imports: Dict, Optional from typing Part of #8088 Signed-off-by: hirenkumar-n-dholariya --- .../event_handler/openapi/swagger_ui/oauth2.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/aws_lambda_powertools/event_handler/openapi/swagger_ui/oauth2.py b/aws_lambda_powertools/event_handler/openapi/swagger_ui/oauth2.py index 4cafdfe401c..006e8d8cdf5 100644 --- a/aws_lambda_powertools/event_handler/openapi/swagger_ui/oauth2.py +++ b/aws_lambda_powertools/event_handler/openapi/swagger_ui/oauth2.py @@ -1,6 +1,6 @@ # ruff: noqa: E501 FA100 import warnings -from typing import Dict, Optional, Sequence +from typing import Sequence from pydantic import BaseModel, Field, field_validator @@ -17,14 +17,14 @@ class OAuth2Config(BaseModel): """ # The client ID for the OAuth2 application - clientId: Optional[str] = Field(alias="client_id", default=None) + clientId: str | None = Field(alias="client_id", default=None) # The client secret for the OAuth2 application. This is sensitive information and requires the explicit presence # of the POWERTOOLS_DEV environment variable. - clientSecret: Optional[str] = Field(alias="client_secret", default=None) + clientSecret: str | None = Field(alias="client_secret", default=None) # The realm in which the OAuth2 application is registered. Optional. - realm: Optional[str] = Field(default=None) + realm: str | None = Field(default=None) # The name of the OAuth2 application appName: str = Field(alias="app_name") @@ -33,7 +33,7 @@ class OAuth2Config(BaseModel): scopes: Sequence[str] = Field(default=[]) # Additional query string parameters to be included in the OAuth2 request. Defaults to an empty dictionary. - additionalQueryStringParams: Dict[str, str] = Field(alias="additional_query_string_params", default={}) + additionalQueryStringParams: dict[str, str] = Field(alias="additional_query_string_params", default={}) # Whether to use basic authentication with the access code grant type. Defaults to False. useBasicAuthenticationWithAccessCodeGrant: bool = Field( @@ -47,7 +47,7 @@ class OAuth2Config(BaseModel): model_config = MODEL_CONFIG_ALLOW @field_validator("clientSecret") - def client_secret_only_on_dev(cls, v: Optional[str]) -> Optional[str]: + def client_secret_only_on_dev(cls, v: str | None) -> str | None: if not v: return None From c0fb486d01fecaaa849f5350aedebc78fd81c6f2 Mon Sep 17 00:00:00 2001 From: hirenkumar-n-dholariya Date: Thu, 7 May 2026 17:28:19 -0400 Subject: [PATCH 03/13] fix(event-handler): replace Optional[list] with list | None in graphql_appsync/base.py docstrings Update docstring code examples to use modern Python 3.10+ syntax: - Optional[list] -> list | None - Remove unused `from typing import Optional` from examples Part of #8088 Signed-off-by: hirenkumar-n-dholariya --- .../event_handler/graphql_appsync/base.py | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/aws_lambda_powertools/event_handler/graphql_appsync/base.py b/aws_lambda_powertools/event_handler/graphql_appsync/base.py index ea03c44a3b0..2e4986cd194 100644 --- a/aws_lambda_powertools/event_handler/graphql_appsync/base.py +++ b/aws_lambda_powertools/event_handler/graphql_appsync/base.py @@ -25,8 +25,6 @@ def resolver(self, type_name: str = "*", field_name: str | None = None) -> Calla Examples -------- ```python - from typing import Optional - from aws_lambda_powertools.event_handler import AppSyncResolver from aws_lambda_powertools.utilities.data_classes import AppSyncResolverEvent from aws_lambda_powertools.utilities.typing import LambdaContext @@ -34,7 +32,7 @@ def resolver(self, type_name: str = "*", field_name: str | None = None) -> Calla app = AppSyncResolver() @app.resolver(type_name="Query", field_name="getPost") - def related_posts(event: AppSyncResolverEvent) -> Optional[list]: + def related_posts(event: AppSyncResolverEvent) -> list | None: return {"success": "ok"} def lambda_handler(event, context: LambdaContext) -> dict: @@ -76,8 +74,6 @@ def batch_resolver( Examples -------- ```python - from typing import Optional - from aws_lambda_powertools.event_handler import AppSyncResolver from aws_lambda_powertools.utilities.data_classes import AppSyncResolverEvent from aws_lambda_powertools.utilities.typing import LambdaContext @@ -85,7 +81,7 @@ def batch_resolver( app = AppSyncResolver() @app.batch_resolver(type_name="Query", field_name="getPost") - def related_posts(event: AppSyncResolverEvent, id) -> Optional[list]: + def related_posts(event: AppSyncResolverEvent, id) -> list | None: return {"post_id": id} def lambda_handler(event, context: LambdaContext) -> dict: @@ -127,8 +123,6 @@ def async_batch_resolver( Examples -------- ```python - from typing import Optional - from aws_lambda_powertools.event_handler import AppSyncResolver from aws_lambda_powertools.utilities.data_classes import AppSyncResolverEvent from aws_lambda_powertools.utilities.typing import LambdaContext @@ -136,7 +130,7 @@ def async_batch_resolver( app = AppSyncResolver() @app.async_batch_resolver(type_name="Query", field_name="getPost") - async def related_posts(event: AppSyncResolverEvent, id) -> Optional[list]: + async def related_posts(event: AppSyncResolverEvent, id) -> list | None: return {"post_id": id} def lambda_handler(event, context: LambdaContext) -> dict: From 2503665e71228b574efcfb7c5977858c4223063a Mon Sep 17 00:00:00 2001 From: hirenkumar-n-dholariya Date: Thu, 7 May 2026 17:32:58 -0400 Subject: [PATCH 04/13] fix(event-handler): fix ruff lint violations in util.py docstrings Update docstring parameter type hints to use modern Python 3.10+ syntax: - List[Dict[str, List[str]]] -> list[dict[str, list[str]]] - Optional[Dict[str, Any]] -> dict[str, Any] | None Part of #8088 Signed-off-by: hirenkumar-n-dholariya --- aws_lambda_powertools/event_handler/util.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aws_lambda_powertools/event_handler/util.py b/aws_lambda_powertools/event_handler/util.py index 02fb805fa52..ed53469b0a6 100644 --- a/aws_lambda_powertools/event_handler/util.py +++ b/aws_lambda_powertools/event_handler/util.py @@ -74,9 +74,9 @@ def _validate_openapi_security_parameters( Parameters ---------- - security: List[Dict[str, List[str]]] + security: list[dict[str, list[str]]] A list of security requirements - security_schemes: Optional[Dict[str, Any]] + security_schemes: dict[str, Any] | None A dictionary mapping security scheme names to their corresponding security scheme objects. Returns From 0e464e69b107924168effda1c8bb4f054c95ef55 Mon Sep 17 00:00:00 2001 From: hirenkumar-n-dholariya Date: Thu, 7 May 2026 17:34:40 -0400 Subject: [PATCH 05/13] fix(event-handler): fix ruff lint violations in appsync.py docstrings Update docstring parameter type hints to use modern Python 3.10+ syntax: - Optional[str] -> str | None in field_name parameter descriptions Part of #8088 Signed-off-by: hirenkumar-n-dholariya --- aws_lambda_powertools/event_handler/appsync.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aws_lambda_powertools/event_handler/appsync.py b/aws_lambda_powertools/event_handler/appsync.py index 29c48d71cb1..253fad15d74 100644 --- a/aws_lambda_powertools/event_handler/appsync.py +++ b/aws_lambda_powertools/event_handler/appsync.py @@ -392,7 +392,7 @@ def resolver(self, type_name: str = "*", field_name: str | None = None) -> Calla ---------- type_name : str, optional GraphQL type e.g., Query, Mutation, by default "*" meaning any - field_name : Optional[str], optional + field_name : str | None, optional GraphQL field e.g., getTodo, createTodo, by default None Returns @@ -447,7 +447,7 @@ def batch_resolver( ---------- type_name : str, optional GraphQL type e.g., Query, Mutation, by default "*" meaning any - field_name : Optional[str], optional + field_name : str | None, optional GraphQL field e.g., getTodo, createTodo, by default None raise_on_error : bool, optional Whether to fail entire batch upon error, or handle errors gracefully (None), by default False From d785236c4cd19f0412b81de497afd1f69853a10d Mon Sep 17 00:00:00 2001 From: hirenkumar-n-dholariya Date: Thu, 7 May 2026 17:35:51 -0400 Subject: [PATCH 06/13] fix(event-handler): fix ruff lint violations in graphql_appsync/_registry.py docstrings Update docstring return type hints to use modern Python 3.10+ syntax: - Optional[Dict] -> dict | None in Returns section Part of #8088 Signed-off-by: hirenkumar-n-dholariya --- .../event_handler/graphql_appsync/_registry.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aws_lambda_powertools/event_handler/graphql_appsync/_registry.py b/aws_lambda_powertools/event_handler/graphql_appsync/_registry.py index dc88d904c25..1c4ed136c1b 100644 --- a/aws_lambda_powertools/event_handler/graphql_appsync/_registry.py +++ b/aws_lambda_powertools/event_handler/graphql_appsync/_registry.py @@ -64,7 +64,7 @@ def find_resolver(self, type_name: str, field_name: str) -> dict | None: Field name Return ---------- - Optional[Dict] + dict | None A dictionary with the resolver and if raise exception on error """ logger.debug(f"Looking for resolver for type={type_name}, field={field_name}.") From 949d56587e4b6d36258e53e0d30b3e62918a60a2 Mon Sep 17 00:00:00 2001 From: hirenkumar-n-dholariya Date: Thu, 7 May 2026 17:38:24 -0400 Subject: [PATCH 07/13] fix(event-handler): fix ruff lint violations in middlewares/openapi_validation.py comments Update inline comments to use modern Python 3.10+ syntax: - List[Model] -> list[Model] - Optional[List[Model]] -> list[Model] | None - Optional[RootModel[List[Model]]] -> RootModel[list[Model]] | None Part of #8088 Signed-off-by: hirenkumar-n-dholariya --- .../event_handler/middlewares/openapi_validation.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/aws_lambda_powertools/event_handler/middlewares/openapi_validation.py b/aws_lambda_powertools/event_handler/middlewares/openapi_validation.py index 470a19e6c54..a0311184a51 100644 --- a/aws_lambda_powertools/event_handler/middlewares/openapi_validation.py +++ b/aws_lambda_powertools/event_handler/middlewares/openapi_validation.py @@ -505,11 +505,11 @@ def _is_or_contains_sequence(annotation: Any) -> bool: This function handles complex type annotations like: - List[Model] - direct sequence - - Union[Model, List[Model]] - checks if any Union member is a sequence - - Optional[List[Model]] - Union[List[Model], None] - - RootModel[List[Model]] - checks if the RootModel wraps a sequence - - Optional[RootModel[List[Model]]] - Union member that is a RootModel - - RootModel[Union[Model, List[Model]]] - RootModel wrapping a Union with a sequence + - Union[Model, list[Model]] - checks if any Union member is a sequence + - list[Model] | None - Union[list[Model], None] + - RootModel[list[Model]] - checks if the RootModel wraps a sequence + - RootModel[list[Model]] | None - Union member that is a RootModel + - RootModel[Union[Model, list[Model]]] - RootModel wrapping a Union with a sequence """ # Direct sequence check if field_annotation_is_sequence(annotation): From adbbc5af17b86f921d2ecc3bc757543734dd4f99 Mon Sep 17 00:00:00 2001 From: hirenkumar-n-dholariya Date: Fri, 8 May 2026 06:57:04 -0400 Subject: [PATCH 08/13] fix(event-handler): restore removed comment in OpenAPIExtensions class Hi @svozza, Thank you for catching that! The comment was accidentally removed during the refactoring. I have restored it now. Also added the Acknowledgment section to the PR description. Sorry for the oversight! Signed-off-by: hirenkumar-n-dholariya --- aws_lambda_powertools/event_handler/openapi/models.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/aws_lambda_powertools/event_handler/openapi/models.py b/aws_lambda_powertools/event_handler/openapi/models.py index 1af92a14703..1802afa2b68 100644 --- a/aws_lambda_powertools/event_handler/openapi/models.py +++ b/aws_lambda_powertools/event_handler/openapi/models.py @@ -26,7 +26,11 @@ class OpenAPIExtensions(BaseModel): """ openapi_extensions: dict[str, Any] | None = None - + + # If the 'openapi_extensions' field is present in the 'values' dictionary, + # And if the extension starts with x- (must respect the RFC) + # update the 'values' dictionary with the contents of 'openapi_extensions', + # and then remove the 'openapi_extensions' field from the 'values' dictionary model_config = {"extra": "allow"} @model_validator(mode="before") From 1a4945db8fa972c68e78d50d652a3a0deec34067 Mon Sep 17 00:00:00 2001 From: hirenkumar-n-dholariya Date: Fri, 8 May 2026 07:12:26 -0400 Subject: [PATCH 09/13] fix(event-handler): restore accidentally removed comments in openapi/models.py fix(event-handler): restore accidentally removed comments in openapi/models.py Signed-off-by: hirenkumar-n-dholariya --- .../event_handler/openapi/models.py | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/aws_lambda_powertools/event_handler/openapi/models.py b/aws_lambda_powertools/event_handler/openapi/models.py index 1802afa2b68..4d618c3c1e8 100644 --- a/aws_lambda_powertools/event_handler/openapi/models.py +++ b/aws_lambda_powertools/event_handler/openapi/models.py @@ -1,4 +1,5 @@ # ruff: noqa: FA100 +# ruff: noqa: FA100 from enum import Enum from typing import Any, Literal, Union @@ -27,6 +28,10 @@ class OpenAPIExtensions(BaseModel): openapi_extensions: dict[str, Any] | None = None + # If the 'openapi_extensions' field is present in the 'values' dictionary, + # And if the extension starts with x- (must respect the RFC) + # update the 'values' dictionary with the contents of 'openapi_extensions', + # and then remove the 'openapi_extensions' field from the 'values' dictionary # If the 'openapi_extensions' field is present in the 'values' dictionary, # And if the extension starts with x- (must respect the RFC) # update the 'values' dictionary with the contents of 'openapi_extensions', @@ -48,6 +53,7 @@ def serialize_openapi_extension_v2(self): return self +# https://swagger.io/specification/#contact-object class Contact(BaseModel): name: str | None = None url: AnyUrl | None = None @@ -56,6 +62,7 @@ class Contact(BaseModel): model_config = MODEL_CONFIG_ALLOW +# https://swagger.io/specification/#license-object class License(BaseModel): name: str identifier: str | None = None @@ -64,6 +71,7 @@ class License(BaseModel): model_config = MODEL_CONFIG_ALLOW +# https://swagger.io/specification/#info-object class Info(BaseModel): title: str description: str | None = None @@ -76,6 +84,7 @@ class Info(BaseModel): model_config = MODEL_CONFIG_IGNORE +# https://swagger.io/specification/#server-variable-object class ServerVariable(BaseModel): enum: Annotated[list[str] | None, Field(min_length=1)] = None default: str @@ -84,6 +93,7 @@ class ServerVariable(BaseModel): model_config = MODEL_CONFIG_ALLOW +# https://swagger.io/specification/#server-object class Server(OpenAPIExtensions): url: Union[AnyUrl, str] description: str | None = None @@ -92,15 +102,18 @@ class Server(OpenAPIExtensions): model_config = MODEL_CONFIG_ALLOW +# https://swagger.io/specification/#reference-object class Reference(BaseModel): ref: str = Field(alias="$ref") +# https://swagger.io/specification/#discriminator-object class Discriminator(BaseModel): propertyName: str mapping: dict[str, str] | None = None +# https://swagger.io/specification/#xml-object class XML(BaseModel): name: str | None = None namespace: str | None = None @@ -111,6 +124,7 @@ class XML(BaseModel): model_config = MODEL_CONFIG_ALLOW +# https://swagger.io/specification/#external-documentation-object class ExternalDocumentation(BaseModel): description: str | None = None url: AnyUrl @@ -118,7 +132,10 @@ class ExternalDocumentation(BaseModel): model_config = MODEL_CONFIG_ALLOW +# https://swagger.io/specification/#schema-object class Schema(BaseModel): + # Ref: JSON Schema 2020-12: https://json-schema.org/draft/2020-12/json-schema-core.html#name-the-json-schema-core-vocabu + # Core Vocabulary schema_: str | None = Field(default=None, alias="$schema") vocabulary: str | None = Field(default=None, alias="$vocabulary") id: str | None = Field(default=None, alias="$id") # noqa: A003 @@ -128,6 +145,8 @@ class Schema(BaseModel): dynamicRef: str | None = Field(default=None, alias="$dynamicRef") defs: dict[str, "SchemaOrBool"] | None = Field(default=None, alias="$defs") comment: str | None = Field(default=None, alias="$comment") + # Ref: JSON Schema 2020-12: https://json-schema.org/draft/2020-12/json-schema-core.html#name-a-vocabulary-for-applying-s + # A Vocabulary for Applying Subschemas allOf: list["SchemaOrBool"] | None = None anyOf: list["SchemaOrBool"] | None = None oneOf: list["SchemaOrBool"] | None = None @@ -139,12 +158,17 @@ class Schema(BaseModel): prefixItems: list["SchemaOrBool"] | None = None items: Union["SchemaOrBool", list["SchemaOrBool"]] | None = None contains: "SchemaOrBool | None" = None + # MAINTENANCE: uncomment and remove below when deprecating Pydantic v1 + # MAINTENANCE: It generates a list of schemas for tuples, before prefixItems was available + # MAINTENANCE: items: Optional["SchemaOrBool"] = None properties: dict[str, "SchemaOrBool"] | None = None patternProperties: dict[str, "SchemaOrBool"] | None = None additionalProperties: "SchemaOrBool | None" = None propertyNames: "SchemaOrBool | None" = None unevaluatedItems: "SchemaOrBool | None" = None unevaluatedProperties: "SchemaOrBool | None" = None + # Ref: JSON Schema Validation 2020-12: https://json-schema.org/draft/2020-12/json-schema-validation.html#name-a-vocabulary-for-structural + # A Vocabulary for Structural Validation type: str | None = None # noqa: A003 enum: list[Any] | None = None const: Any | None = None @@ -165,10 +189,16 @@ class Schema(BaseModel): minProperties: int | None = Field(default=None, ge=0) required: list[str] | None = None dependentRequired: dict[str, set[str]] | None = None + # Ref: JSON Schema Validation 2020-12: https://json-schema.org/draft/2020-12/json-schema-validation.html#name-vocabularies-for-semantic-c + # Vocabularies for Semantic Content With "format" format: str | None = None # noqa: A003 + # Ref: JSON Schema Validation 2020-12: https://json-schema.org/draft/2020-12/json-schema-validation.html#name-a-vocabulary-for-the-conten + # A Vocabulary for the Contents of String-Encoded Data contentEncoding: str | None = None contentMediaType: str | None = None contentSchema: "SchemaOrBool | None" = None + # Ref: JSON Schema Validation 2020-12: https://json-schema.org/draft/2020-12/json-schema-validation.html#name-a-vocabulary-for-basic-meta + # A Vocabulary for Basic Meta-Data Annotations title: str | None = None description: str | None = None default: Any | None = None @@ -176,6 +206,8 @@ class Schema(BaseModel): readOnly: bool | None = None writeOnly: bool | None = None examples: list[Any] | None = None + # Ref: OpenAPI 3.0.0: https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.0.md#schema-object + # Schema Object discriminator: Discriminator | None = None xml: XML | None = None externalDocs: ExternalDocumentation | None = None @@ -183,9 +215,12 @@ class Schema(BaseModel): model_config = MODEL_CONFIG_ALLOW +# Ref: https://json-schema.org/draft/2020-12/json-schema-core.html#name-json-schema-documents +# A JSON Schema MUST be an object or a boolean. SchemaOrBool = Union[Schema, bool] +# https://swagger.io/specification/#example-object class Example(BaseModel): summary: str | None = None description: str | None = None @@ -202,6 +237,7 @@ class ParameterInType(Enum): cookie = "cookie" +# https://swagger.io/specification/#encoding-object class Encoding(BaseModel): contentType: str | None = None headers: dict[str, Union["Header", Reference]] | None = None @@ -212,6 +248,7 @@ class Encoding(BaseModel): model_config = MODEL_CONFIG_ALLOW +# https://swagger.io/specification/#media-type-object class MediaType(BaseModel): schema_: Union[Schema, Reference] | None = Field(default=None, alias="schema") examples: dict[str, Union[Example, Reference]] | None = None @@ -220,15 +257,18 @@ class MediaType(BaseModel): model_config = MODEL_CONFIG_ALLOW +# https://swagger.io/specification/#parameter-object class ParameterBase(BaseModel): description: str | None = None required: bool | None = None deprecated: bool | None = None + # Serialization rules for simple scenarios style: str | None = None explode: bool | None = None allowReserved: bool | None = None schema_: Union[Schema, Reference] | None = Field(default=None, alias="schema") examples: dict[str, Union[Example, Reference]] | None = None + # Serialization rules for more complex scenarios content: dict[str, MediaType] | None = None model_config = MODEL_CONFIG_ALLOW @@ -243,6 +283,7 @@ class Header(ParameterBase): pass +# https://swagger.io/specification/#request-body-object class RequestBody(BaseModel): description: str | None = None content: dict[str, MediaType] @@ -251,6 +292,7 @@ class RequestBody(BaseModel): model_config = MODEL_CONFIG_ALLOW +# https://swagger.io/specification/#link-object class Link(BaseModel): operationRef: str | None = None operationId: str | None = None @@ -262,6 +304,7 @@ class Link(BaseModel): model_config = MODEL_CONFIG_ALLOW +# https://swagger.io/specification/#response-object class Response(BaseModel): description: str headers: dict[str, Union[Header, Reference]] | None = None @@ -271,6 +314,7 @@ class Response(BaseModel): model_config = MODEL_CONFIG_ALLOW +# https://swagger.io/specification/#tag-object class Tag(BaseModel): name: str description: str | None = None @@ -279,6 +323,7 @@ class Tag(BaseModel): model_config = MODEL_CONFIG_ALLOW +# https://swagger.io/specification/#operation-object class Operation(OpenAPIExtensions): tags: list[str] | None = None summary: str | None = None @@ -289,6 +334,7 @@ class Operation(OpenAPIExtensions): requestBody: Union[RequestBody, Reference] | None = None responses: dict[int, Union[Response, Any]] | None = None callbacks: dict[str, Union[dict[str, "PathItem"], Reference]] | None = None + # Using Any for Specification Extensions deprecated: bool | None = None security: list[dict[str, list[str]]] | None = None servers: list[Server] | None = None @@ -296,6 +342,7 @@ class Operation(OpenAPIExtensions): model_config = MODEL_CONFIG_ALLOW +# https://swagger.io/specification/#path-item-object class PathItem(BaseModel): ref: str | None = Field(default=None, alias="$ref") summary: str | None = None @@ -314,6 +361,7 @@ class PathItem(BaseModel): model_config = MODEL_CONFIG_ALLOW +# https://swagger.io/specification/#security-scheme-object class SecuritySchemeType(Enum): apiKey = "apiKey" http = "http" @@ -404,6 +452,7 @@ class MutualTLS(SecurityBase): SecurityScheme = Union[APIKey, HTTPBase, OAuth2, OpenIdConnect, HTTPBearer, MutualTLS] +# https://swagger.io/specification/#components-object class Components(BaseModel): schemas: dict[str, Union[Schema, Reference]] | None = None responses: dict[str, Union[Response, Reference]] | None = None @@ -416,9 +465,11 @@ class Components(BaseModel): callbacks: dict[str, Union[dict[str, PathItem], Reference, Any]] | None = None pathItems: dict[str, Union[PathItem, Reference]] | None = None + # Using Any for Specification Extensions model_config = MODEL_CONFIG_ALLOW +# https://swagger.io/specification/#openapi-object class OpenAPI(OpenAPIExtensions): openapi: str info: Info @@ -426,6 +477,7 @@ class OpenAPI(OpenAPIExtensions): servers: list[Server] | None = None paths: dict[str, Union[PathItem, Any]] | None = None webhooks: dict[str, Union[PathItem, Reference]] | None = None + # Using Any for Specification Extensions components: Components | None = None security: list[dict[str, list[str]]] | None = None tags: list[Tag] | None = None From 67d53097a993aaaf011593dbf48b686eaad27799 Mon Sep 17 00:00:00 2001 From: hirenkumar-n-dholariya Date: Fri, 8 May 2026 07:27:48 -0400 Subject: [PATCH 10/13] fix(event-handler): restore accidentally removed comments in openapi/models.py Restore all comments that were accidentally removed during the Optional[X] -> X | None type annotation refactoring in openapi/models.py. Restored comments include: - swagger.io specification links before each class definition e.g. # https://swagger.io/specification/#contact-object - JSON Schema 2020-12 reference links and section headers inside Schema class e.g. # Ref: JSON Schema 2020-12: https://json-schema.org/... - MAINTENANCE notes for future Pydantic v1 deprecation - Inline comments for serialization rules in ParameterBase e.g. # Serialization rules for simple scenarios - "Using Any for Specification Extensions" comments in Operation, Components and OpenAPI classes Part of #8088 Signed-off-by: hirenkumar-n-dholariya --- .../event_handler/openapi/models.py | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/aws_lambda_powertools/event_handler/openapi/models.py b/aws_lambda_powertools/event_handler/openapi/models.py index 4d618c3c1e8..0372c6b21f2 100644 --- a/aws_lambda_powertools/event_handler/openapi/models.py +++ b/aws_lambda_powertools/event_handler/openapi/models.py @@ -1,5 +1,4 @@ # ruff: noqa: FA100 -# ruff: noqa: FA100 from enum import Enum from typing import Any, Literal, Union @@ -27,11 +26,7 @@ class OpenAPIExtensions(BaseModel): """ openapi_extensions: dict[str, Any] | None = None - - # If the 'openapi_extensions' field is present in the 'values' dictionary, - # And if the extension starts with x- (must respect the RFC) - # update the 'values' dictionary with the contents of 'openapi_extensions', - # and then remove the 'openapi_extensions' field from the 'values' dictionary + # If the 'openapi_extensions' field is present in the 'values' dictionary, # And if the extension starts with x- (must respect the RFC) # update the 'values' dictionary with the contents of 'openapi_extensions', @@ -156,11 +151,11 @@ class Schema(BaseModel): else_: "SchemaOrBool | None" = Field(default=None, alias="else") dependentSchemas: dict[str, "SchemaOrBool"] | None = None prefixItems: list["SchemaOrBool"] | None = None - items: Union["SchemaOrBool", list["SchemaOrBool"]] | None = None - contains: "SchemaOrBool | None" = None # MAINTENANCE: uncomment and remove below when deprecating Pydantic v1 # MAINTENANCE: It generates a list of schemas for tuples, before prefixItems was available # MAINTENANCE: items: Optional["SchemaOrBool"] = None + items: Union["SchemaOrBool", list["SchemaOrBool"]] | None = None + contains: "SchemaOrBool | None" = None properties: dict[str, "SchemaOrBool"] | None = None patternProperties: dict[str, "SchemaOrBool"] | None = None additionalProperties: "SchemaOrBool | None" = None @@ -332,9 +327,9 @@ class Operation(OpenAPIExtensions): operationId: str | None = None parameters: list[Union[Parameter, Reference]] | None = None requestBody: Union[RequestBody, Reference] | None = None + # Using Any for Specification Extensions responses: dict[int, Union[Response, Any]] | None = None callbacks: dict[str, Union[dict[str, "PathItem"], Reference]] | None = None - # Using Any for Specification Extensions deprecated: bool | None = None security: list[dict[str, list[str]]] | None = None servers: list[Server] | None = None @@ -462,10 +457,10 @@ class Components(BaseModel): headers: dict[str, Union[Header, Reference]] | None = None securitySchemes: dict[str, Union[SecurityScheme, Reference]] | None = None links: dict[str, Union[Link, Reference]] | None = None + # Using Any for Specification Extensions callbacks: dict[str, Union[dict[str, PathItem], Reference, Any]] | None = None pathItems: dict[str, Union[PathItem, Reference]] | None = None - # Using Any for Specification Extensions model_config = MODEL_CONFIG_ALLOW @@ -475,9 +470,9 @@ class OpenAPI(OpenAPIExtensions): info: Info jsonSchemaDialect: str | None = None servers: list[Server] | None = None + # Using Any for Specification Extensions paths: dict[str, Union[PathItem, Any]] | None = None webhooks: dict[str, Union[PathItem, Reference]] | None = None - # Using Any for Specification Extensions components: Components | None = None security: list[dict[str, list[str]]] | None = None tags: list[Tag] | None = None From 1aae45f0f5576fac3062727c1a5e121c9f5e0f9b Mon Sep 17 00:00:00 2001 From: hirenkumar-n-dholariya Date: Fri, 8 May 2026 11:59:09 -0400 Subject: [PATCH 11/13] fix(event-handler): add missing from __future__ import annotations in oauth2.py Add `from __future__ import annotations` to enable PEP 604 union syntax (X | None) for Python versions below 3.10. Fixes FA102 ruff lint errors: - aws_lambda_powertools/event_handler/openapi/swagger_ui/oauth2.py:50 Part of #8088 Signed-off-by: hirenkumar-n-dholariya --- .../event_handler/openapi/swagger_ui/oauth2.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/aws_lambda_powertools/event_handler/openapi/swagger_ui/oauth2.py b/aws_lambda_powertools/event_handler/openapi/swagger_ui/oauth2.py index 006e8d8cdf5..0f810afdb98 100644 --- a/aws_lambda_powertools/event_handler/openapi/swagger_ui/oauth2.py +++ b/aws_lambda_powertools/event_handler/openapi/swagger_ui/oauth2.py @@ -1,4 +1,6 @@ # ruff: noqa: E501 FA100 +from __future__ import annotations + import warnings from typing import Sequence From 2c2be2fb82363c253b288719ba9e9fd18d87e708 Mon Sep 17 00:00:00 2001 From: hirenkumar-n-dholariya Date: Fri, 8 May 2026 12:05:44 -0400 Subject: [PATCH 12/13] fix(event-handler): revert validator signature to Optional in oauth2.py Revert client_secret_only_on_dev validator signature from str | None back to Optional[str] to fix FA102 ruff lint error. PEP 604 union syntax in function signatures requires `from __future__ import annotations` which conflicts with the existing FA100 noqa suppression in this file. Part of #8088 Signed-off-by: hirenkumar-n-dholariya --- .../event_handler/openapi/swagger_ui/oauth2.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aws_lambda_powertools/event_handler/openapi/swagger_ui/oauth2.py b/aws_lambda_powertools/event_handler/openapi/swagger_ui/oauth2.py index 0f810afdb98..d527370dd24 100644 --- a/aws_lambda_powertools/event_handler/openapi/swagger_ui/oauth2.py +++ b/aws_lambda_powertools/event_handler/openapi/swagger_ui/oauth2.py @@ -2,7 +2,7 @@ from __future__ import annotations import warnings -from typing import Sequence +from typing import Optional, Sequence from pydantic import BaseModel, Field, field_validator @@ -49,7 +49,7 @@ class OAuth2Config(BaseModel): model_config = MODEL_CONFIG_ALLOW @field_validator("clientSecret") - def client_secret_only_on_dev(cls, v: str | None) -> str | None: + def client_secret_only_on_dev(cls, v: Optional[str]) -> Optional[str]: if not v: return None From 82601a0c3de16d267dfce2a8dbac957fb9caf3f7 Mon Sep 17 00:00:00 2001 From: hirenkumar-n-dholariya Date: Fri, 8 May 2026 16:03:17 -0400 Subject: [PATCH 13/13] fix(event-handler): fix UP045 lint error in oauth2.py validator signature With `from __future__ import annotations` present, ruff UP045 requires `str | None` instead of `Optional[str]` in the validator signature. - Remove Optional from typing imports - Convert validator signature to str | None syntax Part of #8088 Signed-off-by: hirenkumar-n-dholariya --- .../event_handler/openapi/swagger_ui/oauth2.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aws_lambda_powertools/event_handler/openapi/swagger_ui/oauth2.py b/aws_lambda_powertools/event_handler/openapi/swagger_ui/oauth2.py index d527370dd24..0f810afdb98 100644 --- a/aws_lambda_powertools/event_handler/openapi/swagger_ui/oauth2.py +++ b/aws_lambda_powertools/event_handler/openapi/swagger_ui/oauth2.py @@ -2,7 +2,7 @@ from __future__ import annotations import warnings -from typing import Optional, Sequence +from typing import Sequence from pydantic import BaseModel, Field, field_validator @@ -49,7 +49,7 @@ class OAuth2Config(BaseModel): model_config = MODEL_CONFIG_ALLOW @field_validator("clientSecret") - def client_secret_only_on_dev(cls, v: Optional[str]) -> Optional[str]: + def client_secret_only_on_dev(cls, v: str | None) -> str | None: if not v: return None