diff --git a/moto/databrew/responses.py b/moto/databrew/responses.py index b06f5a0e8..826340830 100644 --- a/moto/databrew/responses.py +++ b/moto/databrew/responses.py @@ -1,5 +1,6 @@ import json from typing import Any, Dict, Union +from urllib.parse import unquote from moto.core.common_types import TYPE_RESPONSE from moto.core.responses import BaseResponse @@ -39,7 +40,7 @@ class DataBrewResponse(BaseResponse): self.setup_class(request, full_url, headers) # https://docs.aws.amazon.com/databrew/latest/dg/API_DeleteRecipeVersion.html if request.method == "DELETE": - split_path = self.parsed_url.path.strip("/").split("/") + split_path = self._get_path().strip("/").split("/") recipe_name = split_path[1] recipe_version = split_path[3] self.databrew_backend.delete_recipe_version(recipe_name, recipe_version) @@ -49,6 +50,9 @@ class DataBrewResponse(BaseResponse): json.dumps({"Name": recipe_name, "RecipeVersion": recipe_version}), ) + def _get_path(self) -> str: + return unquote(self.parsed_url.path) + @amzn_request_id def list_recipes(self) -> str: # https://docs.aws.amazon.com/databrew/latest/dg/API_ListRecipes.html @@ -98,7 +102,7 @@ class DataBrewResponse(BaseResponse): def publish_recipe(self, request: Any, full_url: str, headers: Any) -> TYPE_RESPONSE: # type: ignore[return] self.setup_class(request, full_url, headers) if request.method == "POST": - recipe_name = self.parsed_url.path.strip("/").split("/", 2)[1] + recipe_name = self._get_path().strip("/").split("/", 2)[1] recipe_description = self.parameters.get("Description") self.databrew_backend.publish_recipe(recipe_name, recipe_description) return 200, {}, json.dumps({"Name": recipe_name}) @@ -126,7 +130,7 @@ class DataBrewResponse(BaseResponse): def recipe_response(self, request: Any, full_url: str, headers: Any) -> TYPE_RESPONSE: # type: ignore[return] self.setup_class(request, full_url, headers) - recipe_name = self.parsed_url.path.rstrip("/").rsplit("/", 1)[1] + recipe_name = self._get_path().rstrip("/").rsplit("/", 1)[1] if request.method == "PUT": return self.put_recipe_response(recipe_name) @@ -177,7 +181,7 @@ class DataBrewResponse(BaseResponse): def ruleset_response(self, request: Any, full_url: str, headers: Any) -> TYPE_RESPONSE: # type: ignore[return] self.setup_class(request, full_url, headers) - ruleset_name = self.parsed_url.path.split("/")[-1] + ruleset_name = self._get_path().split("/")[-1] if request.method == "PUT": response = self.put_ruleset_response(ruleset_name) @@ -281,7 +285,7 @@ class DataBrewResponse(BaseResponse): def dataset_response(self, request: Any, full_url: str, headers: Any) -> Union[str, TYPE_RESPONSE]: # type: ignore[return] self.setup_class(request, full_url, headers) - dataset_name = self.parsed_url.path.split("/")[-1] + dataset_name = self._get_path().split("/")[-1] if request.method == "POST": return self.create_dataset() @@ -334,7 +338,7 @@ class DataBrewResponse(BaseResponse): def job_response(self, request: Any, full_url: str, headers: Any) -> TYPE_RESPONSE: # type: ignore[return] self.setup_class(request, full_url, headers) - job_name = self.parsed_url.path.rstrip("/").rsplit("/", 1)[1] + job_name = self._get_path().rstrip("/").rsplit("/", 1)[1] if request.method == "GET": return self.get_job_response(job_name) @@ -424,7 +428,7 @@ class DataBrewResponse(BaseResponse): def profile_job_response(self, request: Any, full_url: str, headers: Any) -> str: # type: ignore[return] self.setup_class(request, full_url, headers) - job_name = self.parsed_url.path.rstrip("/").rsplit("/", 1)[1] + job_name = self._get_path().rstrip("/").rsplit("/", 1)[1] if request.method == "PUT": return self.update_profile_job_response(job_name) @@ -433,7 +437,7 @@ class DataBrewResponse(BaseResponse): def recipe_job_response(self, request: Any, full_url: str, headers: Any) -> str: # type: ignore[return] self.setup_class(request, full_url, headers) - job_name = self.parsed_url.path.rstrip("/").rsplit("/", 1)[1] + job_name = self._get_path().rstrip("/").rsplit("/", 1)[1] if request.method == "PUT": return self.update_recipe_job_response(job_name) diff --git a/tests/test_databrew/test_databrew_datasets.py b/tests/test_databrew/test_databrew_datasets.py index 2c501f470..daf959043 100644 --- a/tests/test_databrew/test_databrew_datasets.py +++ b/tests/test_databrew/test_databrew_datasets.py @@ -177,20 +177,22 @@ def test_create_dataset_that_already_exists(): @mock_databrew -def test_delete_dataset(): +@pytest.mark.parametrize("name", ["name", "name with space"]) +def test_delete_dataset(name): client = _create_databrew_client() - response = _create_test_dataset(client) + response = _create_test_dataset(client, dataset_name=name) + assert response["Name"] == name # Check dataset exists - dataset = client.describe_dataset(Name=response["Name"]) - assert dataset["Name"] == response["Name"] + dataset = client.describe_dataset(Name=name) + assert dataset["Name"] == name # Delete the dataset - client.delete_dataset(Name=response["Name"]) + client.delete_dataset(Name=name) # Check it does not exist anymore with pytest.raises(ClientError) as exc: - client.describe_dataset(Name=response["Name"]) + client.describe_dataset(Name=name) err = exc.value.response["Error"] assert err["Code"] == "ResourceNotFoundException" @@ -198,20 +200,21 @@ def test_delete_dataset(): # Check that a dataset that does not exist errors with pytest.raises(ClientError) as exc: - client.delete_dataset(Name=response["Name"]) + client.delete_dataset(Name=name) err = exc.value.response["Error"] assert err["Code"] == "ResourceNotFoundException" assert err["Message"] == "One or more resources can't be found." @mock_databrew -def test_update_dataset(): +@pytest.mark.parametrize("name", ["name", "name with space"]) +def test_update_dataset(name): client = _create_databrew_client() - response = _create_test_dataset(client) + _create_test_dataset(client, dataset_name=name) # Update the dataset and check response dataset = client.update_dataset( - Name=response["Name"], + Name=name, Format="TEST", Input={ "S3InputDefinition": { @@ -232,15 +235,15 @@ def test_update_dataset(): }, }, ) - assert dataset["Name"] == response["Name"] + assert dataset["Name"] == name # Describe the dataset and check the changes - dataset = client.describe_dataset(Name=response["Name"]) - assert dataset["Name"] == response["Name"] + dataset = client.describe_dataset(Name=name) + assert dataset["Name"] == name assert dataset["Format"] == "TEST" assert ( dataset["ResourceArn"] - == f"arn:aws:databrew:us-west-1:{ACCOUNT_ID}:dataset/{response['Name']}" + == f"arn:aws:databrew:us-west-1:{ACCOUNT_ID}:dataset/{name}" ) diff --git a/tests/test_databrew/test_databrew_jobs.py b/tests/test_databrew/test_databrew_jobs.py index e28744e97..d9241f494 100644 --- a/tests/test_databrew/test_databrew_jobs.py +++ b/tests/test_databrew/test_databrew_jobs.py @@ -184,12 +184,12 @@ def test_describe_job_with_long_name(): @mock_databrew -def test_update_profile_job(): +@pytest.mark.parametrize("job_name", ["name", "name with space"]) +def test_update_profile_job(job_name): client = _create_databrew_client() # Create the job - response = _create_test_profile_job(client) - job_name = response["Name"] + response = _create_test_profile_job(client, job_name=job_name) # Update the job by changing RoleArn update_response = client.update_profile_job( @@ -205,12 +205,12 @@ def test_update_profile_job(): @mock_databrew -def test_update_recipe_job(): +@pytest.mark.parametrize("job_name", ["name", "name with space"]) +def test_update_recipe_job(job_name): client = _create_databrew_client() # Create the job - response = _create_test_recipe_job(client) - job_name = response["Name"] + response = _create_test_recipe_job(client, job_name=job_name) # Update the job by changing RoleArn update_response = client.update_recipe_job(Name=job_name, RoleArn="a" * 20) @@ -250,12 +250,12 @@ def test_update_recipe_job_does_not_exist(): @mock_databrew -def test_delete_job(): +@pytest.mark.parametrize("job_name", ["name", "name with space"]) +def test_delete_job(job_name): client = _create_databrew_client() # Create the job - response = _create_test_recipe_job(client) - job_name = response["Name"] + _create_test_recipe_job(client, job_name=job_name) # Delete the job response = client.delete_job(Name=job_name) diff --git a/tests/test_databrew/test_databrew_recipes.py b/tests/test_databrew/test_databrew_recipes.py index 8f9233635..97d1e384c 100644 --- a/tests/test_databrew/test_databrew_recipes.py +++ b/tests/test_databrew/test_databrew_recipes.py @@ -162,13 +162,14 @@ def test_describe_recipe_latest_working(): @mock_databrew -def test_describe_recipe_with_version(): +@pytest.mark.parametrize("name", ["name", "name with space"]) +def test_describe_recipe_with_version(name): client = _create_databrew_client() - response = _create_test_recipe(client) + _create_test_recipe(client, recipe_name=name) - recipe = client.describe_recipe(Name=response["Name"], RecipeVersion="0.1") + recipe = client.describe_recipe(Name=name, RecipeVersion="0.1") - assert recipe["Name"] == response["Name"] + assert recipe["Name"] == name assert len(recipe["Steps"]) == 1 assert recipe["RecipeVersion"] == "0.1" @@ -260,12 +261,13 @@ def test_describe_recipe_with_invalid_version(): @mock_databrew -def test_update_recipe(): +@pytest.mark.parametrize("name", ["name", "name with space"]) +def test_update_recipe(name): client = _create_databrew_client() - response = _create_test_recipe(client) + _create_test_recipe(client, recipe_name=name) recipe = client.update_recipe( - Name=response["Name"], + Name=name, Steps=[ { "Action": { @@ -290,13 +292,11 @@ def test_update_recipe(): ], ) - assert recipe["Name"] == response["Name"] + assert recipe["Name"] == name # Describe the recipe and check the changes - recipe = client.describe_recipe( - Name=response["Name"], RecipeVersion="LATEST_WORKING" - ) - assert recipe["Name"] == response["Name"] + recipe = client.describe_recipe(Name=name, RecipeVersion="LATEST_WORKING") + assert recipe["Name"] == name assert len(recipe["Steps"]) == 1 assert recipe["Steps"][0]["Action"]["Parameters"]["removeCustomValue"] == "true" @@ -349,11 +349,11 @@ def test_create_recipe_that_already_exists(): @mock_databrew -def test_publish_recipe(): +@pytest.mark.parametrize("recipe_name", ["name", "name with space"]) +def test_publish_recipe(recipe_name): client = _create_databrew_client() - response = _create_test_recipe(client) - recipe_name = response["Name"] + _create_test_recipe(client, recipe_name=recipe_name) # Before a recipe is published, we should not be able to retrieve a published version with pytest.raises(ClientError) as exc: @@ -412,10 +412,11 @@ def test_publish_long_recipe_name(): @mock_databrew -def test_delete_recipe_version(): +@pytest.mark.parametrize("recipe_name", ["name", "name with space"]) +def test_delete_recipe_version(recipe_name): client = _create_databrew_client() - response = _create_test_recipe(client) - recipe_name = response["Name"] + _create_test_recipe(client, recipe_name=recipe_name) + client.delete_recipe_version(Name=recipe_name, RecipeVersion="LATEST_WORKING") with pytest.raises(ClientError) as exc: client.describe_recipe(Name=recipe_name) diff --git a/tests/test_databrew/test_databrew_rulesets.py b/tests/test_databrew/test_databrew_rulesets.py index 70ba06a36..6c0dea100 100644 --- a/tests/test_databrew/test_databrew_rulesets.py +++ b/tests/test_databrew/test_databrew_rulesets.py @@ -144,13 +144,14 @@ def test_delete_ruleset(): @mock_databrew -def test_update_ruleset(): +@pytest.mark.parametrize("name", ["name", "name with space"]) +def test_update_ruleset(name): client = _create_databrew_client() - response = _create_test_ruleset(client) + _create_test_ruleset(client, ruleset_name=name) # Update the ruleset and check response ruleset = client.update_ruleset( - Name=response["Name"], + Name=name, Rules=[ { "Name": "Assert values > 0", @@ -165,10 +166,10 @@ def test_update_ruleset(): } ], ) - assert ruleset["Name"] == response["Name"] + assert ruleset["Name"] == name # Describe the ruleset and check the changes - ruleset = client.describe_ruleset(Name=response["Name"]) - assert ruleset["Name"] == response["Name"] + ruleset = client.describe_ruleset(Name=name) + assert ruleset["Name"] == name assert len(ruleset["Rules"]) == 1 assert ruleset["Rules"][0]["SubstitutionMap"][":val1"] == "10"