diff --git a/samcli/commands/_utils/experimental.py b/samcli/commands/_utils/experimental.py index 41e0f046fb..bb75dbd58e 100644 --- a/samcli/commands/_utils/experimental.py +++ b/samcli/commands/_utils/experimental.py @@ -55,6 +55,9 @@ class ExperimentalFlag: ) } RustCargoLambda = ExperimentalEntry("experimentalCargoLambda", EXPERIMENTAL_ENV_VAR_PREFIX + "RUST_CARGO_LAMBDA") + UvPackageManager = ExperimentalEntry( + "experimentalUvPackageManager", EXPERIMENTAL_ENV_VAR_PREFIX + "UV_PACKAGE_MANAGER" + ) def is_experimental_enabled(config_entry: ExperimentalEntry) -> bool: diff --git a/samcli/commands/build/build_context.py b/samcli/commands/build/build_context.py index 4f133a7009..8ca8ebb133 100644 --- a/samcli/commands/build/build_context.py +++ b/samcli/commands/build/build_context.py @@ -281,7 +281,7 @@ def run(self) -> None: ) self._check_exclude_warning() - self._check_rust_cargo_experimental_flag() + self._check_build_method_experimental_flag() for f in self.get_resources_to_build().functions: EventTracker.track_event(EventName.BUILD_FUNCTION_RUNTIME.value, f.runtime) @@ -696,24 +696,26 @@ def _check_exclude_warning(self) -> None: if self._resource_identifier in excludes: LOG.warning(self._EXCLUDE_WARNING_MESSAGE) - def _check_rust_cargo_experimental_flag(self) -> None: + def _check_build_method_experimental_flag(self) -> None: """ Prints warning message and confirms if user wants to use beta feature """ - WARNING_MESSAGE = ( - 'Build method "rust-cargolambda" is a beta feature.\n' - "Please confirm if you would like to proceed\n" - 'You can also enable this beta feature with "sam build --beta-features".' - ) + EXPERIMENTAL_BUILD_METHODS = { + "rust-cargolambda": ExperimentalFlag.RustCargoLambda, + "python-uv": ExperimentalFlag.UvPackageManager, + } + resources_to_build = self.get_resources_to_build() - is_building_rust = False for function in resources_to_build.functions: - if function.metadata and function.metadata.get("BuildMethod", "") == "rust-cargolambda": - is_building_rust = True - break + if function.metadata and function.metadata.get("BuildMethod", "") in EXPERIMENTAL_BUILD_METHODS: + build_method = function.metadata.get("BuildMethod", "") + WARNING_MESSAGE = ( + f'Build method "{build_method}" is a beta feature.\n' + "Please confirm if you would like to proceed\n" + 'You can also enable this beta feature with "sam build --beta-features".' + ) - if is_building_rust: - prompt_experimental(ExperimentalFlag.RustCargoLambda, WARNING_MESSAGE) + prompt_experimental(EXPERIMENTAL_BUILD_METHODS[build_method], WARNING_MESSAGE) @property def build_in_source(self) -> Optional[bool]: diff --git a/samcli/lib/build/workflow_config.py b/samcli/lib/build/workflow_config.py index 32f4601754..a44cba3ef4 100644 --- a/samcli/lib/build/workflow_config.py +++ b/samcli/lib/build/workflow_config.py @@ -17,6 +17,7 @@ NODEJS_NPM_ESBUILD_CONFIG, PROVIDED_MAKE_CONFIG, PYTHON_PIP_CONFIG, + PYTHON_UV_CONFIG, RUBY_BUNDLER_CONFIG, RUST_CARGO_LAMBDA_CONFIG, ) @@ -155,6 +156,7 @@ def get_workflow_config( "dotnet7": BasicWorkflowSelector(DOTNET_CLIPACKAGE_CONFIG), "dotnet": BasicWorkflowSelector(DOTNET_CLIPACKAGE_CONFIG), "rust-cargolambda": BasicWorkflowSelector(RUST_CARGO_LAMBDA_CONFIG), + "python-uv": BasicWorkflowSelector(PYTHON_UV_CONFIG), } selectors_by_runtime = { diff --git a/samcli/lib/build/workflows.py b/samcli/lib/build/workflows.py index d97f83b99e..d92ccef007 100644 --- a/samcli/lib/build/workflows.py +++ b/samcli/lib/build/workflows.py @@ -24,6 +24,15 @@ must_mount_with_write_in_container=False, ) +PYTHON_UV_CONFIG = CONFIG( + language="python", + dependency_manager="uv", + application_framework=None, + manifest_name="pyproject.toml", + executable_search_paths=None, + must_mount_with_write_in_container=False, +) + NODEJS_NPM_CONFIG = CONFIG( language="nodejs", dependency_manager="npm", @@ -117,6 +126,7 @@ ALL_CONFIGS: List[CONFIG] = [ PYTHON_PIP_CONFIG, + PYTHON_UV_CONFIG, NODEJS_NPM_CONFIG, RUBY_BUNDLER_CONFIG, JAVA_GRADLE_CONFIG, diff --git a/schema/samcli.json b/schema/samcli.json index 84ae577f12..1da14b4df9 100644 --- a/schema/samcli.json +++ b/schema/samcli.json @@ -2202,11 +2202,12 @@ "title": "parameter_overrides", "type": [ "array", + "object", "string" ], "description": "String that contains AWS CloudFormation parameter overrides encoded as key=value pairs.", "items": { - "type": "string" + "$ref": "#/$defs/parameter_overrides_items" } }, "stack_name": { @@ -2271,18 +2272,6 @@ "description": "Available parameters for the list stack outputs command:\n* stack_name:\nName of corresponding deployed stack.\n* output:\nOutput the results from the command in a given output format (json or table).\n* profile:\nSelect a specific profile from your credential file to get AWS credentials.\n* region:\nSet the AWS Region of the service. (e.g. us-east-1)\n* beta_features:\nEnable/Disable beta features.\n* debug:\nTurn on debug logging to print debug message generated by AWS SAM CLI and display timestamps.\n* save_params:\nSave the parameters provided via the command line to the configuration file.", "type": "object", "properties": { - "parameter_overrides": { - "title": "parameter_overrides", - "type": [ - "array", - "object", - "string" - ], - "description": "String that contains AWS CloudFormation parameter overrides encoded as key=value pairs.", - "items": { - "$ref": "#/$defs/parameter_overrides_items" - } - }, "stack_name": { "title": "stack_name", "type": "string", diff --git a/tests/unit/commands/_utils/test_experimental.py b/tests/unit/commands/_utils/test_experimental.py index a73760a280..217fd47bcf 100644 --- a/tests/unit/commands/_utils/test_experimental.py +++ b/tests/unit/commands/_utils/test_experimental.py @@ -57,16 +57,16 @@ def test_set_experimental(self): self.gc_mock.return_value.set_value.assert_called_once_with(config_entry, False, is_flag=True, flush=False) def test_get_all_experimental(self): - self.assertEqual(len(get_all_experimental()), 5) + self.assertEqual(len(get_all_experimental()), 6) def test_get_all_experimental_statues(self): - self.assertEqual(len(get_all_experimental_statues()), 5) + self.assertEqual(len(get_all_experimental_statues()), 6) def test_get_all_experimental_env_vars(self): - self.assertEqual(len(get_all_experimental_env_vars()), 5) + self.assertEqual(len(get_all_experimental_env_vars()), 6) def test_get_enabled_experimental_flags(self): - self.assertEqual(len(get_enabled_experimental_flags()), 5) + self.assertEqual(len(get_enabled_experimental_flags()), 6) @patch("samcli.commands._utils.experimental.set_experimental") @patch("samcli.commands._utils.experimental.get_all_experimental") diff --git a/tests/unit/commands/buildcmd/test_build_context.py b/tests/unit/commands/buildcmd/test_build_context.py index 261d654b32..aacd787d70 100644 --- a/tests/unit/commands/buildcmd/test_build_context.py +++ b/tests/unit/commands/buildcmd/test_build_context.py @@ -1254,7 +1254,7 @@ def test_must_catch_function_not_found_exception( @patch("samcli.commands.build.build_context.BuildContext._is_sam_template") @patch("samcli.commands.build.build_context.BuildContext.get_resources_to_build") @patch("samcli.commands.build.build_context.BuildContext._check_exclude_warning") - @patch("samcli.commands.build.build_context.BuildContext._check_rust_cargo_experimental_flag") + @patch("samcli.commands.build.build_context.BuildContext._check_build_method_experimental_flag") @patch("samcli.lib.build.app_builder.ApplicationBuilder.build") @patch("samcli.lib.telemetry.event.EventTracker.track_event") def test_build_in_source_event_sent(