Techdebt: Replace string-format with f-strings (for s* dirs) (#5692)

This commit is contained in:
Bert Blommers 2022-11-21 18:21:34 -01:00 committed by GitHub
parent 2093a99485
commit ba4104c38e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
33 changed files with 244 additions and 421 deletions

View File

@ -177,9 +177,7 @@ class InvalidRequest(S3ClientError):
def __init__(self, method, *args, **kwargs):
super().__init__(
"InvalidRequest",
"Found unsupported HTTP method in CORS config. Unsupported method is {}".format(
method
),
f"Found unsupported HTTP method in CORS config. Unsupported method is {method}",
*args,
**kwargs,
)
@ -241,9 +239,7 @@ class InvalidMaxPartArgument(S3ClientError):
code = 400
def __init__(self, arg, min_val, max_val):
error = "Argument {} must be an integer between {} and {}".format(
arg, min_val, max_val
)
error = f"Argument {arg} must be an integer between {min_val} and {max_val}"
super().__init__("InvalidArgument", error)

View File

@ -170,9 +170,7 @@ class FakeKey(BaseModel, ManagedState):
@property
def arn(self):
# S3 Objects don't have an ARN, but we do need something unique when creating tags against this resource
return "arn:aws:s3:::{}/{}/{}".format(
self.bucket_name, self.name, self.version_id
)
return f"arn:aws:s3:::{self.bucket_name}/{self.name}/{self.version_id}"
@value.setter
def value(self, new_value):
@ -217,7 +215,7 @@ class FakeKey(BaseModel, ManagedState):
value_md5.update(block)
self._etag = value_md5.hexdigest()
return '"{0}"'.format(self._etag)
return f'"{self._etag}"'
@property
def last_modified_ISO8601(self):
@ -254,9 +252,7 @@ class FakeKey(BaseModel, ManagedState):
if self.status == "IN_PROGRESS":
header = 'ongoing-request="true"'
else:
header = 'ongoing-request="false", expiry-date="{0}"'.format(
self.expiry_date
)
header = f'ongoing-request="false", expiry-date="{self.expiry_date}"'
res["x-amz-restore"] = header
if self._is_versioned:
@ -413,7 +409,7 @@ class FakeMultipart(BaseModel):
etag = md5_hash()
etag.update(bytes(md5s))
return total, "{0}-{1}".format(etag.hexdigest(), count)
return total, f"{etag.hexdigest()}-{count}"
def set_part(self, part_id, value):
if part_id < 1:
@ -460,9 +456,7 @@ class FakeGrantee(BaseModel):
return "Group" if self.uri else "CanonicalUser"
def __repr__(self):
return "FakeGrantee(display_name: '{}', id: '{}', uri: '{}')".format(
self.display_name, self.id, self.uri
)
return f"FakeGrantee(display_name: '{self.display_name}', id: '{self.id}', uri: '{self.uri}')"
ALL_USERS_GRANTEE = FakeGrantee(uri="http://acs.amazonaws.com/groups/global/AllUsers")
@ -492,9 +486,7 @@ class FakeGrant(BaseModel):
self.permissions = permissions
def __repr__(self):
return "FakeGrant(grantees: {}, permissions: {})".format(
self.grantees, self.permissions
)
return f"FakeGrant(grantees: {self.grantees}, permissions: {self.permissions})"
class FakeAcl(BaseModel):
@ -513,7 +505,7 @@ class FakeAcl(BaseModel):
return False
def __repr__(self):
return "FakeAcl(grants: {})".format(self.grants)
return f"FakeAcl(grants: {self.grants})"
def to_config_dict(self):
"""Returns the object into the format expected by AWS Config"""
@ -584,7 +576,7 @@ def get_canned_acl(acl):
FakeGrant([LOG_DELIVERY_GRANTEE], [PERMISSION_READ_ACP, PERMISSION_WRITE])
)
else:
assert False, "Unknown canned acl: %s" % (acl,)
assert False, f"Unknown canned acl: {acl}"
return FakeAcl(grants=grants)
@ -1238,25 +1230,23 @@ class FakeBucket(CloudFormationModel):
@property
def arn(self):
return "arn:aws:s3:::{}".format(self.name)
return f"arn:aws:s3:::{self.name}"
@property
def domain_name(self):
return "{}.s3.amazonaws.com".format(self.name)
return f"{self.name}.s3.amazonaws.com"
@property
def dual_stack_domain_name(self):
return "{}.s3.dualstack.{}.amazonaws.com".format(self.name, self.region_name)
return f"{self.name}.s3.dualstack.{self.region_name}.amazonaws.com"
@property
def regional_domain_name(self):
return "{}.s3.{}.amazonaws.com".format(self.name, self.region_name)
return f"{self.name}.s3.{self.region_name}.amazonaws.com"
@property
def website_url(self):
return "http://{}.s3-website.{}.amazonaws.com".format(
self.name, self.region_name
)
return f"http://{self.name}.s3-website.{self.region_name}.amazonaws.com"
@property
def physical_resource_id(self):
@ -2066,7 +2056,7 @@ class S3Backend(BaseBackend, CloudWatchMetricProvider):
# If delimiter, we need to split out folder_results
key_without_delimiter = key_without_prefix.split(delimiter)[0]
folder_results.add(
"{0}{1}{2}".format(prefix, key_without_delimiter, delimiter)
f"{prefix}{key_without_delimiter}{delimiter}"
)
else:
key_results.add(key)

View File

@ -293,9 +293,7 @@ class S3Response(BaseResponse):
return self._response_options(bucket_name)
else:
raise NotImplementedError(
"Method {0} has not been implemented in the S3 backend yet".format(
method
)
f"Method {method} has not been implemented in the S3 backend yet"
)
@staticmethod
@ -404,9 +402,7 @@ class S3Response(BaseResponse):
for unsup in ("delimiter", "max-uploads"):
if unsup in querystring:
raise NotImplementedError(
"Listing multipart uploads with {} has not been implemented yet.".format(
unsup
)
f"Listing multipart uploads with {unsup} has not been implemented yet."
)
multiparts = list(self.backend.get_all_multiparts(bucket_name).values())
if "prefix" in querystring:
@ -1068,9 +1064,7 @@ class S3Response(BaseResponse):
raise InvalidRange(
actual_size=str(length), range_requested=request.headers.get("range")
)
response_headers["content-range"] = "bytes {0}-{1}/{2}".format(
begin, end, length
)
response_headers["content-range"] = f"bytes {begin}-{end}/{length}"
content = response_content[begin : end + 1]
response_headers["content-length"] = len(content)
return 206, response_headers, content
@ -1211,9 +1205,7 @@ class S3Response(BaseResponse):
return self._response_options(bucket_name)
else:
raise NotImplementedError(
"Method {0} has not been implemented in the S3 backend yet".format(
method
)
f"Method {method} has not been implemented in the S3 backend yet"
)
def _key_response_get(self, bucket_name, query, key_name, headers):
@ -1287,7 +1279,7 @@ class S3Response(BaseResponse):
if_unmodified_since = str_to_rfc_1123_datetime(if_unmodified_since)
if key.last_modified.replace(microsecond=0) > if_unmodified_since:
raise PreconditionFailed("If-Unmodified-Since")
if if_match and key.etag not in [if_match, '"{0}"'.format(if_match)]:
if if_match and key.etag not in [if_match, f'"{if_match}"']:
raise PreconditionFailed("If-Match")
if if_modified_since:
@ -1882,17 +1874,17 @@ class S3Response(BaseResponse):
# 1st verify that the proper notification configuration has been passed in (with an ARN that is close
# to being correct -- nothing too complex in the ARN logic):
the_notification = parsed_xml["NotificationConfiguration"].get(
"{}Configuration".format(name)
f"{name}Configuration"
)
if the_notification:
found_notifications += 1
if not isinstance(the_notification, list):
the_notification = parsed_xml["NotificationConfiguration"][
"{}Configuration".format(name)
f"{name}Configuration"
] = [the_notification]
for n in the_notification:
if not n[name].startswith("arn:aws:{}:".format(arn_string)):
if not n[name].startswith(f"arn:aws:{arn_string}:"):
raise InvalidNotificationARN()
# 2nd, verify that the Events list is correct:
@ -1956,7 +1948,7 @@ class S3Response(BaseResponse):
response_headers = {}
if response_meta is not None:
for k in response_meta:
response_headers["x-amz-{}".format(k)] = response_meta[k]
response_headers[f"x-amz-{k}"] = response_meta[k]
return 204, response_headers, ""
def _complete_multipart_body(self, body):

View File

