diff --git a/moto/cognitoidp/models.py b/moto/cognitoidp/models.py index 5cf3ffb2f..c3797d72c 100644 --- a/moto/cognitoidp/models.py +++ b/moto/cognitoidp/models.py @@ -695,7 +695,7 @@ class CognitoIdpUser(BaseModel): for w in wrong_attrs ] ) - + "\\n" + + "\n" ) self.attribute_lookup = flat_attributes self.attributes = expand_attrs(flat_attributes) diff --git a/moto/config/models.py b/moto/config/models.py index 82ca28101..9b9380071 100644 --- a/moto/config/models.py +++ b/moto/config/models.py @@ -794,7 +794,7 @@ class ConfigRule(ConfigEmptyDictable): if not set(param_names).issubset(allowed_names): raise InvalidParameterValueException( "Unknown parameters provided in the inputParameters: " - + self.input_parameters.replace('"', '\\"') + + self.input_parameters ) # Verify all the required parameters are specified. diff --git a/moto/core/exceptions.py b/moto/core/exceptions.py index d7b593283..adcded4f0 100644 --- a/moto/core/exceptions.py +++ b/moto/core/exceptions.py @@ -37,12 +37,6 @@ ERROR_RESPONSE = """ """ -ERROR_JSON_RESPONSE = """{ - "message": "{{message}}", - "__type": "{{error_type}}" -} -""" - class RESTError(HTTPException): code = 400 @@ -53,22 +47,22 @@ class RESTError(HTTPException): "single_error": SINGLE_ERROR_RESPONSE, "wrapped_single_error": WRAPPED_SINGLE_ERROR_RESPONSE, "error": ERROR_RESPONSE, - "error_json": ERROR_JSON_RESPONSE, } def __init__(self, error_type, message, template="error", **kwargs): super(RESTError, self).__init__() - env = Environment(loader=DictLoader(self.templates)) self.error_type = error_type self.message = message - self.description = env.get_template(template).render( - error_type=error_type, - message=message, - request_id_tag=self.request_id_tag_name, - **kwargs - ) - self.content_type = "application/xml" + if template in self.templates.keys(): + env = Environment(loader=DictLoader(self.templates)) + self.description = env.get_template(template).render( + error_type=error_type, + message=message, + request_id_tag=self.request_id_tag_name, + **kwargs + ) + self.content_type = "application/xml" def get_headers(self, *args, **kwargs): return [ @@ -87,6 +81,9 @@ class DryRunClientError(RESTError): class JsonRESTError(RESTError): def __init__(self, error_type, message, template="error_json", **kwargs): super(JsonRESTError, self).__init__(error_type, message, template, **kwargs) + self.description = json.dumps( + {"__type": self.error_type, "message": self.message} + ) self.content_type = "application/json" def get_body(self, *args, **kwargs): diff --git a/moto/ds/validations.py b/moto/ds/validations.py index cd530b18e..326258a2d 100644 --- a/moto/ds/validations.py +++ b/moto/ds/validations.py @@ -31,8 +31,7 @@ def validate_alias(value): alias_pattern = r"^(?!D-|d-)([\da-zA-Z]+)([-]*[\da-zA-Z])*$" if not re.match(alias_pattern, value): - json_pattern = alias_pattern.replace("\\", r"\\") - return fr"satisfy regular expression pattern: {json_pattern}" + return fr"satisfy regular expression pattern: {alias_pattern}" return "" @@ -59,8 +58,7 @@ def validate_dns_ips(value): ) for dnsip in value: if not re.match(dnsip_pattern, dnsip): - json_pattern = dnsip_pattern.replace("\\", r"\\") - return fr"satisfy regular expression pattern: {json_pattern}" + return fr"satisfy regular expression pattern: {dnsip_pattern}" return "" @@ -73,7 +71,7 @@ def validate_edition(value): def validate_name(value): """Raise exception if name fails to match constraints.""" - name_pattern = r"^([a-zA-Z0-9]+[\\.-])+([a-zA-Z0-9])+$" + name_pattern = r"^([a-zA-Z0-9]+[\.-])+([a-zA-Z0-9])+$" if not re.match(name_pattern, value): return fr"satisfy regular expression pattern: {name_pattern}" return "" @@ -88,9 +86,7 @@ def validate_password(value): r"(?=.*\d)(?=.*[A-Z])(?=.*[^A-Za-z0-9\s]))^.*$" ) if not re.match(passwd_pattern, value): - # Can't have an odd number of backslashes in a literal. - json_pattern = passwd_pattern.replace("\\", r"\\") - return fr"satisfy regular expression pattern: {json_pattern}" + return fr"satisfy regular expression pattern: {passwd_pattern}" return "" @@ -98,8 +94,7 @@ def validate_short_name(value): """Raise exception if short name fails to match constraints.""" short_name_pattern = r'^[^\/:*?"<>|.]+[^\/:*?"<>|]*$' if value and not re.match(short_name_pattern, value): - json_pattern = short_name_pattern.replace("\\", r"\\").replace('"', r"\"") - return fr"satisfy regular expression pattern: {json_pattern}" + return fr"satisfy regular expression pattern: {short_name_pattern}" return "" diff --git a/moto/emr/exceptions.py b/moto/emr/exceptions.py index f8af97e81..2dc02ee2c 100644 --- a/moto/emr/exceptions.py +++ b/moto/emr/exceptions.py @@ -1,8 +1,4 @@ -from moto.core.exceptions import RESTError, JsonRESTError - - -class EmrError(RESTError): - code = 400 +from moto.core.exceptions import JsonRESTError class InvalidRequestException(JsonRESTError): @@ -17,3 +13,10 @@ class ValidationException(JsonRESTError): super(ValidationException, self).__init__( "ValidationException", message, **kwargs ) + + +class ResourceNotFoundException(JsonRESTError): + def __init__(self, message, **kwargs): + super(ResourceNotFoundException, self).__init__( + "ResourceNotFoundException", message, **kwargs + ) diff --git a/moto/emr/models.py b/moto/emr/models.py index 1167dd24f..b95d578d9 100644 --- a/moto/emr/models.py +++ b/moto/emr/models.py @@ -7,7 +7,11 @@ import pytz from boto3 import Session from dateutil.parser import parse as dtparse from moto.core import ACCOUNT_ID, BaseBackend, BaseModel -from moto.emr.exceptions import EmrError, InvalidRequestException, ValidationException +from moto.emr.exceptions import ( + InvalidRequestException, + ValidationException, + ResourceNotFoundException, +) from .utils import ( random_instance_group_id, random_cluster_id, @@ -482,7 +486,7 @@ class ElasticMapReduceBackend(BaseBackend): def describe_cluster(self, cluster_id): if cluster_id in self.clusters: return self.clusters[cluster_id] - raise EmrError("ResourceNotFoundException", "", "error_json") + raise ResourceNotFoundException("") def get_instance_groups(self, instance_group_ids): return [ diff --git a/moto/emr/responses.py b/moto/emr/responses.py index e1421b1a5..7e8946bfd 100644 --- a/moto/emr/responses.py +++ b/moto/emr/responses.py @@ -10,7 +10,7 @@ from moto.core.responses import AWSServiceSpec from moto.core.responses import BaseResponse from moto.core.responses import xml_to_json_response from moto.core.utils import tags_from_query_string -from .exceptions import EmrError +from .exceptions import ValidationException from .models import emr_backends from .utils import steps_from_query_string, Unflattener, ReleaseLabel @@ -319,11 +319,7 @@ class ElasticMapReduceResponse(BaseResponse): "Only one AMI version and release label may be specified. " "Provided AMI: {0}, release label: {1}." ).format(ami_version, release_label) - raise EmrError( - error_type="ValidationException", - message=message, - template="error_json", - ) + raise ValidationException(message=message) else: if ami_version: kwargs["requested_ami_version"] = ami_version @@ -338,18 +334,10 @@ class ElasticMapReduceResponse(BaseResponse): ReleaseLabel(release_label) < ReleaseLabel("emr-5.7.0") ): message = "Custom AMI is not allowed" - raise EmrError( - error_type="ValidationException", - message=message, - template="error_json", - ) + raise ValidationException(message=message) elif ami_version: message = "Custom AMI is not supported in this version of EMR" - raise EmrError( - error_type="ValidationException", - message=message, - template="error_json", - ) + raise ValidationException(message=message) step_concurrency_level = self._get_param("StepConcurrencyLevel") if step_concurrency_level: diff --git a/moto/managedblockchain/exceptions.py b/moto/managedblockchain/exceptions.py index 96e15f0d7..d0f547016 100644 --- a/moto/managedblockchain/exceptions.py +++ b/moto/managedblockchain/exceptions.py @@ -1,12 +1,6 @@ +import json from functools import wraps from werkzeug.exceptions import HTTPException -from jinja2 import DictLoader, Environment - - -ERROR_JSON_RESPONSE = """{ - "message": "{{message}}" -} -""" def exception_handler(f): @@ -23,18 +17,11 @@ def exception_handler(f): class ManagedBlockchainClientError(HTTPException): code = 400 - templates = { - "error": ERROR_JSON_RESPONSE, - } - def __init__(self, error_type, message, **kwargs): super(HTTPException, self).__init__() - env = Environment(loader=DictLoader(self.templates)) self.error_type = error_type self.message = message - self.description = env.get_template("error").render( - error_type=error_type, message=message, **kwargs - ) + self.description = json.dumps({"message": self.message}) def get_headers(self, *args, **kwargs): return [ diff --git a/tests/test_cognitoidp/test_cognitoidp.py b/tests/test_cognitoidp/test_cognitoidp.py index 3c8e3d153..af34c63d8 100644 --- a/tests/test_cognitoidp/test_cognitoidp.py +++ b/tests/test_cognitoidp/test_cognitoidp.py @@ -2987,6 +2987,18 @@ def test_admin_delete_user_attributes_non_existing_attribute(): "Invalid user attributes: user.custom:foo: Attribute does not exist in the schema.\n" ) + with pytest.raises(ClientError) as exc: + conn.admin_delete_user_attributes( + UserPoolId=user_pool_id, + Username=username, + UserAttributeNames=["nickname", "custom:foo", "custom:bar"], + ) + err = exc.value.response["Error"] + err["Code"].should.equal("InvalidParameterException") + err["Message"].should.equal( + "Invalid user attributes: user.custom:foo: Attribute does not exist in the schema.\nuser.custom:bar: Attribute does not exist in the schema.\n" + ) + @mock_cognitoidp def test_admin_delete_user_attributes_non_existing_user(): diff --git a/tests/test_emr/test_emr_boto3.py b/tests/test_emr/test_emr_boto3.py index b4d5bcd77..166576c04 100644 --- a/tests/test_emr/test_emr_boto3.py +++ b/tests/test_emr/test_emr_boto3.py @@ -188,13 +188,10 @@ def test_describe_cluster(): @mock_emr def test_describe_cluster_not_found(): conn = boto3.client("emr", region_name="us-east-1") - raised = False - try: + with pytest.raises(ClientError) as e: conn.describe_cluster(ClusterId="DummyId") - except ClientError as e: - if e.response["Error"]["Code"] == "ResourceNotFoundException": - raised = True - raised.should.equal(True) + + assert e.value.response["Error"]["Code"] == "ResourceNotFoundException" @mock_emr