diff --git a/requirements/base.txt b/requirements/base.txt index 8a2c639cc..223fd1fdf 100755 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -1,5 +1,5 @@ boto3>=1.34.0,<2.0.0 -jsonschema<5,>=3.2 # TODO: evaluate risk of removing jsonschema 3.x support +jsonschema<5,>=4.23 typing_extensions>=4.4 # 3.8 doesn't have Required, TypeGuard and ParamSpec # resource validation & schema generation diff --git a/requirements/dev.txt b/requirements/dev.txt index 911e125a7..99b4aa82a 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -29,6 +29,3 @@ mypy~=1.3.0 boto3-stubs[appconfig,serverlessrepo]>=1.34.0,<2.0.0 types-PyYAML~=6.0 types-jsonschema~=3.2 - -# CloudFormation CLI tools -cloudformation-cli>=0.2.39,<0.3.0 diff --git a/samtranslator/model/sam_resources.py b/samtranslator/model/sam_resources.py index 68391316d..3ab6ff6ec 100644 --- a/samtranslator/model/sam_resources.py +++ b/samtranslator/model/sam_resources.py @@ -2,7 +2,9 @@ import copy import re +import sys from contextlib import suppress +from types import ModuleType from typing import Any, Callable, Dict, List, Literal, Optional, Tuple, Union, cast import samtranslator.model.eventsources @@ -34,11 +36,19 @@ SyncConfigType, UserPoolConfigType, ) -from samtranslator.internal.schema_source import ( - aws_serverless_capacity_provider, - aws_serverless_function, - aws_serverless_graphqlapi, -) + +# Pydantic 1 doesn't support Python 3.14 so these imports will fail until we migrate to v2 +try: + from samtranslator.internal.schema_source import ( + aws_serverless_capacity_provider, + aws_serverless_function, + aws_serverless_graphqlapi, + ) +except RuntimeError: # Pydantic fails when initializing the model classes with a RuntimeError in 3.14 + aws_serverless_capacity_provider = cast(ModuleType, None) + aws_serverless_function = cast(ModuleType, None) + aws_serverless_graphqlapi = cast(ModuleType, None) + from samtranslator.internal.schema_source.common import PermissionsType, SamIntrinsicable from samtranslator.internal.types import GetManagedPolicyMap from samtranslator.internal.utils.utils import passthrough_value, remove_none_values @@ -143,6 +153,14 @@ _CONDITION_CHAR_LIMIT = 255 +# Utility function to throw an error when using functionality that doesn't work in Python 3.14 (need migration to Pydantic v2) +def check_python_314_compatibility(module: Optional[ModuleType], functionality: str) -> None: + if sys.version_info >= (3, 14) and module is None: + raise RuntimeError( + f"{functionality} functionalities are temporarily not supported when running SAM in Python 3.14" + ) + + class SamFunction(SamResourceMacro): """SAM function macro.""" @@ -731,6 +749,7 @@ def _transform_capacity_provider_config(self) -> Dict[str, Any]: # Validate CapacityProviderConfig using Pydantic model directly for comprehensive error collection try: + check_python_314_compatibility(aws_serverless_function, "Capacity Provider") validated_model = aws_serverless_function.CapacityProviderConfig.parse_obj(self.CapacityProviderConfig) except Exception as e: raise InvalidResourceException(self.logical_id, f"Invalid CapacityProviderConfig: {e!s}") from e @@ -1459,7 +1478,6 @@ class SamCapacityProvider(SamResourceMacro): """ resource_type = "AWS::Serverless::CapacityProvider" - resource_property_schema = aws_serverless_capacity_provider.Properties property_types = { "CapacityProviderName": Property(False, one_of(IS_STR, IS_DICT)), "VpcConfig": Property(True, IS_DICT), @@ -1492,7 +1510,11 @@ def to_cloudformation(self, **kwargs: Any) -> List[Resource]: """ Transform the SAM CapacityProvider resource to CloudFormation """ - self.validate_before_transform(schema_class=self.resource_property_schema, collect_all_errors=True) + check_python_314_compatibility(aws_serverless_capacity_provider, "Capacity Provider") + self.validate_before_transform( + schema_class=aws_serverless_capacity_provider.Properties, + collect_all_errors=True, + ) # Use enhanced validation method with comprehensive error collection model = self.validate_properties_and_return_model( @@ -2600,6 +2622,7 @@ def __init__( @cw_timer def to_cloudformation(self, **kwargs: Any) -> List[Resource]: + check_python_314_compatibility(aws_serverless_graphqlapi, "GraphQLApi") model = self.validate_properties_and_return_model(aws_serverless_graphqlapi.Properties) appsync_api, cloudwatch_role, auth_connectors = self._construct_appsync_api_resources(model)