@ -406,9 +406,7 @@ class FakeEndpointConfig(BaseObject, CloudFormationModel):
elif "ServerlessConfig" in production_variant.keys():
self.validate_serverless_config(production_variant["ServerlessConfig"])
else:
message = "Invalid Keys for ProductionVariant: received {} but expected it to contain one of {}".format(
production_variant.keys(), ["InstanceType", "ServerlessConfig"]
)
message = f"Invalid Keys for ProductionVariant: received {production_variant.keys()} but expected it to contain one of {['InstanceType', 'ServerlessConfig']}"
raise ValidationError(message=message)
def validate_serverless_config(self, serverless_config):
@ -416,9 +414,7 @@ class FakeEndpointConfig(BaseObject, CloudFormationModel):
if not validators.is_one_of(
serverless_config["MemorySizeInMB"], VALID_SERVERLESS_MEMORY_SIZE
):
message = "Value '{}' at 'MemorySizeInMB' failed to satisfy constraint: Member must satisfy enum value set: {}".format(
serverless_config["MemorySizeInMB"], VALID_SERVERLESS_MEMORY_SIZE
)
message = f"Value '{serverless_config['MemorySizeInMB']}' at 'MemorySizeInMB' failed to satisfy constraint: Member must satisfy enum value set: {VALID_SERVERLESS_MEMORY_SIZE}"
raise ValidationError(message=message)
def validate_instance_type(self, instance_type):
@ -491,9 +487,7 @@ class FakeEndpointConfig(BaseObject, CloudFormationModel):
"ml.m4.4xlarge",
]
if not validators.is_one_of(instance_type, VALID_INSTANCE_TYPES):
message = "Value '{}' at 'instanceType' failed to satisfy constraint: Member must satisfy enum value set: {}".format(
instance_type, VALID_INSTANCE_TYPES
)
message = f"Value '{instance_type}' at 'instanceType' failed to satisfy constraint: Member must satisfy enum value set: {VALID_INSTANCE_TYPES}"
raise ValidationError(message=message)
@property
@ -824,15 +818,13 @@ class FakeSagemakerNotebookInstance(CloudFormationModel):
"ml.m4.4xlarge",
]
if not validators.is_one_of(instance_type, VALID_INSTANCE_TYPES):
message = "Value '{}' at 'instanceType' failed to satisfy constraint: Member must satisfy enum value set: {}".format(
instance_type, VALID_INSTANCE_TYPES
)
message = f"Value '{instance_type}' at 'instanceType' failed to satisfy constraint: Member must satisfy enum value set: {VALID_INSTANCE_TYPES}"
raise ValidationError(message=message)
@property
def url(self):
return "{}.notebook.{}.sagemaker.aws".format(
self.notebook_instance_name, self.region_name
return (
f"{self.notebook_instance_name}.notebook.{self.region_name}.sagemaker.aws"
)
def start(self):
@ -1325,10 +1317,10 @@ class SageMakerModelBackend(BaseBackend):
try:
del self.experiments[experiment_name]
except KeyError:
message = "Could not find experiment configuration '{}'.".format(
FakeTrial.arn_formatter(experiment_name, self.region_name)
arn = FakeTrial.arn_formatter(experiment_name, self.region_name)
raise ValidationError(
message=f"Could not find experiment configuration '{arn}'."
)
raise ValidationError(message=message)
def create_trial(self, trial_name, experiment_name):
trial = FakeTrial(
@ -1346,19 +1338,17 @@ class SageMakerModelBackend(BaseBackend):
try:
return self.trials[trial_name].response_object
except KeyError:
message = "Could not find trial '{}'.".format(
FakeTrial.arn_formatter(trial_name, self.region_name)
)
raise ValidationError(message=message)
arn = FakeTrial.arn_formatter(trial_name, self.region_name)
raise ValidationError(message=f"Could not find trial '{arn}'.")
def delete_trial(self, trial_name):
try:
del self.trials[trial_name]
except KeyError:
message = "Could not find trial configuration '{}'.".format(
FakeTrial.arn_formatter(trial_name, self.region_name)
arn = FakeTrial.arn_formatter(trial_name, self.region_name)
raise ValidationError(
message=f"Could not find trial configuration '{arn}'."
)
raise ValidationError(message=message)
@paginate(pagination_model=PAGINATION_MODEL)
def list_trials(self, experiment_name=None, trial_component_name=None):
@ -1396,21 +1386,19 @@ class SageMakerModelBackend(BaseBackend):
try:
del self.trial_components[trial_component_name]
except KeyError:
message = "Could not find trial-component configuration '{}'.".format(
FakeTrial.arn_formatter(trial_component_name, self.region_name)
arn = FakeTrial.arn_formatter(trial_component_name, self.region_name)
raise ValidationError(
message=f"Could not find trial-component configuration '{arn}'."
)
raise ValidationError(message=message)
def describe_trial_component(self, trial_component_name):
try:
return self.trial_components[trial_component_name].response_object
except KeyError:
message = "Could not find trial component '{}'.".format(
FakeTrialComponent.arn_formatter(
trial_component_name, self.account_id, self.region_name
)
arn = FakeTrialComponent.arn_formatter(
trial_component_name, self.account_id, self.region_name
)
raise ValidationError(message=message)
raise ValidationError(message=f"Could not find trial component '{arn}'.")
def _update_trial_component_details(self, trial_component_name, details_json):
self.trial_components[trial_component_name].update(details_json)
@ -1511,9 +1499,7 @@ class SageMakerModelBackend(BaseBackend):
def _validate_unique_notebook_instance_name(self, notebook_instance_name):
if notebook_instance_name in self.notebook_instances:
duplicate_arn = self.notebook_instances[notebook_instance_name].arn
message = "Cannot create a duplicate Notebook Instance ({})".format(
duplicate_arn
)
message = f"Cannot create a duplicate Notebook Instance ({duplicate_arn})"
raise ValidationError(message=message)
def get_notebook_instance(self, notebook_instance_name):
@ -1533,9 +1519,7 @@ class SageMakerModelBackend(BaseBackend):
def delete_notebook_instance(self, notebook_instance_name):
notebook_instance = self.get_notebook_instance(notebook_instance_name)
if not notebook_instance.is_deletable:
message = "Status ({}) not in ([Stopped, Failed]). Unable to transition to (Deleting) for Notebook Instance ({})".format(
notebook_instance.status, notebook_instance.arn
)
message = f"Status ({notebook_instance.status}) not in ([Stopped, Failed]). Unable to transition to (Deleting) for Notebook Instance ({notebook_instance.arn})"
raise ValidationError(message=message)
del self.notebook_instances[notebook_instance_name]
@ -1546,13 +1530,12 @@ class SageMakerModelBackend(BaseBackend):
notebook_instance_lifecycle_config_name
in self.notebook_instance_lifecycle_configurations
):
message = "Unable to create Notebook Instance Lifecycle Config {}. (Details: Notebook Instance Lifecycle Config already exists.)".format(
FakeSageMakerNotebookInstanceLifecycleConfig.arn_formatter(
notebook_instance_lifecycle_config_name,
self.account_id,
self.region_name,
)
arn = FakeSageMakerNotebookInstanceLifecycleConfig.arn_formatter(
notebook_instance_lifecycle_config_name,
self.account_id,
self.region_name,
)
message = f"Unable to create Notebook Instance Lifecycle Config {arn}. (Details: Notebook Instance Lifecycle Config already exists.)"
raise ValidationError(message=message)
lifecycle_config = FakeSageMakerNotebookInstanceLifecycleConfig(
account_id=self.account_id,
@ -1574,13 +1557,12 @@ class SageMakerModelBackend(BaseBackend):
notebook_instance_lifecycle_config_name
].response_object
except KeyError:
message = "Unable to describe Notebook Instance Lifecycle Config '{}'. (Details: Notebook Instance Lifecycle Config does not exist.)".format(
FakeSageMakerNotebookInstanceLifecycleConfig.arn_formatter(
notebook_instance_lifecycle_config_name,
self.account_id,
self.region_name,
)
arn = FakeSageMakerNotebookInstanceLifecycleConfig.arn_formatter(
notebook_instance_lifecycle_config_name,
self.account_id,
self.region_name,
)
message = f"Unable to describe Notebook Instance Lifecycle Config '{arn}'. (Details: Notebook Instance Lifecycle Config does not exist.)"
raise ValidationError(message=message)
def delete_notebook_instance_lifecycle_config(
@ -1591,13 +1573,12 @@ class SageMakerModelBackend(BaseBackend):
notebook_instance_lifecycle_config_name
]
except KeyError:
message = "Unable to delete Notebook Instance Lifecycle Config '{}'. (Details: Notebook Instance Lifecycle Config does not exist.)".format(
FakeSageMakerNotebookInstanceLifecycleConfig.arn_formatter(
notebook_instance_lifecycle_config_name,
self.account_id,
self.region_name,
)
arn = FakeSageMakerNotebookInstanceLifecycleConfig.arn_formatter(
notebook_instance_lifecycle_config_name,
self.account_id,
self.region_name,
)
message = f"Unable to delete Notebook Instance Lifecycle Config '{arn}'. (Details: Notebook Instance Lifecycle Config does not exist.)"
raise ValidationError(message=message)
def create_endpoint_config(
@ -1867,11 +1848,10 @@ class SageMakerModelBackend(BaseBackend):
try:
return self.training_jobs[training_job_name].response_object
except KeyError:
message = "Could not find training job '{}'.".format(
FakeTrainingJob.arn_formatter(
training_job_name, self.account_id, self.region_name
)
arn = FakeTrainingJob.arn_formatter(
training_job_name, self.account_id, self.region_name
)
message = f"Could not find training job '{arn}'."
raise ValidationError(message=message)
def list_training_jobs(

View File

@ -486,9 +486,7 @@ class SageMakerResponse(BaseResponse):
errors = []
if max_results and max_results not in max_results_range:
errors.append(
"Value '{0}' at 'maxResults' failed to satisfy constraint: Member must have value less than or equal to {1}".format(
max_results, max_results_range[-1]
)
f"Value '{max_results}' at 'maxResults' failed to satisfy constraint: Member must have value less than or equal to {max_results_range[-1]}"
)
if sort_by not in allowed_sort_by:
@ -541,9 +539,7 @@ class SageMakerResponse(BaseResponse):
errors = []
if max_results and max_results not in max_results_range:
errors.append(
"Value '{0}' at 'maxResults' failed to satisfy constraint: Member must have value less than or equal to {1}".format(
max_results, max_results_range[-1]
)
f"Value '{max_results}' at 'maxResults' failed to satisfy constraint: Member must have value less than or equal to {max_results_range[-1]}"
)
if sort_by not in allowed_sort_by:

View File

@ -26,7 +26,7 @@ class SecretHasNoValueException(SecretsManagerClientError):
super().__init__(
"ResourceNotFoundException",
message="Secrets Manager can't find the specified secret "
"value for staging label: {}".format(version_stage),
f"value for staging label: {version_stage}",
)

View File

@ -265,9 +265,7 @@ class SecretsManagerBackend(BaseBackend):
if not secret_version:
raise ResourceNotFoundException(
"An error occurred (ResourceNotFoundException) when calling the GetSecretValue operation: Secrets "
"Manager can't find the specified secret value for VersionId: {}".format(
version_id
)
f"Manager can't find the specified secret value for VersionId: {version_id}"
)
response_data = {
@ -553,9 +551,7 @@ class SecretsManagerBackend(BaseBackend):
try:
func = lambda_backend.get_function(secret.rotation_lambda_arn)
except Exception:
msg = "Resource not found for ARN '{}'.".format(
secret.rotation_lambda_arn
)
msg = f"Resource not found for ARN '{secret.rotation_lambda_arn}'."
raise ResourceNotFoundException(msg)
for step in ["create", "set", "test", "finish"]:
@ -594,11 +590,9 @@ class SecretsManagerBackend(BaseBackend):
# password size must have value less than or equal to 4096
if password_length > 4096:
raise ClientError(
"ClientError: An error occurred (ValidationException) \
when calling the GetRandomPassword operation: 1 validation error detected: Value '{}' at 'passwordLength' \
failed to satisfy constraint: Member must have value less than or equal to 4096".format(
password_length
)
f"ClientError: An error occurred (ValidationException) \
when calling the GetRandomPassword operation: 1 validation error detected: Value '{password_length}' at 'passwordLength' \
failed to satisfy constraint: Member must have value less than or equal to 4096"
)
if password_length < 4:
raise InvalidParameterException(
@ -772,14 +766,13 @@ class SecretsManagerBackend(BaseBackend):
if remove_from_version_id:
if remove_from_version_id not in secret.versions:
raise InvalidParameterException(
"Not a valid version: %s" % remove_from_version_id
f"Not a valid version: {remove_from_version_id}"
)
stages = secret.versions[remove_from_version_id]["version_stages"]
if version_stage not in stages:
raise InvalidParameterException(
"Version stage %s not found in version %s"
% (version_stage, remove_from_version_id)
f"Version stage {version_stage} not found in version {remove_from_version_id}"
)
stages.remove(version_stage)
@ -787,7 +780,7 @@ class SecretsManagerBackend(BaseBackend):
if move_to_version_id:
if move_to_version_id not in secret.versions:
raise InvalidParameterException(
"Not a valid version: %s" % move_to_version_id
f"Not a valid version: {move_to_version_id}"
)
stages = secret.versions[move_to_version_id]["version_stages"]

View File

@ -18,14 +18,12 @@ def _validate_filters(filters):
raise InvalidParameterException("Invalid filter key")
if filter_key not in filter_keys():
raise ValidationException(
"1 validation error detected: Value '{}' at 'filters.{}.member.key' failed to satisfy constraint: "
"Member must satisfy enum value set: [all, name, tag-key, description, tag-value]".format(
filter_key, idx + 1
)
f"1 validation error detected: Value '{filter_key}' at 'filters.{(idx + 1)}.member.key' failed to satisfy constraint: "
"Member must satisfy enum value set: [all, name, tag-key, description, tag-value]"
)
if filter_values is None:
raise InvalidParameterException(
"Invalid filter values for key: {}".format(filter_key)
f"Invalid filter values for key: {filter_key}"
)

View File

@ -85,7 +85,7 @@ def _exclude_characters(password, exclude_characters):
for c in exclude_characters:
if c in string.punctuation:
# Escape punctuation regex usage
c = r"\{0}".format(c)
c = rf"\{c}"
password = re.sub(c, "", str(password))
return password

View File

@ -98,5 +98,5 @@ class MissingRenderingAttributeException(RESTError):
def __init__(self, var):
super().__init__(
"MissingRenderingAttributeException",
"Attribute '{0}' is not present in the rendering data.".format(var),
f"Attribute '{var}' is not present in the rendering data.",
)

View File

@ -189,7 +189,7 @@ class SESBackend(BaseBackend):
raise MessageRejectedError("Too many recipients.")
if not self._is_verified_address(source):
self.rejected_messages_count += 1
raise MessageRejectedError("Email address not verified %s" % source)
raise MessageRejectedError(f"Email address not verified {source}")
destination_addresses = [
address for addresses in destinations.values() for address in addresses
]
@ -221,10 +221,10 @@ class SESBackend(BaseBackend):
if not self._is_verified_address(source):
self.rejected_messages_count += 1
raise MessageRejectedError("Email address not verified %s" % source)
raise MessageRejectedError(f"Email address not verified {source}")
if not self.templates.get(template[0]):
raise TemplateDoesNotExist("Template (%s) does not exist" % template[0])
raise TemplateDoesNotExist(f"Template ({template[0]}) does not exist")
self.__process_sns_feedback__(source, destinations, region)
@ -246,7 +246,7 @@ class SESBackend(BaseBackend):
raise MessageRejectedError("Too many recipients.")
if not self._is_verified_address(source):
self.rejected_messages_count += 1
raise MessageRejectedError("Email address not verified %s" % source)
raise MessageRejectedError(f"Email address not verified {source}")
destination_addresses = [
address for addresses in destinations.values() for address in addresses
]
@ -256,7 +256,7 @@ class SESBackend(BaseBackend):
raise InvalidParameterValue(msg)
if not self.templates.get(template[0]):
raise TemplateDoesNotExist("Template (%s) does not exist" % template[0])
raise TemplateDoesNotExist(f"Template ({template[0]}) does not exist")
self.__process_sns_feedback__(source, destinations, region)
@ -314,8 +314,7 @@ class SESBackend(BaseBackend):
_, source_email_address = parseaddr(source)
if not self._is_verified_address(source_email_address):
raise MessageRejectedError(
"Did not have authority to send from email %s"
% source_email_address
f"Did not have authority to send from email {source_email_address}"
)
recipient_count = len(destinations)
@ -327,8 +326,7 @@ class SESBackend(BaseBackend):
_, source_email_address = parseaddr(message["from"])
if not self._is_verified_address(source_email_address):
raise MessageRejectedError(
"Did not have authority to send from email %s"
% source_email_address
f"Did not have authority to send from email {source_email_address}"
)
for header in "TO", "CC", "BCC":
@ -480,9 +478,9 @@ class SESBackend(BaseBackend):
html_part = template["html_part"]
for key, value in template_data.items():
subject_part = str.replace(str(subject_part), "{{%s}}" % key, value)
text_part = str.replace(str(text_part), "{{%s}}" % key, value)
html_part = str.replace(str(html_part), "{{%s}}" % key, value)
subject_part = str.replace(str(subject_part), "{{" + key + "}}", value)
text_part = str.replace(str(text_part), "{{" + key + "}}", value)
html_part = str.replace(str(html_part), "{{" + key + "}}", value)
email_obj = MIMEMultipart("alternative")
@ -498,10 +496,8 @@ class SESBackend(BaseBackend):
now = datetime.datetime.now().isoformat()
rendered_template = "Date: %s\r\nSubject: %s\r\n%s" % (
now,
subject_part,
email_obj.as_string(),
rendered_template = (
f"Date: {now}\r\nSubject: {subject_part}\r\n{email_obj.as_string()}"
)
return rendered_template
@ -556,9 +552,7 @@ class SESBackend(BaseBackend):
self, identity, mail_from_domain=None, behavior_on_mx_failure=None
):
if identity not in (self.domains + self.addresses):
raise InvalidParameterValue(
"Identity '{0}' does not exist.".format(identity)
)
raise InvalidParameterValue(f"Identity '{identity}' does not exist.")
if mail_from_domain is None:
self.identity_mail_from_domains.pop(identity)
@ -566,16 +560,16 @@ class SESBackend(BaseBackend):
if not mail_from_domain.endswith(identity):
raise InvalidParameterValue(
"Provided MAIL-FROM domain '{0}' is not subdomain of "
"the domain of the identity '{1}'.".format(mail_from_domain, identity)
f"Provided MAIL-FROM domain '{mail_from_domain}' is not subdomain of "
f"the domain of the identity '{identity}'."
)
if behavior_on_mx_failure not in (None, "RejectMessage", "UseDefaultValue"):
raise ValidationError(
"1 validation error detected: "
"Value '{0}' at 'behaviorOnMXFailure'"
f"Value '{behavior_on_mx_failure}' at 'behaviorOnMXFailure'"
"failed to satisfy constraint: Member must satisfy enum value set: "
"[RejectMessage, UseDefaultValue]".format(behavior_on_mx_failure)
"[RejectMessage, UseDefaultValue]"
)
self.identity_mail_from_domains[identity] = {

View File

@ -64,7 +64,7 @@ class EmailResponse(BaseResponse):
for dest_type in destinations:
# consume up to 51 to allow exception
for i in range(1, 52):
field = "Destination.%s.member.%s" % (dest_type, i)
field = f"Destination.{dest_type}.member.{i}"
address = self.querystring.get(field)
if address is None:
break
@ -85,7 +85,7 @@ class EmailResponse(BaseResponse):
for dest_type in destinations:
# consume up to 51 to allow exception
for i in range(1, 52):
field = "Destination.%s.member.%s" % (dest_type, i)
field = f"Destination.{dest_type}.member.{i}"
address = self.querystring.get(field)
if address is None:
break
@ -105,7 +105,7 @@ class EmailResponse(BaseResponse):
destinations = []
for i in range(1, 52):
destination_field = (
"Destinations.member.%s.Destination.ToAddresses.member.1" % (i)
f"Destinations.member.{i}.Destination.ToAddresses.member.1"
)
if self.querystring.get(destination_field) is None:
break
@ -113,10 +113,8 @@ class EmailResponse(BaseResponse):
for dest_type in destination:
# consume up to 51 to allow exception
for j in range(1, 52):
field = "Destinations.member.%s.Destination.%s.member.%s" % (
i,
dest_type,
j,
field = (
f"Destinations.member.{i}.Destination.{dest_type}.member.{j}"
)
address = self.querystring.get(field)
if address is None:
@ -142,7 +140,7 @@ class EmailResponse(BaseResponse):
destinations = []
# consume up to 51 to allow exception
for i in range(1, 52):
field = "Destinations.member.%s" % i
field = f"Destinations.member.{i}"
address = self.querystring.get(field)
if address is None:
break

View File

@ -8,15 +8,7 @@ def random_hex(length):
def get_random_message_id():
return "{0}-{1}-{2}-{3}-{4}-{5}-{6}".format(
random_hex(16),
random_hex(8),
random_hex(4),
random_hex(4),
random_hex(4),
random_hex(12),
random_hex(6),
)
return f"{random_hex(16)}-{random_hex(8)}-{random_hex(4)}-{random_hex(4)}-{random_hex(4)}-{random_hex(12)}-{random_hex(6)}"
def is_valid_address(addr):

View File

@ -445,7 +445,7 @@ class PlatformEndpoint(BaseModel):
def publish(self, message):
if not self.enabled:
raise SnsEndpointDisabled("Endpoint %s disabled" % self.id)
raise SnsEndpointDisabled(f"Endpoint {self.id} disabled")
# This is where we would actually send a message
message_id = str(mock_random.uuid4())
@ -561,13 +561,13 @@ class SNSBackend(BaseBackend):
self.delete_topic_subscriptions(topic)
self.topics.pop(arn)
except KeyError:
raise SNSNotFoundError("Topic with arn {0} not found".format(arn))
raise SNSNotFoundError(f"Topic with arn {arn} not found")
def get_topic(self, arn):
try:
return self.topics[arn]
except KeyError:
raise SNSNotFoundError("Topic with arn {0} not found".format(arn))
raise SNSNotFoundError(f"Topic with arn {arn} not found")
def set_topic_attribute(self, topic_arn, attribute_name, attribute_value):
topic = self.get_topic(topic_arn)
@ -578,12 +578,12 @@ class SNSBackend(BaseBackend):
if re.search(r"[./-]{2,}", endpoint) or re.search(
r"(^[./-]|[./-]$)", endpoint
):
raise SNSInvalidParameter("Invalid SMS endpoint: {}".format(endpoint))
raise SNSInvalidParameter(f"Invalid SMS endpoint: {endpoint}")
reduced_endpoint = re.sub(r"[./-]", "", endpoint)
if not is_e164(reduced_endpoint):
raise SNSInvalidParameter("Invalid SMS endpoint: {}".format(endpoint))
raise SNSInvalidParameter(f"Invalid SMS endpoint: {endpoint}")
# AWS doesn't create duplicates
old_subscription = self._find_subscription(topic_arn, endpoint, protocol)
@ -671,9 +671,9 @@ class SNSBackend(BaseBackend):
else:
if not fifo_topic:
msg = (
"Value {} for parameter MessageGroupId is invalid. "
f"Value {group_id} for parameter MessageGroupId is invalid. "
"Reason: The request include parameter that is not valid for this queue type."
).format(group_id)
)
raise InvalidParameterValue(msg)
message_id = topic.publish(
message,
@ -697,7 +697,7 @@ class SNSBackend(BaseBackend):
try:
return self.applications[arn]
except KeyError:
raise SNSNotFoundError("Application with arn {0} not found".format(arn))
raise SNSNotFoundError(f"Application with arn {arn} not found")
def set_application_attributes(self, arn, attributes):
application = self.get_application(arn)
@ -724,7 +724,7 @@ class SNSBackend(BaseBackend):
):
return endpoint
raise DuplicateSnsEndpointError(
"Duplicate endpoint token with different attributes: %s" % token
f"Duplicate endpoint token with different attributes: {token}"
)
platform_endpoint = PlatformEndpoint(
self.account_id,
@ -761,7 +761,7 @@ class SNSBackend(BaseBackend):
try:
del self.platform_endpoints[arn]
except KeyError:
raise SNSNotFoundError("Endpoint with arn {0} not found".format(arn))
raise SNSNotFoundError(f"Endpoint with arn {arn} not found")
def get_subscription_attributes(self, arn):
subscription = self.subscriptions.get(arn)
@ -786,7 +786,7 @@ class SNSBackend(BaseBackend):
# TODO: should do validation
_subscription = [_ for _ in self.subscriptions.values() if _.arn == arn]
if not _subscription:
raise SNSNotFoundError("Subscription with arn {0} not found".format(arn))
raise SNSNotFoundError(f"Subscription with arn {arn} not found")
subscription = _subscription[0]
subscription.attributes[name] = value
@ -837,9 +837,7 @@ class SNSBackend(BaseBackend):
continue
else:
raise SNSInvalidParameter(
"Invalid parameter: FilterPolicy: Unrecognized match type {type}".format(
type=keyword
)
f"Invalid parameter: FilterPolicy: Unrecognized match type {keyword}"
)
raise SNSInvalidParameter(
@ -867,9 +865,9 @@ class SNSBackend(BaseBackend):
raise SNSInvalidParameter("Policy statement action out of service scope!")
principals = [
"arn:aws:iam::{}:root".format(account_id) for account_id in aws_account_ids
f"arn:aws:iam::{account_id}:root" for account_id in aws_account_ids
]
actions = ["SNS:{}".format(action_name) for action_name in action_names]
actions = [f"SNS:{action_name}" for action_name in action_names]
statement = {
"Sid": label,

View File

@ -49,8 +49,7 @@ class SNSResponse(BaseResponse):
data_type = value["DataType"]
if not data_type:
raise InvalidParameterValue(
"The message attribute '{0}' must contain non-empty "
"message attribute value.".format(name)
f"The message attribute '{name}' must contain non-empty message attribute value."
)
data_type_parts = data_type.split(".")
@ -60,9 +59,9 @@ class SNSResponse(BaseResponse):
"Number",
]:
raise InvalidParameterValue(
"The message attribute '{0}' has an invalid message "
f"The message attribute '{name}' has an invalid message "
"attribute type, the set of supported type prefixes is "
"Binary, Number, and String.".format(name)
"Binary, Number, and String."
)
transform_value = None
@ -77,9 +76,7 @@ class SNSResponse(BaseResponse):
raise InvalidParameterValue(
"An error occurred (ParameterValueInvalid) "
"when calling the Publish operation: "
"Could not cast message attribute '{0}' value to number.".format(
name
)
f"Could not cast message attribute '{name}' value to number."
)
else:
transform_value = value["StringValue"]
@ -87,9 +84,9 @@ class SNSResponse(BaseResponse):
transform_value = value["BinaryValue"]
if transform_value == "":
raise InvalidParameterValue(
"The message attribute '{0}' must contain non-empty "
f"The message attribute '{name}' must contain non-empty "
"message attribute value for message attribute "
"type '{1}'.".format(name, data_type[0])
f"type '{data_type[0]}'."
)
# transformation
@ -767,9 +764,7 @@ class SNSResponse(BaseResponse):
# return error_response, dict(status=400)
template = self.response_template(CONFIRM_SUBSCRIPTION_TEMPLATE)
return template.render(
sub_arn="{0}:68762e72-e9b1-410a-8b3b-903da69ee1d5".format(arn)
)
return template.render(sub_arn=f"{arn}:68762e72-e9b1-410a-8b3b-903da69ee1d5")
def list_tags_for_resource(self):
arn = self._get_param("ResourceArn")

View File

@ -5,12 +5,12 @@ E164_REGEX = re.compile(r"^\+?[1-9]\d{1,14}$")
def make_arn_for_topic(account_id, name, region_name):
return "arn:aws:sns:{0}:{1}:{2}".format(region_name, account_id, name)
return f"arn:aws:sns:{region_name}:{account_id}:{name}"
def make_arn_for_subscription(topic_arn):
subscription_id = mock_random.uuid4()
return "{0}:{1}".format(topic_arn, subscription_id)
return f"{topic_arn}:{subscription_id}"
def is_e164(number):

View File

@ -63,7 +63,7 @@ class BatchRequestTooLong(RESTError):
super().__init__(
"BatchRequestTooLong",
"Batch requests cannot be longer than 262144 bytes. "
"You have sent {} bytes.".format(length),
f"You have sent {length} bytes.",
)
@ -71,7 +71,7 @@ class BatchEntryIdsNotDistinct(RESTError):
code = 400
def __init__(self, entry_id):
super().__init__("BatchEntryIdsNotDistinct", "Id {} repeated.".format(entry_id))
super().__init__("BatchEntryIdsNotDistinct", f"Id {entry_id} repeated.")
class TooManyEntriesInBatchRequest(RESTError):
@ -80,8 +80,7 @@ class TooManyEntriesInBatchRequest(RESTError):
def __init__(self, number):
super().__init__(
"TooManyEntriesInBatchRequest",
"Maximum number of entries per request are 10. "
"You have sent {}.".format(number),
"Maximum number of entries per request are 10. " f"You have sent {number}.",
)
@ -89,9 +88,7 @@ class InvalidAttributeName(RESTError):
code = 400
def __init__(self, attribute_name):
super().__init__(
"InvalidAttributeName", "Unknown Attribute {}.".format(attribute_name)
)
super().__init__("InvalidAttributeName", f"Unknown Attribute {attribute_name}.")
class InvalidAttributeValue(RESTError):
@ -100,7 +97,7 @@ class InvalidAttributeValue(RESTError):
def __init__(self, attribute_name):
super().__init__(
"InvalidAttributeValue",
"Invalid value for the parameter {}.".format(attribute_name),
f"Invalid value for the parameter {attribute_name}.",
)
@ -116,8 +113,7 @@ class MissingParameter(RESTError):
def __init__(self, parameter):
super().__init__(
"MissingParameter",
"The request must contain the parameter {}.".format(parameter),
"MissingParameter", f"The request must contain the parameter {parameter}."
)
@ -126,5 +122,5 @@ class OverLimit(RESTError):
def __init__(self, count):
super().__init__(
"OverLimit", "{} Actions were found, maximum allowed is 7.".format(count)
"OverLimit", f"{count} Actions were found, maximum allowed is 7."
)

View File

@ -135,9 +135,9 @@ class Message(BaseModel):
def validate_attribute_name(name):
if not ATTRIBUTE_NAME_PATTERN.match(name):
raise MessageAttributesInvalid(
"The message attribute name '{0}' is invalid. "
f"The message attribute name '{name}' is invalid. "
"Attribute name can contain A-Z, a-z, 0-9, "
"underscore (_), hyphen (-), and period (.) characters.".format(name)
"underscore (_), hyphen (-), and period (.) characters."
)
@staticmethod
@ -400,9 +400,7 @@ class Queue(CloudFormationModel):
else:
raise RESTError(
"AWS.SimpleQueueService.NonExistentQueue",
"Could not find DLQ for {0}".format(
self.redrive_policy["deadLetterTargetArn"]
),
f"Could not find DLQ for {self.redrive_policy['deadLetterTargetArn']}",
)
@staticmethod
@ -511,8 +509,8 @@ class Queue(CloudFormationModel):
return result
def url(self, request_url):
return "{0}://{1}/{2}/{3}".format(
request_url.scheme, request_url.netloc, self.account_id, self.name
return (
f"{request_url.scheme}://{request_url.netloc}/{self.account_id}/{self.name}"
)
@property
@ -625,7 +623,7 @@ class Queue(CloudFormationModel):
else:
self._policy_json = {
"Version": "2012-10-17",
"Id": "{}/SQSDefaultPolicy".format(self.queue_arn),
"Id": f"{self.queue_arn}/SQSDefaultPolicy",
"Statement": [],
}
@ -692,7 +690,7 @@ class SQSBackend(BaseBackend):
def list_queues(self, queue_name_prefix):
re_str = ".*"
if queue_name_prefix:
re_str = "^{0}.*".format(queue_name_prefix)
re_str = f"^{queue_name_prefix}.*"
prefix_re = re.compile(re_str)
qs = []
for name, q in self.queues.items():
@ -759,9 +757,7 @@ class SQSBackend(BaseBackend):
queue = self.get_queue(queue_name)
if len(message_body) > queue.maximum_message_size:
msg = "One or more parameters are invalid. Reason: Message must be shorter than {} bytes.".format(
queue.maximum_message_size
)
msg = f"One or more parameters are invalid. Reason: Message must be shorter than {queue.maximum_message_size} bytes."
raise InvalidParameterValue(msg)
if delay_seconds:
@ -794,9 +790,9 @@ class SQSBackend(BaseBackend):
else:
if not queue.fifo_queue:
msg = (
"Value {} for parameter MessageGroupId is invalid. "
f"Value {group_id} for parameter MessageGroupId is invalid. "
"Reason: The request include parameter that is not valid for this queue type."
).format(group_id)
)
raise InvalidParameterValue(msg)
message.group_id = group_id
@ -962,10 +958,8 @@ class SQSBackend(BaseBackend):
given_visibility_timeout = unix_time_millis() + visibility_timeout_msec
if given_visibility_timeout - message.sent_timestamp > 43200 * 1000:
raise InvalidParameterValue(
"Value {0} for parameter VisibilityTimeout is invalid. Reason: Total "
"VisibilityTimeout for the message is beyond the limit [43200 seconds]".format(
visibility_timeout
)
f"Value {visibility_timeout} for parameter VisibilityTimeout is invalid. Reason: Total "
"VisibilityTimeout for the message is beyond the limit [43200 seconds]"
)
message.change_visibility(visibility_timeout)
@ -1012,10 +1006,8 @@ class SQSBackend(BaseBackend):
)
if invalid_action:
raise InvalidParameterValue(
"Value SQS:{} for parameter ActionName is invalid. "
"Reason: Only the queue owner is allowed to invoke this action.".format(
invalid_action
)
f"Value SQS:{invalid_action} for parameter ActionName is invalid. "
"Reason: Only the queue owner is allowed to invoke this action."
)
policy = queue._policy_json
@ -1029,14 +1021,11 @@ class SQSBackend(BaseBackend):
)
if statement:
raise InvalidParameterValue(
"Value {} for parameter Label is invalid. "
"Reason: Already exists.".format(label)
f"Value {label} for parameter Label is invalid. Reason: Already exists."
)
principals = [
"arn:aws:iam::{}:root".format(account_id) for account_id in account_ids
]
actions = ["SQS:{}".format(action) for action in actions]
principals = [f"arn:aws:iam::{account_id}:root" for account_id in account_ids]
actions = [f"SQS:{action}" for action in actions]
statement = {
"Sid": label,
@ -1058,8 +1047,8 @@ class SQSBackend(BaseBackend):
if len(statements) == len(statements_new):
raise InvalidParameterValue(
"Value {} for parameter Label is invalid. "
"Reason: can't find label on existing policy.".format(label)
f"Value {label} for parameter Label is invalid. "
"Reason: can't find label on existing policy."
)
queue._policy_json["Statement"] = statements_new
@ -1071,9 +1060,7 @@ class SQSBackend(BaseBackend):
raise MissingParameter("Tags")
if len(tags) > 50:
raise InvalidParameterValue(
"Too many tags added for queue {}.".format(queue_name)
)
raise InvalidParameterValue(f"Too many tags added for queue {queue_name}.")
queue.tags.update(tags)

View File

@ -273,27 +273,25 @@ class SQSResponse(BaseResponse):
message_attributes = parse_message_attributes(
self.querystring,
base="SendMessageBatchRequestEntry.{}.".format(index),
base=f"SendMessageBatchRequestEntry.{index}.",
)
entries[index] = {
"Id": value[0],
"MessageBody": self.querystring.get(
"SendMessageBatchRequestEntry.{}.MessageBody".format(index)
f"SendMessageBatchRequestEntry.{index}.MessageBody"
)[0],
"DelaySeconds": self.querystring.get(
"SendMessageBatchRequestEntry.{}.DelaySeconds".format(index),
f"SendMessageBatchRequestEntry.{index}.DelaySeconds",
[None],
)[0],
"MessageAttributes": message_attributes,
"MessageGroupId": self.querystring.get(
"SendMessageBatchRequestEntry.{}.MessageGroupId".format(index),
f"SendMessageBatchRequestEntry.{index}.MessageGroupId",
[None],
)[0],
"MessageDeduplicationId": self.querystring.get(
"SendMessageBatchRequestEntry.{}.MessageDeduplicationId".format(
index
),
f"SendMessageBatchRequestEntry.{index}.MessageDeduplicationId",
[None],
)[0],
}
@ -329,15 +327,13 @@ class SQSResponse(BaseResponse):
for index in range(1, 11):
# Loop through looking for messages
receipt_key = "DeleteMessageBatchRequestEntry.{0}.ReceiptHandle".format(
index
)
receipt_key = f"DeleteMessageBatchRequestEntry.{index}.ReceiptHandle"
receipt_handle = self.querystring.get(receipt_key)
if not receipt_handle:
# Found all messages
break
message_user_id_key = "DeleteMessageBatchRequestEntry.{0}.Id".format(index)
message_user_id_key = f"DeleteMessageBatchRequestEntry.{index}.Id"
message_user_id = self.querystring.get(message_user_id_key)[0]
receipts.append(
{"receipt_handle": receipt_handle[0], "msg_user_id": message_user_id}
@ -396,9 +392,9 @@ class SQSResponse(BaseResponse):
return self._error(
"InvalidParameterValue",
"An error occurred (InvalidParameterValue) when calling "
"the ReceiveMessage operation: Value %s for parameter "
f"the ReceiveMessage operation: Value {message_count} for parameter "
"MaxNumberOfMessages is invalid. Reason: must be between "
"1 and 10, if provided." % message_count,
"1 and 10, if provided.",
)
try:
@ -410,9 +406,9 @@ class SQSResponse(BaseResponse):
return self._error(
"InvalidParameterValue",
"An error occurred (InvalidParameterValue) when calling "
"the ReceiveMessage operation: Value %s for parameter "
f"the ReceiveMessage operation: Value {wait_time} for parameter "
"WaitTimeSeconds is invalid. Reason: must be &lt;= 0 and "
"&gt;= 20 if provided." % wait_time,
"&gt;= 20 if provided.",
)
try:

View File

@ -14,7 +14,7 @@ def extract_input_message_attributes(querystring):
index = 1
while True:
# Loop through looking for message attributes
name_key = "MessageAttributeName.{0}".format(index)
name_key = f"MessageAttributeName.{index}"
name = querystring.get(name_key)
if not name:
# Found all attributes
@ -31,19 +31,17 @@ def parse_message_attributes(
index = 1
while True:
# Loop through looking for message attributes
name_key = base + "{0}.{1}.Name".format(key, index)
name_key = base + f"{key}.{index}.Name"
name = querystring.get(name_key)
if not name:
# Found all attributes
break
data_type_key = base + "{0}.{1}.{2}DataType".format(key, index, value_namespace)
data_type_key = base + f"{key}.{index}.{value_namespace}DataType"
data_type = querystring.get(data_type_key)
if not data_type:
raise MessageAttributesInvalid(
"The message attribute '{0}' must contain non-empty message attribute value.".format(
name[0]
)
f"The message attribute '{name[0]}' must contain non-empty message attribute value."
)
data_type_parts = data_type[0].split(".")
@ -53,24 +51,18 @@ def parse_message_attributes(
"Number",
]:
raise MessageAttributesInvalid(
"The message attribute '{0}' has an invalid message attribute type, the set of supported type prefixes is Binary, Number, and String.".format(
name[0]
)
f"The message attribute '{name[0]}' has an invalid message attribute type, the set of supported type prefixes is Binary, Number, and String."
)
type_prefix = "String"
if data_type_parts[0] == "Binary":
type_prefix = "Binary"
value_key = base + "{0}.{1}.{2}{3}Value".format(
key, index, value_namespace, type_prefix
)
value_key = base + f"{key}.{index}.{value_namespace}{type_prefix}Value"
value = querystring.get(value_key)
if not value:
raise MessageAttributesInvalid(
"The message attribute '{0}' must contain non-empty message attribute value for message attribute type '{1}'.".format(
name[0], data_type[0]
)
f"The message attribute '{name[0]}' must contain non-empty message attribute value for message attribute type '{data_type[0]}'."
)
message_attributes[name[0]] = {

View File

@ -212,13 +212,13 @@ class Parameter(CloudFormationModel):
self.value = value
def encrypt(self, value):
return "kms:{}:".format(self.keyid) + value
return f"kms:{self.keyid}:" + value
def decrypt(self, value):
if self.type != "SecureString":
return value
prefix = "kms:{}:".format(self.keyid or "default")
prefix = f"kms:{self.keyid or 'default'}:"
if value.startswith(prefix):
return value[len(prefix) :]
@ -1342,9 +1342,7 @@ class SimpleSystemManagerBackend(BaseBackend):
if not re.match(r"^tag:.+|Name|Type|KeyId|Path|Label|Tier$", key):
self._errors.append(
self._format_error(
key="parameterFilters.{index}.member.key".format(
index=(index + 1)
),
key=f"parameterFilters.{index + 1}.member.key",
value=key,
constraint="Member must satisfy regular expression pattern: tag:.+|Name|Type|KeyId|Path|Label|Tier",
)
@ -1353,9 +1351,7 @@ class SimpleSystemManagerBackend(BaseBackend):
if len(key) > 132:
self._errors.append(
self._format_error(
key="parameterFilters.{index}.member.key".format(
index=(index + 1)
),
key=f"parameterFilters.{index + 1}.member.key",
value=key,
constraint="Member must have length less than or equal to 132",
)
@ -1364,9 +1360,7 @@ class SimpleSystemManagerBackend(BaseBackend):
if len(option) > 10:
self._errors.append(
self._format_error(
key="parameterFilters.{index}.member.option".format(
index=(index + 1)
),
key=f"parameterFilters.{index + 1}.member.option",
value="over 10 chars",
constraint="Member must have length less than or equal to 10",
)
@ -1375,9 +1369,7 @@ class SimpleSystemManagerBackend(BaseBackend):
if len(values) > 50:
self._errors.append(
self._format_error(
key="parameterFilters.{index}.member.values".format(
index=(index + 1)
),
key=f"parameterFilters.{index + 1}.member.values",
value=values,
constraint="Member must have length less than or equal to 50",
)
@ -1386,9 +1378,7 @@ class SimpleSystemManagerBackend(BaseBackend):
if any(len(value) > 1024 for value in values):
self._errors.append(
self._format_error(
key="parameterFilters.{index}.member.values".format(
index=(index + 1)
),
key=f"parameterFilters.{index + 1}.member.values",
value=values,
constraint="[Member must have length less than or equal to 1024, Member must have length greater than or equal to 1]",
)
@ -1413,9 +1403,7 @@ class SimpleSystemManagerBackend(BaseBackend):
if by_path and key in ["Name", "Path", "Tier"]:
raise InvalidFilterKey(
"The following filter key is not valid: {key}. Valid filter keys include: [Type, KeyId].".format(
key=key
)
f"The following filter key is not valid: {key}. Valid filter keys include: [Type, KeyId]."
)
if not values:
@ -1431,9 +1419,7 @@ class SimpleSystemManagerBackend(BaseBackend):
if key == "Path":
if option not in ["Recursive", "OneLevel"]:
raise InvalidFilterOption(
"The following filter option is not valid: {option}. Valid options include: [Recursive, OneLevel].".format(
option=option
)
f"The following filter option is not valid: {option}. Valid options include: [Recursive, OneLevel]."
)
if any(value.lower().startswith(("/aws", "/ssm")) for value in values):
raise ValidationException(
@ -1463,18 +1449,14 @@ class SimpleSystemManagerBackend(BaseBackend):
for value in values:
if value not in ["Standard", "Advanced", "Intelligent-Tiering"]:
raise InvalidFilterOption(
"The following filter value is not valid: {value}. Valid values include: [Standard, Advanced, Intelligent-Tiering].".format(
value=value
)
f"The following filter value is not valid: {value}. Valid values include: [Standard, Advanced, Intelligent-Tiering]."
)
if key == "Type":
for value in values:
if value not in ["String", "StringList", "SecureString"]:
raise InvalidFilterOption(
"The following filter value is not valid: {value}. Valid values include: [String, StringList, SecureString].".format(
value=value
)
f"The following filter value is not valid: {value}. Valid values include: [String, StringList, SecureString]."
)
allowed_options = ["Equals", "BeginsWith"]
@ -1482,17 +1464,13 @@ class SimpleSystemManagerBackend(BaseBackend):
allowed_options += ["Contains"]
if key != "Path" and option not in allowed_options:
raise InvalidFilterOption(
"The following filter option is not valid: {option}. Valid options include: [BeginsWith, Equals].".format(
option=option
)
f"The following filter option is not valid: {option}. Valid options include: [BeginsWith, Equals]."
)
filter_keys.append(key)
def _format_error(self, key, value, constraint):
return 'Value "{value}" at "{key}" failed to satisfy constraint: {constraint}'.format(
constraint=constraint, key=key, value=value
)
return f'Value "{value}" at "{key}" failed to satisfy constraint: {constraint}'
def _raise_errors(self):
if self._errors:
@ -1502,9 +1480,7 @@ class SimpleSystemManagerBackend(BaseBackend):
self._errors = [] # reset collected errors
raise ValidationException(
"{count} validation error{plural} detected: {errors}".format(
count=count, plural=plural, errors=errors
)
f"{count} validation error{plural} detected: {errors}"
)
def get_all_parameters(self):
@ -1517,12 +1493,10 @@ class SimpleSystemManagerBackend(BaseBackend):
result = {}
if len(names) > 10:
all_names = ", ".join(names)
raise ValidationException(
"1 validation error detected: "
"Value '[{}]' at 'names' failed to satisfy constraint: "
"Member must have length less than or equal to 10.".format(
", ".join(names)
)
f"Value '[{all_names}]' at 'names' failed to satisfy constraint: Member must have length less than or equal to 10."
)
for name in set(names):
@ -1577,10 +1551,8 @@ class SimpleSystemManagerBackend(BaseBackend):
if max_results > PARAMETER_HISTORY_MAX_RESULTS:
raise ValidationException(
"1 validation error detected: "
"Value '{}' at 'maxResults' failed to satisfy constraint: "
"Member must have value less than or equal to {}.".format(
max_results, PARAMETER_HISTORY_MAX_RESULTS
)
f"Value '{max_results}' at 'maxResults' failed to satisfy constraint: "
f"Member must have value less than or equal to {PARAMETER_HISTORY_MAX_RESULTS}."
)
if name in self._parameters:
@ -1710,7 +1682,7 @@ class SimpleSystemManagerBackend(BaseBackend):
def label_parameter_version(self, name, version, labels):
previous_parameter_versions = self._parameters[name]
if not previous_parameter_versions:
raise ParameterNotFound("Parameter %s not found." % name)
raise ParameterNotFound(f"Parameter {name} not found.")
found_parameter = None
labels_needing_removal = []
if not version:
@ -1727,8 +1699,7 @@ class SimpleSystemManagerBackend(BaseBackend):
labels_needing_removal.append(label)
if not found_parameter:
raise ParameterVersionNotFound(
"Systems Manager could not find version %s of %s. "
"Verify the version and try again." % (version, name)
f"Systems Manager could not find version {version} of {name}. Verify the version and try again."
)
labels_to_append = []
invalid_labels = []
@ -1772,10 +1743,10 @@ class SimpleSystemManagerBackend(BaseBackend):
oldest_parameter = parameter_versions[0]
if oldest_parameter.labels:
raise ParameterMaxVersionLimitExceeded(
"You attempted to create a new version of %s by calling the PutParameter API "
"with the overwrite flag. Version %d, the oldest version, can't be deleted "
f"You attempted to create a new version of {name} by calling the PutParameter API "
f"with the overwrite flag. Version {oldest_parameter.version}, the oldest version, can't be deleted "
"because it has a label associated with it. Move the label to another version "
"of the parameter, and try again." % (name, oldest_parameter.version)
"of the parameter, and try again."
)
def put_parameter(
@ -1807,7 +1778,7 @@ class SimpleSystemManagerBackend(BaseBackend):
is_path = name.count("/") > 1
if name.lower().startswith("/aws") and is_path:
raise AccessDeniedException(
"No access to reserved parameter name: {name}.".format(name=name)
f"No access to reserved parameter name: {name}."
)
if not is_path:
invalid_prefix_error = 'Parameter name: can\'t be prefixed with "aws" or "ssm" (case-insensitive).'

View File

@ -160,7 +160,7 @@ class SimpleSystemManagerResponse(BaseResponse):
if result is None:
error = {
"__type": "ParameterNotFound",
"message": "Parameter {0} not found.".format(name),
"message": f"Parameter {name} not found.",
}
return json.dumps(error), dict(status=400)
return json.dumps({})
@ -195,7 +195,7 @@ class SimpleSystemManagerResponse(BaseResponse):
if result is None:
error = {
"__type": "ParameterNotFound",
"message": "Parameter {0} not found.".format(name),
"message": f"Parameter {name} not found.",
}
return json.dumps(error), dict(status=400)
@ -296,7 +296,7 @@ class SimpleSystemManagerResponse(BaseResponse):
if result is None:
error = {
"__type": "ParameterAlreadyExists",
"message": "Parameter {0} already exists.".format(name),
"message": f"Parameter {name} already exists.",
}
return json.dumps(error), dict(status=400)
@ -316,7 +316,7 @@ class SimpleSystemManagerResponse(BaseResponse):
if result is None:
error = {
"__type": "ParameterNotFound",
"message": "Parameter {0} not found.".format(name),
"message": f"Parameter {name} not found.",
}
return json.dumps(error), dict(status=400)

View File

@ -36,7 +36,7 @@ class InvalidToken(AWSError):
STATUS = 400
def __init__(self, message="Invalid token"):
super().__init__("Invalid Token: {}".format(message))
super().__init__(f"Invalid Token: {message}")
class ResourceNotFound(AWSError):
@ -44,4 +44,4 @@ class ResourceNotFound(AWSError):
STATUS = 400
def __init__(self, arn):
super().__init__("Resource not found: '{}'".format(arn))
super().__init__(f"Resource not found: '{arn}'")

View File

@ -63,13 +63,7 @@ class AssumedRole(BaseModel):
@property
def arn(self):
return (
"arn:aws:sts::{account_id}:assumed-role/{role_name}/{session_name}".format(
account_id=self.account_id,
role_name=self.role_arn.split("/")[-1],
session_name=self.session_name,
)
)
return f"arn:aws:sts::{self.account_id}:assumed-role/{self.role_arn.split('/')[-1]}/{self.session_name}"
class STSBackend(BaseBackend):

View File

@ -28,7 +28,7 @@ class TokenResponse(BaseResponse):
"1 validation error detected: Value "
'\'{"Version": "2012-10-17", "Statement": [...]}\' '
"at 'policy' failed to satisfy constraint: Member must have length less than or "
" equal to %s" % MAX_FEDERATION_TOKEN_POLICY_LENGTH
f" equal to {MAX_FEDERATION_TOKEN_POLICY_LENGTH}"
)
name = self.querystring.get("Name")[0]

View File

@ -166,7 +166,7 @@ class SupportBackend(BaseBackend):
random_case_id = "".join(
random.choice("0123456789ABCDEFGHIJKLMabcdefghijklm") for i in range(16)
)
case_id = "case-12345678910-2020-%s" % random_case_id
case_id = f"case-12345678910-2020-{random_case_id}"
case = SupportCase(
case_id=case_id,
subject=subject,

View File

@ -8,9 +8,9 @@ class SWFClientError(JsonRESTError):
class SWFUnknownResourceFault(SWFClientError):
def __init__(self, resource_type, resource_name=None):
if resource_name:
message = "Unknown {0}: {1}".format(resource_type, resource_name)
message = f"Unknown {resource_type}: {resource_name}"
else:
message = "Unknown {0}".format(resource_type)
message = f"Unknown {resource_type}"
super().__init__("com.amazonaws.swf.base.model#UnknownResourceFault", message)
@ -31,7 +31,7 @@ class SWFDomainDeprecatedFault(SWFClientError):
class SWFSerializationException(SWFClientError):
def __init__(self, value):
message = "class java.lang.Foo can not be converted to an String "
message += " (not a real SWF exception ; happened on: {0})".format(value)
message += f" (not a real SWF exception ; happened on: {value})"
__type = "com.amazonaws.swf.base.model#SerializationException"
super().__init__(__type, message)
@ -40,9 +40,7 @@ class SWFTypeAlreadyExistsFault(SWFClientError):
def __init__(self, _type):
super().__init__(
"com.amazonaws.swf.base.model#TypeAlreadyExistsFault",
"{0}=[name={1}, version={2}]".format(
_type.__class__.__name__, _type.name, _type.version
),
f"{_type.__class__.__name__}=[name={_type.name}, version={_type.version}]",
)
@ -50,9 +48,7 @@ class SWFTypeDeprecatedFault(SWFClientError):
def __init__(self, _type):
super().__init__(
"com.amazonaws.swf.base.model#TypeDeprecatedFault",
"{0}=[name={1}, version={2}]".format(
_type.__class__.__name__, _type.name, _type.version
),
f"{_type.__class__.__name__}=[name={_type.name}, version={_type.version}]",
)
@ -88,19 +84,15 @@ class SWFDecisionValidationException(SWFClientError):
for pb in problems:
if pb["type"] == "null_value":
messages.append(
"Value null at '%(where)s' failed to satisfy constraint: "
"Member must not be null" % pb
f"Value null at '{pb['where']}' failed to satisfy constraint: Member must not be null"
)
elif pb["type"] == "bad_decision_type":
messages.append(
"Value '%(value)s' at '%(where)s' failed to satisfy constraint: "
"Member must satisfy enum value set: "
"[%(possible_values)s]" % pb
f"Value '{pb['value']}' at '{pb['where']}' failed to satisfy constraint: "
f"Member must satisfy enum value set: [{pb['possible_values']}]"
)
else:
raise ValueError(
"Unhandled decision constraint type: {0}".format(pb["type"])
)
raise ValueError(f"Unhandled decision constraint type: {pb['type']}")
# prefix
count = len(problems)
if count < 2:

View File

@ -168,7 +168,7 @@ class SWFBackend(BaseBackend):
workflow_version,
tag_list=None,
workflow_input=None,
**kwargs
**kwargs,
):
domain = self._get_domain(domain_name)
wf_type = domain.get_type("workflow", workflow_name, workflow_version)
@ -180,7 +180,7 @@ class SWFBackend(BaseBackend):
workflow_id,
tag_list=tag_list,
workflow_input=workflow_input,
**kwargs
**kwargs,
)
domain.add_workflow_execution(wfe)
wfe.start()
@ -284,17 +284,13 @@ class SWFBackend(BaseBackend):
if not wfe.open:
raise SWFUnknownResourceFault(
"execution",
"WorkflowExecution=[workflowId={0}, runId={1}]".format(
wfe.workflow_id, wfe.run_id
),
f"WorkflowExecution=[workflowId={wfe.workflow_id}, runId={wfe.run_id}]",
)
# decision task found, but already completed
if decision_task.state != "STARTED":
if decision_task.state == "COMPLETED":
raise SWFUnknownResourceFault(
"decision task, scheduledEventId = {0}".format(
decision_task.scheduled_event_id
)
f"decision task, scheduledEventId = {decision_task.scheduled_event_id}"
)
else:
raise ValueError(
@ -375,17 +371,13 @@ class SWFBackend(BaseBackend):
if not wfe.open:
raise SWFUnknownResourceFault(
"execution",
"WorkflowExecution=[workflowId={0}, runId={1}]".format(
wfe.workflow_id, wfe.run_id
),
f"WorkflowExecution=[workflowId={wfe.workflow_id}, runId={wfe.run_id}]",
)
# activity task found, but already completed
if activity_task.state != "STARTED":
if activity_task.state == "COMPLETED":
raise SWFUnknownResourceFault(
"activity, scheduledEventId = {0}".format(
activity_task.scheduled_event_id
)
f"activity, scheduledEventId = {activity_task.scheduled_event_id}"
)
else:
raise ValueError(

View File

@ -26,7 +26,7 @@ class Domain(BaseModel):
self.decision_task_lists = {}
def __repr__(self):
return "Domain(name: %(name)s, status: %(status)s)" % self.__dict__
return f"Domain(name: {self.name}, status: {self.status})"
def to_short_dict(self):
hsh = {"name": self.name, "status": self.status}
@ -50,9 +50,7 @@ class Domain(BaseModel):
if not ignore_empty:
raise SWFUnknownResourceFault(
"type",
"{0}Type=[name={1}, version={2}]".format(
kind.capitalize(), name, version
),
f"{kind.capitalize()}Type=[name={name}, version={version}]",
)
def add_type(self, _type):
@ -97,12 +95,10 @@ class Domain(BaseModel):
if run_id:
args = [
"execution",
"WorkflowExecution=[workflowId={0}, runId={1}]".format(
workflow_id, run_id
),
f"WorkflowExecution=[workflowId={workflow_id}, runId={run_id}]",
]
else:
args = ["execution, workflowId = {0}".format(workflow_id)]
args = [f"execution, workflowId = {workflow_id}"]
raise SWFUnknownResourceFault(*args)
# at last return workflow execution
return wfe

View File

@ -21,10 +21,8 @@ class GenericType(BaseModel):
def __repr__(self):
cls = self.__class__.__name__
attrs = (
"name: %(name)s, version: %(version)s, status: %(status)s" % self.__dict__
)
return "{0}({1})".format(cls, attrs)
attrs = f"name: {self.name}, version: {self.version}, status: {self.status}"
return f"{cls}({attrs})"
@property
def kind(self):
@ -39,7 +37,7 @@ class GenericType(BaseModel):
def to_medium_dict(self):
hsh = {
"{0}Type".format(self.kind): self.to_short_dict(),
f"{self.kind}Type": self.to_short_dict(),
"creationDate": 1420066800,
"status": self.status,
}

View File

@ -39,9 +39,7 @@ class HistoryEvent(BaseModel):
def __init__(self, event_id, event_type, event_timestamp=None, **kwargs):
if event_type not in SUPPORTED_HISTORY_EVENT_TYPES:
raise NotImplementedError(
"HistoryEvent does not implement attributes for type '{0}'".format(
event_type
)
f"HistoryEvent does not implement attributes for type '{event_type}'"
)
self.event_id = event_id
self.event_type = event_type
@ -71,5 +69,5 @@ class HistoryEvent(BaseModel):
}
def _attributes_key(self):
key = "{0}EventAttributes".format(self.event_type)
key = f"{self.event_type}EventAttributes"
return decapitalize(key)

View File

@ -89,7 +89,7 @@ class WorkflowExecution(BaseModel):
self._timers = {}
def __repr__(self):
return "WorkflowExecution(run_id: {0})".format(self.run_id)
return f"WorkflowExecution(run_id: {self.run_id})"
def _set_from_kwargs_or_workflow_type(
self, kwargs, local_key, workflow_type_key=None
@ -306,7 +306,7 @@ class WorkflowExecution(BaseModel):
for dt in self.decision_tasks:
if dt.task_token == task_token:
return dt
raise ValueError("No decision task with token: {0}".format(task_token))
raise ValueError(f"No decision task with token: {task_token}")
def start_decision_task(self, task_token, identity=None):
dt = self._find_decision_task(task_token)
@ -349,9 +349,7 @@ class WorkflowExecution(BaseModel):
problems.append(
{
"type": "null_value",
"where": "decisions.{0}.member.{1}.{2}".format(
decision_id, kind, key
),
"where": f"decisions.{decision_id}.member.{kind}.{key}",
}
)
return problems
@ -385,9 +383,7 @@ class WorkflowExecution(BaseModel):
attrs_to_check = [d for d in dcs.keys() if d.endswith("DecisionAttributes")]
if dcs["decisionType"] in self.KNOWN_DECISION_TYPES:
decision_type = dcs["decisionType"]
decision_attr = "{0}DecisionAttributes".format(
decapitalize(decision_type)
)
decision_attr = f"{decapitalize(decision_type)}DecisionAttributes"
attrs_to_check.append(decision_attr)
for attr in attrs_to_check:
problems += self._check_decision_attributes(
@ -399,9 +395,7 @@ class WorkflowExecution(BaseModel):
{
"type": "bad_decision_type",
"value": dcs["decisionType"],
"where": "decisions.{0}.member.decisionType".format(
decision_number
),
"where": f"decisions.{decision_number}.member.decisionType",
"possible_values": ", ".join(self.KNOWN_DECISION_TYPES),
}
)
@ -418,7 +412,7 @@ class WorkflowExecution(BaseModel):
# handle each decision separately, in order
for decision in decisions:
decision_type = decision["decisionType"]
attributes_key = "{0}DecisionAttributes".format(decapitalize(decision_type))
attributes_key = f"{decapitalize(decision_type)}DecisionAttributes"
attributes = decision.get(attributes_key, {})
if decision_type == "CompleteWorkflowExecution":
self.complete(event_id, attributes.get("result"))
@ -441,9 +435,7 @@ class WorkflowExecution(BaseModel):
# TODO: implement Decision type: ScheduleLambdaFunction
# TODO: implement Decision type: SignalExternalWorkflowExecution
# TODO: implement Decision type: StartChildWorkflowExecution
raise NotImplementedError(
"Cannot handle decision: {0}".format(decision_type)
)
raise NotImplementedError(f"Cannot handle decision: {decision_type}")
# finally decrement counter if and only if everything went well
self.open_counts["openDecisionTasks"] -= 1
@ -553,7 +545,7 @@ class WorkflowExecution(BaseModel):
if not timeouts[_type]:
error_key = default_key.replace("default_task_", "default_")
fail_schedule_activity_task(
activity_type, "{0}_UNDEFINED".format(error_key.upper())
activity_type, f"{error_key.upper()}_UNDEFINED"
)
return
@ -588,7 +580,7 @@ class WorkflowExecution(BaseModel):
for task in self.activity_tasks:
if task.task_token == task_token:
return task
raise ValueError("No activity task with token: {0}".format(task_token))
raise ValueError(f"No activity task with token: {task_token}")
def start_activity_task(self, task_token, identity=None):
task = self._find_activity_task(task_token)

View File

@ -52,12 +52,9 @@ class SWFResponse(BaseResponse):
return
keys = kwargs.keys()
if len(keys) == 2:
message = "Cannot specify both a {0} and a {1}".format(keys[0], keys[1])
message = f"Cannot specify both a {keys[0]} and a {keys[1]}"
else:
message = (
"Cannot specify more than one exclusive filters in the"
" same query: {0}".format(keys)
)
message = f"Cannot specify more than one exclusive filters in the same query: {keys}"
raise SWFValidationException(message)
def _list_types(self, kind):
@ -73,7 +70,7 @@ class SWFResponse(BaseResponse):
def _describe_type(self, kind):
domain = self._params["domain"]
_type_args = self._params["{0}Type".format(kind)]
_type_args = self._params[f"{kind}Type"]
name = _type_args["name"]
version = _type_args["version"]
self._check_string(domain)
@ -85,7 +82,7 @@ class SWFResponse(BaseResponse):
def _deprecate_type(self, kind):
domain = self._params["domain"]
_type_args = self._params["{0}Type".format(kind)]
_type_args = self._params[f"{kind}Type"]
name = _type_args["name"]
version = _type_args["version"]
self._check_string(domain)
@ -96,7 +93,7 @@ class SWFResponse(BaseResponse):
def _undeprecate_type(self, kind):
domain = self._params["domain"]
_type_args = self._params["{0}Type".format(kind)]
_type_args = self._params[f"{kind}Type"]
name = _type_args["name"]
version = _type_args["version"]
self._check_string(domain)